示例#1
0
        private void DrawAnimationMeshContainer(AnimationMeshContainer meshContainer)
        {
            device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
            device.SetRenderState(RenderState.Lighting, true);

            Cull culling = (Gui.Renderer.Culling) ? Cull.Counterclockwise : Cull.None;

            device.SetRenderState(RenderState.CullMode, culling);

            FillMode fill = (Gui.Renderer.Wireframe) ? FillMode.Wireframe : FillMode.Solid;

            device.SetRenderState(RenderState.FillMode, fill);

            int matIdx = meshContainer.MaterialIndex;

            device.Material = ((matIdx >= 0) && (matIdx < Materials.Length)) ? Materials[matIdx] : nullMaterial;

            int     texIdx = meshContainer.TextureIndex;
            Texture tex    = ((texIdx >= 0) && (texIdx < Textures.Length)) ? Textures[texIdx] : null;

            device.SetTexture(0, tex);

            meshContainer.MeshData.Mesh.DrawSubset(0);

            if (HighlightSubmesh.Contains(submeshNum))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                device.Material = highlightMaterial;
                device.SetTexture(0, null);
                meshContainer.MeshData.Mesh.DrawSubset(0);
            }

            if (Gui.Renderer.ShowNormals)
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightsIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.NormalLines.Length / 2, meshContainer.NormalLines);
            }

            if (Gui.Renderer.ShowBones && (meshContainer.BoneLines != null))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.VertexBlend, VertexBlend.Weights1);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.BoneLines.Length / 2, meshContainer.BoneLines);
            }
        }
示例#2
0
        private void DrawMeshFrame(AnimationFrame frame)
        {
            if (frame.MeshContainer is AnimationMeshContainer)
            {
                AnimationMeshContainer animMeshContainer = (AnimationMeshContainer)frame.MeshContainer;
                if (animMeshContainer.BoneNames.Length > 0)
                {
                    device.SetRenderState(RenderState.VertexBlend, VertexBlend.Weights3);
                    device.SetRenderState(RenderState.IndexedVertexBlendEnable, true);
                    // uncomment to emphazise bone weights and darken everything else
                    // device.SetRenderState(RenderState.DiffuseMaterialSource, ColorSource.Color1);
                    device.SetRenderState(RenderState.AmbientMaterialSource, ColorSource.Color1);

                    for (int i = 0; i < animMeshContainer.BoneNames.Length; i++)
                    {
                        if (animMeshContainer.BoneFrames[i] != null)
                        {
                            device.SetTransform(i, animMeshContainer.BoneOffsets[i] * animMeshContainer.BoneFrames[i].CombinedTransform);
                        }
                    }
                }
                else
                {
                    device.SetRenderState(RenderState.VertexBlend, VertexBlend.Disable);
                    device.SetRenderState(RenderState.AmbientMaterialSource, ColorSource.Material);
                    device.SetTransform(TransformState.World, frame.CombinedTransform);
                }

                submeshNum = 0;
                while (animMeshContainer != null)
                {
                    DrawAnimationMeshContainer(animMeshContainer);
                    animMeshContainer = (AnimationMeshContainer)animMeshContainer.NextMeshContainer;
                    submeshNum++;
                }
            }
            else if (frame.MeshContainer is MorphMeshContainer)
            {
                MorphMeshContainer morphMeshContainer = (MorphMeshContainer)frame.MeshContainer;
                device.SetRenderState(RenderState.AmbientMaterialSource, ColorSource.Material);
                device.SetTransform(TransformState.World, frame.CombinedTransform);

                submeshNum = 0;
                DrawMorphMeshContainer(morphMeshContainer);
            }
        }
