Example #1
0
        public byte[] ToBytes()
        {
            List <byte> outList = new List <byte>();

            using (System.IO.MemoryStream mem = new System.IO.MemoryStream())
            {
                EndianBinaryWriter writer = new EndianBinaryWriter(mem, Endian.Big);

                writer.Write(m_MatrixType);
                writer.Write(m_UnknownIndex);
                writer.Write((sbyte)-1);

                ushort[] compressRot = J3DUtility.CompressRotation(m_Rotation.ToEulerAngles());

                writer.Write(m_Scale);
                writer.Write(compressRot[0]);
                writer.Write(compressRot[1]);
                writer.Write(compressRot[2]);
                writer.Write((short)-1);
                writer.Write(m_Translation);

                Bounds.Write(writer);

                outList.AddRange(mem.ToArray());
            }

            return(outList.ToArray());
        }
Example #2
0
        static GMX_Parser.MESH CreateMesh(Model model, Shape curShape)
        {
            var attributes = model.VertexData.Attributes;

            var mesh = new GMX_Parser.MESH();

            mesh.IndexGroup  = new GMX_Parser.INDX();
            mesh.VertexGroup = new GMX_Parser.VERT();
            mesh.VMapGroup   = new GMX_Parser.VMAP();

            List <GMX_Parser.Vertex> vertices    = new List <GMX_Parser.Vertex>();
            List <ushort>            indices     = new List <ushort>();
            List <ushort>            boneindices = new List <ushort>();
            List <ushort>            vmapindices = new List <ushort>();

            ushort vertexID     = 0;
            uint   vertexStride = 0;

            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx))
            {
                vertexStride += 4;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Position))
            {
                vertexStride += 12;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal))
            {
                vertexStride += 12;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0))
            {
                vertexStride += 4;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1))
            {
                vertexStride += 4;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0))
            {
                vertexStride += 8;
            }
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex1))
            {
                vertexStride += 8;
            }

            uint[] matrices    = new uint[10];
            uint   matrixStart = 0;

            foreach (Packet pack in curShape.Packets)
            {
                for (int i = 0; i < pack.MatrixIndices.Count; i++)
                {
                    if (pack.MatrixIndices[i] != -1)
                    {
                        matrices[i] = (uint)pack.MatrixIndices[i];
                    }
                }

                foreach (Primitive prim in pack.Primitives)
                {
                    List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim);
                    for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3)
                    {
                        indices.AddRange(new ushort[] { (ushort)(vertexID + 2), (ushort)(vertexID + 1), vertexID });

                        for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++)
                        {
                            var gmxVertex = new GMX_Parser.Vertex();

                            Vertex vert     = triVertices[triIndex + triVertIndex];
                            var    position = attributes.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)];

                            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal))
                            {
                                gmxVertex.Normal = attributes.Normals[(int)vert.GetAttributeIndex(GXVertexAttribute.Normal)];
                            }
                            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0))
                            {
                                var color = attributes.Color_0[(int)vert.GetAttributeIndex(GXVertexAttribute.Color0)];
                                gmxVertex.Color = new OpenTK.Vector4(color.R, color.G, color.B, color.A);
                            }
                            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0))
                            {
                                gmxVertex.TexCoord0 = attributes.TexCoord_0[(int)vert.GetAttributeIndex(GXVertexAttribute.Tex0)];
                            }
                            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex1))
                            {
                                gmxVertex.TexCoord1 = attributes.TexCoord_1[(int)vert.GetAttributeIndex(GXVertexAttribute.Tex1)];
                            }
                            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx))
                            {
                                gmxVertex.MatrixID = (uint)(matrixStart + vert.PositionMatrixIDxIndex);
                            }

                            gmxVertex.Position = position;
                            vertices.Add(gmxVertex);
                        }
                    }
                }
                matrixStart += 10;
            }

            indices.Clear();

            //Now optmize the indices
            Dictionary <GMX_Parser.Vertex, int> verticesNew = new Dictionary <GMX_Parser.Vertex, int>();

            foreach (var v in vertices)
            {
                if (!verticesNew.ContainsKey(v))
                {
                    verticesNew.Add(v, verticesNew.Count);
                }

                if (verticesNew.ContainsKey(v))
                {
                    indices.Add((ushort)verticesNew[v]);
                }
            }

            vertices = verticesNew.Keys.ToList();

            foreach (var v in vertices)
            {
                vmapindices.Add(0);
                vmapindices.Add(0);
            }

            mesh.VMapGroup.Indices    = vmapindices.ToArray();
            mesh.VertexSize           = (ushort)vertexStride;
            mesh.VertexCount          = (ushort)vertices.Count;
            mesh.VertexGroup.Vertices = vertices;
            mesh.FaceCount            = (uint)indices.Count;
            mesh.IndexGroup.Indices   = indices.ToArray();
            mesh.SkinningFlags        = 0;
            if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.PositionMatrixIdx))
            {
                mesh.SkinningFlags = 20;
            }
            return(mesh);
        }
