Example #1
0
        /// <summary>
        /// Parses the complete Mesh Section
        /// </summary>
        /// <param name="grps"></param>
        /// <param name="ct"></param>
        void ParseBonesSection(ImportedGroups grps, int ct)
        {
            SimPe.IntArrayList sort = Gmdc.SortJoints();
            for (int i = 0; i < ct; i++)
            {
                ImportedBone b = new ImportedBone(Gmdc);
                b.TargetIndex = sort[i];
                b.Action      = GmdcImporterAction.Replace;

                //Read the Bones Data
                ReadJointDescription(b);

                ReadJointData(b);

                int poscount = ReadCount();
                for (int k = 0; k < poscount; k++)
                {
                    ReadJointPosPhase(b, k, poscount);
                }

                int rotcount = ReadCount();
                for (int k = 0; k < rotcount; k++)
                {
                    ReadJointRotPhase(b, k, rotcount);
                }

                bones.Add(b);
            }
        }
Example #2
0
        void ReadJointRotPhase(ImportedBone b, int index, int count)
        {
            string[] linetoks = GetNonEmptyTokens();
            if (linetoks.Length < 4)
            {
                lineerror = "Unable to read JointRotation Line.";
                return;
            }

            try
            {
                float t        = Convert.ToSingle(linetoks[0], AbstractGmdcImporter.DefaultCulture);
                bool  isscaled = (t == -1);
                t = Math.Max(0, t - 1);
                Vector3f rot = new Vector3f(
                    ToDouble(linetoks[1]),
                    ToDouble(linetoks[2]),
                    ToDouble(linetoks[3])
                    );

                Quaternion q = Quaternion.FromEulerAngles(rot);
                rot = q.Axis;
                rot = Component.InverseTransform(rot);
                q   = Quaternion.FromAxisAngle(rot, q.Angle);
                rot = q.GetEulerAngles();

                if (currotblock != null)
                {
                    //Brand this Block as Rotation (ignoring all Translation!)
                    if (currotblock.TransformationType == FrameType.Unknown)
                    {
                        currotblock.TransformationType = FrameType.Rotation;
                    }



                    //only process if the Block Type is Rotation
                    if (currotblock.TransformationType == FrameType.Rotation)
                    {
                        if (isscaled && index == 0)
                        {
                            for (int i = 0; i < currotblock.AxisCount; i++)
                            {
                                currotblock.AxisSet[i].Locked = true;
                            }
                        }

                        currotblock.AddFrame((short)t, rot, false);
                    }
                }
            }
            catch
            {
                lineerror = "Unable to Convert to Number (ReadJointRotPhase)";
            }
        }
Example #3
0
        void ReadJointData(ImportedBone b)
        {
            string[] linetoks = GetNonEmptyTokens();
            if (linetoks.Length < 7)
            {
                lineerror = "Unable to read Joint Line.";
                return;
            }

            try
            {
                Vector3f trans = new Vector3f(
                    ToDouble(linetoks[1]),
                    ToDouble(linetoks[2]),
                    ToDouble(linetoks[3])
                    );
                trans = Component.InverseTransformScaled(trans);

                Vector3f rot = new Vector3f(
                    ToDouble(linetoks[4]),
                    ToDouble(linetoks[5]),
                    ToDouble(linetoks[6])
                    );
                Quaternion q = Quaternion.FromEulerAngles(rot);
                rot = Component.InverseTransform(q.Axis);



                //Quaternion from Euler Angles
                b.Transformation.Translation = trans;
                b.Transformation.Rotation    = SimPe.Geometry.Quaternion.FromAxisAngle(rot, q.Angle);
            }
            catch
            {
                lineerror = "Unable to Convert to Number(ReadJointData)";
            }
        }
Example #4
0
        void ReadJointDescription(ImportedBone b)
        {
            string[] linetoks = GetNonEmptyTokens();
            if (linetoks.Length < 1)
            {
                lineerror = "Unable to read Joint Description.";
                return;
            }
            linetoks[0]    = linetoks[0].Replace("\"", "");
            b.ImportedName = linetoks[0];

            linetoks = GetNonEmptyTokens();
            if (linetoks.Length < 1)
            {
                lineerror = "Unable to read Joint Description.";
                return;
            }
            linetoks[0]  = linetoks[0].Replace("\"", "");
            b.ParentName = linetoks[0];

            //Animations
            if (this.AnimationBlocks != null && Gmdc.LinkedAnimation != null)
            {
                curtransblock = null; currotblock = null;

                ImportedFrameBlock ifb = new ImportedFrameBlock(new AnimationFrameBlock(Gmdc.LinkedAnimation));


                ifb.FrameBlock.Name = b.ImportedName;
                ifb.FindTarget(Gmdc.LinkedAnimation);
                if (ifb.Target != null)
                {
                    ifb.FrameBlock.TransformationType = ifb.Target.TransformationType;

                    if (ifb.FrameBlock.TransformationType == FrameType.Translation)
                    {
                        curtransblock = ifb.FrameBlock;
                    }
                    else
                    {
                        currotblock = ifb.FrameBlock;
                    }
                }
                else
                {
                    ifb.FrameBlock.TransformationType = FrameType.Rotation;
                    if (b.ImportedName.EndsWith("_rot"))
                    {
                        ifb.FrameBlock.TransformationType = FrameType.Rotation;
                        currotblock = ifb.FrameBlock;
                    }
                    else if (b.ImportedName.EndsWith("_trans"))
                    {
                        ifb.FrameBlock.TransformationType = FrameType.Translation;
                        curtransblock = ifb.FrameBlock;
                    }
                    else
                    {
                        currotblock = ifb.FrameBlock;
                        ifb.FrameBlock.CreateBaseAxisSet(AnimationTokenType.SixByte);
                        this.AnimationBlocks.Add(ifb);

                        ifb = new ImportedFrameBlock(new AnimationFrameBlock(Gmdc.LinkedAnimation));
                        ifb.FrameBlock.TransformationType = FrameType.Translation;
                        ifb.FrameBlock.Name = b.ImportedName;
                        curtransblock       = ifb.FrameBlock;
                    }
                }

                ifb.FrameBlock.CreateBaseAxisSet(AnimationTokenType.SixByte);



                this.AnimationBlocks.Add(ifb);
            }

            //if (curanimblock==null) curanimblock = new SimPe.Plugin.AnimBlock2();
        }
Example #5
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 #6
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();
                            }
                        }
                    }
                }
            }
Example #7
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 #8
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 #9
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 #10
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 #11
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];
                            }
                        }
                    }
                }
            }