Export unity .obj files

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/wangjiangrong/article/details/97400515

.obj file suffix, is a 3D model file format, text files. Support polygon models (three or more point and area), normals and texture coordinates record. Animation does not record information, material properties, route maps, dynamics and particles.

The main purpose is to export the scene Mesh information to the server to do collision detection (after .obj file server to get a description of how the time being not very good friends), unity can be recognized .obj file, we will export .obj file into unity, the effect is as follows

First look at the contents of a simple .obj files

#type mesh
#Cube
#-------
g Cube
v -53.00000 -2.00000 -62.00000
v 66.00000 -2.00000 -62.00000
v -53.00000 1.00000 -62.00000
v 66.00000 1.00000 -62.00000
v 66.00000 -2.00000 -62.00000
v 66.00000 -2.00000 49.50000
v 66.00000 1.00000 -62.00000
v 66.00000 1.00000 50.50000
v 66.00000 -2.00000 49.50000
v -53.00000 -2.00000 49.50000
v 66.00000 1.00000 50.50000
v -53.00000 1.00000 50.50000
v -53.00000 -2.00000 49.50000
v -53.00000 -2.00000 -62.00000
v -53.00000 1.00000 50.50000
v -53.00000 1.00000 -62.00000
v -53.00000 1.00000 -62.00000
v 66.00000 1.00000 -62.00000
v -53.00000 1.00000 50.50000
v 66.00000 1.00000 50.50000
v -53.00000 -2.00000 49.50000
v 66.00000 -2.00000 49.50000
v -53.00000 -2.00000 -62.00000
v 66.00000 -2.00000 -62.00000

vn 0 0 1
vn 0 0 1
vn 0 0 1
vn 0 0 1
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn -1 0 0
vn 0 0.3162278 -0.9486833
vn 0 0.3162278 -0.9486833
vn 0 0.3162278 -0.9486833
vn 0 0.3162278 -0.9486833
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 1 0 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 -1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0
vn 0 1 0

vt 53 -2
vt -66 -2
vt 53 1
vt -66 1
vt 62 -2
vt -49.5 -2
vt 62 1
vt -50.5 1
vt 66 13.75591
vt -53 13.75591
vt 66 16.91819
vt -53 16.91819
vt 49.5 -2
vt -62 -2
vt 50.5 1
vt -62 1
vt -53 62
vt 66 62
vt -53 -50.5
vt 66 -50.5
vt 53 -49.5
vt -66 -49.5
vt 53 62
vt -66 62

usemtl ProBuilderDefault
usemap ProBuilderDefault
f 1/1/1 2/2/2 3/3/3
f 2/2/2 4/4/4 3/3/3
f 5/5/5 6/6/6 7/7/7
f 6/6/6 8/8/8 7/7/7
f 9/9/9 10/10/10 11/11/11
f 10/10/10 12/12/12 11/11/11
f 13/13/13 14/14/14 15/15/15
f 14/14/14 16/16/16 15/15/15
f 17/17/17 18/18/18 19/19/19
f 18/18/18 20/20/20 19/19/19
f 21/21/21 22/22/22 23/23/23
f 22/22/22 24/24/24 23/23/23

The meaning of a few keywords

#

It represents the beginning of a comment
v Represents the apex
vn Denotes the normal, the normal line can be shared
vt Uv coordinate representation
f Denotes a surface, such as parameters 1/4/1, indices of vertices / UV Index / normal Index
usemtl Material names (Material name) 

These position information can build a framework model.

 

As for how to export .obj file, refer to the documentation: http://wiki.unity3d.com/index.php/ExportOBJ  , we can make some small changes to their own needs, according to some projects, such as our export only static objects, more than one gameobject scenes to merge export and Resolution export and so on.

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.IO;
using System.Text;
using Base.Framework.Tools;

public class ObjExporter : ScriptableObject
{
    [MenuItem("Tools/Export/Export OBJ")]
    static void DoExportWSubmeshes()
    {
        Export(true);
    }

    [MenuItem("Tools/Export/Export OBJ (No Submeshes)")]
    static void DoExportWOSubmeshes()
    {
        Export(false);
    }

    static void Export(bool isSubmeshes)
    {
        if (Selection.gameObjects == null)
        {
            Debug.Log("Didn't Export Any Meshes; Nothing was selected!");
            return;
        }
        string fileName = EditorUtility.SaveFilePanel("Export .obj file", "", Selection.gameObjects[0].name, "obj");
        PrefabExportToObj.DoExport(Selection.gameObjects[0], fileName, isSubmeshes);
    }

    [MenuItem("Tools/Export/Split Export OBJ")]
    static void SplitExport()
    {
        if (Selection.gameObjects == null)
        {
            Debug.Log("Didn't Export Any Meshes; Nothing was selected!");
            return;
        }
        string filePath = EditorUtility.SaveFolderPanel("Export .obj file", "", Selection.gameObjects[0].name);
        PrefabExportToObj.SplitExport(Selection.gameObjects[0], filePath, true);
    }

    [MenuItem("Tools/Export/Export All OBJ")]
    static void AllExport()
    {
        if (Selection.gameObjects == null)
        {
            Debug.Log("Didn't Export Any Meshes; Nothing was selected!");
            return;
        }
        string filePath = EditorUtility.SaveFolderPanel("Export .obj file", "", Selection.gameObjects[0].name);
        PrefabExportToObj.SplitExport(Selection.gameObjects[0], filePath, true);
        PrefabExportToObj.DoExport(Selection.gameObjects[0], filePath + "/" + Selection.gameObjects[0].name + ".obj", true);
    }
}
using System;
using System.IO;
using System.Text;
using UnityEngine;