示例#3
0
        public void HighlightBone(xxMesh xxMesh, int boneIdx, bool show)
        {
            int submeshIdx = 0;

            for (AnimationMeshContainer mesh = (AnimationMeshContainer)meshFrames[0].MeshContainer;
                 mesh != null;
                 mesh = (AnimationMeshContainer)mesh.NextMeshContainer, submeshIdx++)
            {
                if (mesh.MeshData != null && mesh.MeshData.Mesh != null)
                {
                    List <xxVertex> vertexList = xxMesh.SubmeshList[submeshIdx].VertexList;
                    FillVertexBuffer(mesh.MeshData.Mesh, vertexList, show ? boneIdx : -1);
                }
                if (mesh.BoneLines != null)
                {
                    for (int j = 0; j < BoneObjSize; j++)
                    {
                        mesh.BoneLines[boneIdx * BoneObjSize + j].Color = show ? Color.Crimson.ToArgb(): Color.CornflowerBlue.ToArgb();
                    }
                }
            }
        }
        private void DrawAnimationMeshContainer(AnimationMeshContainer meshContainer)
        {
            device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
            device.SetRenderState(RenderState.Lighting, true);

            Cull culling = (Gui.Renderer.Culling) ? Cull.Counterclockwise : Cull.None;
            device.SetRenderState(RenderState.CullMode, culling);

            FillMode fill = (Gui.Renderer.Wireframe) ? FillMode.Wireframe : FillMode.Solid;
            device.SetRenderState(RenderState.FillMode, fill);

            int matIdx = meshContainer.MaterialIndex;
            device.Material = ((matIdx >= 0) && (matIdx < Materials.Length)) ? Materials[matIdx] : nullMaterial;

            int texIdx = meshContainer.TextureIndex;
            Texture tex = ((texIdx >= 0) && (texIdx < Textures.Length)) ? Textures[texIdx] : null;
            device.SetTexture(0, tex);

            meshContainer.MeshData.Mesh.DrawSubset(0);

            if (HighlightSubmesh.Contains(submeshNum))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                device.Material = highlightMaterial;
                device.SetTexture(0, null);
                meshContainer.MeshData.Mesh.DrawSubset(0);
            }

            if (Gui.Renderer.ShowNormals)
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightsIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.NormalLines.Length / 2, meshContainer.NormalLines);
            }

            if (Gui.Renderer.ShowBones && (meshContainer.BoneLines != null))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.VertexBlend, VertexBlend.Weights1);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.BoneLines.Length / 2, meshContainer.BoneLines);
            }
        }
        private AnimationFrame CreateFrame(xxFrame frame, xxParser parser, HashSet<string> extractFrames, HashSet<string> meshNames, 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;

            xxMesh mesh = frame.Mesh;
            if (meshNames.Contains(frame.Name) && (mesh != null))
            {
                List<xxBone> boneList = mesh.BoneList;

                string[] boneNames = new string[boneList.Count];
                Matrix[] boneOffsets = new Matrix[boneList.Count];
                for (int i = 0; i < boneList.Count; i++)
                {
                    xxBone bone = boneList[i];
                    boneNames[i] = bone.Name;
                    boneOffsets[i] = bone.Matrix;
                }

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

                    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[2]);
                            indexStream.Write(indices[1]);
                        }
                        animationMesh.UnlockIndexBuffer();
                    }

                    FillVertexBuffer(animationMesh, vertexList, -1);

                    var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2];
                    for (int j = 0; j < vertexList.Count; j++)
                    {
                        xxVertex vertex = vertexList[j];

                        normalLines[j * 2] = new PositionBlendWeightsIndexedColored(vertex.Position, vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb());
                        normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.Position + (vertex.Normal / 16), vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb());

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

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

                    int matIdx = submesh.MaterialIndex;
                    if ((matIdx >= 0) && (matIdx < parser.MaterialList.Count))
                    {
                        int texIdx;
                        if (!MatTexIndices.TryGetValue(matIdx, out texIdx))
                        {
                            texIdx = -1;

                            xxMaterial mat = parser.MaterialList[matIdx];
                            Material materialD3D = new Material();
                            materialD3D.Ambient = mat.Ambient;
                            materialD3D.Diffuse = mat.Diffuse;
                            materialD3D.Emissive = mat.Emissive;
                            materialD3D.Specular = mat.Specular;
                            materialD3D.Power = mat.Power;
                            Materials[matIdx] = materialD3D;

                            xxMaterialTexture matTex = mat.Textures[0];
                            string matTexName = matTex.Name;
                            if (matTexName != String.Empty)
                            {
                                for (int j = 0; j < parser.TextureList.Count; j++)
                                {
                                    xxTexture tex = parser.TextureList[j];
                                    if (tex.Name == matTexName)
                                    {
                                        texIdx = j;
                                        if (Textures[j] == null)
                                        {
                                            ImportedTexture importedTex = xx.ImportedTexture(tex);
                                            Textures[j] = Texture.FromMemory(device, importedTex.Data);
                                        }
                                        break;
                                    }
                                }
                            }

                            MatTexIndices.Add(matIdx, texIdx);
                        }

                        meshContainer.MaterialIndex = matIdx;
                        meshContainer.TextureIndex = texIdx;
                    }
                }

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

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

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

            numFrames++;
            return animationFrame;
        }
