예제 #1
0
        public void ExportAssImp(string fileName, string modelType, ExportSettings settings, Arguments cmdargs)
        {
            fileName = Path.GetFullPath(fileName); // Get absolute path instead of relative
            string outDir        = Path.GetDirectoryName(fileName);
            string fileNameNoExt = Path.GetFileNameWithoutExtension(fileName);

            if (modelType == "obj")
            {
                fileName = Path.Combine(outDir, fileNameNoExt + ".obj");
            }
            else
            {
                fileName = Path.Combine(outDir, fileNameNoExt + ".dae");
            }
            Scene outScene = new Scene {
                RootNode = new Node("RootNode")
            };

            Console.WriteLine();
            Console.WriteLine("Processing Materials ->");
            Materials.FillScene(outScene, Textures, outDir);
            Console.WriteLine();
            Console.WriteLine("Processing Meshes ->");
            Shapes.FillScene(outScene, VertexData.Attributes, Joints.FlatSkeleton, SkinningEnvelopes.InverseBindMatrices);
            Console.WriteLine();
            Console.Write("Processing Skeleton");
            Scenegraph.FillScene(outScene, Joints.FlatSkeleton, settings.UseSkeletonRoot);
            Scenegraph.CorrectMaterialIndices(outScene, Materials);
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Processing Textures ->");
            Textures.DumpTextures(outDir, fileNameNoExt + "_tex_headers.json", true, cmdargs.readMipmaps);

            string infPath = Path.Combine(outDir, fileNameNoExt + "_hierarchy.json");

            this.Scenegraph.DumpJson(infPath);

            Console.WriteLine();
            Console.WriteLine("Removing Duplicate Verticies ->");
            foreach (Mesh mesh in outScene.Meshes)
            {
                Console.Write(mesh.Name.Replace('_', ' ') + ": ");
                // Assimp has a JoinIdenticalVertices post process step, but we can't use that or the skinning info we manually add won't take it into account.
                RemoveDuplicateVertices(mesh);
                Console.Write("✓");
                Console.WriteLine();
            }


            AssimpContext cont = new AssimpContext();

            if (modelType == "obj")
            {
                Console.WriteLine("Writing the OBJ file...");
                cont.ExportFile(outScene, fileName, "obj");//, PostProcessSteps.ValidateDataStructure);
                using (System.IO.StreamWriter file = new System.IO.StreamWriter(fileName)) {
                    string mtllibname = fileName.Split(new char[] { '\\', '/' }, StringSplitOptions.RemoveEmptyEntries).Last() + ".mtl";
                    file.WriteLine(String.Format("mtllib {0}", mtllibname));
                    foreach (Assimp.Mesh mesh in outScene.Meshes)
                    {
                        foreach (Assimp.Vector3D vertex in mesh.Vertices)
                        {
                            file.WriteLine(String.Format("v {0} {1} {2}", vertex.X, vertex.Y, vertex.Z));
                        }
                    }

                    foreach (Assimp.Mesh mesh in outScene.Meshes)
                    {
                        foreach (Assimp.Vector3D normal in mesh.Normals)
                        {
                            file.WriteLine(String.Format("vn {0} {1} {2}", normal.X, normal.Y, normal.Z));
                        }
                    }

                    foreach (Assimp.Mesh mesh in outScene.Meshes)
                    {
                        if (mesh.HasTextureCoords(0))
                        {
                            foreach (Assimp.Vector3D uv in mesh.TextureCoordinateChannels[0])
                            {
                                file.WriteLine(String.Format("vt {0} {1}", uv.X, uv.Y));
                            }
                        }
                    }

                    int vertex_offset = 1;

                    foreach (Assimp.Mesh mesh in outScene.Meshes)
                    {
                        string material_name = outScene.Materials[mesh.MaterialIndex].Name;
                        file.WriteLine(String.Format("usemtl {0}", material_name));



                        foreach (Assimp.Face face in mesh.Faces)
                        {
                            file.Write("f ");
                            foreach (int index in face.Indices)
                            {
                                file.Write(index + vertex_offset);
                                if (mesh.HasTextureCoords(0))
                                {
                                    file.Write("/");
                                    file.Write(index + vertex_offset);
                                }
                                if (!mesh.HasTextureCoords(0) && mesh.HasNormals)
                                {
                                    file.Write("//");
                                    file.Write(index + vertex_offset);
                                }
                                else if (mesh.HasNormals)
                                {
                                    file.Write("/");
                                    file.Write(index + vertex_offset);
                                }
                                file.Write(" ");
                            }
                            file.Write("\n");
                        }

                        vertex_offset += mesh.VertexCount;
                    }
                }
                return;
            }
            else
            {
                cont.ExportFile(outScene, fileName, "collada", PostProcessSteps.ValidateDataStructure);
            }

            //if (SkinningEnvelopes.Weights.Count == 0)
            //    return; // There's no skinning information, so we can stop here

            // Now we need to add some skinning info, since AssImp doesn't do it for some bizarre reason

            StreamWriter test = new StreamWriter(fileName + ".tmp");
            StreamReader dae  = File.OpenText(fileName);

            Console.WriteLine();
            Console.Write("Finalizing the Mesh");
            while (!dae.EndOfStream)
            {
                string line = dae.ReadLine();

                if (line == "  <library_visual_scenes>")
                {
                    AddControllerLibrary(outScene, test);
                    test.WriteLine(line);
                    test.Flush();
                }
                else if (line.Contains("<node"))
                {
                    string[] testLn = line.Split('\"');
                    string   name   = testLn[3];

                    if (Joints.FlatSkeleton.Exists(x => x.Name == name))
                    {
                        string jointLine = line.Replace(">", $" sid=\"{ name }\" type=\"JOINT\">");
                        test.WriteLine(jointLine);
                        test.Flush();
                    }
                    else
                    {
                        test.WriteLine(line);
                        test.Flush();
                    }
                }
                else if (line.Contains("</visual_scene>"))
                {
                    foreach (Mesh mesh in outScene.Meshes)
                    {
                        string matname      = "mat";
                        bool   keepmatnames = false;
                        if (keepmatnames == true)
                        {
                            matname = AssimpMatnameSanitize(mesh.MaterialIndex, outScene.Materials[mesh.MaterialIndex].Name);
                        }
                        else
                        {
                            matname = AssimpMatnameSanitize(mesh.MaterialIndex, Materials.m_Materials[mesh.MaterialIndex].Name);
                        }

                        test.WriteLine($"      <node id=\"{ mesh.Name }\" name=\"{ mesh.Name }\" type=\"NODE\">");

                        test.WriteLine($"       <instance_controller url=\"#{ mesh.Name }-skin\">");
                        test.WriteLine("        <skeleton>#skeleton_root</skeleton>");
                        test.WriteLine("        <bind_material>");
                        test.WriteLine("         <technique_common>");
                        test.WriteLine($"          <instance_material symbol=\"m{matname}\" target=\"#{matname}\" />");
                        test.WriteLine("         </technique_common>");
                        test.WriteLine("        </bind_material>");
                        test.WriteLine("       </instance_controller>");

                        test.WriteLine("      </node>");
                        test.Flush();
                    }

                    test.WriteLine(line);
                    test.Flush();
                }
                else if (line.Contains("<matrix"))
                {
                    string matLine = line.Replace("<matrix>", "<matrix sid=\"matrix\">");
                    test.WriteLine(matLine);
                    test.Flush();
                }
                else
                {
                    test.WriteLine(line);
                    test.Flush();
                }
                Console.Write(".");
            }

            Console.Write("✓");
            Console.WriteLine();

            test.Close();
            dae.Close();

            File.Copy(fileName + ".tmp", fileName, true);
            File.Delete(fileName + ".tmp");
        }