Example #1
0
        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);
        }
Example #2
0
            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);
                }
            }
Example #3
0
        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;
        }
Example #4
0
            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);
                    }
                }
            }
Example #5
0
        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);
            }
        }
Example #6
0
            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);
                }
            }
Example #7
0
 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];
                 }
             }
         }
     }
 }
Example #8
0
            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);
            }
        }
Example #10
0
            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);
                }
            }
Example #11
0
            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;
            }
Example #12
0
            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];
                            }
                        }
                    }
                }
            }
Example #13
0
            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);
                }
            }
Example #14
0
File: Fbx.cs Project: kkdevs/sb3u
            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);
                    }
                }
            }
Example #15
0
            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);
                }
            }
Example #16
0
            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;
            }
Example #17
0
            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);
            }
Example #18
0
File: Fbx.cs Project: kkdevs/sb3u
            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];
                            }
                        }
                    }
                }
            }