示例#6
0
        public float SetMorphKeyframe(xxFrame meshFrame, xaMorphIndexSet idxSet, xaMorphKeyframe keyframe, bool asStart)
        {
            foreach (AnimationFrame frame in meshFrames)
            {
                if (frame.Name == meshFrame.Name)
                {
                    xxMesh xxMesh     = meshFrame.Mesh;
                    int    meshObjIdx = xa.MorphMeshObjIdx(idxSet.MeshIndices, xxMesh);
                    if (meshObjIdx < 0)
                    {
                        Report.ReportLog("no valid mesh object was found for the morph");
                        return(-1f);
                    }
                    MorphMeshContainer     morphMesh = null;
                    AnimationMeshContainer animMesh  = frame.MeshContainer as AnimationMeshContainer;
                    if (animMesh != null)
                    {
                        for (int i = 1; i < meshObjIdx; i++)
                        {
                            animMesh = (AnimationMeshContainer)animMesh.NextMeshContainer;
                            if (animMesh == null)
                            {
                                break;
                            }
                        }
                        if (animMesh == null)
                        {
                            Report.ReportLog("Bad submesh specified.");
                            return(-1f);
                        }

                        morphMesh             = new MorphMeshContainer();
                        morphMesh.FaceCount   = xxMesh.SubmeshList[meshObjIdx].FaceList.Count;
                        morphMesh.IndexBuffer = animMesh.MeshData.Mesh.IndexBuffer;

                        morphMesh.VertexCount = xxMesh.SubmeshList[meshObjIdx].VertexList.Count;
                        List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList;
                        VertexBuffer    vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList);
                        morphMesh.StartBuffer = morphMesh.EndBuffer = vertBuffer;

                        int vertBufferSize = morphMesh.VertexCount * Marshal.SizeOf(typeof(TweeningMeshesVertexBufferFormat.Stream2));
                        vertBuffer = new VertexBuffer(device, vertBufferSize, Usage.WriteOnly, VertexFormat.Texture1, Pool.Managed);
                        using (DataStream vertexStream = vertBuffer.Lock(0, vertBufferSize, LockFlags.None))
                        {
                            for (int i = 0; i < vertexList.Count; i++)
                            {
                                xxVertex vertex = vertexList[i];
                                vertexStream.Write(vertex.UV[0]);
                                vertexStream.Write(vertex.UV[1]);
                            }
                            vertBuffer.Unlock();
                        }
                        morphMesh.CommonBuffer = vertBuffer;

                        morphMesh.MaterialIndex = animMesh.MaterialIndex;
                        morphMesh.TextureIndex  = animMesh.TextureIndex;

                        morphMesh.NextMeshContainer = animMesh;
                        frame.MeshContainer         = morphMesh;

                        morphMesh.TweenFactor = 0.0f;
                    }
                    else
                    {
                        morphMesh = frame.MeshContainer as MorphMeshContainer;
                        List <xxVertex> vertexList = xxMesh.SubmeshList[meshObjIdx].VertexList;
                        VertexBuffer    vertBuffer = CreateMorphVertexBuffer(idxSet, keyframe, vertexList);
                        if (asStart)
                        {
                            if (morphMesh.StartBuffer != morphMesh.EndBuffer)
                            {
                                morphMesh.StartBuffer.Dispose();
                            }
                            morphMesh.StartBuffer = vertBuffer;
                            morphMesh.TweenFactor = 0.0f;
                        }
                        else
                        {
                            if (morphMesh.StartBuffer != morphMesh.EndBuffer)
                            {
                                morphMesh.EndBuffer.Dispose();
                            }
                            morphMesh.EndBuffer   = vertBuffer;
                            morphMesh.TweenFactor = 1.0f;
                        }
                    }
                    return(morphMesh.TweenFactor);
                }
            }
            Report.ReportLog("Mesh frame " + meshFrame + " not displayed.");
            return(-1f);
        }