namespace Base.Framework.Tools
{
    public class PrefabExportToObj
    {
        static StringBuilder filesString;
        static int fileCount;
        public static void StartRecordFiles(string msg)
        {
            filesString = new StringBuilder();
            filesString.Append("#");
            filesString.Append(msg);
            filesString.Append("\n");
            fileCount = 0;
        }

        public static void ExportRecordFiles(string path)
        {
            if(filesString!=null&& filesString.Length > 0)
            {
                WriteToFile(filesString.ToString(), path);
            }
            filesString.Length = 0;
            filesString = null;
        }

        public static void SplitExport(GameObject target, string path, bool makeSubmeshes)
        {            
            PrefabExportToObj.StartRecordFiles("GameObject:" + target.name);
            Split(target, path);
            PrefabExportToObj.ExportRecordFiles(path + "/dependencies.txt");
        }

        static void Split(GameObject go, string path)
        {
            if (go.isStatic && go.activeSelf && go.activeInHierarchy && go.GetComponent<MeshFilter>() != null)
            {
                DoExport(go, path + "/" + fileCount + ".obj", true);
                fileCount++;
            }
            for (int i = 0; i < go.transform.childCount; i++)
            {
                //Split(go.transform.GetChild(i).gameObject, path + "/" + go.transform.GetChild(i).gameObject.name);
                Split(go.transform.GetChild(i).gameObject, path);
            }
        }

        /// <param name="target"></param>
        /// <param name="path">x/y/z.obj</param>
        /// <param name="makeSubmeshes"></param>
        public static void DoExport(GameObject target, string path, bool makeSubmeshes)
        {
            if (target == null)
            {
                Debug.Log("Didn't Export Any Meshes; Nothing was selected!");
                return;
            }

            string meshName = target.name;

            ObjExporterScript.Start();

            StringBuilder meshString = new StringBuilder();

            Transform t = target.transform;

            meshString.Append($"#type mesh\n");

            //Vector3 originalPosition = t.position;
            //t.position = Vector3.zero;

            if (!makeSubmeshes)
            {
                meshString.Append("g ").Append(t.name).Append("\n");
            }
            meshString.Append(processTransform(t, makeSubmeshes));

            if (filesString != null)
            {
                filesString.Append(Path.GetFileName(path));
                filesString.Append("\n");
            }
            WriteToFile(meshString.ToString(), path);

            //t.position = originalPosition;

            ObjExporterScript.End();
            Debug.Log("Exported Mesh: " + path);
        }

        static string processTransform(Transform t, bool makeSubmeshes)
        {
            StringBuilder meshString = new StringBuilder();

            meshString.Append("#" + t.name
                            + "\n#-------"
                            + "\n");

            if (t.gameObject.isStatic)
            {
                if (makeSubmeshes)
                {
                    meshString.Append("g ").Append(t.name).Append("\n");
                }

                MeshFilter mf = t.GetComponent<MeshFilter>();
                if (mf)
                {
                    meshString.Append(ObjExporterScript.MeshToString(mf, t));
                }
            }

            for (int i = 0; i < t.childCount; i++)
            {
                Transform tc = t.GetChild(i);
                if (tc.gameObject.isStatic && tc.gameObject.activeSelf && tc.gameObject.activeInHierarchy)
                {
                    meshString.Append(processTransform(tc, makeSubmeshes));
                }
            }

            return meshString.ToString();
        }

        static void WriteToFile(string s, string filename)
        {
            string path = Path.GetDirectoryName(filename);
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            using (StreamWriter sw = new StreamWriter(filename))
            {
                sw.Write(s);
            }
        }
    }

    public class ObjExporterScript
    {
        private static int StartIndex = 0;

        public static void Start()
        {
            StartIndex = 0;
        }
        public static void End()
        {
            StartIndex = 0;
        }

        public static string MeshToString(MeshFilter mf, Transform t)
        {
            Vector3 s = t.localScale;
            Vector3 p = t.localPosition;
            Quaternion r = t.localRotation;

            int numVertices = 0;
            Mesh m = mf.sharedMesh;
            if (!m)
            {
                return "####Error####";
            }
            Material[] mats = mf.GetComponent<Renderer>().sharedMaterials;

            StringBuilder sb = new StringBuilder();

            foreach (Vector3 vv in m.vertices)
            {
                Vector3 v = t.TransformPoint(vv);
                numVertices++;
                sb.Append(string.Format("v {0:f5} {1:f5} {2:f5}\n", v.x, v.y, -v.z));
                //sb.Append(string.Format("v {0:f5} {1:f5} {2:f5}\n", v.x, v.y, v.z));
            }
            sb.Append("\n");
            foreach (Vector3 nn in m.normals)
            {
                Vector3 v = r * nn;
                sb.Append(string.Format("vn {0} {1} {2}\n", -v.x, -v.y, v.z));
                //sb.Append(string.Format("vn {0} {1} {2}\n", v.x, v.y, v.z));
            }
            sb.Append("\n");
            foreach (Vector3 v in m.uv)
            {
                sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
            }
            for (int material = 0; material < m.subMeshCount; material++)
            {
                sb.Append("\n");
                sb.Append("usemtl ").Append(mats[material].name).Append("\n");
                sb.Append("usemap ").Append(mats[material].name).Append("\n");

                int[] triangles = m.GetTriangles(material);
                for (int i = 0; i < triangles.Length; i += 3)
                {
                    sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n",
                        triangles[i] + 1 + StartIndex, triangles[i + 1] + 1 + StartIndex, triangles[i + 2] + 1 + StartIndex));
                }
            }

            StartIndex += numVertices;
            return sb.ToString();
        }
    }
}

Finally, we need to choose to export gameobject, select Tool -> Export to

 

Guess you like

Origin blog.csdn.net/wangjiangrong/article/details/97400515