private void AddInput(source collSource, string inputSemantic, string localInputSemantic = null, ulong setIndex = 0) { if (collSource != null) { Sources.Add(collSource); } if (inputSemantic != null) { var input = new InputLocal(); input.semantic = inputSemantic; input.source = "#" + collSource.id; Inputs.Add(input); } if (localInputSemantic != null) { var vertexInputOff = new InputLocalOffset(); vertexInputOff.semantic = localInputSemantic; vertexInputOff.source = "#" + collSource.id; vertexInputOff.offset = LastInputOffset++; if (localInputSemantic == "TEXCOORD" || localInputSemantic == "COLOR") { vertexInputOff.set = setIndex; } InputOffsets.Add(vertexInputOff); } }
public static InputLocalOffset makeInputOffset(string source, string semantic, ulong offset, bool setSpecified, ulong set) { InputLocalOffset input = new InputLocalOffset(); input.source = "#" + source; input.semantic = semantic; input.offset = offset; input.set = set; input.setSpecified = setSpecified; return(input); }
public static source FindSourceFromInput(InputLocalOffset input, source[] sources) { string inputSource = input.source.Trim('#'); if (sources.Any(x => x.id == inputSource)) { return(Array.Find(sources, x => x.id == inputSource)); } else { return(null); } }
private void SetVertices(InputLocalOffset input, int[] p, int stepSize, Dictionary <string, MeshSource> sources, DAEVertexDescription[] outputVertices) { if (input.semantic.Equals("VERTEX")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].Vertex = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("NORMAL")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].Normal = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("TEXCOORD")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexCoord = meshSource.GetVector3(idx); outputVertices[i].TexCoord = new DAEVector3(outputVertices[i].TexCoord.X, 1 - outputVertices[i].TexCoord.Y, outputVertices[i].TexCoord.Z); } } else if (input.semantic.Equals("TEXTANGENT")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexTangent = meshSource.GetVector3(idx); } } else if (input.semantic.Equals("TEXBINORMAL")) { MeshSource meshSource = sources[DAEUtils.GetUrl(input.source).Id]; for (int i = 0; i < outputVertices.Length; i++) { int idx = p[i * stepSize + (int)input.offset]; outputVertices[i].TexBinormal = meshSource.GetVector3(idx); } } }
public skin ExportSkin(List <Bone> bones, Dictionary <string, Bone> nameMaps, string geometryId) { var sources = new List <source>(); var joints = new List <string>(); var poses = new List <float>(); var boundBones = new HashSet <string>(); var orderedBones = new List <Bone>(); foreach (var boneBinding in BoneBindings) { boundBones.Add(boneBinding.BoneName); orderedBones.Add(nameMaps[boneBinding.BoneName]); } /* * Append all bones to the end of the bone list, even if they're not influencing the mesh. * We need this because some tools (eg. Blender) expect all bones to be present, otherwise their * inverse world transform would reset to identity. */ foreach (var bone in bones) { if (!boundBones.Contains(bone.Name)) { orderedBones.Add(bone); } } foreach (var bone in orderedBones) { boundBones.Add(bone.Name); joints.Add(bone.Name); var invWorldTransform = FloatsToMatrix(bone.InverseWorldTransform); invWorldTransform.Transpose(); poses.AddRange(new float[] { invWorldTransform.M11, invWorldTransform.M12, invWorldTransform.M13, invWorldTransform.M14, invWorldTransform.M21, invWorldTransform.M22, invWorldTransform.M23, invWorldTransform.M24, invWorldTransform.M31, invWorldTransform.M32, invWorldTransform.M33, invWorldTransform.M34, invWorldTransform.M41, invWorldTransform.M42, invWorldTransform.M43, invWorldTransform.M44 }); } var jointSource = ColladaUtils.MakeNameSource(Name, "joints", new string[] { "JOINT" }, joints.ToArray()); var poseSource = ColladaUtils.MakeFloatSource(Name, "poses", new string[] { "TRANSFORM" }, poses.ToArray(), 16, "float4x4"); var weightsSource = PrimaryVertexData.MakeBoneWeights(Name); var vertices = PrimaryVertexData.Deduplicator.DeduplicatedPositions; var vertexInfluenceCounts = new List <int>(vertices.Count); var vertexInfluences = new List <int>(vertices.Count); int weightIdx = 0; foreach (var vertex in vertices) { int influences = 0; var indices = vertex.BoneIndices; var weights = vertex.BoneWeights; for (int i = 0; i < 4; i++) { if (weights[i] > 0) { influences++; vertexInfluences.Add(indices[i]); vertexInfluences.Add(weightIdx++); } } vertexInfluenceCounts.Add(influences); } var jointOffsets = new InputLocalOffset(); jointOffsets.semantic = "JOINT"; jointOffsets.source = "#" + jointSource.id; jointOffsets.offset = 0; var weightOffsets = new InputLocalOffset(); weightOffsets.semantic = "WEIGHT"; weightOffsets.source = "#" + weightsSource.id; weightOffsets.offset = 1; var vertWeights = new skinVertex_weights(); vertWeights.count = (ulong)vertices.Count; vertWeights.input = new InputLocalOffset[] { jointOffsets, weightOffsets }; vertWeights.v = string.Join(" ", vertexInfluences.Select(x => x.ToString()).ToArray()); vertWeights.vcount = string.Join(" ", vertexInfluenceCounts.Select(x => x.ToString()).ToArray()); var skin = new skin(); skin.source1 = "#" + geometryId; skin.bind_shape_matrix = "1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1"; var skinJoints = new skinJoints(); var skinJointInput = new InputLocal(); skinJointInput.semantic = "JOINT"; skinJointInput.source = "#" + jointSource.id; var skinInvBindInput = new InputLocal(); skinInvBindInput.semantic = "INV_BIND_MATRIX"; skinInvBindInput.source = "#" + poseSource.id; skinJoints.input = new InputLocal[] { skinJointInput, skinInvBindInput }; skin.joints = skinJoints; skin.source = new source[] { jointSource, poseSource, weightsSource }; skin.vertex_weights = vertWeights; return(skin); }
public mesh ExportToCollada(ExporterOptions options) { // TODO: model transform/inverse transform? source vertexSource = null; var sources = new List <source>(); ulong inputOffset = 0; var inputs = new List <InputLocal>(); var inputOffsets = new List <InputLocalOffset>(); foreach (var component in PrimaryVertexData.VertexComponentNames) { var input = new InputLocal(); source source = null; switch (component.String) { case "Position": { source = PrimaryVertexData.MakeColladaPositions(Name); vertexSource = source; input.semantic = "POSITION"; var vertexInputOff = new InputLocalOffset(); vertexInputOff.semantic = "VERTEX"; vertexInputOff.source = "#" + source.id; vertexInputOff.offset = inputOffset++; inputOffsets.Add(vertexInputOff); break; } case "Normal": { if (options.ExportNormals) { source = PrimaryVertexData.MakeColladaNormals(Name); input.semantic = "NORMAL"; } break; } case "Tangent": { if (options.ExportTangents) { source = PrimaryVertexData.MakeColladaTangents(Name); input.semantic = "TANGENT"; } break; } case "Binormal": { if (options.ExportTangents) { source = PrimaryVertexData.MakeColladaBinormals(Name); input.semantic = "BINORMAL"; } break; } case "MaxChannel_1": case "MaxChannel_2": case "UVChannel_1": case "UVChannel_2": { if (options.ExportUVs) { int uvIndex = Int32.Parse(component.String.Substring(11)) - 1; source = PrimaryVertexData.MakeColladaUVs(Name, uvIndex); var texInputOff = new InputLocalOffset(); texInputOff.semantic = "TEXCOORD"; texInputOff.source = "#" + source.id; texInputOff.offset = inputOffset++; inputOffsets.Add(texInputOff); } break; } case "BoneWeights": case "BoneIndices": // These are handled in ExportSkin() break; case "DiffuseColor0": case "map1": // Possibly bogus D:OS name for DiffuseColor0 // TODO: This is not exported at the moment. break; default: throw new NotImplementedException("Vertex component not supported: " + component.String); } if (source != null) { sources.Add(source); } if (input.semantic != null) { input.source = "#" + source.id; inputs.Add(input); } } var triangles = PrimaryTopology.MakeColladaTriangles( inputOffsets.ToArray(), PrimaryVertexData.Deduplicator.VertexDeduplicationMap, PrimaryVertexData.Deduplicator.UVDeduplicationMaps ); var colladaMesh = new mesh(); colladaMesh.vertices = new vertices(); colladaMesh.vertices.id = Name + "-vertices"; colladaMesh.vertices.input = inputs.ToArray(); colladaMesh.source = sources.ToArray(); colladaMesh.Items = new object[] { triangles }; return(colladaMesh); }