示例#7
0
        private void SetupBoneMatrices(AnimationFrame frame, AnimationFrame root)
        {
            AnimationMeshContainer mesh = (AnimationMeshContainer)frame.MeshContainer;

            if (mesh != null)
            {
                byte             numBones   = (byte)mesh.BoneNames.Length;
                AnimationFrame[] boneFrames = null;
                PositionBlendWeightIndexedColored[] boneLines = null;
                if (numBones > 0)
                {
                    boneFrames = new AnimationFrame[numBones];
                    var boneDic = new Dictionary <string, byte>();
                    for (byte i = 0; i < numBones; i++)
                    {
                        string         boneName = mesh.BoneNames[i];
                        AnimationFrame bone     = (AnimationFrame)root.FindChild(boneName);
                        boneFrames[i] = bone;

                        boneDic.Add(boneName, i);
                    }

                    float boneWidth = 0.05f;
                    int   boneColor = Color.CornflowerBlue.ToArgb();
                    boneLines = new PositionBlendWeightIndexedColored[numBones * BoneObjSize];
                    for (byte i = 0; i < numBones; i++)
                    {
                        AnimationFrame bone = boneFrames[i];

                        byte boneParentId;
                        if ((bone != null) && (bone.Parent != null) && boneDic.TryGetValue(bone.Parent.Name, out boneParentId))
                        {
                            Matrix boneMatrix       = Matrix.Invert(mesh.BoneOffsets[i]);
                            Matrix boneParentMatrix = Matrix.Invert(mesh.BoneOffsets[boneParentId]);

                            Vector3 bonePos       = Vector3.TransformCoordinate(new Vector3(), boneMatrix);
                            Vector3 boneParentPos = Vector3.TransformCoordinate(new Vector3(), boneParentMatrix);

                            Vector3 direction     = bonePos - boneParentPos;
                            float   scale         = boneWidth * (1 + direction.Length() / 2);
                            Vector3 perpendicular = direction.Perpendicular();
                            Vector3 cross         = Vector3.Cross(direction, perpendicular);
                            perpendicular = Vector3.Normalize(perpendicular) * scale;
                            cross         = Vector3.Normalize(cross) * scale;

                            Vector3 bottomLeft  = -perpendicular + -cross + boneParentPos;
                            Vector3 bottomRight = -perpendicular + cross + boneParentPos;
                            Vector3 topLeft     = perpendicular + -cross + boneParentPos;
                            Vector3 topRight    = perpendicular + cross + boneParentPos;

                            boneLines[i * BoneObjSize]       = new PositionBlendWeightIndexedColored(bottomLeft, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 1] = new PositionBlendWeightIndexedColored(bottomRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 2] = new PositionBlendWeightIndexedColored(bottomRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 3] = new PositionBlendWeightIndexedColored(topRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 4] = new PositionBlendWeightIndexedColored(topRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 5] = new PositionBlendWeightIndexedColored(topLeft, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 6] = new PositionBlendWeightIndexedColored(topLeft, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 7] = new PositionBlendWeightIndexedColored(bottomLeft, boneParentId, boneColor);

                            boneLines[(i * BoneObjSize) + 8]  = new PositionBlendWeightIndexedColored(bottomLeft, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 9]  = new PositionBlendWeightIndexedColored(bonePos, i, boneColor);
                            boneLines[(i * BoneObjSize) + 10] = new PositionBlendWeightIndexedColored(bottomRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 11] = new PositionBlendWeightIndexedColored(bonePos, i, boneColor);
                            boneLines[(i * BoneObjSize) + 12] = new PositionBlendWeightIndexedColored(topLeft, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 13] = new PositionBlendWeightIndexedColored(bonePos, i, boneColor);
                            boneLines[(i * BoneObjSize) + 14] = new PositionBlendWeightIndexedColored(topRight, boneParentId, boneColor);
                            boneLines[(i * BoneObjSize) + 15] = new PositionBlendWeightIndexedColored(bonePos, i, boneColor);
                        }
                    }
                }

                while (mesh != null)
                {
                    if (mesh.NextMeshContainer == null)
                    {
                        mesh.BoneLines = boneLines;
                    }

                    mesh.BoneFrames = boneFrames;
                    mesh            = (AnimationMeshContainer)mesh.NextMeshContainer;
                }
            }

            if (frame.Sibling != null)
            {
                SetupBoneMatrices(frame.Sibling as AnimationFrame, root);
            }

            if (frame.FirstChild != null)
            {
                SetupBoneMatrices(frame.FirstChild as AnimationFrame, root);
            }
        }
示例#8
0
        private AnimationFrame CreateFrame(xxFrame frame, xxParser parser, HashSet <string> extractFrames, HashSet <string> meshNames, 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;

            xxMesh mesh = frame.Mesh;

            if (meshNames.Contains(frame.Name) && (mesh != null))
            {
                List <xxBone> boneList = mesh.BoneList;

                string[] boneNames   = new string[boneList.Count];
                Matrix[] boneOffsets = new Matrix[boneList.Count];
                for (int i = 0; i < boneList.Count; i++)
                {
                    xxBone bone = boneList[i];
                    boneNames[i]   = bone.Name;
                    boneOffsets[i] = bone.Matrix;
                }

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

                    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[2]);
                            indexStream.Write(indices[1]);
                        }
                        animationMesh.UnlockIndexBuffer();
                    }

                    FillVertexBuffer(animationMesh, vertexList, -1);

                    var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2];
                    for (int j = 0; j < vertexList.Count; j++)
                    {
                        xxVertex vertex = vertexList[j];

                        normalLines[j * 2]       = new PositionBlendWeightsIndexedColored(vertex.Position, vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb());
                        normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.Position + (vertex.Normal / 16), vertex.Weights3, vertex.BoneIndices, Color.Yellow.ToArgb());

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

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

                    int matIdx = submesh.MaterialIndex;
                    if ((matIdx >= 0) && (matIdx < parser.MaterialList.Count))
                    {
                        int texIdx;
                        if (!MatTexIndices.TryGetValue(matIdx, out texIdx))
                        {
                            texIdx = -1;

                            xxMaterial mat         = parser.MaterialList[matIdx];
                            Material   materialD3D = new Material();
                            materialD3D.Ambient  = mat.Ambient;
                            materialD3D.Diffuse  = mat.Diffuse;
                            materialD3D.Emissive = mat.Emissive;
                            materialD3D.Specular = mat.Specular;
                            materialD3D.Power    = mat.Power;
                            Materials[matIdx]    = materialD3D;

                            xxMaterialTexture matTex     = mat.Textures[0];
                            string            matTexName = matTex.Name;
                            if (matTexName != String.Empty)
                            {
                                for (int j = 0; j < parser.TextureList.Count; j++)
                                {
                                    xxTexture tex = parser.TextureList[j];
                                    if (tex.Name == matTexName)
                                    {
                                        texIdx = j;
                                        if (Textures[j] == null)
                                        {
                                            ImportedTexture importedTex = xx.ImportedTexture(tex);
                                            Textures[j] = Texture.FromMemory(device, importedTex.Data);
                                        }
                                        break;
                                    }
                                }
                            }

                            MatTexIndices.Add(matIdx, texIdx);
                        }

                        meshContainer.MaterialIndex = matIdx;
                        meshContainer.TextureIndex  = texIdx;
                    }
                }

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

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

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

            numFrames++;
            return(animationFrame);
        }
