Beispiel #1
0
 public static Vector3 ColorRGB(XObjectStructure color)
 {
     return(new Vector3(Convert.ToSingle(color["red"].Values[0]), Convert.ToSingle(color["green"].Values[0]), Convert.ToSingle(color["blue"].Values[0])));
 }
Beispiel #2
0
 public static Vector3 Vector(XObjectStructure vector)
 {
     return(new Vector3(Convert.ToSingle(vector["x"].Values[0]), Convert.ToSingle(vector["y"].Values[0]), Convert.ToSingle(vector["z"].Values[0])));
 }
Beispiel #3
0
 public static Vector2 TexCoord(XObjectStructure coords2d)
 {
     return(new Vector2(Convert.ToSingle(coords2d["u"].Values[0]), Convert.ToSingle(coords2d["v"].Values[0])));
 }
Beispiel #4
0
            public static void ExportOBJ(XObject mesh, string filename, Matrix transform, bool flipV = true, string textureExtension = null, bool splitMaterials = false)
            {
                if (mesh.DataType.NameData != "Mesh")
                {
                    throw new ArgumentException("'mesh' must be a Mesh object!");
                }

                int vertexCount = (int)mesh["nVertices"].Values[0];
                int faceCount   = (int)mesh["nFaces"].Values[0];

                XObject meshNormals       = null;
                XObject meshTextureCoords = null;
                XObject meshMaterialList  = null;
                XObject meshVertexColors  = null;

                foreach (XChildObject child in mesh.Children)
                {
                    if (child.Object.DataType.NameData == "MeshNormals")
                    {
                        meshNormals = child.Object;
                    }
                    else if (child.Object.DataType.NameData == "MeshTextureCoords")
                    {
                        meshTextureCoords = child.Object;
                    }
                    else if (child.Object.DataType.NameData == "MeshMaterialList")
                    {
                        meshMaterialList = child.Object;
                    }
                    else if ((LOMNTool.Program.Config.GetValueOrDefault("OBJ", "ExportVertexColors", "false").ToLower() == "true" || LOMNTool.Program.Config.GetValueOrDefault("OBJ", "ExportVertexColors", "false").ToLower() == "zbrush") && child.Object.DataType.NameData == "MeshVertexColors")
                    {
                        meshVertexColors = child.Object;
                    }
                }

                using (System.IO.StreamWriter writer = new System.IO.StreamWriter(filename, false))
                    using (System.IO.StreamWriter matWriter = new System.IO.StreamWriter(System.IO.Path.ChangeExtension(filename, ".mtl")))
                    {
                        writer.WriteLine("mtllib " + System.IO.Path.GetFileNameWithoutExtension(filename) + ".mtl");
                        // Write materials
                        for (int i = 0; i < (int)meshMaterialList["nMaterials"].Values[0]; i++)
                        {
                            matWriter.WriteLine("newmtl Material_" + i.ToString().PadLeft(3, '0') + "_Mat");
                            XObject          material      = meshMaterialList[i].Object;
                            XObjectStructure faceColor     = (XObjectStructure)material["faceColor"].Values[0];
                            float            specExponent  = (float)(double)material["power"].Values[0];
                            XObjectStructure specularColor = (XObjectStructure)material["specularColor"].Values[0];
                            XObjectStructure emissiveColor = (XObjectStructure)material["emissiveColor"].Values[0];

                            matWriter.WriteLine("Kd " + (double)faceColor["red"].Values[0] + " " + (double)faceColor["green"].Values[0] + " " + (double)faceColor["blue"].Values[0]);
                            matWriter.WriteLine("d " + (double)faceColor["alpha"].Values[0]);
                            matWriter.WriteLine("Tr " + (1.0 - (double)faceColor["alpha"].Values[0]));

                            matWriter.WriteLine("Ns " + specExponent);
                            // Hack for games with white spec color but zero exponent that means no spec
                            if (specExponent > 0.0)
                            {
                                matWriter.WriteLine("Ks " + (double)specularColor["red"].Values[0] + " " + (double)specularColor["green"].Values[0] + " " + (double)specularColor["blue"].Values[0]);
                            }
                            else
                            {
                                matWriter.WriteLine("Ks 0 0 0");
                            }

                            matWriter.WriteLine("Ke " + (double)emissiveColor["red"].Values[0] + " " + (double)emissiveColor["green"].Values[0] + " " + (double)emissiveColor["blue"].Values[0]);

                            // Look for the possible TextureFilename
                            foreach (XChildObject child in material.Children)
                            {
                                if (child.Object.DataType.NameData == "TextureFilename")
                                {
                                    string texFilename = (string)child.Object["filename"].Values[0];
                                    if (textureExtension != null)
                                    {
                                        texFilename = System.IO.Path.ChangeExtension(texFilename, textureExtension);
                                    }
                                    matWriter.WriteLine("map_Kd " + texFilename);
                                    break;
                                }
                            }
                        }

                        // Gather positions
                        for (int i = 0; i < vertexCount; i++)
                        {
                            Vector3 pos  = Vector((XObjectStructure)mesh["vertices"].Values[i]);
                            Vector4 pos2 = Vector3.Transform(pos, transform);
                            writer.WriteLine("v " + pos2.X + " " + pos2.Y + " " + pos2.Z);
                        }

                        /*if (LOMNTool.Program.Config.GetValueOrDefault("OBJ", "ExportVertexColors", "false").ToLower() == "zbrush" && meshVertexColors != null)
                         * {
                         *  writer.WriteLine("\n\n# Here goes my attempt at writing the MRGB block for ZBrush polypaint:");
                         *
                         *  writer.Write("#MRGB ");
                         *  foreach
                         *
                         *  writer.WriteLine("# End of MRGB block");
                         * }*/

                        // Gather normals
                        int normalCount = (int)meshNormals["nNormals"].Values[0];
                        for (int i = 0; i < normalCount; i++)
                        {
                            Vector3 norm  = Vector((XObjectStructure)meshNormals["normals"].Values[i]);
                            Vector4 norm2 = Vector3.Transform(norm, transform);
                            writer.WriteLine("vn " + norm2.X + " " + norm2.Y + " " + norm2.Z);
                        }

                        // Gather texture coordinates
                        int uvCount = (int)meshTextureCoords["nTextureCoords"].Values[0];
                        if (uvCount != vertexCount)
                        {
                            throw new FormatException("Different number of vertices and texture coordinates!");
                        }
                        for (int i = 0; i < uvCount; i++)
                        {
                            Vector2 uv = TexCoord((XObjectStructure)meshTextureCoords["textureCoords"].Values[i]);
                            if (flipV)
                            {
                                uv.Y = 1.0f - uv.Y;
                            }
                            writer.WriteLine("vt " + uv.X + " " + uv.Y);
                        }

                        if (meshVertexColors != null)
                        {
                            int colorCount = (int)meshVertexColors["nVertexColors"].Values[0];
                            if (colorCount != vertexCount)
                            {
                                throw new FormatException("ExportOBJ: Mesh vertex count (" + vertexCount + ") isn't equal to the vertex color count! (" + colorCount + ")");
                            }
                            Vector4[] colors = new Vector4[colorCount];
                            foreach (XObjectStructure value in meshVertexColors["vertexColors"].Values)
                            {
                                int     index = (int)value["index"].Values[0];
                                Vector4 color = XUtils.ColorRGBA((XObjectStructure)value.Members[1].Values[0]); // ["indexColor"]
                                if (colors[index] == Vector4.Zero)
                                {
                                    colors[index] = color;
                                }
                                else
                                {
                                    Console.WriteLine("ExportCOLLADA: Multiple colors defined for vertex " + index + "!");
                                }
                            }

                            switch (LOMNTool.Program.Config.GetValueOrDefault("OBJ", "ExportVertexColors", "false").ToLower())
                            {
                            case "true":
                                for (int i = 0; i < colorCount; i++)
                                {
                                    writer.WriteLine("vc " + colors[i].X.ToString(System.Globalization.CultureInfo.InvariantCulture) + " "
                                                     + colors[i].Y.ToString(System.Globalization.CultureInfo.InvariantCulture) + " "
                                                     + colors[i].Z.ToString(System.Globalization.CultureInfo.InvariantCulture) + " "
                                                     + colors[i].W.ToString(System.Globalization.CultureInfo.InvariantCulture));
                                }
                                break;

                            case "zbrush":
                                writer.WriteLine("\n\n# Here goes my attempt at writing the MRGB block for ZBrush polypaint:");

                                writer.Write("#MRGB ");

                                for (int i = 0; i < colors.Length; i++)
                                {
                                    writer.Write("FF");
                                    writer.Write(((byte)(colors[i].X * colors[i].W * 255)).ToString("X2"));
                                    writer.Write(((byte)(colors[i].Y * colors[i].W * 255)).ToString("X2"));
                                    writer.Write(((byte)(colors[i].Z * colors[i].W * 255)).ToString("X2"));

                                    if (i % 64 == 0 && i > 0 && i < colors.Length - 1)
                                    {
                                        writer.Write("\n#MRGB ");
                                    }
                                }

                                writer.WriteLine("\n# End of MRGB block\n");
                                break;
                            }
                        }

                        // Write each face
                        int mtl = -1;
                        for (int i = 0; i < faceCount; i++)
                        {
                            if ((int)(meshNormals["nFaceNormals"].Values[0]) == 0)
                            {
                                Console.WriteLine("[ERROR]: No normals!");
                            }

                            XObjectStructure face        = (XObjectStructure)mesh["faces"].Values[i];
                            XObjectStructure faceNormals = (XObjectStructure)meshNormals["faceNormals"].Values[i];

                            int newMaterialIndex = (int)meshMaterialList["faceIndexes"].Values[i];
                            if (newMaterialIndex != mtl)
                            {
                                if (splitMaterials)
                                {
                                    writer.WriteLine("g Material_" + newMaterialIndex.ToString().PadLeft(3, '0'));
                                }
                                writer.WriteLine("usemtl Material_" + newMaterialIndex.ToString().PadLeft(3, '0') + "_Mat");
                                mtl = newMaterialIndex;
                            }

                            writer.Write("f ");
                            for (int v = 0; v < (int)face["nFaceVertexIndices"].Values[0]; v++)
                            {
                                int vIndex = (int)face["faceVertexIndices"].Values[v] + 1;
                                int nIndex = (int)faceNormals["faceVertexIndices"].Values[v] + 1;

                                writer.Write(vIndex + "/" + vIndex + "/" + nIndex + (meshVertexColors != null ? "/" + vIndex : "") + " ");
                            }
                            writer.WriteLine();
                        }
                    }
            }