public static List <ImportedFace> ImportedFaceList(List <odfFace> faceList) { List <ImportedFace> importedList = new List <ImportedFace>(faceList.Count); for (int i = 0; i < faceList.Count; i++) { ImportedFace importedFace = new ImportedFace(); importedList.Add(importedFace); importedFace.VertexIndices = new int[3]; for (int j = 0; j < 3; j++) { importedFace.VertexIndices[j] = faceList[i].VertexIndices[j]; } } return(importedList); }
public static List <ImportedFace> ImportedFaceList(List <int> faceList) { int numFaces = faceList.Count / 3; List <ImportedFace> importedList = new List <ImportedFace>(numFaces); for (int i = 0; i < numFaces; i++) { ImportedFace importedFace = new ImportedFace(); importedList.Add(importedFace); importedFace.VertexIndices = new int[3]; for (int j = 0; j < 3; j++) { importedFace.VertexIndices[j] = faceList[i * 3 + j]; } } return(importedList); }
private void ImportMesh(Section section, ImportedMesh meshList, SortedDictionary<string, byte> boneDic, List<bool> hasBonesList) { int vertIdxOffset = 0; foreach (ImportedSubmesh submesh in meshList.SubmeshList) { vertIdxOffset += submesh.VertexList.Count; } LinkedListNode<object> node = section.data.First; int numVertices = ConvertInt32(node.Value); node = node.Next; DXVertex[] vertices = new DXVertex[numVertices]; for (int i = 0; i < numVertices; i++) { vertices[i] = new DXVertex(); float[] pos = new float[3]; for (int j = 0; j < pos.Length; j++) { pos[j] = ConvertFloat(node.Value); node = node.Next; } pos[2] = -pos[2]; vertices[i].position = pos; } int numFaces = ConvertInt32(node.Value); node = node.Next; DXFace[] faces = new DXFace[numFaces]; for (int i = 0; i < numFaces; i++) { int numFaceVerts = ConvertInt32(node.Value); node = node.Next; if (numFaceVerts != 3) { throw new Exception("Meshes must be triangulated"); } faces[i] = new DXFace(); faces[i].vertexIndices[0] = ConvertUInt16(node.Value); node = node.Next; faces[i].vertexIndices[2] = ConvertUInt16(node.Value); node = node.Next; faces[i].vertexIndices[1] = ConvertUInt16(node.Value); node = node.Next; } string[] materials = new string[] { String.Empty }; bool hasNormals = false; bool hasBones = false; bool hasUVs = false; List<KeyValuePair<byte, float>>[] boneAssignments = new List<KeyValuePair<byte, float>>[numVertices]; for (int i = 0; i < boneAssignments.Length; i++) { boneAssignments[i] = new List<KeyValuePair<byte, float>>(); } foreach (Section child in section.children) { if (child.type == "VertexDuplicationIndices") { } else if (child.type == "MeshNormals") { hasNormals = true; LinkedListNode<object> childNode = child.data.First; int numNormals = ConvertInt32(childNode.Value); childNode = childNode.Next; if (numNormals != numVertices) { throw new Exception("Number of normals doesn't match the number of vertices"); } foreach (DXVertex vert in vertices) { float[] norm = new float[3]; for (int i = 0; i < norm.Length; i++) { norm[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } norm[2] = -norm[2]; vert.normal = norm; } } else if (child.type == "MeshTextureCoords") { hasUVs = true; LinkedListNode<object> childNode = child.data.First; int numTexCoords = ConvertInt32(childNode.Value); childNode = childNode.Next; if (numTexCoords != numVertices) { throw new Exception("Number of texture coordinates doesn't match the number of vertices"); } foreach (DXVertex vert in vertices) { float[] uv = new float[2]; for (int i = 0; i < uv.Length; i++) { uv[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } vert.uv = uv; } } else if (child.type == "MeshMaterialList") { materials = ImportMaterials(child, faces); } else if (child.type == "XSkinMeshHeader") { hasBones = true; } else if (child.type == "SkinWeights") { LinkedListNode<object> childNode = child.data.First; string boneName = ConvertString(childNode.Value); childNode = childNode.Next; int numWeights = ConvertInt32(childNode.Value); childNode = childNode.Next; int[] vertIndices = new int[numWeights]; for (int i = 0; i < numWeights; i++) { vertIndices[i] = ConvertInt32(childNode.Value); childNode = childNode.Next; } float[] weights = new float[numWeights]; for (int i = 0; i < numWeights; i++) { weights[i] = ConvertFloat(childNode.Value); childNode = childNode.Next; } byte boneIdx; if (!boneDic.TryGetValue(boneName, out boneIdx)) { boneIdx = (byte)boneDic.Count; boneDic.Add(boneName, boneIdx); ImportedBone boneInfo = new ImportedBone(); meshList.BoneList.Add(boneInfo); boneInfo.Name = boneName; Matrix matrix = new Matrix(); for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrix[i, j] = ConvertFloat(childNode.Value); childNode = childNode.Next; } } boneInfo.Matrix = RHToLHMatrix(matrix); } for (int i = 0; i < numWeights; i++) { boneAssignments[vertIndices[i]].Add(new KeyValuePair<byte, float>(boneIdx, weights[i])); } } else { Report.ReportLog("Warning: unexpected section " + child.type); } } if (hasBones) { for (int i = 0; i < boneAssignments.Length; i++) { byte[] boneIndices = new byte[4]; float[] weights4 = new float[4]; for (int j = 0; (j < 4) && (j < boneAssignments[i].Count); j++) { boneIndices[j] = boneAssignments[i][j].Key; weights4[j] = boneAssignments[i][j].Value; } for (int j = boneAssignments[i].Count; j < 4; j++) { boneIndices[j] = 0xFF; weights4[j] = 0; } vertices[i].boneIndices = boneIndices; vertices[i].weights = new float[] { weights4[0], weights4[1], weights4[2], weights4[3] }; } } SortedDictionary<ushort, ushort>[] vertexMaps = new SortedDictionary<ushort, ushort>[materials.Length]; ImportedSubmesh[] submeshes = new ImportedSubmesh[materials.Length]; for (int i = 0; i < materials.Length; i++) { submeshes[i] = new ImportedSubmesh(); submeshes[i].Material = materials[i]; submeshes[i].VertexList = new List<ImportedVertex>(vertices.Length); submeshes[i].FaceList = new List<ImportedFace>(faces.Length); vertexMaps[i] = new SortedDictionary<ushort, ushort>(); } foreach (DXFace dxFace in faces) { ImportedSubmesh submesh = submeshes[dxFace.materialIndex]; ImportedFace face = new ImportedFace(); submesh.FaceList.Add(face); ushort[] foundVertexIndices = new ushort[3]; for (int i = 0; i < dxFace.vertexIndices.Length; i++) { ushort dxVertIdx = dxFace.vertexIndices[i]; SortedDictionary<ushort, ushort> vertexMap = vertexMaps[dxFace.materialIndex]; if (!vertexMap.TryGetValue(dxVertIdx, out foundVertexIndices[i])) { DXVertex dxVert = vertices[dxVertIdx]; ImportedVertex vert = new ImportedVertex(); submesh.VertexList.Add(vert); if (hasNormals) { vert.Normal = new Vector3(dxVert.normal[0], dxVert.normal[1], dxVert.normal[2]); } if (hasUVs) { vert.UV = (float[])dxVert.uv.Clone(); } if (hasBones) { vert.BoneIndices = (byte[])dxVert.boneIndices.Clone(); vert.Weights = (float[])dxVert.weights.Clone(); } vert.Position = new Vector3(dxVert.position[0], dxVert.position[1], dxVert.position[2]); vertIdxOffset++; foundVertexIndices[i] = (ushort)vertexMap.Count; vertexMap.Add(dxVertIdx, foundVertexIndices[i]); } } face.VertexIndices = new int[] { foundVertexIndices[0], foundVertexIndices[1], foundVertexIndices[2] }; } foreach (ImportedSubmesh submesh in submeshes) { if (submesh.VertexList.Count > 0) { submesh.VertexList.TrimExcess(); submesh.FaceList.TrimExcess(); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); hasBonesList.Add(hasBones); if (!hasNormals) { for (int i = 0; i < submesh.VertexList.Count; i++) { submesh.VertexList[i].Normal = new Vector3(); } } } } }
public static remMesh CreateMesh(WorkspaceMesh mesh, out string[] materialNames, out int[] indices, out bool[] worldCoords, out bool[] replaceSubmeshesOption) { int numUncheckedSubmeshes = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { if (!mesh.isSubmeshEnabled(submesh)) { numUncheckedSubmeshes++; } } int numSubmeshes = mesh.SubmeshList.Count - numUncheckedSubmeshes; materialNames = new string[numSubmeshes]; indices = new int[numSubmeshes]; worldCoords = new bool[numSubmeshes]; replaceSubmeshesOption = new bool[numSubmeshes]; remMesh newMesh = new remMesh(numSubmeshes); newMesh.name = new remId(mesh.Name); List <remVertex> newVertices = new List <remVertex>(); List <int> newFaces = new List <int>(); List <int> newFaceMarks = new List <int>(); for (int i = 0, submeshIdx = 0; i < numSubmeshes; i++, submeshIdx++) { while (!mesh.isSubmeshEnabled(mesh.SubmeshList[submeshIdx])) { submeshIdx++; } ImportedSubmesh submesh = mesh.SubmeshList[submeshIdx]; newMesh.AddMaterial(new remId(submesh.Material)); materialNames[i] = submesh.Material; indices[i] = submesh.Index; worldCoords[i] = submesh.WorldCoords; replaceSubmeshesOption[i] = mesh.isSubmeshReplacingOriginal(submesh); List <ImportedFace> faceList = submesh.FaceList; newFaces.Capacity += faceList.Count * 3; int[] faceMarks = new int[faceList.Count]; for (int j = 0; j < faceList.Count; j++) { ImportedFace face = faceList[j]; for (int k = 0; k < 3; k++) { newFaces.Add(face.VertexIndices[k] + newVertices.Count); } faceMarks[j] = i; } newFaceMarks.AddRange(faceMarks); List <ImportedVertex> vertexList = submesh.VertexList; newVertices.Capacity += vertexList.Count; for (int j = 0; j < vertexList.Count; j++) { ImportedVertex vert = vertexList[j]; remVertex newVertex = new remVertex(); if (submesh.WorldCoords) { newVertex.Position = vert.Position; newVertex.Normal = vert.Normal; } else { newVertex.Position = new Vector3(vert.Position.X, -vert.Position.Z, vert.Position.Y); newVertex.Normal = new Vector3(vert.Normal.X, -vert.Normal.Z, vert.Normal.Y); } newVertex.UV = new Vector2(vert.UV[0], vert.UV[1]); newVertices.Add(newVertex); } } newMesh.vertices = newVertices.ToArray(); newMesh.faces = newFaces.ToArray(); newMesh.faceMarks = newFaceMarks.ToArray(); return(newMesh); }
private ImportedSubmesh ImportGeometry(Document.Geometry geo, ref int vertInfoIdx) { ImportedSubmesh submesh = null; try { bool hasNormalInput = false; Document.Input positionInput = null; Document.Input normalInput = null; Document.Input texcoordInput = null; for (int i = 0; i < geo.mesh.vertices.inputs.Count; i++) { switch (geo.mesh.vertices.inputs[i].semantic) { case "POSITION": positionInput = geo.mesh.vertices.inputs[i]; break; case "NORMAL": normalInput = geo.mesh.vertices.inputs[i]; break; case "TEXCOORD": texcoordInput = geo.mesh.vertices.inputs[i]; break; } } if (positionInput == null) { throw new Exception("No POSITION vertex input in " + geo.id); } int numVerts = ((Document.Source)positionInput.source).accessor.count; List<ImportedVertex> vertList = new List<ImportedVertex>(numVerts); for (int i = 0; i < numVerts; i++) { ImportedVertex vert = new ImportedVertex(); vertList.Add(vert); vert.Normal = new Vector3(0, 0, 0); vert.UV = new float[] { 0, 0 }; vert.BoneIndices = new byte[] { 0, 0, 0, 0 }; vert.Weights = new float[] { 0, 0, 0, 0 }; if (Z_UP) { vert.Position = new Vector3( GetSourceValue(positionInput, 0, i), GetSourceValue(positionInput, 2, i), -GetSourceValue(positionInput, 1, i)); } else { vert.Position = new Vector3( GetSourceValue(positionInput, 0, i), GetSourceValue(positionInput, 1, i), GetSourceValue(positionInput, 2, i)); } if (normalInput != null) { hasNormalInput = true; if (Z_UP) { vert.Normal = new Vector3( GetSourceValue(normalInput, 0, i), GetSourceValue(normalInput, 2, i), -GetSourceValue(normalInput, 1, i)); } else { vert.Normal = new Vector3( GetSourceValue(normalInput, 0, i), GetSourceValue(normalInput, 1, i), GetSourceValue(normalInput, 2, i)); } } if (texcoordInput == null) { vert.UV = new float[2]; } else { if (IsBlender) { vert.UV = new float[] { GetSourceValue(texcoordInput, 0, i), -GetSourceValue(texcoordInput, 1, i) }; } else { vert.UV = new float[] { GetSourceValue(texcoordInput, 0, i), 1.0f - GetSourceValue(texcoordInput, 1, i) }; } } vertInfoIdx++; } List<ImportedFace> faceList = new List<ImportedFace>(); foreach (Document.Primitive primitive in geo.mesh.primitives) { if (primitive is Document.Triangle) { Document.Input vertexInput = null; List<Document.Input> normalInputs = new List<Document.Input>(); List<Document.Input> textureInputs = new List<Document.Input>(); foreach (Document.Input input in primitive.Inputs) { switch (input.semantic) { case "VERTEX": vertexInput = input; break; case "NORMAL": hasNormalInput = true; normalInputs.Add(input); break; case "TEXCOORD": textureInputs.Add(input); break; } } if (vertexInput != null) { for (int faceIdx = 0; faceIdx < primitive.count; faceIdx++) { ushort[] faceVerts = new ushort[3]; for (int i = 0; i < 3; i++) { int pIdx = (faceIdx * 3) + i; int vertIdx = GetPValue(vertexInput, primitive, pIdx); faceVerts[i] = (ushort)vertIdx; ImportedVertex vert = vertList[vertIdx]; for (int j = 0; j < normalInputs.Count; j++) { int p = GetPValue(normalInputs[j], primitive, pIdx); if (Z_UP) { vert.Normal = new Vector3( GetSourceValue(normalInputs[j], 0, p), GetSourceValue(normalInputs[j], 2, p), -GetSourceValue(normalInputs[j], 1, p)); } else { vert.Normal = new Vector3( GetSourceValue(normalInputs[j], 0, p), GetSourceValue(normalInputs[j], 1, p), GetSourceValue(normalInputs[j], 2, p)); } } for (int j = 0; j < textureInputs.Count; j++) { int p = GetPValue(textureInputs[j], primitive, pIdx); if (IsBlender) { vert.UV = new float[] { GetSourceValue(textureInputs[j], 0, p), -GetSourceValue(textureInputs[j], 1, p) }; } else { vert.UV = new float[] { GetSourceValue(textureInputs[j], 0, p), 1.0f - GetSourceValue(textureInputs[j], 1, p) }; } } } ImportedFace face = new ImportedFace(); faceList.Add(face); face.VertexIndices = new int[3] { faceVerts[0], faceVerts[1], faceVerts[2] }; } } } } submesh = new ImportedSubmesh(); submesh.VertexList = vertList; submesh.FaceList = faceList; if (!hasNormalInput) { for (int i = 0; i < submesh.VertexList.Count; i++) { submesh.VertexList[i].Normal = new Vector3(); } } } catch (Exception e) { Report.ReportLog("Error importing " + geo.id + ": " + e.Message); } return submesh; }
private void ConvertMeshes(List<odfMesh> meshes, odfParser parser) { MeshList = new List<ImportedMesh>(meshes.Count); MaterialList = new List<ImportedMaterial>(meshes.Count); TextureList = new List<ImportedTexture>(parser.TextureSection != null ? parser.TextureSection.Count : 0); foreach (odfMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.Name = odf.FindMeshFrame(mesh.Id, parser.FrameSection.RootFrame).Name; iMesh.BoneList = new List<ImportedBone>(); Dictionary<ObjectID, byte> boneDic = new Dictionary<ObjectID, byte>(); iMesh.SubmeshList = new List<ImportedSubmesh>(mesh.Count); foreach (odfSubmesh submesh in mesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { iSubmesh.Material = mat.Name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = mat.Diffuse; iMat.Ambient = mat.Ambient; iMat.Specular = mat.Specular; iMat.Emissive = mat.Emissive; iMat.Power = mat.SpecularPower; iMat.Textures = new string[4]; for (int i = 0; i < 4; i++) { if (submesh.TextureIds[i] != ObjectID.INVALID) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[i], parser.TextureSection); iMat.Textures[i] = tex.Name; if (ImportedHelpers.FindTexture(iMat.Textures[i], TextureList) == null) { try { odfTextureFile texFile = new odfTextureFile(iMat.Textures[i], Path.GetDirectoryName(parser.ODFPath) + @"\" + iMat.Textures[i]); MemoryStream memStream; int filesize = 0; using (BinaryReader reader = texFile.DecryptFile(ref filesize)) { memStream = new MemoryStream(reader.ReadBytes(filesize)); } ImportedTexture iTex = new ImportedTexture(memStream, iMat.Textures[i]); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[i]); } } } else { iMat.Textures[i] = String.Empty; } } } } List<Tuple<byte, float>>[] skin = new List<Tuple<byte, float>>[submesh.NumVertices]; for (int i = 0; i < submesh.NumVertices; i++) { skin[i] = new List<Tuple<byte, float>>(4); } odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (odfBone bone in boneList) { byte idx; if (!boneDic.TryGetValue(bone.FrameId, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; iBone.Matrix = bone.Matrix; boneDic.Add(bone.FrameId, idx = (byte)boneDic.Count); } for (int i = 0; i < bone.NumberIndices; i++) { skin[bone.VertexIndexArray[i]].Add(new Tuple<byte, float>(idx, bone.WeightArray[i])); } } } iSubmesh.VertexList = new List<ImportedVertex>(submesh.NumVertices); for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = vert.Position; iVert.Normal = vert.Normal; iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < skin[i].Count) { Tuple<byte, float> vertIdxWeight = skin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = new List<ImportedFace>(submesh.NumVertexIndices / 3); foreach (odfFace face in submesh.FaceList) { ImportedFace iFace = new ImportedFace(); iSubmesh.FaceList.Add(iFace); iFace.VertexIndices = new int[3]; for (int i = 0; i < 3; i++) { iFace.VertexIndices[i] = face.VertexIndices[i]; } } } } }
private void ConvertMeshRenderers(List <MeshRenderer> meshList, bool skins, bool morphs) { MeshList = new List <ImportedMesh>(meshList.Count); MaterialList = new List <ImportedMaterial>(meshList.Count); TextureList = new List <ImportedTexture>(meshList.Count); MorphList = new List <ImportedMorph>(meshList.Count); foreach (MeshRenderer meshR in meshList) { Mesh mesh = Operations.GetMesh(meshR); if (mesh == null) { Report.ReportLog("skipping " + meshR.m_GameObject.instance.m_Name + " - no mesh"); continue; } ImportedMesh iMesh = new ImportedMesh(); Transform meshTransform = meshR.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); iMesh.Name = meshTransform.GetTransformPath(); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.m_SubMeshes.Count); using (BinaryReader vertReader = new BinaryReader(new MemoryStream(mesh.m_VertexData.m_DataSize)), indexReader = new BinaryReader(new MemoryStream(mesh.m_IndexBuffer))) { for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { SubMesh submesh = mesh.m_SubMeshes[i]; ImportedSubmesh iSubmesh = new ImportedSubmesh(); iSubmesh.Index = i; iSubmesh.Visible = true; Material mat = meshR.m_Materials[i].instance; ConvertMaterial(mat); iSubmesh.Material = mat.m_Name; iSubmesh.VertexList = new List <ImportedVertex>((int)submesh.vertexCount); for (int str = 0; str < mesh.m_VertexData.m_Streams.Count; str++) { StreamInfo sInfo = mesh.m_VertexData.m_Streams[str]; if (sInfo.channelMask == 0) { continue; } for (int j = 0; j < mesh.m_SubMeshes[i].vertexCount; j++) { ImportedVertex iVertex; if (iSubmesh.VertexList.Count < mesh.m_SubMeshes[i].vertexCount) { iVertex = new ImportedVertex(); iSubmesh.VertexList.Add(iVertex); } else { iVertex = iSubmesh.VertexList[j]; } for (int chn = 0; chn < mesh.m_VertexData.m_Channels.Count; chn++) { ChannelInfo cInfo = mesh.m_VertexData.m_Channels[chn]; if ((sInfo.channelMask & (1 << chn)) == 0) { continue; } vertReader.BaseStream.Position = sInfo.offset + (submesh.firstVertex + j) * sInfo.stride + cInfo.offset; switch (chn) { case 0: iVertex.Position = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 1: iVertex.Normal = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 3: iVertex.UV = new float[2] { vertReader.ReadSingle(), vertReader.ReadSingle() }; break; case 5: iVertex.Tangent = new SlimDX.Vector4(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle(), -vertReader.ReadSingle()); break; } } if (skins && iVertex.BoneIndices == null && mesh.m_Skin.Count > 0) { BoneInfluence inf = mesh.m_Skin[(int)submesh.firstVertex + j]; iVertex.BoneIndices = new byte[inf.boneIndex.Length]; for (int k = 0; k < iVertex.BoneIndices.Length; k++) { iVertex.BoneIndices[k] = (byte)inf.boneIndex[k]; } iVertex.Weights = (float[])inf.weight.Clone(); } } } int numFaces = (int)(submesh.indexCount / 3); iSubmesh.FaceList = new List <ImportedFace>(numFaces); indexReader.BaseStream.Position = submesh.firstByte; for (int j = 0; j < numFaces; j++) { ImportedFace face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[2] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[1] = indexReader.ReadUInt16() - (int)submesh.firstVertex; iSubmesh.FaceList.Add(face); } iMesh.SubmeshList.Add(iSubmesh); } } if (skins && meshR is SkinnedMeshRenderer) { SkinnedMeshRenderer sMesh = (SkinnedMeshRenderer)meshR; if (sMesh.m_Bones.Count >= 256) { throw new Exception("Too many bones (" + mesh.m_BindPose.Count + ")"); } if (sMesh.m_Bones.Count != mesh.m_BindPose.Count || sMesh.m_Bones.Count != mesh.m_BoneNameHashes.Count) { throw new Exception("Mismatching number of bones bind pose=" + mesh.m_BindPose.Count + " hashes=" + mesh.m_BoneNameHashes.Count + " numBones=" + sMesh.m_Bones.Count); } iMesh.BoneList = new List <ImportedBone>(sMesh.m_Bones.Count); for (int i = 0; i < sMesh.m_Bones.Count; i++) { ImportedBone bone = new ImportedBone(); uint boneHash = mesh.m_BoneNameHashes[i]; bone.Name = avatar.FindBoneName(boneHash); Matrix m = Matrix.Transpose(mesh.m_BindPose[i]); Vector3 s, t; Quaternion q; m.Decompose(out s, out q, out t); t.X *= -1; Vector3 euler = FbxUtility.QuaternionToEuler(q); euler.Y *= -1; euler.Z *= -1; q = FbxUtility.EulerToQuaternion(euler); bone.Matrix = Matrix.Scaling(s) * Matrix.RotationQuaternion(q) * Matrix.Translation(t); iMesh.BoneList.Add(bone); } } if (morphs && mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = new ImportedMorph(); morph.Name = iMesh.Name; morph.ClipName = Operations.BlendShapeName(mesh); morph.KeyframeList = new List <ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = Operations.BlendShapeKeyframeName(mesh, i); keyframe.VertexList = new List <ImportedVertex>((int)mesh.m_Shapes.shapes[i].vertexCount); keyframe.MorphedVertexIndices = new List <ushort>((int)mesh.m_Shapes.shapes[i].vertexCount); int lastVertIndex = (int)(mesh.m_Shapes.shapes[i].firstVertex + mesh.m_Shapes.shapes[i].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[i].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex morphVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); ImportedVertex destVert = new ImportedVertex(); Vector3 morphPos = morphVert.vertex; morphPos.X *= -1; destVert.Position = vert.Position + morphPos; Vector3 morphNormal = morphVert.normal; morphNormal.X *= -1; destVert.Normal = morphNormal; Vector4 morphTangent = new Vector4(morphVert.tangent, 0); morphTangent.X *= -1; destVert.Tangent = morphTangent; keyframe.VertexList.Add(destVert); keyframe.MorphedVertexIndices.Add((ushort)morphVert.index); } morph.KeyframeList.Add(keyframe); } MorphList.Add(morph); } MeshList.Add(iMesh); } }
private void ConvertMeshRenderers(List<MeshRenderer> meshList, bool skins, bool morphs) { MeshList = new List<ImportedMesh>(meshList.Count); MaterialList = new List<ImportedMaterial>(meshList.Count); TextureList = new List<ImportedTexture>(meshList.Count); MorphList = new List<ImportedMorph>(meshList.Count); foreach (MeshRenderer meshR in meshList) { Mesh mesh = Operations.GetMesh(meshR); if (mesh == null) { Report.ReportLog("skipping " + meshR.m_GameObject.instance.m_Name + " - no mesh"); continue; } ImportedMesh iMesh = new ImportedMesh(); Transform meshTransform = meshR.m_GameObject.instance.FindLinkedComponent(UnityClassID.Transform); iMesh.Name = meshTransform.GetTransformPath(); iMesh.SubmeshList = new List<ImportedSubmesh>(mesh.m_SubMeshes.Count); using (BinaryReader vertReader = new BinaryReader(new MemoryStream(mesh.m_VertexData.m_DataSize)), indexReader = new BinaryReader(new MemoryStream(mesh.m_IndexBuffer))) { for (int i = 0; i < mesh.m_SubMeshes.Count; i++) { SubMesh submesh = mesh.m_SubMeshes[i]; ImportedSubmesh iSubmesh = new ImportedSubmesh(); iSubmesh.Index = i; iSubmesh.Visible = true; Material mat = meshR.m_Materials[i].instance; ConvertMaterial(mat); iSubmesh.Material = mat.m_Name; iSubmesh.VertexList = new List<ImportedVertex>((int)submesh.vertexCount); for (int str = 0; str < mesh.m_VertexData.m_Streams.Count; str++) { StreamInfo sInfo = mesh.m_VertexData.m_Streams[str]; if (sInfo.channelMask == 0) { continue; } for (int j = 0; j < mesh.m_SubMeshes[i].vertexCount; j++) { ImportedVertex iVertex; if (iSubmesh.VertexList.Count < mesh.m_SubMeshes[i].vertexCount) { iVertex = new ImportedVertex(); iSubmesh.VertexList.Add(iVertex); } else { iVertex = iSubmesh.VertexList[j]; } for (int chn = 0; chn < mesh.m_VertexData.m_Channels.Count; chn++) { ChannelInfo cInfo = mesh.m_VertexData.m_Channels[chn]; if ((sInfo.channelMask & (1 << chn)) == 0) { continue; } vertReader.BaseStream.Position = sInfo.offset + (submesh.firstVertex + j) * sInfo.stride + cInfo.offset; switch (chn) { case 0: iVertex.Position = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 1: iVertex.Normal = new SlimDX.Vector3(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle()); break; case 3: iVertex.UV = new float[2] { vertReader.ReadSingle(), vertReader.ReadSingle() }; break; case 5: iVertex.Tangent = new SlimDX.Vector4(-vertReader.ReadSingle(), vertReader.ReadSingle(), vertReader.ReadSingle(), -vertReader.ReadSingle()); break; } } if (skins && iVertex.BoneIndices == null && mesh.m_Skin.Count > 0) { BoneInfluence inf = mesh.m_Skin[(int)submesh.firstVertex + j]; iVertex.BoneIndices = new byte[inf.boneIndex.Length]; for (int k = 0; k < iVertex.BoneIndices.Length; k++) { iVertex.BoneIndices[k] = (byte)inf.boneIndex[k]; } iVertex.Weights = (float[])inf.weight.Clone(); } } } int numFaces = (int)(submesh.indexCount / 3); iSubmesh.FaceList = new List<ImportedFace>(numFaces); indexReader.BaseStream.Position = submesh.firstByte; for (int j = 0; j < numFaces; j++) { ImportedFace face = new ImportedFace(); face.VertexIndices = new int[3]; face.VertexIndices[0] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[2] = indexReader.ReadUInt16() - (int)submesh.firstVertex; face.VertexIndices[1] = indexReader.ReadUInt16() - (int)submesh.firstVertex; iSubmesh.FaceList.Add(face); } iMesh.SubmeshList.Add(iSubmesh); } } if (skins && meshR is SkinnedMeshRenderer) { SkinnedMeshRenderer sMesh = (SkinnedMeshRenderer)meshR; if (sMesh.m_Bones.Count >= 256) { throw new Exception("Too many bones (" + mesh.m_BindPose.Count + ")"); } if (sMesh.m_Bones.Count != mesh.m_BindPose.Count || sMesh.m_Bones.Count != mesh.m_BoneNameHashes.Count) { throw new Exception("Mismatching number of bones bind pose=" + mesh.m_BindPose.Count + " hashes=" + mesh.m_BoneNameHashes.Count + " numBones=" + sMesh.m_Bones.Count); } iMesh.BoneList = new List<ImportedBone>(sMesh.m_Bones.Count); for (int i = 0; i < sMesh.m_Bones.Count; i++) { ImportedBone bone = new ImportedBone(); uint boneHash = mesh.m_BoneNameHashes[i]; bone.Name = avatar.FindBoneName(boneHash); Matrix m = Matrix.Transpose(mesh.m_BindPose[i]); Vector3 s, t; Quaternion q; m.Decompose(out s, out q, out t); t.X *= -1; Vector3 euler = FbxUtility.QuaternionToEuler(q); euler.Y *= -1; euler.Z *= -1; q = FbxUtility.EulerToQuaternion(euler); bone.Matrix = Matrix.Scaling(s) * Matrix.RotationQuaternion(q) * Matrix.Translation(t); iMesh.BoneList.Add(bone); } } if (morphs && mesh.m_Shapes.shapes.Count > 0) { ImportedMorph morph = new ImportedMorph(); morph.Name = iMesh.Name; morph.ClipName = Operations.BlendShapeName(mesh); morph.KeyframeList = new List<ImportedMorphKeyframe>(mesh.m_Shapes.shapes.Count); for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { ImportedMorphKeyframe keyframe = new ImportedMorphKeyframe(); keyframe.Name = Operations.BlendShapeKeyframeName(mesh, i); keyframe.VertexList = new List<ImportedVertex>((int)mesh.m_Shapes.shapes[i].vertexCount); keyframe.MorphedVertexIndices = new List<ushort>((int)mesh.m_Shapes.shapes[i].vertexCount); int lastVertIndex = (int)(mesh.m_Shapes.shapes[i].firstVertex + mesh.m_Shapes.shapes[i].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[i].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex morphVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = GetSourceVertex(iMesh.SubmeshList, (int)morphVert.index); ImportedVertex destVert = new ImportedVertex(); Vector3 morphPos = morphVert.vertex; morphPos.X *= -1; destVert.Position = vert.Position + morphPos; Vector3 morphNormal = morphVert.normal; morphNormal.X *= -1; destVert.Normal = morphNormal; Vector4 morphTangent = new Vector4(morphVert.tangent, 0); morphTangent.X *= -1; destVert.Tangent = morphTangent; keyframe.VertexList.Add(destVert); keyframe.MorphedVertexIndices.Add((ushort)morphVert.index); } morph.KeyframeList.Add(keyframe); } MorphList.Add(morph); } MeshList.Add(iMesh); } }
private void ConvertMeshes(List <odfMesh> meshes, odfParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.TextureSection != null ? parser.TextureSection.Count : 0); foreach (odfMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.Name = odf.FindMeshFrame(mesh.Id, parser.FrameSection.RootFrame).Name; iMesh.BoneList = new List <ImportedBone>(); Dictionary <ObjectID, byte> boneDic = new Dictionary <ObjectID, byte>(); iMesh.SubmeshList = new List <ImportedSubmesh>(mesh.Count); foreach (odfSubmesh submesh in mesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection); if (mat != null) { iSubmesh.Material = mat.Name; ImportedMaterial iMat = ImportedHelpers.FindMaterial(iSubmesh.Material, MaterialList); if (iMat == null) { iMat = new ImportedMaterial(); MaterialList.Add(iMat); iMat.Name = iSubmesh.Material; iMat.Diffuse = mat.Diffuse; iMat.Ambient = mat.Ambient; iMat.Specular = mat.Specular; iMat.Emissive = mat.Emissive; iMat.Power = mat.SpecularPower; iMat.Textures = new string[4]; for (int i = 0; i < 4; i++) { if (submesh.TextureIds[i] != ObjectID.INVALID) { odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[i], parser.TextureSection); iMat.Textures[i] = tex.Name; if (ImportedHelpers.FindTexture(iMat.Textures[i], TextureList) == null) { try { odfTextureFile texFile = new odfTextureFile(iMat.Textures[i], Path.GetDirectoryName(parser.ODFPath) + @"\" + iMat.Textures[i]); MemoryStream memStream; int filesize = 0; using (BinaryReader reader = texFile.DecryptFile(ref filesize)) { memStream = new MemoryStream(reader.ReadBytes(filesize)); } ImportedTexture iTex = new ImportedTexture(memStream, iMat.Textures[i]); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[i]); } } } else { iMat.Textures[i] = String.Empty; } } } } List <Tuple <byte, float> >[] skin = new List <Tuple <byte, float> > [submesh.NumVertices]; for (int i = 0; i < submesh.NumVertices; i++) { skin[i] = new List <Tuple <byte, float> >(4); } odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection); if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (odfBone bone in boneList) { byte idx; if (!boneDic.TryGetValue(bone.FrameId, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name; iBone.Matrix = bone.Matrix; boneDic.Add(bone.FrameId, idx = (byte)boneDic.Count); } for (int i = 0; i < bone.NumberIndices; i++) { skin[bone.VertexIndexArray[i]].Add(new Tuple <byte, float>(idx, bone.WeightArray[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.NumVertices); for (int i = 0; i < submesh.NumVertices; i++) { odfVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = vert.Position; iVert.Normal = vert.Normal; iVert.UV = new float[] { vert.UV[0], vert.UV[1] }; iVert.BoneIndices = new byte[4]; iVert.Weights = new float[4]; for (int j = 0; j < 4; j++) { if (j < skin[i].Count) { Tuple <byte, float> vertIdxWeight = skin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = new List <ImportedFace>(submesh.NumVertexIndices / 3); foreach (odfFace face in submesh.FaceList) { ImportedFace iFace = new ImportedFace(); iSubmesh.FaceList.Add(iFace); iFace.VertexIndices = new int[3]; for (int i = 0; i < 3; i++) { iFace.VertexIndices[i] = face.VertexIndices[i]; } } } } }