Example #3
0
        private SHP1(EndianBinaryReader reader, int offset)
        {
            Shapes     = new List <Shape>();
            RemapTable = new List <int>();

            reader.BaseStream.Seek(offset, System.IO.SeekOrigin.Begin);
            reader.SkipInt32();
            int shp1Size   = reader.ReadInt32();
            int entryCount = reader.ReadInt16();

            reader.SkipInt16();

            int shapeHeaderDataOffset = reader.ReadInt32();
            int shapeRemapTableOffset = reader.ReadInt32();
            int unusedOffset          = reader.ReadInt32();
            int attributeDataOffset   = reader.ReadInt32();
            int matrixIndexDataOffset = reader.ReadInt32();
            int primitiveDataOffset   = reader.ReadInt32();
            int matrixDataOffset      = reader.ReadInt32();
            int PacketInfoDataOffset  = reader.ReadInt32();

            reader.BaseStream.Seek(offset + shapeRemapTableOffset, System.IO.SeekOrigin.Begin);

            // Remap table
            for (int i = 0; i < entryCount; i++)
            {
                RemapTable.Add(reader.ReadInt16());
            }

            int highestIndex = J3DUtility.GetHighestValue(RemapTable);

            // Packet data
            List <Tuple <int, int> > packetData = new List <Tuple <int, int> >(); // <packet size, packet offset>
            int packetDataCount = (shp1Size - PacketInfoDataOffset) / 8;

            reader.BaseStream.Seek(PacketInfoDataOffset + offset, System.IO.SeekOrigin.Begin);

            for (int i = 0; i < packetDataCount; i++)
            {
                packetData.Add(new Tuple <int, int>(reader.ReadInt32(), reader.ReadInt32()));
            }

            // Matrix data
            List <Tuple <int, int> > matrixData    = new List <Tuple <int, int> >(); // <index count, start index>
            List <int[]>             matrixIndices = new List <int[]>();

            int matrixDataCount = (PacketInfoDataOffset - matrixDataOffset) / 8;

            reader.BaseStream.Seek(matrixDataOffset + offset, System.IO.SeekOrigin.Begin);

            for (int i = 0; i < matrixDataCount; i++)
            {
                reader.SkipInt16();
                matrixData.Add(new Tuple <int, int>(reader.ReadInt16(), reader.ReadInt32()));
            }

            for (int i = 0; i < matrixDataCount; i++)
            {
                reader.BaseStream.Seek(offset + matrixIndexDataOffset + (matrixData[i].Item2 * 2), System.IO.SeekOrigin.Begin);
                int[] indices = new int[matrixData[i].Item1];

                for (int j = 0; j < matrixData[i].Item1; j++)
                {
                    indices[j] = reader.ReadInt16();
                }

                matrixIndices.Add(indices);
            }

            // Shape data
            List <Shape> tempShapeList = new List <Shape>();

            reader.BaseStream.Seek(offset + shapeHeaderDataOffset, System.IO.SeekOrigin.Begin);

            for (int i = 0; i < highestIndex + 1; i++)
            {
                byte matrixType = reader.ReadByte();
                reader.SkipByte();

                int packetCount          = reader.ReadInt16();
                int shapeAttributeOffset = reader.ReadInt16();
                int shapeMatrixDataIndex = reader.ReadInt16();
                int firstPacketIndex     = reader.ReadInt16();
                reader.SkipInt16();

                BoundingVolume shapeVol = new BoundingVolume(reader);

                long curOffset = reader.BaseStream.Position;

                ShapeVertexDescriptor descriptor = new ShapeVertexDescriptor(reader, offset + attributeDataOffset + shapeAttributeOffset);

                List <Packet> shapePackets = new List <Packet>();
                for (int j = 0; j < packetCount; j++)
                {
                    int packetSize   = packetData[j + firstPacketIndex].Item1;
                    int packetOffset = packetData[j + firstPacketIndex].Item2;

                    Packet pack = new Packet(packetSize, packetOffset + primitiveDataOffset + offset, matrixIndices[j + firstPacketIndex]);
                    pack.ReadPrimitives(reader, descriptor);

                    shapePackets.Add(pack);
                }

                tempShapeList.Add(new Shape(descriptor, shapeVol, shapePackets, matrixType));

                reader.BaseStream.Seek(curOffset, System.IO.SeekOrigin.Begin);
            }

            for (int i = 0; i < entryCount; i++)
            {
                Shapes.Add(tempShapeList[RemapTable[i]]);
            }

            reader.BaseStream.Seek(offset + shp1Size, System.IO.SeekOrigin.Begin);
        }
