Esempio n. 1
0
        public Model(Scene scene, Arguments args)
        {
            EnsureOneMaterialPerMesh(scene);
            SortMeshesByObjectNames(scene);

            VertexData = new VTX1(scene);
            Joints     = new JNT1(scene, VertexData);
            Textures   = new TEX1(scene, args);

            SkinningEnvelopes = new EVP1();
            SkinningEnvelopes.SetInverseBindMatrices(scene, Joints.FlatSkeleton);

            PartialWeightData = new DRW1(scene, Joints.BoneNameIndices);

            Shapes = SHP1.Create(scene, Joints.BoneNameIndices, VertexData.Attributes, SkinningEnvelopes, PartialWeightData, args.tristrip_mode);

            Materials = new MAT3(scene, Textures, Shapes, args);

            if (args.output_bdl)
            {
                MatDisplayList = new MDL3(Materials.m_Materials, Textures.Textures);
            }

            Scenegraph = new INF1(scene, Joints);

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 2
0
        public Model(EndianBinaryReader reader, List <Materials.Material> mat_presets = null)
        {
            int j3d2Magic  = reader.ReadInt32();
            int modelMagic = reader.ReadInt32();

            if (j3d2Magic != 0x4A334432)
            {
                throw new Exception("Model was not a BMD or BDL! (J3D2 magic not found)");
            }
            if ((modelMagic != 0x62646C34) && (modelMagic != 0x626D6433))
            {
                throw new Exception("Model was not a BMD or BDL! (Model type was not bmd3 or bdl4)");
            }

            int modelSize    = reader.ReadInt32();
            int sectionCount = reader.ReadInt32();

            // Skip the dummy section, SVR3
            reader.Skip(16);

            Scenegraph        = new INF1(reader, 32);
            VertexData        = new VTX1(reader, (int)reader.BaseStream.Position);
            SkinningEnvelopes = new EVP1(reader, (int)reader.BaseStream.Position);
            PartialWeightData = new DRW1(reader, (int)reader.BaseStream.Position);
            Joints            = new JNT1(reader, (int)reader.BaseStream.Position);
            //Joints.SetInverseBindMatrices(SkinningEnvelopes.InverseBindMatrices);
            SkinningEnvelopes.SetInverseBindMatrices(Joints.FlatSkeleton);
            Shapes = SHP1.Create(reader, (int)reader.BaseStream.Position);
            Shapes.SetVertexWeights(SkinningEnvelopes, PartialWeightData);
            Materials = new MAT3(reader, (int)reader.BaseStream.Position, mat_presets);
            SkipMDL3(reader);
            Textures = new TEX1(reader, (int)reader.BaseStream.Position);

            // This is useful for dumping material data to json
            Materials.FillTextureNames(Textures);

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 3
0
        public Model(Scene scene, Arguments args)
        {
            VertexData = new VTX1(scene);
            Joints     = new JNT1(scene, VertexData);
            Scenegraph = new INF1(scene, Joints);
            Textures   = new TEX1(scene, args);

            SkinningEnvelopes = new EVP1();
            SkinningEnvelopes.SetInverseBindMatrices(scene, Joints.FlatSkeleton);

            PartialWeightData = new DRW1(scene, Joints.BoneNameIndices);

            Shapes = SHP1.Create(scene, Joints.BoneNameIndices, VertexData.Attributes, SkinningEnvelopes, PartialWeightData);

            Materials = new MAT3(scene, Textures, Shapes);

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 4
0
        public Model(
            Scene scene, string modelDirectory,
            List <Materials.Material> mat_presets = null, TristripOption triopt = TristripOption.DoNotTriStrip,
            bool flipAxis = false, bool fixNormals = false, string additionalTexPath = null)
        {
            Assimp.Node root = null;
            for (int i = 0; i < scene.RootNode.ChildCount; i++)
            {
                if (scene.RootNode.Children[i].Name.ToLowerInvariant() == "skeleton_root")
                {
                    if (scene.RootNode.Children[i].ChildCount == 0)
                    {
                        throw new System.Exception("skeleton_root has no children! If you are making a rigged model, make sure skeleton_root contains the root of your skeleton.");
                    }
                    root = scene.RootNode.Children[i].Children[0];
                    break;
                }
            }

            foreach (Mesh mesh in scene.Meshes)
            {
                if (mesh.HasBones && root == null)
                {
                    throw new System.Exception("Model uses bones but the skeleton root has not been found! Make sure your skeleton is inside a dummy object called 'skeleton_root'.");
                }
            }

            Matrix3x3 rotateXminus90 = Matrix3x3.FromRotationX((float)(-(1 / 2.0) * Math.PI));
            Matrix3x3 rotateXplus90  = Matrix3x3.FromRotationX((float)((1 / 2.0) * Math.PI));
            Matrix3x3 rotateYminus90 = Matrix3x3.FromRotationY((float)(-(1 / 2.0) * Math.PI));
            Matrix3x3 rotateYplus90  = Matrix3x3.FromRotationY((float)((1 / 2.0) * Math.PI));
            Matrix3x3 rotateZminus90 = Matrix3x3.FromRotationZ((float)(-(1 / 2.0) * Math.PI));
            Matrix3x3 rotateZplus90  = Matrix3x3.FromRotationZ((float)((1 / 2.0) * Math.PI));

            if (flipAxis)
            {
                Console.WriteLine("Rotating the model...");
                int       i      = 0;
                Matrix4x4 rotate = Matrix4x4.FromRotationX((float)(-(1 / 2.0) * Math.PI));
                //rotate = Matrix4x4.FromRotationZ((float)(-(1 / 2.0) * Math.PI));
                Matrix4x4 rotateinv = rotate;



                //Matrix3x3 rotvec = rotateZplus90 * rotateXplus90;
                //Matrix3x3 rotvec = rotateYplus90*rotateYplus90 * rotateZplus90 * rotateZplus90* rotateXplus90* rotateXplus90;

                rotateinv.Inverse();
                //rotate = Matrix4x4.FromRotationY((float)(-(1 / 2.0) * Math.PI));
                //rotate = Matrix4x4.FromRotationZ((float)(-(1 / 2.0) * Math.PI));
                Matrix4x4 rotateC = Matrix4x4.FromRotationX((float)(-(1 / 2.0) * Math.PI));
                Matrix4x4 trans;

                if (root != null)
                {
                    // Rotate rigged mesh
                    foreach (Mesh mesh in scene.Meshes)
                    {
                        Console.WriteLine(mesh.Name);
                        Console.WriteLine(String.Format("Does it have bones? {0}", mesh.HasBones));

                        Matrix3x3[] weightedmats = new Matrix3x3[mesh.Normals.Count];

                        foreach (Assimp.Bone bone in mesh.Bones)
                        {
                            bone.OffsetMatrix = rotateinv * bone.OffsetMatrix;

                            /*Matrix3x3 invbind = bone.OffsetMatrix;
                             * //bind.Inverse();
                             * //List<int> vertices = new List<VertexWeight>();
                             *
                             * foreach (Assimp.VertexWeight weight in bone.VertexWeights) {
                             *  Matrix3x3 weightedcurrentmat = new Matrix3x3(
                             *          weight.Weight * invbind.A1, weight.Weight * invbind.A2, weight.Weight * invbind.A1,
                             *          weight.Weight * invbind.B1, weight.Weight * invbind.B2, weight.Weight * invbind.B3,
                             *          weight.Weight * invbind.C1, weight.Weight * invbind.C2, weight.Weight * invbind.C3);
                             *
                             *  if (weightedmats[weight.VertexID] == null) {
                             *      weightedmats[weight.VertexID] = weightedcurrentmat;
                             *  }
                             *  else {
                             *      Matrix3x3 existingmat = weightedmats[weight.VertexID];
                             *      weightedmats[weight.VertexID] = new Matrix3x3(
                             *          existingmat.A1 + invbind.A1, existingmat.A2 + invbind.A2, existingmat.A3 + invbind.A3,
                             *          existingmat.B1 + invbind.B1, existingmat.B2 + invbind.B2, existingmat.B3 + invbind.B3,
                             *          existingmat.C1 + invbind.C1, existingmat.C2 + invbind.C2, existingmat.C3 + invbind.C3);
                             *  }
                             * }*/

                            //Matrix4x4 bindMat = bone.OffsetMatrix;
                            //bindMat.Inverse();
                            //trans =

                            /*bone.OffsetMatrix = root.Transform * bone.OffsetMatrix;
                             * Matrix4x4 newtransform = root.Transform * rotate;
                             * newtransform.Inverse();
                             * bone.OffsetMatrix = newtransform * bone.OffsetMatrix;*/
                        }

                        for (i = 0; i < mesh.VertexCount; i++)
                        {
                            Vector3D vertex = mesh.Vertices[i];
                            vertex.Set(vertex.X, vertex.Z, -vertex.Y);
                            mesh.Vertices[i] = vertex;
                        }
                        for (i = 0; i < mesh.Normals.Count; i++)
                        {
                            Vector3D norm = mesh.Normals[i];
                            norm.Set(norm.X, norm.Z, -norm.Y);

                            //Matrix3x3 invbind = weightedmats[i];
                            //invbind.Inverse();
                            //norm = invbind * norm;

                            mesh.Normals[i] = norm;
                        }
                    }
                }
                else
                {
                    // Rotate static mesh
                    foreach (Mesh mesh in scene.Meshes)
                    {
                        for (i = 0; i < mesh.VertexCount; i++)
                        {
                            Vector3D vertex = mesh.Vertices[i];
                            vertex.Set(vertex.X, vertex.Z, -vertex.Y);
                            mesh.Vertices[i] = vertex;
                        }
                        for (i = 0; i < mesh.Normals.Count; i++)
                        {
                            Vector3D norm = mesh.Normals[i];
                            norm.Set(norm.X, norm.Z, -norm.Y);
                            mesh.Normals[i] = norm;
                        }
                    }
                }



                if (root != null)
                {
                    List <Assimp.Node> allnodes     = new List <Assimp.Node>();
                    List <Assimp.Node> processnodes = new List <Assimp.Node>();
                    processnodes.Add(root);
                    root.Transform = root.Transform * rotate;

                    /*while (processnodes.Count > 0) {
                     *  Assimp.Node current = processnodes[0];
                     *  processnodes.RemoveAt(0);
                     *
                     *  current.Transform = current.Transform * rotate;
                     *
                     *  foreach (Assimp.Node child in current.Children) {
                     *      processnodes.Add(child);
                     *  }
                     * }*/
                }
            }

            // On rigged models we attempt to fix normals for shading to work properly (when using materials)
            // That works by multiplying the normal for a vertex with the inverse bind matrices that have an effect on the vertex.
            // Seems to work semi-well, might need to look over this at a later point again though.
            Console.WriteLine(String.Format("fixNormals is {0}", fixNormals));
            if (fixNormals && root != null)
            {
                Console.WriteLine("Fixing the normals on the rigged mesh...");
                foreach (Mesh mesh in scene.Meshes)
                {
                    List <Tuple <float, Matrix3x3> >[] weightedmats = new List <Tuple <float, Matrix3x3> > [mesh.Normals.Count];//new Matrix3x3[mesh.Normals.Count];

                    foreach (Assimp.Bone bone in mesh.Bones)
                    {
                        Matrix3x3 invbind = bone.OffsetMatrix;

                        foreach (Assimp.VertexWeight weight in bone.VertexWeights)
                        {
                            if (weightedmats[weight.VertexID] == null)
                            {
                                weightedmats[weight.VertexID] = new List <Tuple <float, Matrix3x3> >();
                            }
                            weightedmats[weight.VertexID].Add(Tuple.Create(weight.Weight, invbind));

                            /*Matrix3x3 weightedcurrentmat = new Matrix3x3(
                             *      weight.Weight * invbind.A1, weight.Weight * invbind.A2, weight.Weight * invbind.A1,
                             *      weight.Weight * invbind.B1, weight.Weight * invbind.B2, weight.Weight * invbind.B3,
                             *      weight.Weight * invbind.C1, weight.Weight * invbind.C2, weight.Weight * invbind.C3);
                             *
                             * if (weightedmats[weight.VertexID] == null) {
                             *  weightedmats[weight.VertexID] = weightedcurrentmat;
                             * }
                             * else {
                             *  Matrix3x3 existingmat = weightedmats[weight.VertexID];
                             *  weightedmats[weight.VertexID] = new Matrix3x3(
                             *      existingmat.A1 + invbind.A1, existingmat.A2 + invbind.A2, existingmat.A3 + invbind.A3,
                             *      existingmat.B1 + invbind.B1, existingmat.B2 + invbind.B2, existingmat.B3 + invbind.B3,
                             *      existingmat.C1 + invbind.C1, existingmat.C2 + invbind.C2, existingmat.C3 + invbind.C3);
                             * }*/
                        }
                    }

                    for (int i = 0; i < mesh.Normals.Count; i++)
                    {
                        if (weightedmats[i] == null)
                        {
                            continue; // means that index hasn't been weighted to so we can't do anything?
                        }

                        //weightedmats[i].Sort((x, y) => y.Item1.CompareTo(x.Item1));

                        Vector3D norm = mesh.Normals[i];

                        Matrix3x3 invbind = ScalarMultiply3x3(weightedmats[i][0].Item1, weightedmats[i][0].Item2);
                        for (int j = 1; j < weightedmats[i].Count; j++)
                        {
                            invbind = AddMatrix3x3(
                                invbind,
                                ScalarMultiply3x3(weightedmats[i][j].Item1, weightedmats[i][j].Item2)
                                );
                        }

                        norm = invbind * norm;

                        mesh.Normals[i] = norm;
                    }
                }
            }

            // We check if the model mixes weighted and unweighted vertices.
            // If that is the case, we throw an exception here. If we don't,
            // an exception will be thrown later on that is less helpful to the user.
            if (true)
            {
                bool usesWeights = false;
                foreach (Mesh mesh in scene.Meshes)
                {
                    bool[] weightedmats = new bool[mesh.VertexCount];

                    foreach (Assimp.Bone bone in mesh.Bones)
                    {
                        foreach (Assimp.VertexWeight weight in bone.VertexWeights)
                        {
                            weightedmats[weight.VertexID] = true;
                        }
                    }

                    for (uint i = 0; i < mesh.VertexCount; i++)
                    {
                        if (weightedmats[i] == true)
                        {
                            usesWeights = true;
                        }
                        else if (usesWeights)
                        {
                            throw new System.Exception("Model has a mixture of weighted and unweighted vertices! Please weight all vertices to at least one bone.");
                        }
                    }
                }
            }
            VertexData = new VTX1(scene);
            Joints     = new JNT1(scene, VertexData);
            Scenegraph = new INF1(scene, Joints);
            Textures   = new TEX1(scene, Path.GetDirectoryName(modelDirectory));

            SkinningEnvelopes = new EVP1();
            SkinningEnvelopes.SetInverseBindMatrices(scene, Joints.FlatSkeleton);
            //SkinningEnvelopes.AddInverseBindMatrices(Joints.FlatSkeleton);

            PartialWeightData = new DRW1(scene, Joints.BoneNameIndices);

            Shapes    = SHP1.Create(scene, Joints.BoneNameIndices, VertexData.Attributes, SkinningEnvelopes, PartialWeightData, triopt);
            Materials = new MAT3(scene, Textures, Shapes, mat_presets);

            if (additionalTexPath == null)
            {
                Materials.LoadAdditionalTextures(Textures, Path.GetDirectoryName(modelDirectory));
            }
            else
            {
                Materials.LoadAdditionalTextures(Textures, additionalTexPath);
            }

            Materials.MapTextureNamesToIndices(Textures);

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 5
0
        public void ProcessVerticesWithWeights(Mesh mesh, VertexData vertData, Dictionary <string, int> boneNames, EVP1 envelopes, DRW1 partialWeight, bool doStrip = true)
        {
            Weight[] weights = new Weight[mesh.Vertices.Count];

            for (int i = 0; i < mesh.Vertices.Count; i++)
            {
                int    vertexid   = i;
                Weight vertWeight = new Weight();

                foreach (Assimp.Bone bone in mesh.Bones)
                {
                    foreach (VertexWeight weight in bone.VertexWeights)
                    {
                        if (weight.VertexID == vertexid)
                        {
                            vertWeight.AddWeight(weight.Weight, boneNames[bone.Name]);
                        }
                    }
                }
                vertWeight.reorderBones();
                weights[vertexid] = vertWeight;
            }

            //Primitive prim = new Primitive(Enums.GXPrimitiveType.Triangles);
            List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes();

            AttributeData.SetAttributesFromList(activeAttribs);


            uint[] triindices = MakeTriIndexList(mesh);

            List <PrimitiveBrawl> primlist;

            if (doStrip)
            {
                //Console.WriteLine("Calculating triangle strips for Weighted");
                TriStripper stripper = new TriStripper(triindices, weights);
                primlist = stripper.Strip();
            }
            else
            {
                //Console.WriteLine("Calculating triangle list for Weighted");
                primlist = new List <PrimitiveBrawl>();
                PrimitiveBrawl prim = new PrimitiveBrawl(PrimType.TriangleList); // Trilist
                foreach (uint index in triindices)
                {
                    prim.Indices.Add(index);
                }
                primlist.Add(prim);
            }

            //Console.WriteLine(String.Format("Done, {0} primitives", primlist.Count));



            Packet        pack          = new Packet();
            List <Weight> packetWeights = new List <Weight>();
            int           numMatrices   = 0;

            foreach (PrimitiveBrawl primbrawl in primlist)
            {
                int numNewMatricesForFirstThreeVerts = 0;
                if (!packetWeights.Contains(weights[primbrawl.Indices[0]]))
                {
                    numNewMatricesForFirstThreeVerts++;
                }
                if (!packetWeights.Contains(weights[primbrawl.Indices[1]]))
                {
                    numNewMatricesForFirstThreeVerts++;
                }
                if (!packetWeights.Contains(weights[primbrawl.Indices[2]]))
                {
                    numNewMatricesForFirstThreeVerts++;
                }
                if (numMatrices + numNewMatricesForFirstThreeVerts > MaxMatricesPerPacket)
                {
                    // We won't be able to fit even the first 3 vertices of this primitive without going over the matrix limit.
                    // So we need to start a new packet.
                    packetWeights.Clear();
                    numMatrices = 0;
                    Packets.Add(pack);
                    pack = new Packet();
                }


                Primitive prim = new Primitive((Enums.GXPrimitiveType)primbrawl.Type);

                int currvert = -1;
                int maxvert  = primbrawl.Indices.Count - 1;
                Enums.GXPrimitiveType primtype = (Enums.GXPrimitiveType)primbrawl.Type;

                if (primtype == Enums.GXPrimitiveType.TriangleStrip)
                {
                    //Console.WriteLine("Doing Tristrip");
                    foreach (int vertIndex in primbrawl.Indices)
                    {
                        currvert++;
                        Weight vertWeight = weights[vertIndex];

                        int oldmat = numMatrices;
                        if (!packetWeights.Contains(vertWeight))
                        {
                            packetWeights.Add(vertWeight);
                            numMatrices++;
                        }

                        //Console.WriteLine(String.Format("Added {0} matrices, is now {1}", numMatrices - oldmat, numMatrices));

                        // There are too many matrices, we need to create a new packet
                        if (numMatrices > MaxMatricesPerPacket)
                        {
                            // If we break up and the resulting TriStrip becomes invalid,
                            // then we need to handle those cases.

                            //Console.WriteLine(String.Format("Breaking up because over the limit: {0}", numMatrices));

                            if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip)
                            {
                                Debug.Assert(prim.Vertices.Count >= 3);
                            }
                            else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles)
                            {
                                Debug.Assert(prim.Vertices.Count % 3 == 0);
                            }
                            pack.Primitives.Add(prim);


                            Primitive newprim = new Primitive(Enums.GXPrimitiveType.TriangleStrip);
                            Vertex    prev3   = new Vertex(prim.Vertices[prim.Vertices.Count - 3]);
                            Vertex    prev2   = new Vertex(prim.Vertices[prim.Vertices.Count - 2]);
                            Vertex    prev    = new Vertex(prim.Vertices[prim.Vertices.Count - 1]);
                            bool      isOdd   = currvert % 2 != 0;
                            if (isOdd)
                            {
                                // Need to preserve whether each vertex is even or odd inside the triangle strip.
                                // Do this by adding an extra vertex from the previous packet to the start of this one.
                                newprim.Vertices.Add(prev3);
                            }
                            newprim.Vertices.Add(prev2);
                            newprim.Vertices.Add(prev);

                            prim = newprim;

                            packetWeights.Clear();
                            numMatrices = 0;
                            Packets.Add(pack);
                            Packet oldPack = pack;
                            pack = new Packet();

                            // Calculate matrices for current packet in case we added vertices
                            foreach (Vertex vertex in prim.Vertices)
                            {
                                if (!packetWeights.Contains(vertex.VertexWeight))
                                {
                                    packetWeights.Add(vertex.VertexWeight);
                                    numMatrices++;
                                }

                                // Re-add the matrix index for the duplicated verts to the new packet.
                                // And recalculate the matrix index index in each vert's attribute data.
                                uint oldMatrixIndexIndex = vertex.GetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx);
                                int  matrixIndex         = oldPack.MatrixIndices[(int)oldMatrixIndexIndex];

                                if (!pack.MatrixIndices.Contains(matrixIndex))
                                {
                                    pack.MatrixIndices.Add(matrixIndex);
                                }
                                vertex.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(matrixIndex));
                            }

                            if (!packetWeights.Contains(vertWeight))
                            {
                                packetWeights.Add(vertWeight);
                                numMatrices++;
                            }
                        }

                        Vertex vert      = new Vertex();
                        Weight curWeight = vertWeight;

                        vert.SetWeight(curWeight);

                        foreach (Enums.GXVertexAttribute attrib in activeAttribs)
                        {
                            switch (attrib)
                            {
                            case Enums.GXVertexAttribute.PositionMatrixIdx:
                                int newMatrixIndex = -1;

                                if (curWeight.WeightCount == 1)
                                {
                                    newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight);
                                }
                                else
                                {
                                    if (!envelopes.Weights.Contains(curWeight))
                                    {
                                        envelopes.Weights.Add(curWeight);
                                    }

                                    int envIndex = envelopes.Weights.IndexOf(curWeight);
                                    int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight);

                                    if (drwIndex == -1)
                                    {
                                        throw new System.Exception($"Model has unweighted vertices in mesh \"{mesh.Name}\". Please weight all vertices to at least one bone.");
                                    }

                                    newMatrixIndex = drwIndex;
                                    partialWeight.Indices[drwIndex] = envIndex;
                                }

                                if (!pack.MatrixIndices.Contains(newMatrixIndex))
                                {
                                    pack.MatrixIndices.Add(newMatrixIndex);
                                }

                                vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex));
                                break;

                            case Enums.GXVertexAttribute.Position:
                                List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position);
                                Vector3        vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3();

                                if (curWeight.WeightCount == 1)
                                {
                                    Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]];

                                    Vector3 transVec = Vector3.TransformPosition(vertPos, ibm);
                                    if (!posData.Contains(transVec))
                                    {
                                        posData.Add(transVec);
                                    }
                                    AttributeData.Positions.Add(transVec);
                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec));
                                }
                                else
                                {
                                    if (!posData.Contains(vertPos))
                                    {
                                        posData.Add(vertPos);
                                    }
                                    AttributeData.Positions.Add(vertPos);

                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos));
                                }
                                break;

                            case Enums.GXVertexAttribute.Normal:
                                List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal);
                                Vector3        vertNrm  = mesh.Normals[vertIndex].ToOpenTKVector3();

                                if (curWeight.WeightCount == 1)
                                {
                                    Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]];
                                    vertNrm = Vector3.TransformNormal(vertNrm, ibm);
                                    if (!normData.Contains(vertNrm))
                                    {
                                        normData.Add(vertNrm);
                                    }
                                }
                                else
                                {
                                    if (!normData.Contains(vertNrm))
                                    {
                                        normData.Add(vertNrm);
                                    }
                                }

                                AttributeData.Normals.Add(vertNrm);
                                vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm));
                                break;

                            case Enums.GXVertexAttribute.Color0:
                            case Enums.GXVertexAttribute.Color1:
                                int          colNo   = (int)attrib - 11;
                                List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo);
                                Color        vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA();

                                if (colNo == 0)
                                {
                                    AttributeData.Color_0.Add(vertCol);
                                }
                                else
                                {
                                    AttributeData.Color_1.Add(vertCol);
                                }

                                vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol));
                                break;

                            case Enums.GXVertexAttribute.Tex0:
                            case Enums.GXVertexAttribute.Tex1:
                            case Enums.GXVertexAttribute.Tex2:
                            case Enums.GXVertexAttribute.Tex3:
                            case Enums.GXVertexAttribute.Tex4:
                            case Enums.GXVertexAttribute.Tex5:
                            case Enums.GXVertexAttribute.Tex6:
                            case Enums.GXVertexAttribute.Tex7:
                                int            texNo        = (int)attrib - 13;
                                List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo);
                                Vector2        vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2();
                                vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y);

                                switch (texNo)
                                {
                                case 0:
                                    AttributeData.TexCoord_0.Add(vertTexCoord);
                                    break;

                                case 1:
                                    AttributeData.TexCoord_1.Add(vertTexCoord);
                                    break;

                                case 2:
                                    AttributeData.TexCoord_2.Add(vertTexCoord);
                                    break;

                                case 3:
                                    AttributeData.TexCoord_3.Add(vertTexCoord);
                                    break;

                                case 4:
                                    AttributeData.TexCoord_4.Add(vertTexCoord);
                                    break;

                                case 5:
                                    AttributeData.TexCoord_5.Add(vertTexCoord);
                                    break;

                                case 6:
                                    AttributeData.TexCoord_6.Add(vertTexCoord);
                                    break;

                                case 7:
                                    AttributeData.TexCoord_7.Add(vertTexCoord);
                                    break;
                                }

                                vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord));
                                break;
                            }
                        }
                        prim.Vertices.Add(vert);
                    }
                }
                else if (primtype == Enums.GXPrimitiveType.Triangles)
                {
                    for (int j = 0; j < primbrawl.Indices.Count / 3; j++)
                    {
                        int    vert1Index  = (int)primbrawl.Indices[j * 3 + 0];
                        int    vert2Index  = (int)primbrawl.Indices[j * 3 + 1];
                        int    vert3Index  = (int)primbrawl.Indices[j * 3 + 2];
                        Weight vert1Weight = weights[vert1Index];
                        Weight vert2Weight = weights[vert2Index];
                        Weight vert3Weight = weights[vert3Index];
                        int    oldcount    = numMatrices;
                        if (!packetWeights.Contains(vert1Weight))
                        {
                            packetWeights.Add(vert1Weight);
                            numMatrices++;
                        }
                        if (!packetWeights.Contains(vert2Weight))
                        {
                            packetWeights.Add(vert2Weight);
                            numMatrices++;
                        }
                        if (!packetWeights.Contains(vert3Weight))
                        {
                            packetWeights.Add(vert3Weight);
                            numMatrices++;
                        }

                        // There are too many matrices, we need to create a new packet
                        if (numMatrices > MaxMatricesPerPacket)
                        {
                            //Console.WriteLine(String.Format("Making new packet because previous one would have {0}", numMatrices));
                            //Console.WriteLine(oldcount);
                            pack.Primitives.Add(prim);
                            Packets.Add(pack);

                            prim = new Primitive(Enums.GXPrimitiveType.Triangles);
                            pack = new Packet();

                            packetWeights.Clear();
                            numMatrices = 0;

                            if (!packetWeights.Contains(vert1Weight))
                            {
                                packetWeights.Add(vert1Weight);
                                numMatrices++;
                            }
                            if (!packetWeights.Contains(vert2Weight))
                            {
                                packetWeights.Add(vert2Weight);
                                numMatrices++;
                            }
                            if (!packetWeights.Contains(vert3Weight))
                            {
                                packetWeights.Add(vert3Weight);
                                numMatrices++;
                            }
                        }

                        int[]    vertexIndexArray = new int[] { vert1Index, vert2Index, vert3Index };
                        Weight[] vertWeightArray  = new Weight[] { vert1Weight, vert2Weight, vert3Weight };

                        for (int i = 0; i < 3; i++)
                        {
                            Vertex vert      = new Vertex();
                            int    vertIndex = vertexIndexArray[i];
                            Weight curWeight = vertWeightArray[i];

                            vert.SetWeight(curWeight);

                            foreach (Enums.GXVertexAttribute attrib in activeAttribs)
                            {
                                switch (attrib)
                                {
                                case Enums.GXVertexAttribute.PositionMatrixIdx:
                                    int newMatrixIndex = -1;

                                    if (curWeight.WeightCount == 1)
                                    {
                                        newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight);
                                    }
                                    else
                                    {
                                        if (!envelopes.Weights.Contains(curWeight))
                                        {
                                            envelopes.Weights.Add(curWeight);
                                        }

                                        int envIndex = envelopes.Weights.IndexOf(curWeight);
                                        int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight);

                                        if (drwIndex == -1)
                                        {
                                            throw new System.Exception($"Model has unweighted vertices in mesh \"{mesh.Name}\". Please weight all vertices to at least one bone.");
                                        }

                                        newMatrixIndex = drwIndex;
                                        partialWeight.Indices[drwIndex] = envIndex;
                                    }

                                    if (!pack.MatrixIndices.Contains(newMatrixIndex))
                                    {
                                        pack.MatrixIndices.Add(newMatrixIndex);
                                    }

                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex));
                                    break;

                                case Enums.GXVertexAttribute.Position:
                                    List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position);
                                    Vector3        vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3();

                                    if (curWeight.WeightCount == 1)
                                    {
                                        Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]];

                                        Vector3 transVec = Vector3.TransformPosition(vertPos, ibm);
                                        if (!posData.Contains(transVec))
                                        {
                                            posData.Add(transVec);
                                        }
                                        AttributeData.Positions.Add(transVec);
                                        vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec));
                                    }
                                    else
                                    {
                                        if (!posData.Contains(vertPos))
                                        {
                                            posData.Add(vertPos);
                                        }
                                        AttributeData.Positions.Add(vertPos);

                                        vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos));
                                    }
                                    break;

                                case Enums.GXVertexAttribute.Normal:
                                    List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal);
                                    Vector3        vertNrm  = mesh.Normals[vertIndex].ToOpenTKVector3();

                                    if (curWeight.WeightCount == 1)
                                    {
                                        Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]];
                                        vertNrm = Vector3.TransformNormal(vertNrm, ibm);
                                        if (!normData.Contains(vertNrm))
                                        {
                                            normData.Add(vertNrm);
                                        }
                                    }
                                    else
                                    {
                                        if (!normData.Contains(vertNrm))
                                        {
                                            normData.Add(vertNrm);
                                        }
                                    }

                                    AttributeData.Normals.Add(vertNrm);
                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm));
                                    break;

                                case Enums.GXVertexAttribute.Color0:
                                case Enums.GXVertexAttribute.Color1:
                                    int          colNo   = (int)attrib - 11;
                                    List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo);
                                    Color        vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA();

                                    if (colNo == 0)
                                    {
                                        AttributeData.Color_0.Add(vertCol);
                                    }
                                    else
                                    {
                                        AttributeData.Color_1.Add(vertCol);
                                    }

                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol));
                                    break;

                                case Enums.GXVertexAttribute.Tex0:
                                case Enums.GXVertexAttribute.Tex1:
                                case Enums.GXVertexAttribute.Tex2:
                                case Enums.GXVertexAttribute.Tex3:
                                case Enums.GXVertexAttribute.Tex4:
                                case Enums.GXVertexAttribute.Tex5:
                                case Enums.GXVertexAttribute.Tex6:
                                case Enums.GXVertexAttribute.Tex7:
                                    int            texNo        = (int)attrib - 13;
                                    List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo);
                                    Vector2        vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2();
                                    vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y);

                                    switch (texNo)
                                    {
                                    case 0:
                                        AttributeData.TexCoord_0.Add(vertTexCoord);
                                        break;

                                    case 1:
                                        AttributeData.TexCoord_1.Add(vertTexCoord);
                                        break;

                                    case 2:
                                        AttributeData.TexCoord_2.Add(vertTexCoord);
                                        break;

                                    case 3:
                                        AttributeData.TexCoord_3.Add(vertTexCoord);
                                        break;

                                    case 4:
                                        AttributeData.TexCoord_4.Add(vertTexCoord);
                                        break;

                                    case 5:
                                        AttributeData.TexCoord_5.Add(vertTexCoord);
                                        break;

                                    case 6:
                                        AttributeData.TexCoord_6.Add(vertTexCoord);
                                        break;

                                    case 7:
                                        AttributeData.TexCoord_7.Add(vertTexCoord);
                                        break;
                                    }

                                    vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord));
                                    break;
                                }
                            }

                            prim.Vertices.Add(vert);
                        }
                    }
                }

                /*
                 * if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip) {
                 *  Debug.Assert(prim.Vertices.Count >= 3);
                 * }
                 * else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles) {
                 *  Debug.Assert(prim.Vertices.Count % 3 == 0);
                 * }*/
                //Console.WriteLine(String.Format("We had this many matrices: {0}", numMatrices));
                pack.Primitives.Add(prim);
            }
            Packets.Add(pack);

            int mostmatrices = 0;

            if (true)
            {
                List <Weight> packWeights = new List <Weight>();
                foreach (Packet packet in Packets)
                {
                    int matrices = 0;

                    foreach (Primitive prim in packet.Primitives)
                    {
                        foreach (Vertex vert in prim.Vertices)
                        {
                            if (!packWeights.Contains(vert.VertexWeight))
                            {
                                packWeights.Add(vert.VertexWeight);
                                matrices++;
                            }
                        }


                        if (prim.PrimitiveType == Enums.GXPrimitiveType.TriangleStrip)
                        {
                            Debug.Assert(prim.Vertices.Count >= 3);
                        }
                        else if (prim.PrimitiveType == Enums.GXPrimitiveType.Triangles)
                        {
                            Debug.Assert(prim.Vertices.Count % 3 == 0);
                        }
                    }
                    if (matrices > mostmatrices)
                    {
                        mostmatrices = matrices;
                    }
                    //Debug.Assert(matrices <= MaxMatricesPerPacket);
                    //Console.WriteLine(matrices);
                    packWeights.Clear();
                }
            }
            //Console.WriteLine(String.Format("Most matrices: {0}", mostmatrices));
        }
