コード例 #1
0
ファイル: odfEditor.cs プロジェクト: kkdevs/sb3u
        public void CopyBone(int boneListIdx, int boneIdx)
        {
            odfBoneList boneList = Parser.EnvelopeSection[boneListIdx];
            odfBone     bone     = boneList[boneIdx];

            boneList.AddChild(bone.Clone());
        }
コード例 #2
0
ファイル: RenderObjectODF.cs プロジェクト: kkdevs/sb3u
        private float[][] ConvertVertexWeights(List <odfVertex> vertexList, odfBoneList boneList)
        {
            int numBones = boneList != null ? boneList.Count : 0;

            float[][] vertexWeights = new float[vertexList.Count][];
            for (int j = 0; j < vertexList.Count; j++)
            {
                vertexWeights[j] = new float[4];
                int weightIdx = 0;
                for (int k = 0; k < numBones; k++)
                {
                    odfBone bone = boneList[k];
                    for (int l = 0; l < bone.NumberIndices; l++)
                    {
                        if (bone.VertexIndexArray[l] == j)
                        {
                            vertexList[j].BoneIndices[weightIdx] = (byte)k;
                            if (weightIdx < 3)
                            {
                                vertexWeights[j][weightIdx++] = bone.WeightArray[l];
                            }
                            else
                            {
                                vertexWeights[j][3] = 1f - vertexWeights[j][0] - vertexWeights[j][1] - vertexWeights[j][2];
                            }
                            break;
                        }
                    }
                }
            }

            return(vertexWeights);
        }
コード例 #3
0
        public static void RemoveSubmesh(odfParser parser, odfSubmesh submesh, bool deleteMorphs)
        {
            odfBoneList boneList = odf.FindBoneList(submesh.Id, parser.EnvelopeSection);

            if (boneList != null)
            {
                parser.EnvelopeSection.RemoveChild(boneList);
                parser.UsedIDs.Remove((int)boneList.Id);
            }

            if (parser.MorphSection != null && deleteMorphs)
            {
                for (int i = 0; i < parser.MorphSection.Count; i++)
                {
                    odfMorphObject morphObj = parser.MorphSection[i];
                    if (morphObj.SubmeshId == submesh.Id)
                    {
                        parser.MorphSection.RemoveChild(i);
                        --i;
                    }
                }
            }

            ((odfMesh)submesh.Parent).RemoveChild(submesh);
        }
コード例 #4
0
        public static odfBoneList ParseBoneList(BinaryReader reader, int formatType)
        {
            ObjectName  name      = new ObjectName(reader.ReadBytes(64));
            ObjectID    id        = new ObjectID(reader.ReadBytes(4));
            ObjectID    frameId   = new ObjectID(reader.ReadBytes(4));
            ObjectID    meshObjId = new ObjectID(reader.ReadBytes(4));
            int         numBones  = reader.ReadInt32();
            odfBoneList boneList  = new odfBoneList(name, id, numBones);

            boneList.MeshFrameId = frameId;
            boneList.SubmeshId   = meshObjId;
            if (formatType >= 10)
            {
                boneList.AlwaysZero4 = reader.ReadBytes(4);
            }

            for (int boneIdx = 0; boneIdx < numBones; boneIdx++)
            {
                id = new ObjectID(reader.ReadBytes(4));
                odfBone bone = new odfBone(id);

                int numberIndices = reader.ReadInt32();
                bone.AlwaysZero24perIndex = reader.ReadBytes(24 * numberIndices);
                bone.VertexIndexArray     = reader.ReadInt32Array(numberIndices);
                bone.WeightArray          = reader.ReadSingleArray(numberIndices);
                bone.Matrix = reader.ReadMatrix();

                boneList.AddChild(bone);
            }
            return(boneList);
        }
コード例 #5
0
ファイル: RenderObjectODF.cs プロジェクト: kkdevs/sb3u
        public void HighlightBone(odfParser parser, int meshIdx, int submeshIdx, int boneIdx)
        {
            const int boneObjSize = 16;

            odfSubmesh  submesh       = parser.MeshSection[meshIdx][submeshIdx];
            odfBoneList boneList      = odf.FindBoneList(submesh.Id, parser.EnvelopeSection);
            string      boneFrameName = null;

            if (boneIdx >= 0)
            {
                odfBone bone = boneList[boneIdx];
                boneFrameName = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name;
            }

            AnimationMeshContainer mesh = (AnimationMeshContainer)meshFrames[0].MeshContainer;

            for (int i = 0; mesh != null; i++)
            {
                if (i == submeshIdx && (mesh.MeshData != null) && (mesh.MeshData.Mesh != null))
                {
                    List <odfVertex> vertexList    = submesh.VertexList;
                    float[][]        vertexWeights = ConvertVertexWeights(vertexList, boneList);
                    FillVertexBuffer(mesh.MeshData.Mesh, vertexList, vertexWeights, boneIdx);
//					break;
                }
                if (boneIdx >= 0)
                {
                    for (int idx = 0; idx < mesh.BoneLines.Length / boneObjSize; idx++)
                    {
                        if (mesh.BoneNames[idx] == boneFrameName)
                        {
                            for (int j = 0; j < boneObjSize; j++)
                            {
                                mesh.BoneLines[idx * boneObjSize + j].Color = Color.Crimson.ToArgb();
                            }
                            break;
                        }
                    }
                }
                else
                {
                    for (int idx = 0; idx < mesh.BoneLines.Length / boneObjSize; idx++)
                    {
                        for (int j = 0; j < boneObjSize; j++)
                        {
                            mesh.BoneLines[idx * boneObjSize + j].Color = Color.CornflowerBlue.ToArgb();
                        }
                    }
                }
                mesh = (AnimationMeshContainer)mesh.NextMeshContainer;
            }
        }