Example #4
0
        public void FillScene(Scene scene, VertexData vertData, List <Rigging.Bone> flatSkeleton, List <Matrix4> inverseBindMatrices)
        {
            for (int i = 0; i < Shapes.Count; i++)
            {
                Mesh mesh = new Mesh($"mesh_{ i }", PrimitiveType.Triangle);
                mesh.MaterialIndex = i;

                int   vertexID = 0;
                Shape curShape = Shapes[i];
                foreach (Packet pack in curShape.Packets)
                {
                    foreach (Primitive prim in pack.Primitives)
                    {
                        List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim);

                        for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3)
                        {
                            Face newFace = new Face(new int[] { vertexID + 2, vertexID + 1, vertexID });
                            mesh.Faces.Add(newFace);

                            for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++)
                            {
                                Vertex vert = triVertices[triIndex + triVertIndex];

                                for (int j = 0; j < vert.VertexWeight.WeightCount; j++)
                                {
                                    Rigging.Bone curWeightBone = flatSkeleton[vert.VertexWeight.BoneIndices[j]];

                                    int assBoneIndex = mesh.Bones.FindIndex(x => x.Name == curWeightBone.Name);

                                    if (assBoneIndex == -1)
                                    {
                                        Assimp.Bone newBone = new Assimp.Bone();
                                        newBone.Name         = curWeightBone.Name;
                                        newBone.OffsetMatrix = curWeightBone.InverseBindMatrix.ToMatrix4x4();
                                        mesh.Bones.Add(newBone);
                                        assBoneIndex = mesh.Bones.IndexOf(newBone);
                                    }

                                    mesh.Bones[assBoneIndex].VertexWeights.Add(new VertexWeight(vertexID, vert.VertexWeight.Weights[j]));
                                }

                                OpenTK.Vector3 posVec    = vertData.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)];
                                OpenTK.Vector4 openTKVec = new Vector4(posVec.X, posVec.Y, posVec.Z, 1);

                                Vector3D vertVec = new Vector3D(openTKVec.X, openTKVec.Y, openTKVec.Z);

                                if (vert.VertexWeight.WeightCount == 1)
                                {
                                    if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0])
                                    {
                                        Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted();
                                        test.Transpose();
                                        Vector4 trans = OpenTK.Vector4.Transform(openTKVec, test);
                                        vertVec = new Vector3D(trans.X, trans.Y, trans.Z);
                                    }
                                    else
                                    {
                                        Vector4 trans = OpenTK.Vector4.Transform(openTKVec, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix);
                                        vertVec = new Vector3D(trans.X, trans.Y, trans.Z);
                                    }
                                }

                                /*else
                                 * {
                                 *  Matrix4 finalMatrix = Matrix4.Zero;
                                 *
                                 *  for (int m = 0; m < vert.VertexWeight.WeightCount; m++)
                                 *  {
                                 *      Matrix4 sm1 = inverseBindMatrices[vert.VertexWeight.BoneIndices[m]];
                                 *      //sm1.Transpose();
                                 *      Matrix4 sm2 = flatSkeleton[vert.VertexWeight.BoneIndices[m]].TransformationMatrix;
                                 *      //sm2.Transpose();
                                 *
                                 *      finalMatrix += Matrix4.Mult(sm1, vert.VertexWeight.Weights[m]);
                                 *  }
                                 *
                                 *  Vector4 final = Vector4.Transform(openTKVec, finalMatrix);
                                 *
                                 *  vertVec = new Vector3D(final.X, final.Y, final.Z);
                                 * }*/

                                mesh.Vertices.Add(vertVec);

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal))
                                {
                                    mesh.Normals.Add(vertData.Normals[(int)vert.NormalIndex].ToVector3D());
                                }

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0))
                                {
                                    mesh.VertexColorChannels[0].Add(vertData.Color_0[(int)vert.Color0Index].ToColor4D());
                                }

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1))
                                {
                                    mesh.VertexColorChannels[1].Add(vertData.Color_1[(int)vert.Color1Index].ToColor4D());
                                }

                                for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++)
                                {
                                    if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum))
                                    {
                                        Vector3D texCoord = new Vector3D();
                                        switch (texCoordNum)
                                        {
                                        case 0:
                                            texCoord = vertData.TexCoord_0[(int)vert.TexCoord0Index].ToVector2D();
                                            break;

                                        case 1:
                                            texCoord = vertData.TexCoord_1[(int)vert.TexCoord1Index].ToVector2D();
                                            break;

                                        case 2:
                                            texCoord = vertData.TexCoord_2[(int)vert.TexCoord2Index].ToVector2D();
                                            break;

                                        case 3:
                                            texCoord = vertData.TexCoord_3[(int)vert.TexCoord3Index].ToVector2D();
                                            break;

                                        case 4:
                                            texCoord = vertData.TexCoord_4[(int)vert.TexCoord4Index].ToVector2D();
                                            break;

                                        case 5:
                                            texCoord = vertData.TexCoord_5[(int)vert.TexCoord5Index].ToVector2D();
                                            break;

                                        case 6:
                                            texCoord = vertData.TexCoord_6[(int)vert.TexCoord6Index].ToVector2D();
                                            break;

                                        case 7:
                                            texCoord = vertData.TexCoord_7[(int)vert.TexCoord7Index].ToVector2D();
                                            break;
                                        }

                                        mesh.TextureCoordinateChannels[texCoordNum].Add(texCoord);
                                    }
                                }

                                vertexID++;
                            }
                        }
                    }
                }

                scene.Meshes.Add(mesh);
            }
        }