Esempio n. 6
0
        public Model(EndianBinaryReader reader, Arguments args)
        {
            ModelStats = new BMDInfo();

            int j3d2Magic  = reader.ReadInt32();
            int modelMagic = reader.ReadInt32();

            if (j3d2Magic != 0x4A334432 && j3d2Magic != 0x3244334A)
            {
                throw new Exception("Model was not a BMD or BDL! (J3D2 magic not found)");
            }
            if ((modelMagic != 0x62646C34) && (modelMagic != 0x626D6433 && modelMagic != 0x346C6462))
            {
                throw new Exception("Model was not a BMD or BDL! (Model type was not bmd3 or bdl4)");
            }

            //Reversed magic found. File uses little endian byte order.
            if (j3d2Magic == 0x3244334A)
            {
                reader.CurrentEndian = Endian.Little;
                littleEndian         = true;
            }

            int modelSize    = reader.ReadInt32();
            int sectionCount = reader.ReadInt32();

            ModelStats.TotalSize = modelSize;

            // Skip the dummy section, SVR3
            reader.Skip(16);

            Scenegraph        = new INF1(reader, 32, ModelStats);
            VertexData        = new VTX1(reader, (int)reader.BaseStream.Position, ModelStats);
            SkinningEnvelopes = new EVP1(reader, (int)reader.BaseStream.Position, ModelStats);
            PartialWeightData = new DRW1(reader, (int)reader.BaseStream.Position, ModelStats);
            Joints            = new JNT1(reader, (int)reader.BaseStream.Position, ModelStats);
            SkinningEnvelopes.SetInverseBindMatrices(Joints.FlatSkeleton);
            Shapes = SHP1.Create(reader, (int)reader.BaseStream.Position, ModelStats);
            Shapes.SetVertexWeights(SkinningEnvelopes, PartialWeightData);
            Materials = new MAT3(reader, (int)reader.BaseStream.Position, ModelStats);
            SkipMDL3(reader);
            Textures = new TEX1(reader, (int)reader.BaseStream.Position, ModelStats);
            Materials.SetTextureNames(Textures);


            if (args.output_materials_path != "")
            {
                Materials.DumpMaterials(Path.GetDirectoryName(args.output_materials_path));
            }
            else
            {
                if (args.output_path != "")
                {
                    string outDir        = Path.GetDirectoryName(args.output_path);
                    string filenameNoExt = Path.GetFileNameWithoutExtension(args.input_path);
                    Materials.DumpMaterials(Path.Combine(outDir, filenameNoExt + "_materials.json"));
                }
                else
                {
                    string inDir         = Path.GetDirectoryName(args.input_path);
                    string filenameNoExt = Path.GetFileNameWithoutExtension(args.input_path);

                    Materials.DumpMaterials(Path.Combine(inDir, filenameNoExt + "_materials.json"));
                }
            }

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 7
0
        public Model(Scene scene, Arguments args, List <SuperBMDLib.Materials.Material> mat_presets = null, string additionalTexPath = null)
        {
            ModelStats = new BMDInfo();
            if (args.ensure_one_material_per_mesh)
            {
                EnsureOneMaterialPerMesh(scene);
            }

            Console.WriteLine();
            if (args.sort_meshes)
            {
                SortMeshesByObjectNames(scene);
                Console.WriteLine();
            }


            // For FBX mesh names are empty, instead we need to check the nodes and rename
            // the meshes after the node names.
            foreach (Assimp.Node node in scene.RootNode.Children)
            {
                foreach (int meshindex in node.MeshIndices)
                {
                    Assimp.Mesh mesh = scene.Meshes[meshindex];
                    if (mesh.Name == String.Empty)
                    {
                        mesh.Name = node.Name;
                    }
                }
            }

            Console.WriteLine();
            Console.Write("Searching for the Skeleton Root");
            Assimp.Node root = null;
            for (int i = 0; i < scene.RootNode.ChildCount; i++)
            {
                if (scene.RootNode.Children[i].Name.ToLowerInvariant() == "skeleton_root")
                {
                    if (scene.RootNode.Children[i].ChildCount == 0)
                    {
                        throw new System.Exception("skeleton_root has no children! If you are making a rigged model, make sure skeleton_root contains the root of your skeleton.");
                    }
                    root = scene.RootNode.Children[i].Children[0];
                    break;
                }
                Console.Write(".");
            }

            Console.Write(root == null ? "✓ No Skeleton found" : "✓ Skeleton Found");
            Console.WriteLine();

            foreach (Mesh mesh in scene.Meshes)
            {
                if (mesh.HasBones && root == null)
                {
                    throw new System.Exception("Model uses bones but the skeleton root has not been found! Make sure your skeleton is inside a dummy object called 'skeleton_root'.");
                }
            }


            if (args.rotate_model)
            {
                Console.WriteLine();
                Console.Write("Rotating the model");
                int       i         = 0;
                Matrix4x4 rotate    = Matrix4x4.FromRotationX((float)(-(1 / 2.0) * Math.PI));
                Matrix4x4 rotateinv = rotate;
                rotateinv.Inverse();


                foreach (Mesh mesh in scene.Meshes)
                {
                    if (root != null)
                    {
                        foreach (Assimp.Bone bone in mesh.Bones)
                        {
                            bone.OffsetMatrix = rotateinv * bone.OffsetMatrix;
                            Console.Write("|");
                        }
                    }

                    for (i = 0; i < mesh.VertexCount; i++)
                    {
                        Vector3D vertex = mesh.Vertices[i];
                        vertex.Set(vertex.X, vertex.Z, -vertex.Y);
                        mesh.Vertices[i] = vertex;
                    }
                    for (i = 0; i < mesh.Normals.Count; i++)
                    {
                        Vector3D norm = mesh.Normals[i];
                        norm.Set(norm.X, norm.Z, -norm.Y);

                        mesh.Normals[i] = norm;
                    }
                    Console.Write(".");
                }
                Console.Write("✓");
                Console.WriteLine();
            }

            foreach (Mesh mesh in scene.Meshes)
            {
                if (mesh.HasNormals)
                {
                    for (int i = 0; i < mesh.Normals.Count; i++)
                    {
                        Vector3D normal = mesh.Normals[i];
                        normal.X        = (float)Math.Round(normal.X, 4);
                        normal.Y        = (float)Math.Round(normal.Y, 4);
                        normal.Z        = (float)Math.Round(normal.Z, 4);
                        mesh.Normals[i] = normal;
                    }
                }
            }

            Console.WriteLine();
            Console.WriteLine("Generating the Vertex Data ->");
            VertexData = new VTX1(scene, args.forceFloat);
            Console.WriteLine();
            Console.Write("Generating the Bone Data");
            Joints = new JNT1(scene, VertexData);
            Console.WriteLine();
            Console.WriteLine("Generating the Texture Data -> ");
            Textures = new TEX1(scene, args);
            Console.WriteLine();
            Console.Write("Generating the Envelope Data");
            SkinningEnvelopes = new EVP1();
            SkinningEnvelopes.SetInverseBindMatrices(scene, Joints.FlatSkeleton);

            Console.WriteLine();
            Console.Write("Generating the Weight Data");
            PartialWeightData = new DRW1(scene, Joints.BoneNameIndices);
            Console.WriteLine();

            Console.WriteLine();
            Console.WriteLine("Generating the Mesh Data ->");
            Shapes = SHP1.Create(scene, Joints.BoneNameIndices, VertexData.Attributes, SkinningEnvelopes, PartialWeightData,
                                 args.tristrip_mode, args.degenerateTriangles);

            Console.WriteLine();
            Console.WriteLine("Generating the Material Data ->");
            Materials = new MAT3(scene, Textures, Shapes, args, mat_presets);

            Console.WriteLine();
            Console.WriteLine("Loading the Textures ->");
            if (additionalTexPath == null)
            {
                Materials.LoadAdditionalTextures(Textures, Path.GetDirectoryName(args.input_path), args.readMipmaps);
            }
            else
            {
                Materials.LoadAdditionalTextures(Textures, additionalTexPath, args.readMipmaps);
            }

            Materials.MapTextureNamesToIndices(Textures);

            if (args.output_bdl)
            {
                Console.WriteLine();
                Console.WriteLine("Compiling the MDL3 ->");
                MatDisplayList = new MDL3(Materials.m_Materials, Textures.Textures);
            }
            if (args.littleEndian)
            {
                littleEndian = true;
            }

            Console.WriteLine();
            Console.Write("Generating the Joints");
            Scenegraph = new INF1(scene, Joints);

            foreach (Geometry.Shape shape in Shapes.Shapes)
            {
                packetCount += shape.Packets.Count;
            }

            vertexCount = VertexData.Attributes.Positions.Count;
        }
Esempio n. 8
0
        public void ProcessVerticesWithWeights(Mesh mesh, VertexData vertData, Dictionary <string, int> boneNames, EVP1 envelopes, DRW1 partialWeight)
        {
            Packet pack = new Packet();

            Primitive prim = new Primitive(Enums.GXPrimitiveType.Triangles);
            List <Enums.GXVertexAttribute> activeAttribs = Descriptor.GetActiveAttributes();

            AttributeData.SetAttributesFromList(activeAttribs);

            List <Weight> packetWeights = new List <Weight>();
            int           numMatrices   = 0;

            foreach (Face face in mesh.Faces)
            {
                int    vert1Index  = face.Indices[0];
                int    vert2Index  = face.Indices[1];
                int    vert3Index  = face.Indices[2];
                Weight vert1Weight = new Weight();
                Weight vert2Weight = new Weight();
                Weight vert3Weight = new Weight();

                // Get the weights for this tri's vertices
                foreach (Assimp.Bone bone in mesh.Bones)
                {
                    foreach (VertexWeight weight in bone.VertexWeights)
                    {
                        if (weight.VertexID == vert1Index)
                        {
                            vert1Weight.AddWeight(weight.Weight, boneNames[bone.Name]);
                        }
                        if (weight.VertexID == vert2Index)
                        {
                            vert2Weight.AddWeight(weight.Weight, boneNames[bone.Name]);
                        }
                        if (weight.VertexID == vert3Index)
                        {
                            vert3Weight.AddWeight(weight.Weight, boneNames[bone.Name]);
                        }
                    }
                }

                if (!packetWeights.Contains(vert1Weight))
                {
                    numMatrices += vert1Weight.WeightCount;
                }
                if (!packetWeights.Contains(vert2Weight))
                {
                    numMatrices += vert2Weight.WeightCount;
                }
                if (!packetWeights.Contains(vert3Weight))
                {
                    numMatrices += vert1Weight.WeightCount;
                }

                // There are too many matrices, we need to create a new packet
                if (numMatrices > 10)
                {
                    pack.Primitives.Add(prim);
                    Packets.Add(pack);

                    prim = new Primitive(Enums.GXPrimitiveType.Triangles);
                    pack = new Packet();

                    packetWeights.Clear();
                    numMatrices = 0;

                    packetWeights.Add(vert1Weight);
                    packetWeights.Add(vert2Weight);
                    packetWeights.Add(vert3Weight);

                    if (!packetWeights.Contains(vert1Weight))
                    {
                        numMatrices += vert1Weight.WeightCount;
                    }
                    if (!packetWeights.Contains(vert2Weight))
                    {
                        numMatrices += vert2Weight.WeightCount;
                    }
                    if (!packetWeights.Contains(vert3Weight))
                    {
                        numMatrices += vert1Weight.WeightCount;
                    }
                }
                // Matrix count is below 10, we can continue using the current packet
                else
                {
                    if (!packetWeights.Contains(vert1Weight))
                    {
                        packetWeights.Add(vert1Weight);
                    }
                    if (!packetWeights.Contains(vert2Weight))
                    {
                        packetWeights.Add(vert2Weight);
                    }
                    if (!packetWeights.Contains(vert3Weight))
                    {
                        packetWeights.Add(vert3Weight);
                    }
                }

                int[]    vertexIndexArray = new int[] { vert1Index, vert2Index, vert3Index };
                Weight[] vertWeightArray  = new Weight[] { vert1Weight, vert2Weight, vert3Weight };

                for (int i = 0; i < 3; i++)
                {
                    Vertex vert      = new Vertex();
                    int    vertIndex = vertexIndexArray[i];
                    Weight curWeight = vertWeightArray[i];

                    vert.SetWeight(curWeight);

                    foreach (Enums.GXVertexAttribute attrib in activeAttribs)
                    {
                        switch (attrib)
                        {
                        case Enums.GXVertexAttribute.PositionMatrixIdx:
                            int newMatrixIndex = -1;

                            if (curWeight.WeightCount == 1)
                            {
                                newMatrixIndex = partialWeight.MeshWeights.IndexOf(curWeight);
                            }
                            else
                            {
                                if (!envelopes.Weights.Contains(curWeight))
                                {
                                    envelopes.Weights.Add(curWeight);
                                }

                                int envIndex = envelopes.Weights.IndexOf(curWeight);
                                int drwIndex = partialWeight.MeshWeights.IndexOf(curWeight);

                                newMatrixIndex = drwIndex;
                                partialWeight.Indices[drwIndex] = envIndex;
                            }

                            if (!pack.MatrixIndices.Contains(newMatrixIndex))
                            {
                                pack.MatrixIndices.Add(newMatrixIndex);
                            }

                            vert.SetAttributeIndex(Enums.GXVertexAttribute.PositionMatrixIdx, (uint)pack.MatrixIndices.IndexOf(newMatrixIndex));
                            break;

                        case Enums.GXVertexAttribute.Position:
                            List <Vector3> posData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Position);
                            Vector3        vertPos = mesh.Vertices[vertIndex].ToOpenTKVector3();

                            if (curWeight.WeightCount == 1)
                            {
                                Matrix4 ibm = envelopes.InverseBindMatrices[curWeight.BoneIndices[0]];

                                Vector3 transVec = Vector3.TransformPosition(vertPos, ibm);
                                posData.Add(transVec);
                                AttributeData.Positions.Add(transVec);
                                vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(transVec));
                            }
                            else
                            {
                                AttributeData.Positions.Add(vertPos);

                                vert.SetAttributeIndex(Enums.GXVertexAttribute.Position, (uint)posData.IndexOf(vertPos));
                            }
                            break;

                        case Enums.GXVertexAttribute.Normal:
                            List <Vector3> normData = (List <Vector3>)vertData.GetAttributeData(Enums.GXVertexAttribute.Normal);
                            Vector3        vertNrm  = mesh.Normals[vertIndex].ToOpenTKVector3();
                            AttributeData.Normals.Add(vertNrm);

                            vert.SetAttributeIndex(Enums.GXVertexAttribute.Normal, (uint)normData.IndexOf(vertNrm));
                            break;

                        case Enums.GXVertexAttribute.Color0:
                        case Enums.GXVertexAttribute.Color1:
                            int          colNo   = (int)attrib - 11;
                            List <Color> colData = (List <Color>)vertData.GetAttributeData(Enums.GXVertexAttribute.Color0 + colNo);
                            Color        vertCol = mesh.VertexColorChannels[colNo][vertIndex].ToSuperBMDColorRGBA();

                            if (colNo == 0)
                            {
                                AttributeData.Color_0.Add(vertCol);
                            }
                            else
                            {
                                AttributeData.Color_1.Add(vertCol);
                            }

                            vert.SetAttributeIndex(Enums.GXVertexAttribute.Color0 + colNo, (uint)colData.IndexOf(vertCol));
                            break;

                        case Enums.GXVertexAttribute.Tex0:
                        case Enums.GXVertexAttribute.Tex1:
                        case Enums.GXVertexAttribute.Tex2:
                        case Enums.GXVertexAttribute.Tex3:
                        case Enums.GXVertexAttribute.Tex4:
                        case Enums.GXVertexAttribute.Tex5:
                        case Enums.GXVertexAttribute.Tex6:
                        case Enums.GXVertexAttribute.Tex7:
                            int            texNo        = (int)attrib - 13;
                            List <Vector2> texCoordData = (List <Vector2>)vertData.GetAttributeData(Enums.GXVertexAttribute.Tex0 + texNo);
                            Vector2        vertTexCoord = mesh.TextureCoordinateChannels[texNo][vertIndex].ToOpenTKVector2();
                            vertTexCoord = new Vector2(vertTexCoord.X, 1.0f - vertTexCoord.Y);

                            switch (texNo)
                            {
                            case 0:
                                AttributeData.TexCoord_0.Add(vertTexCoord);
                                break;

                            case 1:
                                AttributeData.TexCoord_1.Add(vertTexCoord);
                                break;

                            case 2:
                                AttributeData.TexCoord_2.Add(vertTexCoord);
                                break;

                            case 3:
                                AttributeData.TexCoord_3.Add(vertTexCoord);
                                break;

                            case 4:
                                AttributeData.TexCoord_4.Add(vertTexCoord);
                                break;

                            case 5:
                                AttributeData.TexCoord_5.Add(vertTexCoord);
                                break;

                            case 6:
                                AttributeData.TexCoord_6.Add(vertTexCoord);
                                break;

                            case 7:
                                AttributeData.TexCoord_7.Add(vertTexCoord);
                                break;
                            }

                            vert.SetAttributeIndex(Enums.GXVertexAttribute.Tex0 + texNo, (uint)texCoordData.IndexOf(vertTexCoord));
                            break;
                        }
                    }

                    prim.Vertices.Add(vert);
                }
            }

            pack.Primitives.Add(prim);
            Packets.Add(pack);
        }