示例#1
0
文件: Model.cs 项目: kai13xd/SuperBMD
        public static Model Load(
            string filePath, List <Materials.Material> mat_presets = null,
            TristripOption triopt = TristripOption.DoNotTriStrip,
            bool flipAxis         = false, bool fixNormals = false, string additionalTexPath = null)
        {
            string extension = Path.GetExtension(filePath);
            Model  output    = null;

            if (extension == ".bmd" || extension == ".bdl")
            {
                using (FileStream str = new FileStream(filePath, FileMode.Open, FileAccess.Read))
                {
                    EndianBinaryReader reader = new EndianBinaryReader(str, Endian.Big);
                    output = new Model(reader, mat_presets);
                }
            }
            else
            {
                Assimp.AssimpContext cont = new Assimp.AssimpContext();

                // AssImp adds dummy nodes for pivots from FBX, so we'll force them off
                cont.SetConfig(new Assimp.Configs.FBXPreservePivotsConfig(false));

                Assimp.PostProcessSteps postprocess = Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.JoinIdenticalVertices;

                if (triopt == TristripOption.DoNotTriStrip)
                {
                    // By not joining identical vertices, the Tri Strip algorithm we use cannot make tristrips,
                    // effectively disabling tri stripping
                    postprocess = Assimp.PostProcessSteps.Triangulate;
                }
                Assimp.Scene aiScene = cont.ImportFile(filePath, postprocess);

                output = new Model(aiScene, filePath, mat_presets, triopt, flipAxis, fixNormals, additionalTexPath);
            }

            return(output);
        }
示例#2
0
文件: Model.cs 项目: kai13xd/SuperBMD
        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;
        }
示例#3
0
 private void TriStripComboBox_SelectedIndexChanged(object sender, EventArgs e) => triopt = (TristripOption)Enum.Parse(typeof(TristripOption), TriStripComboBox.SelectedValue.ToString(), true);