Example #5
0
        private void LoadBMD(Model model)
        {
            Nodes.Clear();

            ShapeFolder    = new TreeNode("Shapes");
            SkeletonFolder = new TreeNode("Skeleton");
            MaterialFolder = new TreeNode("Materials");
            TextureFolder  = new BMDTextureFolder("Textures");
            Nodes.Add(ShapeFolder);
            Nodes.Add(MaterialFolder);
            Nodes.Add(SkeletonFolder);
            Nodes.Add(TextureFolder);

            BMDFile = model;

            FillSkeleton(BMDFile.Scenegraph, Skeleton, BMDFile.Joints.FlatSkeleton);

            foreach (var bone in Skeleton.bones)
            {
                if (bone.Parent == null)
                {
                    SkeletonFolder.Nodes.Add(bone);
                }
            }

            for (int i = 0; i < BMDFile.Shapes.Shapes.Count; i++)
            {
                var curShape = BMDFile.Shapes.Shapes[i];

                var mat = new BMDMaterialWrapper(BMDFile.Materials.GetMaterial(i), BMDFile);
                MaterialFolder.Nodes.Add(mat);

                var shpWrapper = new BMDShapeWrapper(curShape, BMDFile, mat);
                shpWrapper.Text = $"Shape {i}";
                ShapeFolder.Nodes.Add(shpWrapper);
                Renderer.Meshes.Add(shpWrapper);

                var polyGroup = new STGenericPolygonGroup();
                shpWrapper.PolygonGroups.Add(polyGroup);

                var VertexAttributes = BMDFile.VertexData.Attributes;

                int vertexID = 0;
                int packetID = 0;

                foreach (var att in curShape.Descriptor.Attributes)
                {
                    shpWrapper.Nodes.Add($"Attribute {att.Key} {att.Value.Item1}");
                }

                foreach (SuperBMDLib.Geometry.Packet pack in curShape.Packets)
                {
                    int primID = 0;
                    foreach (SuperBMDLib.Geometry.Primitive prim in pack.Primitives)
                    {
                        List <SuperBMDLib.Geometry.Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim);
                        for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3)
                        {
                            polyGroup.faces.AddRange(new int[] { vertexID + 2, vertexID + 1, vertexID });

                            for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++)
                            {
                                SuperBMDLib.Geometry.Vertex vert = triVertices[triIndex + triVertIndex];

                                Vertex vertex = new Vertex();
                                vertex.pos = VertexAttributes.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)];
                                shpWrapper.vertices.Add(vertex);

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal))
                                {
                                    vertex.nrm = VertexAttributes.Normals[(int)vert.NormalIndex];
                                }
                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0))
                                {
                                    var color0 = VertexAttributes.Color_0[(int)vert.Color0Index];
                                    vertex.col = new OpenTK.Vector4(color0.R, color0.G, color0.B, color0.A);
                                }

                                for (int j = 0; j < vert.VertexWeight.WeightCount; j++)
                                {
                                    vertex.boneWeights.Add(vert.VertexWeight.Weights[j]);
                                    vertex.boneIds.Add(vert.VertexWeight.BoneIndices[j]);
                                }

                                if (vert.VertexWeight.WeightCount == 1)
                                {
                                    if (BMDFile.SkinningEnvelopes.InverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0])
                                    {
                                        Matrix4 test = BMDFile.SkinningEnvelopes.InverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted();
                                        test.Transpose();
                                        vertex.pos = OpenTK.Vector3.TransformPosition(vertex.pos, test);
                                        vertex.nrm = OpenTK.Vector3.TransformNormal(vertex.nrm, test);
                                    }
                                    else
                                    {
                                        vertex.pos = OpenTK.Vector3.TransformPosition(vertex.pos, BMDFile.Joints.FlatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix);
                                        vertex.nrm = OpenTK.Vector3.TransformNormal(vertex.nrm, BMDFile.Joints.FlatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix);
                                    }
                                }

                                for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++)
                                {
                                    if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum))
                                    {
                                        switch (texCoordNum)
                                        {
                                        case 0:
                                            vertex.uv0 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index];
                                            break;

                                        case 1:
                                            vertex.uv1 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index];
                                            break;

                                        case 2:
                                            vertex.uv2 = VertexAttributes.TexCoord_0[(int)vert.TexCoord0Index];
                                            break;
                                        }
                                    }
                                }

                                vertexID++;
                            }
                        }

                        primID++;
                    }

                    packetID++;
                }
            }

            CorrectMaterialIndices(Renderer.Meshes, BMDFile.Scenegraph, BMDFile.Materials);

            for (int i = 0; i < BMDFile.Textures.Textures.Count; i++)
            {
                var texWrapper = new BMDTextureWrapper(BMDFile.Textures.Textures[i]);
                TextureFolder.Nodes.Add(texWrapper);
                Renderer.TextureList.Add(texWrapper);
            }
        }