コード例 #6
0
ファイル: odfEditor.cs プロジェクト: kkdevs/sb3u
        public void MergeFrame(odfFrame srcFrame, odfParser srcParser, int destParentIdx)
        {
            List <ObjectID>    newMeshIDs   = new List <ObjectID>();
            odfFrame           newFrame     = srcFrame.Clone(true, newMeshIDs, true);
            List <odfMesh>     newMeshes    = new List <odfMesh>(newMeshIDs.Count);
            List <odfBoneList> newBoneLists = new List <odfBoneList>(srcParser.EnvelopeSection != null ? srcParser.EnvelopeSection.Count : 0);
            string             boneWarning  = String.Empty;

            foreach (ObjectID meshID in newMeshIDs)
            {
                odfMesh srcMesh = odf.FindMeshListSome(meshID, srcParser.MeshSection);
                odfMesh mesh    = srcMesh.Clone();
                newMeshes.Add(mesh);
                if (srcParser.EnvelopeSection != null)
                {
                    foreach (odfSubmesh submesh in mesh)
                    {
                        odfBoneList boneList = odf.FindBoneList(submesh.Id, srcParser.EnvelopeSection);
                        if (boneList != null)
                        {
                            if (Parser.EnvelopeSection != null)
                            {
                                odfBoneList copy = boneList.Clone();
                                newBoneLists.Add(copy);
                            }
                            else
                            {
                                boneWarning += (boneWarning != String.Empty ? ", " : "") + mesh.ToString();
                                break;
                            }
                        }
                    }
                }
            }
            MergeFrame(newFrame, destParentIdx);
            foreach (odfMesh mesh in newMeshes)
            {
                Parser.MeshSection.AddChild(mesh);
            }
            if (Parser.EnvelopeSection != null)
            {
                foreach (odfBoneList boneList in newBoneLists)
                {
                    Parser.EnvelopeSection.AddChild(boneList);
                }
            }
            Parser.CollectObjectIDs();
            if (boneWarning != String.Empty)
            {
                Report.ReportLog("Warning! Bones of " + boneWarning + " dropped because the destination had no Envelope section.");
            }
        }
コード例 #7
0
ファイル: odfEditor.cs プロジェクト: kkdevs/sb3u
        public bool RemoveBone(int boneListIdx, int boneIdx)
        {
            odfBoneList boneList = Parser.EnvelopeSection[boneListIdx];

            if (boneList.Count == 1)
            {
                Parser.EnvelopeSection.RemoveChild(boneList);
                return(true);
            }
            else
            {
                boneList.RemoveChild(boneIdx);
                return(false);
            }
        }
コード例 #8
0
ファイル: odfOps.cs プロジェクト: kkdevs/sb3u
 public static void MergeBoneLists(odfMesh mesh, Dictionary <ObjectID, ObjectID> submeshIDtrans, odfParser parser)
 {
     foreach (odfSubmesh submesh in mesh)
     {
         ObjectID baseSubmeshId = submeshIDtrans[submesh.Id];
         for (int i = 0; i < parser.EnvelopeSection.Count; i++)
         {
             odfBoneList boneList = parser.EnvelopeSection[i];
             if (boneList.SubmeshId == baseSubmeshId)
             {
                 Dictionary <int, int> boneDic = new Dictionary <int, int>(boneList.Count);
                 for (int j = 0; j < boneList.Count; j++)
                 {
                     odfBone bone = boneList[j];
                     boneDic.Add((int)bone.FrameId, j);
                 }
                 for (int j = i + 1; j < parser.EnvelopeSection.Count; j++)
                 {
                     odfBoneList boneList2 = parser.EnvelopeSection[j];
                     if (boneList2.SubmeshId == submesh.Id)
                     {
                         foreach (odfBone bone in boneList2)
                         {
                             int boneIdx;
                             if (boneDic.TryGetValue((int)bone.FrameId, out boneIdx))
                             {
                                 boneList.RemoveChild(boneIdx);
                                 boneList.InsertChild(boneIdx, bone);
                             }
                             else
                             {
                                 boneList.AddChild(bone);
                                 boneDic.Add((int)bone.FrameId, boneDic.Count);
                             }
                         }
                         parser.EnvelopeSection.RemoveChild(boneList2);
                     }
                 }
                 break;
             }
             else
             {
                 Report.ReportLog("wrong");
             }
         }
     }
 }
コード例 #9
0
ファイル: odfStructures.cs プロジェクト: kkdevs/sb3u
        public odfBoneList Clone()
        {
            odfBoneList boneList = new odfBoneList(Name, Id, Count);

            boneList.MeshFrameId = new ObjectID(MeshFrameId);
            boneList.SubmeshId   = new ObjectID(SubmeshId);
            if (AlwaysZero4 != null)
            {
                boneList.AlwaysZero4 = (byte[])AlwaysZero4.Clone();
            }
            foreach (odfBone bone in this)
            {
                odfBone newBone = bone.Clone();
                boneList.AddChild(newBone);
            }
            return(boneList);
        }