示例#9
0
        private void DrawMeshContainer(AnimationMeshContainer meshContainer, AnimationFrame frame)
        {
            device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
            device.SetRenderState(RenderState.Lighting, true);

            #if !DONT_MIRROR
            Cull culling = (Gui.Renderer.Culling) ? Cull.Counterclockwise : Cull.None;
            #else
            Cull culling = (Gui.Renderer.Culling) ? Cull.Clockwise : Cull.None;
            #endif
            device.SetRenderState(RenderState.CullMode, culling);

            FillMode fill = (Gui.Renderer.Wireframe) ? FillMode.Wireframe : FillMode.Solid;
            device.SetRenderState(RenderState.FillMode, fill);

            if (meshContainer.BoneNames.Length > 0)
            {
                device.SetRenderState(RenderState.VertexBlend, VertexBlend.Weights3);
                device.SetRenderState(RenderState.IndexedVertexBlendEnable, true);
            //				device.SetRenderState(RenderState.ColorVertex, true);
                device.SetRenderState(RenderState.DiffuseMaterialSource, ColorSource.Material);
                device.SetRenderState(RenderState.AmbientMaterialSource, ColorSource.Material);
                switch (Gui.Renderer.ShowBoneWeights)
                {
                case ShowBoneWeights.Weak:
                    device.SetRenderState(RenderState.AmbientMaterialSource, ColorSource.Color1);
                    break;
                case ShowBoneWeights.Strong:
                    device.SetRenderState(RenderState.DiffuseMaterialSource, ColorSource.Color1);
                    break;
                case ShowBoneWeights.Off:
                    break;
                }

                for (int i = 0; i < meshContainer.BoneNames.Length; i++)
                {
                    if (meshContainer.BoneFrames[i] != null)
                    {
                        device.SetTransform(i, meshContainer.BoneOffsets[i] * meshContainer.BoneFrames[i].CombinedTransform);
                    }
                }
            }
            else
            {
                device.SetRenderState(RenderState.VertexBlend, VertexBlend.Disable);
            #if !DONT_MIRROR
                device.SetTransform(TransformState.World, Matrix.Scaling(1.0f, 1.0f, -1.0f) * frame.CombinedTransform);
            #else
                device.SetTransform(TransformState.World, frame.CombinedTransform);
            #endif
            }

            int matIdx = meshContainer.MaterialIndex;
            device.Material = ((matIdx >= 0) && (matIdx < Materials.Length)) ? Materials[matIdx] : nullMaterial;

            int texIdx = meshContainer.TextureIndex;
            Texture tex = ((texIdx >= 0) && (texIdx < Textures.Length)) ? Textures[texIdx] : null;
            device.SetTexture(0, tex);

            meshContainer.MeshData.Mesh.DrawSubset(0);

            if (HighlightSubmesh.Contains(submeshNum))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.FillMode, FillMode.Wireframe);
                device.Material = highlightMaterial;
                device.SetTexture(0, null);
                meshContainer.MeshData.Mesh.DrawSubset(0);
            }

            if (Gui.Renderer.ShowNormals)
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.UseZBuffer);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightsIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.NormalLines.Length / 2, meshContainer.NormalLines);
            }

            if (Gui.Renderer.ShowBones && (meshContainer.BoneLines != null))
            {
                device.SetRenderState(RenderState.ZEnable, ZBufferType.DontUseZBuffer);
                device.SetRenderState(RenderState.VertexBlend, VertexBlend.Weights1);
                device.SetRenderState(RenderState.IndexedVertexBlendEnable, true);
                device.SetRenderState(RenderState.Lighting, false);
                device.Material = nullMaterial;
                device.SetTexture(0, null);
                device.VertexFormat = PositionBlendWeightIndexedColored.Format;
                device.DrawUserPrimitives(PrimitiveType.LineList, meshContainer.BoneLines.Length / 2, meshContainer.BoneLines);
            }
        }
示例#10
0
        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;
        }