Example #6
0
        public void FillScene(Scene scene, VertexData vertData, List <Rigging.Bone> flatSkeleton, List <Matrix4> inverseBindMatrices)
        {
            for (int i = 0; i < Shapes.Count; i++)
            {
                int   vertexID = 0;
                Shape curShape = Shapes[i];

                Console.Write("Mesh " + i + ": ");
                string meshname = $"mesh_{ i }";

                switch (curShape.MatrixType)
                {
                case MatrixType.BillboardX:
                    meshname += "_BillX";
                    Console.Write("Billboarding Detected! ");
                    break;

                case MatrixType.BillboardXY:
                    meshname += "_BillXY";
                    Console.Write("Billboarding Detected! ");
                    break;

                default:
                    break;
                }

                Mesh mesh = new Mesh($"mesh_{ i }", PrimitiveType.Triangle);
                mesh.MaterialIndex = i;

                foreach (Packet pack in curShape.Packets)
                {
                    foreach (Primitive prim in pack.Primitives)
                    {
                        List <Vertex> triVertices = J3DUtility.PrimitiveToTriangles(prim);

                        for (int triIndex = 0; triIndex < triVertices.Count; triIndex += 3)
                        {
                            Face newFace = new Face(new int[] { vertexID + 2, vertexID + 1, vertexID });
                            mesh.Faces.Add(newFace);

                            for (int triVertIndex = 0; triVertIndex < 3; triVertIndex++)
                            {
                                Vertex vert = triVertices[triIndex + triVertIndex];

                                for (int j = 0; j < vert.VertexWeight.WeightCount; j++)
                                {
                                    Rigging.Bone curWeightBone = flatSkeleton[vert.VertexWeight.BoneIndices[j]];

                                    int assBoneIndex = mesh.Bones.FindIndex(x => x.Name == curWeightBone.Name);

                                    if (assBoneIndex == -1)
                                    {
                                        Assimp.Bone newBone = new Assimp.Bone();
                                        newBone.Name         = curWeightBone.Name;
                                        newBone.OffsetMatrix = curWeightBone.InverseBindMatrix.ToMatrix4x4();
                                        mesh.Bones.Add(newBone);
                                        assBoneIndex = mesh.Bones.IndexOf(newBone);
                                    }

                                    mesh.Bones[assBoneIndex].VertexWeights.Add(new VertexWeight(vertexID, vert.VertexWeight.Weights[j]));
                                }

                                OpenTK.Vector3 posVec    = vertData.Positions[(int)vert.GetAttributeIndex(GXVertexAttribute.Position)];
                                OpenTK.Vector4 openTKVec = new Vector4(posVec.X, posVec.Y, posVec.Z, 1);

                                Vector3D vertVec = new Vector3D(openTKVec.X, openTKVec.Y, openTKVec.Z);

                                if (vert.VertexWeight.WeightCount == 1)
                                {
                                    if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0])
                                    {
                                        Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted();
                                        test.Transpose();
                                        Vector4 trans = OpenTK.Vector4.Transform(openTKVec, test);
                                        vertVec = new Vector3D(trans.X, trans.Y, trans.Z);
                                    }
                                    else
                                    {
                                        Vector4 trans = OpenTK.Vector4.Transform(openTKVec, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix);
                                        vertVec = new Vector3D(trans.X, trans.Y, trans.Z);
                                    }
                                }

                                mesh.Vertices.Add(vertVec);

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Normal))
                                {
                                    OpenTK.Vector3 nrmVec    = vertData.Normals[(int)vert.NormalIndex];
                                    OpenTK.Vector4 openTKNrm = new Vector4(nrmVec.X, nrmVec.Y, nrmVec.Z, 1);
                                    Vector3D       vertNrm   = new Vector3D(nrmVec.X, nrmVec.Y, nrmVec.Z);

                                    if (vert.VertexWeight.WeightCount == 1)
                                    {
                                        if (inverseBindMatrices.Count > vert.VertexWeight.BoneIndices[0])
                                        {
                                            Matrix4 test = inverseBindMatrices[vert.VertexWeight.BoneIndices[0]].Inverted();
                                            vertNrm = Vector3.TransformNormalInverse(nrmVec, test).ToVector3D();
                                        }
                                        else
                                        {
                                            Vector4 trans = OpenTK.Vector4.Transform(openTKNrm, flatSkeleton[vert.VertexWeight.BoneIndices[0]].TransformationMatrix);
                                            vertNrm = new Vector3D(trans.X, trans.Y, trans.Z);
                                        }
                                    }

                                    mesh.Normals.Add(vertNrm);
                                }

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color0))
                                {
                                    mesh.VertexColorChannels[0].Add(vertData.Color_0[(int)vert.Color0Index].ToColor4D());
                                }

                                if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Color1))
                                {
                                    mesh.VertexColorChannels[1].Add(vertData.Color_1[(int)vert.Color1Index].ToColor4D());
                                }

                                for (int texCoordNum = 0; texCoordNum < 8; texCoordNum++)
                                {
                                    if (curShape.Descriptor.CheckAttribute(GXVertexAttribute.Tex0 + texCoordNum))
                                    {
                                        Vector3D texCoord = new Vector3D();
                                        switch (texCoordNum)
                                        {
                                        case 0:
                                            texCoord = vertData.TexCoord_0[(int)vert.TexCoord0Index].ToVector2D();
                                            break;

                                        case 1:
                                            texCoord = vertData.TexCoord_1[(int)vert.TexCoord1Index].ToVector2D();
                                            break;

                                        case 2:
                                            texCoord = vertData.TexCoord_2[(int)vert.TexCoord2Index].ToVector2D();
                                            break;

                                        case 3:
                                            texCoord = vertData.TexCoord_3[(int)vert.TexCoord3Index].ToVector2D();
                                            break;

                                        case 4:
                                            texCoord = vertData.TexCoord_4[(int)vert.TexCoord4Index].ToVector2D();
                                            break;

                                        case 5:
                                            texCoord = vertData.TexCoord_5[(int)vert.TexCoord5Index].ToVector2D();
                                            break;

                                        case 6:
                                            texCoord = vertData.TexCoord_6[(int)vert.TexCoord6Index].ToVector2D();
                                            break;

                                        case 7:
                                            texCoord = vertData.TexCoord_7[(int)vert.TexCoord7Index].ToVector2D();
                                            break;
                                        }

                                        mesh.TextureCoordinateChannels[texCoordNum].Add(texCoord);
                                    }
                                }

                                vertexID++;
                            }
                        }
                    }
                    Console.Write("...");
                }

                scene.Meshes.Add(mesh);
                Console.Write("✓");
                Console.WriteLine();
            }
        }