コード例 #10
0
        private new void listViewAnimationTrack_ItemSelectionChanged(object sender, ListViewItemSelectionChangedEventArgs e)
        {
            List <DockContent> formODFList;

            if (!Gui.Docking.DockContents.TryGetValue(typeof(FormMeshView), out formODFList))
            {
                return;
            }

            foreach (FormMeshView formMesh in formODFList)
            {
                odfFrame boneFrame = odf.FindFrame(e.Item.Text, formMesh.Editor.Parser.FrameSection.RootFrame);
                if (boneFrame == null)
                {
                    continue;
                }
                for (int i = 0; i < formMesh.renderObjectMeshes.Count; i++)
                {
                    RenderObjectODF mesh = formMesh.renderObjectMeshes[i];
                    if (mesh != null && formMesh.renderObjectIds[i] > -1)
                    {
                        odfMesh odfMesh = formMesh.Editor.Parser.MeshSection[i];
                        for (int j = 0; j < odfMesh.Count; j++)
                        {
                            odfSubmesh  submesh = odfMesh[j];
                            odfBoneList bones   = odf.FindBoneList(submesh.Id, formMesh.Editor.Parser.EnvelopeSection);
                            if (bones == null)
                            {
                                continue;
                            }
                            for (int k = 0; k < bones.Count; k++)
                            {
                                if (bones[k].FrameId == boneFrame.Id)
                                {
                                    mesh.HighlightBone(formMesh.Editor.Parser, i, j, e.IsSelected ? k : -1);
                                    Gui.Renderer.Render();
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
コード例 #11
0
ファイル: odfOps.cs プロジェクト: kkdevs/sb3u
        public static HashSet <int> SearchHierarchy(odfParser parser, HashSet <int> meshIDs)
        {
            HashSet <int> exportFrames = new HashSet <int>();

            SearchHierarchy(parser.FrameSection.RootFrame, parser.FrameSection.RootFrame, meshIDs, exportFrames);
            if (parser.EnvelopeSection != null)
            {
                for (int meshIdx = 0; meshIdx < parser.MeshSection.Count; meshIdx++)
                {
                    odfMesh mesh = parser.MeshSection[meshIdx];
                    if (!meshIDs.Contains((int)mesh.Id))
                    {
                        continue;
                    }
                    for (int meshObjIdx = 0; meshObjIdx < mesh.Count; meshObjIdx++)
                    {
                        odfSubmesh meshObj = mesh[meshObjIdx];
                        for (int envIdx = 0; envIdx < parser.EnvelopeSection.Count; envIdx++)
                        {
                            odfBoneList boneList = parser.EnvelopeSection[envIdx];
                            if (meshObj.Id != boneList.SubmeshId)
                            {
                                continue;
                            }
                            for (int i = 0; i < boneList.Count; i++)
                            {
                                ObjectID boneID = boneList[i].FrameId;
                                if (!exportFrames.Contains((int)boneID))
                                {
                                    odfFrame boneParent = FindFrame(boneID, parser.FrameSection.RootFrame);
                                    while (boneParent != null && exportFrames.Add((int)boneParent.Id))
                                    {
                                        boneParent = boneParent.Parent as odfFrame;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(exportFrames);
        }
コード例 #12
0
        private bool loadENVL(BinaryReader reader, odfFileSection fileSec)
        {
            ObjectID id = new ObjectID(reader.ReadBytes(4));

            byte[]             alwaysZero   = reader.ReadBytes(64);
            int                numEnvelopes = reader.ReadInt32();
            odfEnvelopeSection envSection   = new odfEnvelopeSection(numEnvelopes);

            envSection.Id           = id;
            envSection.AlwaysZero64 = alwaysZero;
            envSection._FormatType  = MeshSection != null ? MeshSection._FormatType : -1;
            for (int envIdx = 0; envIdx < numEnvelopes; envIdx++)
            {
                odfBoneList boneList = ParseBoneList(reader, envSection._FormatType);
                envSection.AddChild(boneList);
            }

            fileSec.Section = envSection;
            EnvelopeSection = envSection;
            return(true);
        }
コード例 #13
0
ファイル: odfEditor.cs プロジェクト: kkdevs/sb3u
        public void ReplaceFrame(odfFrame srcFrame, odfParser srcParser, int destParentIdx, bool deleteMorphs)
        {
            List <ObjectID> meshIDs  = new List <ObjectID>();
            odfFrame        newFrame = srcFrame.Clone(true, meshIDs, true);

            ReplaceFrame(newFrame, destParentIdx, deleteMorphs);
            string boneWarning = String.Empty;

            foreach (ObjectID meshID in meshIDs)
            {
                odfMesh srcMesh = odf.FindMeshListSome(meshID, srcParser.MeshSection);
                odfMesh mesh    = srcMesh.Clone();
                Parser.MeshSection.AddChild(mesh);
                if (srcParser.EnvelopeSection != null)
                {
                    foreach (odfSubmesh submesh in mesh)
                    {
                        odfBoneList boneList = odf.FindBoneList(submesh.Id, srcParser.EnvelopeSection);
                        if (boneList != null)
                        {
                            if (Parser.EnvelopeSection != null)
                            {
                                odfBoneList copy = boneList.Clone();
                                Parser.EnvelopeSection.AddChild(copy);
                            }
                            else
                            {
                                boneWarning += (boneWarning != String.Empty ? ", " : "") + mesh.ToString();
                                break;
                            }
                        }
                    }
                }
            }
            Parser.CollectObjectIDs();
            if (boneWarning != String.Empty)
            {
                Report.ReportLog("Warning! Bones of " + boneWarning + " dropped because the destination had no Envelope section.");
            }
        }
コード例 #14
0
ファイル: odfEditor.cs プロジェクト: kkdevs/sb3u
        void DeleteReferringBones(odfFrame frame)
        {
            for (int i = 0; i < Parser.EnvelopeSection.Count; i++)
            {
                odfBoneList boneList = Parser.EnvelopeSection[i];
                for (int j = 0; j < boneList.Count; j++)
                {
                    odfBone bone = boneList[j];
                    if (bone.FrameId == frame.Id)
                    {
                        if (RemoveBone(Parser.EnvelopeSection.IndexOf(boneList), j))
                        {
                            i--;
                        }
                        break;
                    }
                }
            }

            foreach (odfFrame child in frame)
            {
                DeleteReferringBones(child);
            }
        }
コード例 #15
0
        public static odfBoneList CreateBoneList(ObjectID id, ObjectID meshFrameId, odfSubmesh submesh, List <ImportedBone> boneList, Matrix lMeshMatrixInv, odfFrame rootFrame)
        {
            if (boneList == null || boneList.Count == 0)
            {
                return(null);
            }
            Dictionary <byte, Tuple <byte, odfBone> > boneDic = new Dictionary <byte, Tuple <byte, odfBone> >(boneList.Count);

            Tuple <List <int>, List <float> >[] newBoneListComponents = new Tuple <List <int>, List <float> > [boneList.Count];
            int boneframeNotFound = 0;

            for (int i = 0; i < submesh.NumVertices; i++)
            {
                odfVertex vert = submesh.VertexList[i];
                for (int j = 0; j < vert.BoneIndices.Length; j++)
                {
                    byte boneIdx = vert.BoneIndices[j];
                    if (boneIdx == 0xFF)
                    {
                        continue;
                    }
                    Tuple <byte, odfBone> boneDesc;
                    odfBone newBone;
                    if (!boneDic.TryGetValue(boneIdx, out boneDesc))
                    {
                        odfFrame boneFrame = odf.FindFrame(boneList[boneIdx].Name, rootFrame);
                        if (boneFrame == null)
                        {
                            boneframeNotFound++;
                            continue;
                        }

                        newBone        = new odfBone(boneFrame.Id);
                        newBone.Matrix = boneList[boneIdx].Matrix;

                        boneDesc = new Tuple <byte, odfBone>((byte)boneDic.Count, newBone);
                        boneDic.Add(boneIdx, boneDesc);
                        newBoneListComponents[boneDesc.Item1] = new Tuple <List <int>, List <float> >(new List <int>(200), new List <float>(200));
                    }
                    else
                    {
                        newBone = boneDesc.Item2;
                    }
                    byte       newBoneIdx     = boneDesc.Item1;
                    List <int> newBoneIdxList = newBoneListComponents[newBoneIdx].Item1;
                    newBoneIdxList.Add(i);
                    List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2;
                    newBoneWeightList.Add(vert.Weights[j]);
                }
            }

            if (boneDic.Count == 0)
            {
                Report.ReportLog(submesh.ToString() + ": all bones dropped because of missing skeleton.");
                return(null);
            }
            odfBoneList newBoneList = new odfBoneList(new ObjectName(String.Empty, null), id, boneDic.Count);

            newBoneList.MeshFrameId = meshFrameId;
            newBoneList.SubmeshId   = submesh.Id;
            newBoneList.AlwaysZero4 = new byte[4];
            foreach (Tuple <byte, odfBone> boneDesc in boneDic.Values)
            {
                byte         newBoneIdx        = boneDesc.Item1;
                List <int>   newBoneIdxList    = newBoneListComponents[newBoneIdx].Item1;
                List <float> newBoneWeightList = newBoneListComponents[newBoneIdx].Item2;
                odfBone      newBone           = boneDesc.Item2;
                newBone.AlwaysZero24perIndex = new byte[24 * newBoneIdxList.Count];
                newBone.VertexIndexArray     = newBoneIdxList.ToArray();
                newBone.WeightArray          = newBoneWeightList.ToArray();

                Matrix lMatrix = Matrix.Invert(newBone.Matrix);
                newBone.Matrix = Matrix.Invert(lMatrix * lMeshMatrixInv);

                newBoneList.AddChild(newBone);
            }
            if (boneframeNotFound > 0)
            {
                Report.ReportLog(submesh.ToString() + ": " + boneframeNotFound + " bone(s) because of missing boneframe(s) dropped.");
            }

            return(newBoneList);
        }
コード例 #16
0
ファイル: RenderObjectODF.cs プロジェクト: kkdevs/sb3u
        private AnimationFrame CreateFrame(odfFrame frame, odfParser parser, HashSet <int> extractFrames, HashSet <int> meshIDs, Device device, Matrix combinedParent, List <AnimationFrame> meshFrames)
        {
            AnimationFrame animationFrame = new AnimationFrame();

            animationFrame.Name = frame.Name;
            animationFrame.TransformationMatrix = frame.Matrix;
            animationFrame.OriginalTransform    = animationFrame.TransformationMatrix;
            animationFrame.CombinedTransform    = combinedParent * animationFrame.TransformationMatrix;

            if ((int)frame.MeshId != 0 && meshIDs.Contains((int)frame.MeshId))
            {
                odfMesh            mesh      = odf.FindMeshListSome(frame.MeshId, parser.MeshSection);
                ExtendedMaterial[] materials = new ExtendedMaterial[mesh.Count];

                AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.Count];
                Vector3 min = new Vector3(Single.MaxValue);
                Vector3 max = new Vector3(Single.MinValue);
                for (int i = 0; i < mesh.Count; i++)
                {
                    odfSubmesh       submesh    = mesh[i];
                    List <odfFace>   faceList   = submesh.FaceList;
                    List <odfVertex> vertexList = submesh.VertexList;

                    odfBoneList boneList    = odf.FindBoneList(submesh.Id, parser.EnvelopeSection);
                    bool        skinned     = boneList != null;
                    int         numBones    = skinned ? boneList.Count : 0;
                    string[]    boneNames   = new string[numBones];
                    Matrix[]    boneOffsets = new Matrix[numBones];
                    for (int boneIdx = 0; boneIdx < numBones; boneIdx++)
                    {
                        odfBone bone = boneList[boneIdx];
                        boneNames[boneIdx] = odf.FindFrame(bone.FrameId, parser.FrameSection.RootFrame).Name;
                        Matrix mirrored;
                        if (!BoneMatrixDic.TryGetValue(boneNames[boneIdx], out mirrored))
                        {
#if !DONT_MIRROR
                            Vector3    translate, scale;
                            Quaternion rotate;
                            bone.Matrix.Decompose(out scale, out rotate, out translate);
                            mirrored = Matrix.Scaling(scale.X, scale.Y, -scale.Z) * Matrix.RotationQuaternion(rotate) * Matrix.Translation(translate);
#else
                            mirrored = bone.Matrix;
#endif
                            BoneMatrixDic.Add(boneNames[boneIdx], mirrored);
                        }
                        boneOffsets[boneIdx] = mirrored;
                    }

                    Mesh animationMesh = new Mesh(device, faceList.Count, vertexList.Count, MeshFlags.Managed, PositionBlendWeightsIndexedNormalTexturedColoured.Format);

                    using (DataStream indexStream = animationMesh.LockIndexBuffer(LockFlags.None))
                    {
                        for (int j = 0; j < faceList.Count; j++)
                        {
                            ushort[] indices = faceList[j].VertexIndices;
                            indexStream.Write(indices[0]);
                            indexStream.Write(indices[1]);
                            indexStream.Write(indices[2]);
                        }
                        animationMesh.UnlockIndexBuffer();
                    }

                    float[][] vertexWeights = ConvertVertexWeights(vertexList, boneList);
                    FillVertexBuffer(animationMesh, vertexList, vertexWeights, -1);

                    var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2];
                    for (int j = 0; j < vertexList.Count; j++)
                    {
                        odfVertex vertex = vertexList[j];
#if !DONT_MIRROR
                        Vector3 position = new Vector3(vertex.Position.X, vertex.Position.Y, -vertex.Position.Z);
                        Vector3 normal   = new Vector3(vertex.Normal.X, vertex.Normal.Y, -vertex.Normal.Z);
#else
                        Vector3 position = vertex.Position;
                        Vector3 normal   = vertex.Normal;
#endif
                        float[] boneWeights = vertexWeights[j];

                        normalLines[j * 2]       = new PositionBlendWeightsIndexedColored(position, boneWeights, vertex.BoneIndices, Color.Yellow.ToArgb());
                        normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + (normal / 11), boneWeights, vertex.BoneIndices, Color.Blue.ToArgb());

                        min = Vector3.Minimize(min, position);
                        max = Vector3.Maximize(max, position);
                    }

                    AnimationMeshContainer meshContainer = new AnimationMeshContainer();
                    meshContainer.Name        = animationFrame.Name;
                    meshContainer.MeshData    = new MeshData(animationMesh);
                    meshContainer.NormalLines = normalLines;
                    meshContainer.BoneNames   = boneNames;
                    meshContainer.BoneOffsets = boneOffsets;
                    meshContainers[i]         = meshContainer;

                    odfMaterial mat = odf.FindMaterialInfo(submesh.MaterialId, parser.MaterialSection);
                    if (mat != null)
                    {
                        Material material3D = new Material();
                        material3D.Ambient  = mat.Ambient;
                        material3D.Diffuse  = mat.Diffuse;
                        material3D.Emissive = mat.Emissive;
                        material3D.Specular = mat.Specular;
                        material3D.Power    = mat.SpecularPower;
                        int matIdx = parser.MaterialSection.IndexOf(mat);
                        Materials[matIdx]           = material3D;
                        meshContainer.MaterialIndex = matIdx;

                        int texIdx = -1;
                        if ((int)submesh.TextureIds[0] != 0 && !TextureDic.TryGetValue((int)submesh.TextureIds[0], out texIdx))
                        {
                            odfTexture tex = odf.FindTextureInfo(submesh.TextureIds[0], parser.TextureSection);
                            if (tex != null)
                            {
                                try
                                {
                                    odfTextureFile  texFile  = new odfTextureFile(null, Path.GetDirectoryName(parser.ODFPath) + Path.DirectorySeparatorChar + tex.TextureFile);
                                    int             fileSize = 0;
                                    ImportedTexture impTex   = new ImportedTexture(texFile.DecryptFile(ref fileSize).BaseStream, tex.TextureFile);
                                    Texture         memTex   = impTex.ToTexture(device);
                                    texIdx = TextureDic.Count;
                                    TextureDic.Add((int)submesh.TextureIds[0], texIdx);
                                    Textures[texIdx] = memTex;
                                }
                                catch (SlimDXException ex)
                                {
                                    Utility.ReportException(ex);
                                    Report.ReportLog("Please check " + tex.TextureFile + ". It may have an unsupported format.");
                                }
                                catch (Exception ex)
                                {
                                    Utility.ReportException(ex);
                                }
                            }
                        }
                        meshContainer.TextureIndex = texIdx;
                    }
                }

                for (int i = 0; i < (meshContainers.Length - 1); i++)
                {
                    meshContainers[i].NextMeshContainer = meshContainers[i + 1];
                }

                animationFrame.Bounds        = new BoundingBox(min, max);
                animationFrame.MeshContainer = meshContainers[0];
                meshFrames.Add(animationFrame);
            }

            for (int i = 0; i < frame.Count; i++)
            {
                odfFrame child = frame[i];
                if (extractFrames.Contains((int)child.Id))
                {
                    AnimationFrame childAnimationFrame = CreateFrame(child, parser, extractFrames, meshIDs, device, animationFrame.CombinedTransform, meshFrames);
                    childAnimationFrame.Parent = animationFrame;
                    animationFrame.AppendChild(childAnimationFrame);
                }
            }

            numFrames++;
            return(animationFrame);
        }
コード例 #17
0
        public static void ReplaceMesh(odfFrame frame, odfParser parser, WorkspaceMesh mesh, List <ImportedMaterial> materials, List <ImportedTexture> textures, bool merge, CopyMeshMethod normalsMethod, CopyMeshMethod bonesMethod)
        {
            Matrix   transform      = Matrix.Identity;
            odfFrame transformFrame = frame;

            while (transformFrame != null)
            {
                transform     *= transformFrame.Matrix;
                transformFrame = transformFrame.Parent as odfFrame;
            }
            transform.Invert();

            string[] materialNames;
            int[]    indices;
            bool[]   worldCoords;
            bool[]   replaceSubmeshesOption;
            odfMesh  newMesh = CreateMesh(mesh, parser.MeshSection._FormatType, out materialNames, out indices, out worldCoords, out replaceSubmeshesOption);

            odfMesh frameMesh = odf.FindMeshListSome(frame.MeshId, parser.MeshSection);

            if (frameMesh != null)
            {
                if (parser.UsedIDs == null)                 // prevent misleading error message
                {
                    parser.CollectObjectIDs();
                }
                newMesh.Id   = frameMesh.Id;
                newMesh.Name = frameMesh.Name;
                parser.MeshSection.InsertChild(parser.MeshSection.IndexOf(frameMesh), newMesh);
            }
            else
            {
                newMesh.Id   = parser.GetNewID(typeof(odfMesh));
                frame.MeshId = newMesh.Id;
                parser.MeshSection.AddChild(newMesh);
            }

            Dictionary <ObjectID, ObjectID> submeshIDtranslation = new Dictionary <ObjectID, ObjectID>(newMesh.Count);

            odfSubmesh[]      replaceSubmeshes = frameMesh != null ? new odfSubmesh[frameMesh.Count] : null;
            List <odfSubmesh> addSubmeshes     = new List <odfSubmesh>(newMesh.Count);

            for (int i = 0; i < newMesh.Count; i++)
            {
                ObjectID[] texIDs = new ObjectID[4] {
                    ObjectID.INVALID, ObjectID.INVALID, ObjectID.INVALID, ObjectID.INVALID
                };
                odfMaterial mat = odf.FindMaterialInfo(materialNames[i], parser.MaterialSection);
                if (materials != null && mat == null)
                {
                    ImportedMaterial impMat = ImportedHelpers.FindMaterial(materialNames[i], materials);
                    if (impMat != null)
                    {
                        mat = CreateMaterial(impMat, parser.GetNewID(typeof(odfMaterial)));
                        parser.MaterialSection.AddChild(mat);
                        for (int j = 0; j < impMat.Textures.Length; j++)
                        {
                            string     texName = impMat.Textures[j];
                            odfTexture tex     = odf.FindTextureInfo(texName, parser.TextureSection);
                            if (tex == null)
                            {
                                ImportedTexture impTex = ImportedHelpers.FindTexture(texName, textures);
                                if (impTex != null)
                                {
                                    tex = CreateTexture(impTex, parser.GetNewID(typeof(odfTexture)), parser.TextureSection._FormatType, Path.GetDirectoryName(parser.ODFPath));
                                    parser.TextureSection.AddChild(tex);
                                    texIDs[j] = tex.Id;
                                }
                            }
                            else
                            {
                                texIDs[j] = tex.Id;
                            }
                        }
                    }
                }

                odfSubmesh newSubmesh = newMesh[i];
                newSubmesh.Id         = parser.GetNewID(typeof(odfSubmesh));
                newSubmesh.MaterialId = mat != null ? mat.Id : ObjectID.INVALID;
                newSubmesh.TextureIds = texIDs;

                List <odfVertex> newVertexList = newSubmesh.VertexList;
                if (worldCoords[i])
                {
                    for (int j = 0; j < newVertexList.Count; j++)
                    {
                        newVertexList[j].Position = Vector3.TransformCoordinate(newVertexList[j].Position, transform);
                    }
                }

                odfSubmesh  baseSubmesh = null;
                odfBoneList newBones    = null;
                int         newBonesIdx = -1;
                int         idx         = indices[i];
                if ((frameMesh != null) && (idx >= 0) && (idx < frameMesh.Count))
                {
                    baseSubmesh = frameMesh[idx];
                    submeshIDtranslation.Add(newSubmesh.Id, baseSubmesh.Id);
                    for (int j = 0; j < baseSubmesh.TextureIds.Length; j++)
                    {
                        ObjectID texID = baseSubmesh.TextureIds[j];
                        newSubmesh.TextureIds[j] = texID;
                    }
                    newSubmesh.Name = new ObjectName(baseSubmesh.Name.Name, baseSubmesh.Name.Info);
                    CopyUnknowns(baseSubmesh, newSubmesh, parser.MeshSection._FormatType);

                    if ((bonesMethod == CopyMeshMethod.CopyOrder) || (bonesMethod == CopyMeshMethod.CopyNear))
                    {
                        odfBoneList baseBones = odf.FindBoneList(baseSubmesh.Id, parser.EnvelopeSection);
                        if (baseBones != null)
                        {
                            newBones           = baseBones.Clone();
                            newBones.Id        = ObjectID.INVALID;                     // parser.GetNewID(typeof(odfBoneList));
                            newBones.SubmeshId = newSubmesh.Id;
                            newBonesIdx        = parser.EnvelopeSection.IndexOf(baseBones);
                        }
                    }
                    else if (bonesMethod == CopyMeshMethod.Replace)
                    {
                        newBones    = CreateBoneList(ObjectID.INVALID /*parser.GetNewID(typeof(odfBoneList))*/, frame.Id, newSubmesh, mesh.BoneList, transform, parser.FrameSection.RootFrame);
                        newBonesIdx = parser.EnvelopeSection.Count;
                    }
                }
                else
                {
                    CreateUnknowns(newSubmesh, parser.MeshSection._FormatType);

                    newBones    = CreateBoneList(ObjectID.INVALID /*parser.GetNewID(typeof(odfBoneList))*/, frame.Id, newSubmesh, mesh.BoneList, transform, parser.FrameSection.RootFrame);
                    newBonesIdx = parser.EnvelopeSection.Count;
                }
                if (newBones != null)
                {
                    parser.EnvelopeSection.InsertChild(newBonesIdx, newBones);
                }

                if (baseSubmesh != null)
                {
                    if (normalsMethod == CopyMeshMethod.CopyOrder)
                    {
                        odf.CopyNormalsOrder(baseSubmesh.VertexList, newSubmesh.VertexList);
                    }
                    else if (normalsMethod == CopyMeshMethod.CopyNear)
                    {
                        odf.CopyNormalsNear(baseSubmesh.VertexList, newSubmesh.VertexList);
                    }

                    if (bonesMethod == CopyMeshMethod.CopyOrder)
                    {
                        odf.CopyBonesOrder(baseSubmesh.VertexList, newSubmesh.VertexList, newBones);
                    }
                    else if (bonesMethod == CopyMeshMethod.CopyNear)
                    {
                        odf.CopyBonesNear(baseSubmesh.VertexList, newSubmesh.VertexList, newBones);
                    }
                }

                if ((baseSubmesh != null) && merge && replaceSubmeshesOption[i])
                {
                    replaceSubmeshes[idx] = newSubmesh;
                }
                else
                {
                    addSubmeshes.Add(newSubmesh);
                }
            }

            if ((frameMesh != null) && merge)
            {
                newMesh.Clear();
                newMesh.Capacity = replaceSubmeshes.Length + addSubmeshes.Count;
                for (int i = 0, submeshesRemoved = 0; i < replaceSubmeshes.Length; i++)
                {
                    if (replaceSubmeshes[i] == null)
                    {
                        odfSubmesh newSubmesh = frameMesh[i - submeshesRemoved++];
                        frameMesh.RemoveChild(newSubmesh);                         // save the bone list from being deleted in RemoveMesh
                        newMesh.AddChild(newSubmesh);
                    }
                    else
                    {
                        newMesh.AddChild(replaceSubmeshes[i]);
                    }
                }
                newMesh.AddRange(addSubmeshes);
            }

            if (frameMesh != null)
            {
                RemoveMesh(parser, frameMesh, frame, false);
                parser.UsedIDs.Add((int)newMesh.Id, typeof(odfMesh));
                frame.MeshId = newMesh.Id;
                List <ObjectID> removeKeyList = new List <ObjectID>();
                foreach (odfSubmesh submesh in newMesh)
                {
                    ObjectID newSubmeshID = submesh.Id;
                    ObjectID baseSubmeshID;
                    if (submeshIDtranslation.TryGetValue(newSubmeshID, out baseSubmeshID))
                    {
                        if (odf.FindBoneList(baseSubmeshID, parser.EnvelopeSection) == null)
                        {
                            odfBoneList boneList = odf.FindBoneList(newSubmeshID, parser.EnvelopeSection);
                            if (boneList != null)
                            {
                                boneList.SubmeshId = baseSubmeshID;
                            }
                            submesh.Id = baseSubmeshID;
                            parser.UsedIDs.Remove((int)newSubmeshID);
                        }

                        foreach (KeyValuePair <ObjectID, ObjectID> pair in submeshIDtranslation)
                        {
                            if (pair.Value == baseSubmeshID)
                            {
                                removeKeyList.Add(pair.Key);
                            }
                        }
                        foreach (ObjectID removeId in removeKeyList)
                        {
                            submeshIDtranslation.Remove(removeId);
                        }
                        removeKeyList.Clear();
                    }
                }
            }
        }
コード例 #18
0
        private void CollectObjectIDs(IObjInfo obj)
        {
            ObjectID id = null;

            if (obj is odfMaterial)
            {
                id = ((odfMaterial)obj).Id;
            }
            else if (obj is odfTexture)
            {
                id = ((odfTexture)obj).Id;
            }
            else if (obj is odfMesh)
            {
                odfMesh mesh = (odfMesh)obj;
                for (int i = 0; i < mesh.Count; i++)
                {
                    odfSubmesh submesh = mesh[i];
                    CollectObjectIDs(submesh);
                }
                id = ((odfMesh)obj).Id;
            }
            else if (obj is odfSubmesh)
            {
                id = ((odfSubmesh)obj).Id;
            }
            else if (obj is odfFrame)
            {
                odfFrame frame = (odfFrame)obj;
                for (int i = 0; i < frame.Count; i++)
                {
                    odfFrame childFrame = frame[i];
                    CollectObjectIDs(childFrame);
                }
                id = frame.Id;
            }
            else if (obj is odfMaterialSection)
            {
                odfMaterialSection matSec = (odfMaterialSection)obj;
                foreach (odfMaterial mat in matSec)
                {
                    CollectObjectIDs(mat);
                }
            }
            else if (obj is odfTextureSection)
            {
                odfTextureSection texSec = (odfTextureSection)obj;
                foreach (odfTexture tex in texSec)
                {
                    CollectObjectIDs(tex);
                }
            }
            else if (obj is odfMeshSection)
            {
                odfMeshSection meshSec = (odfMeshSection)obj;
                foreach (odfMesh mesh in meshSec)
                {
                    CollectObjectIDs(mesh);
                }
            }
            else if (obj is odfFrameSection)
            {
                odfFrameSection frameSec = (odfFrameSection)obj;
                foreach (odfFrame frame in frameSec)
                {
                    CollectObjectIDs(frame);
                }
            }
            else if (obj is odfEnvelopeSection)
            {
                odfEnvelopeSection envSec = (odfEnvelopeSection)obj;
                foreach (odfBoneList boneList in envSec.ChildList)
                {
                    CollectObjectIDs(boneList);
                }
                id = envSec.Id;
            }
            else if (obj is odfBoneList)
            {
                odfBoneList boneList = (odfBoneList)obj;
                foreach (odfBone bone in boneList)
                {
                    CollectObjectIDs(bone);
                }
                id = boneList.Id;
            }
            else if (obj is odfMorphSection)
            {
                id = ((odfMorphSection)obj).Id;
            }
            else if (obj is odfTXPTSection)
            {
                id = ((odfTXPTSection)obj).Id;
            }
            else if (obj is odfMATASection)
            {
                id = ((odfMATASection)obj).Id;
            }
            else if (obj is odfANIMSection)
            {
                id = ((odfANIMSection)obj).Id;
            }
            else if (obj is odfBANMSection)
            {
                id = ((odfBANMSection)obj).Id;
            }

            if (id != null)
            {
                int idVal = (int)id;
                if (idVal != 0)
                {
                    try
                    {
                        this.UsedIDs.Add(idVal, obj.GetType());
                    }
                    catch (ArgumentException argEx)
                    {
                        Type typeInDic;
                        this.UsedIDs.TryGetValue(idVal, out typeInDic);
                        Report.ReportLog(obj.GetType() + " ID: " + id + " - " + argEx.Message + " - " + typeInDic);
                    }
                    catch (Exception ex)
                    {
                        Report.ReportLog(obj.GetType() + " ID: " + id + " - " + ex.Message);
                    }
                }
                else if (!(obj is odfBoneList))
                {
                    Report.ReportLog("Invalid ID used by " + obj.GetType().Name);
                }
            }
        }
コード例 #19
0
ファイル: odfOps.cs プロジェクト: kkdevs/sb3u
 public static void CopyBonesOrder(List <odfVertex> src, List <odfVertex> dest, odfBoneList destBones)
 {
     if (src.Count > dest.Count)
     {
         int invalidIndex = dest.Count;
         foreach (odfBone bone in destBones)
         {
             List <int>   idxList    = new List <int>(bone.NumberIndices);
             List <float> weightList = new List <float>(bone.NumberIndices);
             for (int i = 0; i < bone.NumberIndices; i++)
             {
                 if (bone.VertexIndexArray[i] < invalidIndex)
                 {
                     idxList.Add(bone.VertexIndexArray[i]);
                     weightList.Add(bone.WeightArray[i]);
                 }
             }
             if (idxList.Count != bone.NumberIndices)
             {
                 int oldLength = bone.VertexIndexArray.Length;
                 bone.VertexIndexArray = idxList.ToArray();
                 bone.WeightArray      = weightList.ToArray();
                 if (bone.VertexIndexArray.Length != oldLength)
                 {
                     bone.AlwaysZero24perIndex = new byte[24 * bone.VertexIndexArray.Length];
                 }
             }
         }
     }
 }
コード例 #20
0
ファイル: odfOps.cs プロジェクト: kkdevs/sb3u
        public static void CopyBonesNear(List <odfVertex> src, List <odfVertex> dest, odfBoneList destBones)
        {
            Dictionary <odfBone, Tuple <List <int>, List <float> > > boneTranslation = new Dictionary <odfBone, Tuple <List <int>, List <float> > >(destBones.Count);

            for (int i = 0; i < dest.Count; i++)
            {
                var   destVert       = dest[i];
                var   destPos        = destVert.Position;
                float minDistSq      = Single.MaxValue;
                int   nearestVertIdx = -1;
                for (int j = 0; j < src.Count; j++)
                {
                    odfVertex srcVert = src[j];
                    var       srcPos  = srcVert.Position;
                    float[]   diff    = new float[] { destPos[0] - srcPos[0], destPos[1] - srcPos[1], destPos[2] - srcPos[2] };
                    float     distSq  = (diff[0] * diff[0]) + (diff[1] * diff[1]) + (diff[2] * diff[2]);
                    if (distSq < minDistSq)
                    {
                        minDistSq      = distSq;
                        nearestVertIdx = j;
                    }
                }

                int numInfluences = 0;
                foreach (odfBone srcBone in destBones)
                {
                    for (int k = 0; k < srcBone.NumberIndices; k++)
                    {
                        if (srcBone.VertexIndexArray[k] == nearestVertIdx)
                        {
                            List <int>   idxList;
                            List <float> weightList;
                            Tuple <List <int>, List <float> > destLists;
                            if (!boneTranslation.TryGetValue(srcBone, out destLists))
                            {
                                idxList    = new List <int>();
                                weightList = new List <float>();
                                destLists  = new Tuple <List <int>, List <float> >(idxList, weightList);
                                boneTranslation.Add(srcBone, destLists);
                            }
                            else
                            {
                                idxList    = destLists.Item1;
                                weightList = destLists.Item2;
                            }
                            idxList.Add(i);
                            weightList.Add(srcBone.WeightArray[k]);
                            numInfluences++;
                            break;
                        }
                    }
                    if (numInfluences == 4)
                    {
                        break;
                    }
                }
            }
            foreach (var boneListPair in boneTranslation)
            {
                odfBone srcBone   = boneListPair.Key;
                int     oldLength = srcBone.VertexIndexArray.Length;
                Tuple <List <int>, List <float> > destLists = boneListPair.Value;
                srcBone.VertexIndexArray = destLists.Item1.ToArray();
                srcBone.WeightArray      = destLists.Item2.ToArray();
                if (srcBone.VertexIndexArray.Length != oldLength)
                {
                    srcBone.AlwaysZero24perIndex = new byte[24 * srcBone.VertexIndexArray.Length];
                }
            }
        }
コード例 #21
0
ファイル: Fbx.cs プロジェクト: 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];
                            }
                        }
                    }
                }
            }