示例#11
0
        private AnimationFrame CreateFrame(Transform frame, AnimatorEditor editor, HashSet<string> extractFrames, HashSet<string> meshNames, Device device, List<AnimationFrame> meshFrames, Dictionary<string, Tuple<Matrix, Matrix>> extractMatrices)
        {
            AnimationFrame animationFrame = new AnimationFrame();
            animationFrame.Name = frame.GetTransformPath();
            animationFrame.TransformationMatrix = Matrix.Scaling(frame.m_LocalScale) * Matrix.RotationQuaternion(frame.m_LocalRotation) * Matrix.Translation(frame.m_LocalPosition);
            animationFrame.OriginalTransform = animationFrame.TransformationMatrix;
            animationFrame.CombinedTransform = extractMatrices[animationFrame.Name].Item1;

            if (meshNames.Contains(animationFrame.Name))
            {
                MeshRenderer meshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.SkinnedMeshRenderer);
                if (meshR == null)
                {
                    meshR = frame.m_GameObject.instance.FindLinkedComponent(UnityClassID.MeshRenderer);
                }
                if (meshR != null)
                {
                    Mesh mesh = Operations.GetMesh(meshR);
                    if (mesh != null)
                    {
                        SkinnedMeshRenderer smr = meshR as SkinnedMeshRenderer;
                        List<PPtr<Transform>> boneList = null;
                        string[] boneNames = null;
                        Matrix[] boneOffsets = null;
                        if (smr != null && smr.m_Bones.Count > 0)
                        {
                            boneList = smr.m_Bones;

                            int numBones = boneList.Count > 0 ? extractFrames.Count : 0;
                            boneNames = new string[numBones];
                            boneOffsets = new Matrix[numBones];
                            if (numBones > 0)
                            {
                                string[] extractArray = new string[numBones];
                                extractFrames.CopyTo(extractArray);
                                HashSet<string> extractCopy = new HashSet<string>(extractArray);
                                int invalidBones = 0;
                                for (int i = 0; i < boneList.Count; i++)
                                {
                                    Transform bone = boneList[i].instance;
                                    if (bone == null || bone.m_GameObject.instance == null || !extractCopy.Remove(bone.GetTransformPath()))
                                    {
                                        invalidBones++;
                                    }
                                    else if (i < numBones)
                                    {
                                        boneNames[i] = bone.GetTransformPath();
                                        boneOffsets[i] = Operations.Mirror(Matrix.Transpose(mesh.m_BindPose[i]));
                                    }
                                }
                                extractCopy.CopyTo(boneNames, boneList.Count - invalidBones);
                                for (int i = boneList.Count; i < extractFrames.Count; i++)
                                {
                                    boneOffsets[i] = extractMatrices[boneNames[i]].Item2;
                                }
                            }
                        }

                        AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[mesh.m_SubMeshes.Count];
                        Vector3 min = new Vector3(Single.MaxValue);
                        Vector3 max = new Vector3(Single.MinValue);
                        Operations.vMesh vMesh = new Operations.vMesh(meshR, true, true);
                        for (int i = 0; i < mesh.m_SubMeshes.Count; i++)
                        {
                            Operations.vSubmesh submesh = vMesh.submeshes[i];
                            List<Operations.vFace> faceList = submesh.faceList;
                            List<Operations.vVertex> vertexList = submesh.vertexList;

                            SlimDX.Direct3D9.Mesh animationMesh = null;
                            PositionBlendWeightsIndexedColored[] normalLines = null;
                            try
                            {
                                animationMesh = new SlimDX.Direct3D9.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].index;
                                        indexStream.Write(indices[0]);
                                        indexStream.Write(indices[2]);
                                        indexStream.Write(indices[1]);
                                    }
                                    animationMesh.UnlockIndexBuffer();
                                }

                                FillVertexBuffer(animationMesh, vertexList, -1);

                                normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2];
                                for (int j = 0; j < vertexList.Count; j++)
                                {
                                    Operations.vVertex vertex = vertexList[j];

                                    byte[] bIdx;
                                    float[] bWeights;
                                    if (vertex.boneIndices != null)
                                    {
                                        bIdx = new byte[4] { (byte)vertex.boneIndices[0], (byte)vertex.boneIndices[1], (byte)vertex.boneIndices[2], (byte)vertex.boneIndices[3] };
                                        bWeights = vertex.weights;
                                    }
                                    else
                                    {
                                        bIdx = new byte[4];
                                        bWeights = new float[4];
                                    }
                                    normalLines[j * 2] = new PositionBlendWeightsIndexedColored(vertex.position, bWeights, bIdx, Color.Yellow.ToArgb());
                                    normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(vertex.position + (vertex.normal / 64), bWeights, bIdx, Color.Yellow.ToArgb());

                                    min = Vector3.Minimize(min, vertex.position);
                                    max = Vector3.Maximize(max, vertex.position);
                                }
                            }
                            catch
                            {
                                Report.ReportLog("No display of submeshes with more than 64k vertices!");
                            }

                            AnimationMeshContainer meshContainer = new AnimationMeshContainer();
                            if (animationMesh != null)
                            {
                                meshContainer.Name = animationFrame.Name;
                                meshContainer.MeshData = new MeshData(animationMesh);
                                meshContainer.NormalLines = normalLines;
                            }
                            meshContainers[i] = meshContainer;

                            if (submesh.matList.Count > 0 && submesh.matList[0].instance != null)
                            {
                                Material mat = submesh.matList[0].instance;
                                int matIdx = editor.Materials.IndexOf(mat);
                                int texIdx;
                                if (!MatTexIndices.TryGetValue(matIdx, out texIdx))
                                {
                                    texIdx = -1;

                                    SlimDX.Direct3D9.Material materialD3D = new SlimDX.Direct3D9.Material();
                                    materialD3D.Ambient = GetColour(mat, "_SColor");
                                    materialD3D.Diffuse = GetColour(mat, "_Color");
                                    materialD3D.Emissive = GetColour(mat, "_ReflectColor");
                                    materialD3D.Specular = GetColour(mat, "_SpecColor");
                                    materialD3D.Power = GetFloat(mat, "_Shininess");
                                    Materials[matIdx] = materialD3D;

                                    Texture2D matTex = GetTexture(mat, "_MainTex");
                                    if (matTex != null)
                                    {
                                        texIdx = editor.Textures.IndexOf(matTex);
                                        if (Textures[texIdx] == null)
                                        {
                                            using (MemoryStream mem = new MemoryStream())
                                            {
                                                matTex.Export(mem);
                                                mem.Position = 0;
                                                ImportedTexture image = new ImportedTexture(mem, matTex.m_Name);
                                                Textures[texIdx] = Texture.FromMemory(device, image.Data);
                                            }
                                        }
                                    }

                                    MatTexIndices.Add(matIdx, texIdx);
                                }

                                meshContainer.MaterialIndex = matIdx;
                                meshContainer.TextureIndex = texIdx;
                            }
                        }

                        for (int i = 0; i < (meshContainers.Length - 1); i++)
                        {
                            meshContainers[i].NextMeshContainer = meshContainers[i + 1];
                        }
                        if (boneList != null)
                        {
                            for (int i = 0; i < meshContainers.Length; i++)
                            {
                                meshContainers[i].BoneNames = boneNames;
                                meshContainers[i].BoneOffsets = boneOffsets;
                                meshContainers[i].RealBones = boneList.Count;
                            }
                        }

                        Matrix mirrorCombined = Operations.Mirror(animationFrame.CombinedTransform);
                        min = Vector3.TransformCoordinate(min, mirrorCombined);
                        max = Vector3.TransformCoordinate(max, mirrorCombined);
                        animationFrame.Bounds = new BoundingBox(min, max);
                        animationFrame.MeshContainer = meshContainers[0];
                        meshFrames.Add(animationFrame);
                    }
                }
            }

            for (int i = 0; i < frame.Count; i++)
            {
                Transform child = frame[i];
                if (extractFrames.Contains(child.GetTransformPath()))
                {
                    AnimationFrame childAnimationFrame = CreateFrame(child, editor, extractFrames, meshNames, device, meshFrames, extractMatrices);
                    childAnimationFrame.Parent = animationFrame;
                    animationFrame.AppendChild(childAnimationFrame);
                }
            }

            numFrames++;
            return animationFrame;
        }
