public static remSkin CreateBoneList(ImportedMesh mesh, Matrix lMeshMatrixInv) { if (mesh.BoneList == null || mesh.BoneList.Count == 0) { return(null); } Dictionary <int, float>[] boneDic = new Dictionary <int, float> [mesh.BoneList.Count]; for (int i = 0; i < mesh.BoneList.Count; i++) { boneDic[i] = new Dictionary <int, float>(); } int vertexOffset = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { List <ImportedVertex> vertices = submesh.VertexList; for (int i = 0; i < vertices.Count; i++) { ImportedVertex vert = vertices[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { if (vert.BoneIndices[j] == 0xFF) { continue; } boneDic[vert.BoneIndices[j]].Add(vertexOffset + i, vert.Weights[j]); } } vertexOffset += vertices.Count; } remSkin remBoneList = new remSkin(mesh.BoneList.Count); remBoneList.mesh = new remId(mesh.Name); Vector3 scale, translate; Quaternion rotate; lMeshMatrixInv.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); Matrix combinedCorrection = Matrix.Scaling(-1f / scale.X, 1f / scale.Y, -1f / scale.Z) * lMeshMatrixInv; for (int i = 0; i < mesh.BoneList.Count; i++) { remBoneWeights boneWeights = new remBoneWeights(); boneWeights.bone = new remId(mesh.BoneList[i].Name); Matrix lMatrix = Matrix.Invert(mesh.BoneList[i].Matrix); boneWeights.matrix = Matrix.Invert(lMatrix * combinedCorrection); boneWeights.vertexIndices = new int[boneDic[i].Count]; boneDic[i].Keys.CopyTo(boneWeights.vertexIndices, 0); boneWeights.vertexWeights = new float[boneDic[i].Count]; boneDic[i].Values.CopyTo(boneWeights.vertexWeights, 0); remBoneList.AddChild(boneWeights); } return(remBoneList); }
private void Export(DirectoryInfo dir) { try { List <MeshRenderer> meshList = new List <MeshRenderer>(1); meshList.Add(morphObj); Mesh mesh = Operations.GetMesh(morphObj); colorLists = new bool[mesh.m_Shapes.shapes.Count][]; vertLists = new List <ImportedVertex> [mesh.m_Shapes.shapes.Count]; for (int i = 0; i < mesh.m_Shapes.shapes.Count; i++) { Plugins.UnityConverter conv = new Plugins.UnityConverter(parser, meshList, false, false); ImportedMesh meshObjBase = conv.MeshList[0]; if (faceList == null) { faceList = meshObjBase.SubmeshList[0].FaceList; } List <ImportedVertex> vertList = conv.MeshList[0].SubmeshList[0].VertexList; vertLists[i] = vertList; colorLists[i] = new bool[meshObjBase.SubmeshList[0].VertexList.Count]; 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 srcVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = vertList[(int)srcVert.index]; vert.Position += srcVert.vertex; colorLists[i][(int)srcVert.index] = true; } } string dest = Utility.GetDestFile(dir, morphObj.m_GameObject.instance.m_Name + "-" + mesh.m_Name + "-", ".morph.mqo"); Material mat = morphObj.m_Materials[0].instance; Export(dest, mat, mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance); foreach (Texture2D tex in usedTextures) { try { tex.Export(dir.FullName); } catch (Exception ex) { Utility.ReportException(ex); } } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }
public static remSkin CreateBoneList(ImportedMesh mesh, Matrix lMeshMatrixInv) { if (mesh.BoneList == null || mesh.BoneList.Count == 0) { return null; } Dictionary<int, float>[] boneDic = new Dictionary<int, float>[mesh.BoneList.Count]; for (int i= 0; i < mesh.BoneList.Count; i++) { boneDic[i] = new Dictionary<int, float>(); } int vertexOffset = 0; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { List<ImportedVertex> vertices = submesh.VertexList; for (int i = 0; i < vertices.Count; i++) { ImportedVertex vert = vertices[i]; for (int j = 0; j < vert.BoneIndices.Length; j++) { if (vert.BoneIndices[j] == 0xFF) continue; boneDic[vert.BoneIndices[j]].Add(vertexOffset + i, vert.Weights[j]); } } vertexOffset += vertices.Count; } remSkin remBoneList = new remSkin(mesh.BoneList.Count); remBoneList.mesh = new remId(mesh.Name); Vector3 scale, translate; Quaternion rotate; lMeshMatrixInv.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); Matrix combinedCorrection = Matrix.Scaling(-1f / scale.X, 1f / scale.Y, -1f / scale.Z) * lMeshMatrixInv; for (int i = 0; i < mesh.BoneList.Count; i++) { remBoneWeights boneWeights = new remBoneWeights(); boneWeights.bone = new remId(mesh.BoneList[i].Name); Matrix lMatrix = Matrix.Invert(mesh.BoneList[i].Matrix); boneWeights.matrix = Matrix.Invert(lMatrix * combinedCorrection); boneWeights.vertexIndices = new int[boneDic[i].Count]; boneDic[i].Keys.CopyTo(boneWeights.vertexIndices, 0); boneWeights.vertexWeights = new float[boneDic[i].Count]; boneDic[i].Values.CopyTo(boneWeights.vertexWeights, 0); remBoneList.AddChild(boneWeights); } return remBoneList; }
public void WorldCoordinates(int meshIdx, Matrix worldTransform) { ImportedMesh mesh = MeshList[meshIdx]; foreach (ImportedSubmesh submesh in mesh.SubmeshList) { List <ImportedVertex> vertList = submesh.VertexList; for (int i = 0; i < vertList.Count; i++) { vertList[i].Position = Vector3.TransformCoordinate(vertList[i].Position, worldTransform); } } }
public WorkspaceMesh(ImportedMesh importedMesh) : base() { this.Name = importedMesh.Name; this.SubmeshList = importedMesh.SubmeshList; this.BoneList = importedMesh.BoneList; this.SubmeshOptions = new Dictionary<ImportedSubmesh, AdditionalSubmeshOptions>(importedMesh.SubmeshList.Count); foreach (ImportedSubmesh submesh in importedMesh.SubmeshList) { AdditionalSubmeshOptions options = new AdditionalSubmeshOptions(); this.SubmeshOptions.Add(submesh, options); } }
public Importer(string path) { try { FrameList = new List<ImportedFrame>(); MeshList = new List<ImportedMesh>(); MaterialList = new List<ImportedMaterial>(); TextureList = new List<ImportedTexture>(); AnimationList = new List<ImportedAnimation>(); MorphList = new List<ImportedMorph>(); this.path = path; List<Section> sectionList = new List<Section>(); using (BinaryReader reader = new BinaryReader(File.OpenRead(path))) { string header = Encoding.ASCII.GetString(reader.ReadBytes(16)); if (!header.StartsWith("xof ")) { throw new Exception("invalid .x format"); } if (!header.EndsWith("0032")) { throw new Exception("only 32-bit .x format is supported"); } string type = header.Substring(8, 4).Trim(); if (type == "txt") { ParserTxt parser = new ParserTxt(path); Section newSection; while ((newSection = parser.ParseSection(null)) != null) { sectionList.Add(newSection); } } else if (type == "bin") { ParserBin parser = new ParserBin(path); Section newSection; while ((newSection = parser.ParseSection(0, null)) != null) { sectionList.Add(newSection); } } else { throw new Exception("unexpected .x format"); } } List<bool> hasBonesList = new List<bool>(); SortedDictionary<string, byte> boneDic = new SortedDictionary<string, byte>(); ImportedMesh mesh = new ImportedMesh(); mesh.Name = "no_name_meshes"; mesh.BoneList = new List<ImportedBone>(0); mesh.SubmeshList = new List<ImportedSubmesh>(); foreach (Section section in sectionList) { if (section.type == "Frame") { ImportedFrame frame = ImportFrame(section); if (frame != null) { FrameList.Add(frame); } } else if (section.type == "Mesh") { ImportMesh(section, mesh, boneDic, hasBonesList); } else if (section.type == "AnimationSet") { ImportAnimation(section); } else if (section.type == "template") { } else if (section.type == "AnimTicksPerSecond") { } else if (section.type == "AnimationOptions") { } else { Report.ReportLog("Warning: unexpected section " + section.type); } } SetBones(mesh, hasBonesList); if (mesh.SubmeshList.Count > 0) { MeshList.Add(mesh); } } catch (Exception ex) { Report.ReportLog("Error importing .x: " + ex.Message); } }
private void SetBones(ImportedMesh mesh, List<bool> hasBonesList) { for (int i = 0; i < mesh.SubmeshList.Count; i++) { if (!hasBonesList[i]) { if (mesh.BoneList.Count > 0) { foreach (ImportedVertex vert in mesh.SubmeshList[i].VertexList) { vert.BoneIndices = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; vert.Weights = new float[] { 1, 0, 0, 0 }; } } else { foreach (ImportedVertex vert in mesh.SubmeshList[i].VertexList) { vert.BoneIndices = new byte[4]; vert.Weights = new float[4]; } } } } }
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(); } } } } }
private void ExportMesh(ImportedFrame rootFrame, List <ImportedMaterial> materialList, List <ImportedTexture> textureList, IntPtr frameNode, ImportedMesh importedMesh, bool exportSkins) { var boneList = importedMesh.BoneList; var totalBoneCount = 0; var hasBones = false; if (exportSkins && boneList?.Count > 0) { totalBoneCount = boneList.Count; hasBones = true; } var pClusterArray = IntPtr.Zero; try { if (hasBones) { pClusterArray = AsFbxMeshCreateClusterArray(totalBoneCount); foreach (var bone in boneList) { if (bone.Path != null) { var frame = rootFrame.FindFrameByPath(bone.Path); var boneNode = _frameToNode[frame]; var cluster = AsFbxMeshCreateCluster(_pContext, boneNode); AsFbxMeshAddCluster(pClusterArray, cluster); } else { AsFbxMeshAddCluster(pClusterArray, IntPtr.Zero); } } } var mesh = AsFbxMeshCreateMesh(_pContext, frameNode); var totalVertexCount = 0; foreach (var m in importedMesh.SubmeshList) { totalVertexCount += m.VertexList.Count; } AsFbxMeshInitControlPoints(mesh, totalVertexCount); if (importedMesh.hasNormal) { AsFbxMeshCreateElementNormal(mesh); } if (importedMesh.hasUV[0]) { AsFbxMeshCreateDiffuseUV(mesh, 0); } if (importedMesh.hasUV[1]) { AsFbxMeshCreateNormalMapUV(mesh, 1); } if (importedMesh.hasTangent) { AsFbxMeshCreateElementTangent(mesh); } if (importedMesh.hasColor) { AsFbxMeshCreateElementVertexColor(mesh); } AsFbxMeshCreateElementMaterial(mesh); var firstVertex = 0; foreach (var meshObj in importedMesh.SubmeshList) { var materialIndex = 0; var mat = ImportedHelpers.FindMaterial(meshObj.Material, materialList); if (mat != null) { var foundMat = _createdMaterials.FindIndex(kv => kv.Key == mat.Name); IntPtr pMat; if (foundMat >= 0) { pMat = _createdMaterials[foundMat].Value; } else { var diffuse = mat.Diffuse; var ambient = mat.Ambient; var emissive = mat.Emissive; var specular = mat.Specular; var reflection = mat.Reflection; pMat = AsFbxCreateMaterial(_pContext, mat.Name, in diffuse, in ambient, in emissive, in specular, in reflection, mat.Shininess, mat.Transparency); _createdMaterials.Add(new KeyValuePair <string, IntPtr>(mat.Name, pMat)); } materialIndex = AsFbxAddMaterialToFrame(frameNode, pMat); var hasTexture = false; foreach (var texture in mat.Textures) { var tex = ImportedHelpers.FindTexture(texture.Name, textureList); var pTexture = ExportTexture(tex); if (pTexture != IntPtr.Zero) { switch (texture.Dest) { case 0: case 1: case 2: case 3: { AsFbxLinkTexture(texture.Dest, pTexture, pMat, texture.Offset.X, texture.Offset.Y, texture.Scale.X, texture.Scale.Y); hasTexture = true; break; } default: break; } } } if (hasTexture) { AsFbxSetFrameShadingModeToTextureShading(frameNode); } } var vertexList = meshObj.VertexList; var vertexCount = vertexList.Count; for (var j = 0; j < vertexCount; j += 1) { var importedVertex = vertexList[j]; var vertex = importedVertex.Vertex; AsFbxMeshSetControlPoint(mesh, j + firstVertex, vertex.X, vertex.Y, vertex.Z); if (importedMesh.hasNormal) { var normal = importedVertex.Normal; AsFbxMeshElementNormalAdd(mesh, 0, normal.X, normal.Y, normal.Z); } for (var uvIndex = 0; uvIndex < 2; uvIndex += 1) { if (importedMesh.hasUV[uvIndex]) { var uv = importedVertex.UV[uvIndex]; AsFbxMeshElementUVAdd(mesh, uvIndex, uv[0], uv[1]); } } if (importedMesh.hasTangent) { var tangent = importedVertex.Tangent; AsFbxMeshElementTangentAdd(mesh, 0, tangent.X, tangent.Y, tangent.Z, tangent.W); } if (importedMesh.hasColor) { var color = importedVertex.Color; AsFbxMeshElementVertexColorAdd(mesh, 0, color.R, color.G, color.B, color.A); } if (hasBones && importedVertex.BoneIndices != null) { var boneIndices = importedVertex.BoneIndices; var boneWeights = importedVertex.Weights; for (var k = 0; k < 4; k += 1) { if (boneIndices[k] < totalBoneCount && boneWeights[k] > 0) { AsFbxMeshSetBoneWeight(pClusterArray, boneIndices[k], j + firstVertex, boneWeights[k]); } } } } foreach (var face in meshObj.FaceList) { var index0 = face.VertexIndices[0] + firstVertex; var index1 = face.VertexIndices[1] + firstVertex; var index2 = face.VertexIndices[2] + firstVertex; AsFbxMeshAddPolygon(mesh, materialIndex, index0, index1, index2); } firstVertex += vertexCount; } if (hasBones) { IntPtr pSkinContext = IntPtr.Zero; try { pSkinContext = AsFbxMeshCreateSkinContext(_pContext, frameNode); unsafe { var boneMatrix = stackalloc float[16]; for (var j = 0; j < totalBoneCount; j += 1) { if (!FbxClusterArray_HasItemAt(pClusterArray, j)) { continue; } var m = boneList[j].Matrix; CopyMatrix4x4(in m, boneMatrix); AsFbxMeshSkinAddCluster(pSkinContext, pClusterArray, j, boneMatrix); } } AsFbxMeshAddDeformer(pSkinContext, mesh); } finally { AsFbxMeshDisposeSkinContext(ref pSkinContext); } } } finally { AsFbxMeshDisposeClusterArray(ref pClusterArray); } }
private void Export(DirectoryInfo dir) { try { List <MeshRenderer> meshList = new List <MeshRenderer>(1); meshList.Add(morphObj); Mesh mesh = Operations.GetMesh(morphObj); ImageFileFormat preferredUncompressedFormat = (string)Properties.Settings.Default["ExportUncompressedAs"] == "BMP" ? ImageFileFormat.Bmp : (ImageFileFormat)(-1); colorLists = new List <bool[]>(mesh.m_Shapes.shapes.Count); vertLists = new List <List <ImportedVertex> >(mesh.m_Shapes.shapes.Count); HashSet <int> morphIndices = morphList != null && morphList[0] != null ? new HashSet <int>(morphList[0]) : null; for (int i = 0; i < mesh.m_Shapes.channels.Count; i++) { if (morphIndices != null && !morphIndices.Contains(i)) { continue; } for (int frameIdx = 0; frameIdx < mesh.m_Shapes.channels[i].frameCount; frameIdx++) { int shapeIdx = mesh.m_Shapes.channels[i].frameIndex + frameIdx; Operations.UnityConverter conv = new Operations.UnityConverter(parser, meshList, false, null, false, preferredUncompressedFormat, false); ImportedMesh meshObjBase = conv.MeshList[0]; if (faceList == null) { faceList = meshObjBase.SubmeshList[0].FaceList; } List <ImportedVertex> vertList = conv.MeshList[0].SubmeshList[0].VertexList; vertLists.Add(vertList); bool[] colours = new bool[meshObjBase.SubmeshList[0].VertexList.Count]; colorLists.Add(colours); int lastVertIndex = (int)(mesh.m_Shapes.shapes[shapeIdx].firstVertex + mesh.m_Shapes.shapes[shapeIdx].vertexCount); for (int j = (int)mesh.m_Shapes.shapes[shapeIdx].firstVertex; j < lastVertIndex; j++) { BlendShapeVertex srcVert = mesh.m_Shapes.vertices[j]; ImportedVertex vert = vertList[(int)srcVert.index]; vert.Position = new Vector3 ( vert.Position.X - srcVert.vertex.X, vert.Position.Y + srcVert.vertex.Y, vert.Position.Z + srcVert.vertex.Z ); colours[(int)srcVert.index] = true; } } } string dest = Utility.GetDestFile(dir, morphObj.m_GameObject.instance.m_Name + "-" + mesh.m_Name + "-", ".morph.mqo"); Material mat = null; Texture2D matTex = null; if (morphObj.m_Materials.Count > 0) { mat = morphObj.m_Materials[0].instance; if (mat != null && mat.m_SavedProperties.m_TexEnvs.Count > 0) { matTex = mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance; for (int i = 1; i < mat.m_SavedProperties.m_TexEnvs.Count; i++) { var texProp = mat.m_SavedProperties.m_TexEnvs[i]; if (texProp.Key.name == "_MainTex") { matTex = texProp.Value.m_Texture.instance; break; } } } } Export(dest, mat, matTex); foreach (Texture2D tex in usedTextures) { try { tex.Export(dir.FullName, preferredUncompressedFormat); } catch (Exception ex) { Utility.ReportException(ex); } } Report.ReportLog("Finished exporting morph to " + dest); } catch (Exception ex) { Report.ReportLog("Error exporting morph: " + ex.Message); } }
private ImportedFrame ImportNode(Document.Node node) { ImportedFrame frame = new ImportedFrame(); try { frame.Name = DecodeName(node.id); frame.Matrix = ProcessNodeMatrix(node); ImportedMesh meshList = new ImportedMesh(); meshList.Name = frame.Name; meshList.SubmeshList = new List<ImportedSubmesh>(); List<string> boneNames = new List<string>(255); List<Matrix> boneMatrices = new List<Matrix>(255); List<Document.InstanceGeometry> geometries = new List<Document.InstanceGeometry>(); List<Document.InstanceController> controllers = new List<Document.InstanceController>(); List<Document.InstanceNode> instanceNodes; ProcessNodeInstances(node, geometries, controllers, out instanceNodes); for (int i = 0; i < instanceNodes.Count; i++) { List<Document.InstanceNode> dummy; Document.Node instanceNode = (Document.Node)colladaDoc.dic[instanceNodes[i].url.Fragment]; if (ProcessNodeInstances(instanceNode, geometries, controllers, out dummy)) { ImportedFrame child = ImportNode(instanceNode); if (child != null) { frame.AddChild(child); } } for (int j = 0; j < dummy.Count; j++) { Report.ReportLog("Warning: instance node " + dummy[j].name + " wasn't processed"); } } if (node.children != null) { for (int i = 0; i < node.children.Count; i++) { List<Document.InstanceNode> dummy; if (ProcessNodeInstances(node.children[i], geometries, controllers, out dummy)) { ImportedFrame child = ImportNode(node.children[i]); if (child != null) { frame.AddChild(child); } } for (int j = 0; j < dummy.Count; j++) { Report.ReportLog("Warning: instance node " + dummy[j].name + " wasn't processed"); } } } int vertInfoIdx = 0; for (int i = 0; i < controllers.Count; i++) { ImportedSubmesh submesh = ImportController((Document.Controller)colladaDoc.dic[controllers[i].url.Fragment], boneNames, boneMatrices, ref vertInfoIdx); if (submesh != null) { SetMaterial(controllers[i], submesh); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); } } for (int i = 0; i < geometries.Count; i++) { ImportedSubmesh submesh = ImportGeometry((Document.Geometry)colladaDoc.dic[geometries[i].url.Fragment], ref vertInfoIdx); if (submesh != null) { SetMaterial(geometries[i], submesh); submesh.Index = meshList.SubmeshList.Count; meshList.SubmeshList.Add(submesh); foreach (ImportedVertex vert in submesh.VertexList) { if (boneNames.Count > 0) { vert.BoneIndices = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF }; vert.Weights = new float[] { 1, 0, 0, 0 }; } else { vert.BoneIndices = new byte[4]; vert.Weights = new float[4]; } } } } if (meshList.SubmeshList.Count > 0) { meshList.BoneList = new List<ImportedBone>(boneNames.Count); for (int i = 0; i < boneNames.Count; i++) { string name = boneNames[i]; ImportedBone bone = new ImportedBone(); bone.Name = DecodeName(name); bone.Matrix = boneMatrices[i]; meshList.BoneList.Add(bone); } MeshList.Add(meshList); } } catch (Exception e) { Report.ReportLog("Error importing node " + node.id + ": " + e.Message); frame = null; } return frame; }
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 ConvertMeshes(List <remMesh> meshes, remParser parser) { MeshList = new List <ImportedMesh>(meshes.Count); MaterialList = new List <ImportedMaterial>(meshes.Count); TextureList = new List <ImportedTexture>(parser.MATC.Count); foreach (remMesh mesh in meshes) { ImportedMesh iMesh = new ImportedMesh(); MeshList.Add(iMesh); iMesh.BoneList = new List <ImportedBone>(); Dictionary <remId, byte> boneDic = new Dictionary <remId, byte>(); remSkin skin = rem.FindSkin(mesh.name, parser.SKIC); rem.Mesh convertedMesh = new rem.Mesh(mesh, skin); iMesh.SubmeshList = new List <ImportedSubmesh>(convertedMesh.Count); remBone meshFrame = rem.FindFrame(mesh.frame, parser.BONC.rootFrame); ImportedFrame iFrame = ImportedHelpers.FindFrame(mesh.frame, FrameList[0]); float s = (float)Math.Round(Math.Abs(meshFrame.matrix.M11), 5); iFrame.Name = iMesh.Name = mesh.name + (s != 1f ? "(Scale=" + s.ToString() + ")" : String.Empty); foreach (rem.Submesh submesh in convertedMesh) { ImportedSubmesh iSubmesh = new ImportedSubmesh(); iMesh.SubmeshList.Add(iSubmesh); remMaterial mat = rem.FindMaterial(submesh.MaterialName, parser.MATC); 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 = new Color4(mat.diffuse); iMat.Ambient = new Color4(mat.ambient); iMat.Specular = new Color4(mat.specular); iMat.Emissive = new Color4(mat.emissive); iMat.Power = mat.specularPower; iMat.Textures = new string[4] { String.Empty, String.Empty, String.Empty, String.Empty }; if (mat.texture != null) { iMat.Textures[0] = mat.texture; if (ImportedHelpers.FindTexture(iMat.Textures[0], TextureList) == null) { try { ImportedTexture iTex = rem.ImportedTexture(mat.texture, parser.RemPath, true); TextureList.Add(iTex); } catch { Report.ReportLog("cant read texture " + iMat.Textures[0]); } } } } } List <Tuple <byte, float> >[] iSkin = new List <Tuple <byte, float> > [submesh.numVertices]; for (int i = 0; i < submesh.numVertices; i++) { iSkin[i] = new List <Tuple <byte, float> >(4); } List <remBoneWeights> boneList = submesh.BoneList; if (boneList != null) { if (iMesh.BoneList.Capacity < boneList.Count) { iMesh.BoneList.Capacity += boneList.Count; } foreach (remBoneWeights boneWeights in boneList) { byte idx; if (!boneDic.TryGetValue(boneWeights.bone, out idx)) { ImportedBone iBone = new ImportedBone(); iMesh.BoneList.Add(iBone); iBone.Name = boneWeights.bone; Vector3 scale, translate; Quaternion rotate; meshFrame.matrix.Decompose(out scale, out rotate, out translate); scale.X = Math.Abs(scale.X); scale.Y = Math.Abs(scale.Y); scale.Z = Math.Abs(scale.Z); iBone.Matrix = Matrix.Scaling(1f, 1f, -1f) * Matrix.Invert(meshFrame.matrix) * Matrix.Scaling(scale) * boneWeights.matrix; boneDic.Add(boneWeights.bone, idx = (byte)boneDic.Count); } for (int i = 0; i < boneWeights.numVertIdxWts; i++) { iSkin[boneWeights.vertexIndices[i]].Add(new Tuple <byte, float>(idx, boneWeights.vertexWeights[i])); } } } iSubmesh.VertexList = new List <ImportedVertex>(submesh.numVertices); for (int i = 0; i < submesh.numVertices; i++) { remVertex vert = submesh.VertexList[i]; ImportedVertex iVert = new ImportedVertex(); iSubmesh.VertexList.Add(iVert); iVert.Position = new Vector3(vert.Position.X, vert.Position.Z, -vert.Position.Y); iVert.Normal = new Vector3(vert.Normal.X, vert.Normal.Z, -vert.Normal.Y); 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 < iSkin[i].Count) { Tuple <byte, float> vertIdxWeight = iSkin[i][j]; iVert.BoneIndices[j] = vertIdxWeight.Item1; iVert.Weights[j] = vertIdxWeight.Item2; } else { iVert.BoneIndices[j] = 0xFF; } } } iSubmesh.FaceList = rem.ImportedFaceList(submesh.FaceList); } } }
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 ImportedFrame ImportFrame(Section section) { ImportedFrame frame = new ImportedFrame(); frame.InitChildren(0); if (section.name == null) { frame.Name = "no_name" + noNameCount; noNameCount++; } else { frame.Name = section.name; } List<bool> hasBonesList = new List<bool>(); SortedDictionary<string, byte> boneDic = new SortedDictionary<string, byte>(); ImportedMesh meshList = new ImportedMesh(); meshList.Name = frame.Name; meshList.BoneList = new List<ImportedBone>(); meshList.SubmeshList = new List<ImportedSubmesh>(); Matrix matrix = new Matrix(); foreach (Section child in section.children) { if (child.type == "FrameTransformMatrix") { LinkedListNode<object> node = child.data.First; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { matrix[i, j] = ConvertFloat(node.Value); node = node.Next; } } frame.Matrix = RHToLHMatrix(matrix); } else if (child.type == "Mesh") { ImportMesh(child, meshList, boneDic, hasBonesList); } else if (child.type == "Frame") { ImportedFrame childFrame = ImportFrame(child); if (childFrame != null) { frame.AddChild(childFrame); } } else { Report.ReportLog("Warning: unexpected section " + child.type); } } SetBones(meshList, hasBonesList); if (meshList.SubmeshList.Count > 0) { MeshList.Add(meshList); } if (matrix == null) { frame.Matrix = Matrix.Identity; } return frame; }
private static List <Texture2D> Export(string dest, Animator parser, List <MeshRenderer> meshes, bool worldCoords) { DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(dest)); if (!dir.Exists) { dir.Create(); } ImageFileFormat preferredUncompressedFormat = (string)Properties.Settings.Default["ExportUncompressedAs"] == "BMP" ? ImageFileFormat.Bmp : (ImageFileFormat)(-1); Operations.UnityConverter conv = new Operations.UnityConverter(parser, meshes, false, null, false, preferredUncompressedFormat, false); List <Material> materialList = new List <Material>(meshes.Count); using (StreamWriter writer = new StreamWriter(dest, false)) { for (int i = 0; i < meshes.Count; i++) { MeshRenderer meshRenderer = meshes[i]; ImportedMesh meshListSome = conv.MeshList[i]; for (int j = 0; j < meshListSome.SubmeshList.Count; j++) { Material mat = j < meshRenderer.m_Materials.Count ? meshRenderer.m_Materials[j].instance : null; if (mat != null) { if (!materialList.Contains(mat)) { materialList.Add(mat); } } else { Report.ReportLog("Warning: Mesh " + meshes[i].m_GameObject.instance.m_Name + " Object " + j + " has an invalid material"); } } } writer.WriteLine("Metasequoia Document"); writer.WriteLine("Format Text Ver 1.0"); writer.WriteLine(); writer.WriteLine("Material " + materialList.Count + " {"); for (int matIdx = 0; matIdx < materialList.Count; matIdx++) { Material mat = materialList[matIdx]; string s = "\t\"" + mat.m_Name + "\" col(0.800 0.800 0.800 1.000) dif(0.500) amb(0.100) emi(0.500) spc(0.100) power(30.00)"; try { Texture2D tex = null; if (mat.m_SavedProperties.m_TexEnvs.Count > 0) { tex = mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance; for (int i = 1; i < mat.m_SavedProperties.m_TexEnvs.Count; i++) { var texProp = mat.m_SavedProperties.m_TexEnvs[i]; if (texProp.Key.name == "_MainTex") { tex = texProp.Value.m_Texture.instance; break; } } } if (tex != null) { string matTexName = tex.m_Name + "-" + tex.m_TextureFormat; string extension = tex.m_TextureFormat == TextureFormat.DXT1 || tex.m_TextureFormat == TextureFormat.DXT5 ? ".dds" : ".tga"; s += " tex(\"" + matTexName + extension + "\")"; } } catch { } writer.WriteLine(s); } writer.WriteLine("}"); Random rand = new Random(); for (int i = 0; i < meshes.Count; i++) { MeshRenderer mesh = meshes[i]; if (worldCoords) { Transform parent = meshes[i].m_GameObject.instance.FindLinkedComponent(typeof(Transform)); conv.WorldCoordinates(i, Transform.WorldTransform(parent)); } string meshName = mesh.m_GameObject.instance.m_Name; ImportedMesh meshListSome = conv.MeshList[i]; for (int j = 0; j < meshListSome.SubmeshList.Count; j++) { ImportedSubmesh meshObj = meshListSome.SubmeshList[j]; Material mat = j < mesh.m_Materials.Count ? mesh.m_Materials[j].instance : null; int mqoMatIdx = -1; if (mat != null) { mqoMatIdx = materialList.IndexOf(mat); } float[] color = new float[3]; for (int k = 0; k < color.Length; k++) { color[k] = (float)((rand.NextDouble() / 2) + 0.5); } string mqoName = meshName + "(Scale=1000)[" + j + "]"; if (worldCoords) { mqoName += "[W]"; } writer.WriteLine("Object \"" + mqoName + "\" {"); writer.WriteLine("\tshading 1"); writer.WriteLine("\tcolor " + color[0].ToFloatString() + " " + color[1].ToFloatString() + " " + color[2].ToFloatString()); writer.WriteLine("\tcolor_type 1"); List <ImportedVertex> vertList = meshObj.VertexList; List <ImportedFace> faceList = meshObj.FaceList; SB3Utility.Mqo.ExporterCommon.WriteMeshObject(writer, vertList, faceList, mqoMatIdx, null, 1000); writer.WriteLine("}"); } } writer.WriteLine("Eof"); } List <Texture2D> usedTextures = new List <Texture2D>(meshes.Count); foreach (Material mat in materialList) { try { Texture2D matTex = mat.m_SavedProperties.m_TexEnvs[0].Value.m_Texture.instance; for (int i = 1; i < mat.m_SavedProperties.m_TexEnvs.Count; i++) { var texProp = mat.m_SavedProperties.m_TexEnvs[i]; if (texProp.Key.name == "_MainTex") { matTex = texProp.Value.m_Texture.instance; break; } } if (matTex != null && !usedTextures.Contains(matTex)) { usedTextures.Add(matTex); } } catch { } } return(usedTextures); }
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]; } } } } }