示例#12
0
        private AnimationFrame CreateFrame(remBone frame, remParser parser, HashSet<string> extractFrames, remMesh mesh, Device device, Matrix combinedParent, List<AnimationFrame> meshFrames)
        {
            AnimationFrame animationFrame = new AnimationFrame();
            animationFrame.Name = frame.name.ToString();
            animationFrame.TransformationMatrix = frame.matrix;
            animationFrame.OriginalTransform = animationFrame.TransformationMatrix;
            animationFrame.CombinedTransform = combinedParent * animationFrame.TransformationMatrix;

            if (frame.name == mesh.frame)
            {
                ExtendedMaterial[] materials = new ExtendedMaterial[mesh.numMats];

                List<List<remVertex>> submeshVertLists = new List<List<remVertex>>(mesh.numMats);
                List<List<ushort>> submeshFaceLists = new List<List<ushort>>(mesh.numMats);
                List<int[]> submeshVertIndices = new List<int[]>(mesh.numMats);
                SplitMesh(mesh, submeshVertLists, submeshFaceLists, submeshVertIndices);

                remSkin boneList = rem.FindSkin(mesh.name, parser.SKIC);
                bool skinned = boneList != null;
                int numBones = skinned ? boneList.Count : 0;
                List<string> boneNamesList = new List<string>(numBones);
                List<Matrix> boneOffsetsList = new List<Matrix>(numBones);
                for (int boneIdx = 0; boneIdx < numBones; boneIdx++)
                {
                    boneNamesList.Add(boneList[boneIdx].bone.ToString());
                    boneOffsetsList.Add(boneList[boneIdx].matrix);
                }
                List<string> boneFrameParentNames = new List<string>(numBones);
                List<Matrix> boneFrameParentMatrices = new List<Matrix>(numBones);
                for (int boneIdx = 0; boneIdx < numBones; boneIdx++)
                {
                    remBone boneFrame = rem.FindFrame(boneList[boneIdx].bone, parser.BONC.rootFrame);
                    if (boneFrame == null)
                    {
                        continue;
                    }
                    remBone boneFrameParent = boneFrame.Parent;
                    if (!boneNamesList.Contains(boneFrameParent.name) && !boneFrameParentNames.Contains(boneFrameParent.name))
                    {
                        boneFrameParentNames.Add(boneFrameParent.name);
                        Matrix incompleteMeshFrameCorrection = Matrix.Invert(frame.matrix);
                        boneFrameParentMatrices.Add(incompleteMeshFrameCorrection * Matrix.Invert(boneFrame.matrix) * boneList[boneIdx].matrix);
                    }
                }
                boneNamesList.AddRange(boneFrameParentNames);
                string[] boneNames = boneNamesList.ToArray();
                boneOffsetsList.AddRange(boneFrameParentMatrices);
                Matrix[] boneOffsets = boneOffsetsList.ToArray();

                AnimationMeshContainer[] meshContainers = new AnimationMeshContainer[submeshFaceLists.Count];
                Vector3 min = new Vector3(Single.MaxValue);
                Vector3 max = new Vector3(Single.MinValue);
                for (int i = 0; i < submeshFaceLists.Count; i++)
                {
                    List<ushort> faceList = submeshFaceLists[i];
                    List<remVertex> vertexList = submeshVertLists[i];

                    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++)
                        {
                            indexStream.Write(faceList[j]);
                        }
                        animationMesh.UnlockIndexBuffer();
                    }

                    byte[][] vertexBoneIndices = null;
                    float[][] vertexWeights = ConvertVertexWeights(vertexList, submeshVertIndices[i], boneList, out vertexBoneIndices);
                    FillVertexBuffer(animationMesh, vertexList, vertexWeights, vertexBoneIndices, -1);

                    var normalLines = new PositionBlendWeightsIndexedColored[vertexList.Count * 2];
                    for (int j = 0; j < vertexList.Count; j++)
                    {
                        remVertex vertex = vertexList[j];
                        Vector3 position = vertex.Position;
                        Vector3 normal = vertex.Normal;
                        float[] boneWeights = vertexWeights[j];

                        normalLines[j * 2] = new PositionBlendWeightsIndexedColored(position, boneWeights, vertexBoneIndices[j], Color.Coral.ToArgb());
                        normalLines[(j * 2) + 1] = new PositionBlendWeightsIndexedColored(position + normal, boneWeights, vertexBoneIndices[j], Color.Blue.ToArgb());

            #if !DONT_MIRROR
                        position.Z *= -1f;
            #endif
                        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;

                    remMaterial mat = rem.FindMaterial(mesh.materials[i], parser.MATC);
                    if (mat != null)
                    {
                        Material material3D = new Material();
                        material3D.Ambient = new Color4(mat.ambient);
                        material3D.Diffuse = new Color4(mat.diffuse);
                        material3D.Emissive = new Color4(mat.emissive);
                        material3D.Specular = new Color4(mat.specular);
                        material3D.Power = mat.specularPower;
                        int matIdx = parser.MATC.IndexOf(mat);
                        Materials[matIdx] = material3D;
                        meshContainer.MaterialIndex = matIdx;

                        int texIdx = 0;
                        if (mat.texture != null && !TextureDic.TryGetValue(mat.texture.ToString(), out texIdx))
                        {
                            ImportedTexture importedTex = null;
                            if (!ImportedTextures.TryGetValue(mat.texture.ToString(), out importedTex))
                            {
                                importedTex = rem.ImportedTexture(mat.texture, parser.RemPath, true);
                                if (importedTex == null)
                                {
                                    Report.ReportLog("Export textures of TEXH.FPK!");
                                    continue;
                                }
                                ImportedTextures.Add(mat.texture.ToString(), importedTex);
                            }
                            Texture memTex = Texture.FromMemory(device, importedTex.Data);
                            texIdx = TextureDic.Count;
                            TextureDic.Add(mat.texture.ToString(), texIdx);
                            Textures.Add(memTex);
                        }
                        meshContainer.TextureIndex = texIdx;
                    }
                }

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

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

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

            numFrames++;
            return animationFrame;
        }