Advertisement
artemisart

Unity3d_OBJ_ImportExport_update1

Nov 3rd, 2012
762
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. public enum SaveFormat {
  2.     OBJ,
  3.     QMO
  4. }
  5. public enum LoadFormat {
  6.     Auto,
  7.     OBJ,
  8.     QMO
  9. }
  10.  
  11. public static class ImportExport {
  12.  
  13. // NEW CODE (more complex but can load .obj from "anywhere" (normally) and generated files are lighter)
  14.     /// <summary>
  15.     /// Save a Mesh to a file.
  16.     /// path : the path were the mesh will be created WITHOUT THE EXTENSION.
  17.     /// format : format of the file (obj/qmo).
  18.     /// overwrite : if the file already exists, should it overwrite ?
  19.     /// </summary>
  20.     public static void SaveToFile (this Mesh mesh, string path, SaveFormat format, bool overwrite) {
  21.         path = path + '.' + format.ToString ().ToLower ();
  22.  
  23.         try {
  24.             if (!File.Exists (path) || overwrite) {
  25.                 File.WriteAllText (path, mesh.SaveToText (format));
  26.             }
  27.             else {
  28.                 Debug.LogWarning ("This file already exists, can't save mesh : " + mesh.name + ", or set overwrite to true.\n@" + path);
  29.             }
  30.         }
  31.         catch (Exception ex) {
  32.             Debug.LogWarning ("Exception while saving mesh : " + mesh.name + "\n@ " + path + "\nex: " + ex);
  33.         }
  34.     }
  35.  
  36.     /// <summary>
  37.     /// Save a Mesh to a text.
  38.     /// </summary>
  39.     public static string SaveToText (this Mesh mesh, SaveFormat format) {
  40.         StringBuilder text = new StringBuilder ();
  41.  
  42.         if (format == SaveFormat.OBJ) {
  43.             text.AppendFormat ("# ModelisaTools exported obj file\n\no {0}\n\n", mesh.name);
  44.  
  45.             List<Vector3> vertices = new List<Vector3> ();
  46.             List<int> veIndex = new List<int> ();
  47.             List<Vector3> uv = new List<Vector3> ();
  48.             List<int> uvIndex = new List<int> ();
  49.             List<Vector3> normals = new List<Vector3> ();
  50.             List<int> noIndex = new List<int> ();
  51.  
  52.             Vector3 tempV3;
  53.             Vector2 tempV2;
  54.  
  55.             for (int i = 0; i < mesh.vertices.Length; i++) {
  56.                 if (!vertices.Contains (mesh.vertices[i])) {
  57.                     vertices.Add (mesh.vertices[i]);
  58.                     veIndex.Add (vertices.Count - 1);
  59.                 }
  60.                 else {
  61.                     veIndex.Add (vertices.IndexOf (mesh.vertices[i]));
  62.                 }
  63.             }
  64.  
  65.             for (int i = 0; i < mesh.uv.Length; i++) {
  66.                 if (!uv.Contains (mesh.uv[i])) {
  67.                     uv.Add (mesh.uv[i]);
  68.                     uvIndex.Add (uv.Count - 1);
  69.                 }
  70.                 else {
  71.                     uvIndex.Add (uv.IndexOf (mesh.uv[i]));
  72.                 }
  73.             }
  74.  
  75.             for (int i = 0; i < mesh.normals.Length; i++) {
  76.                 if (!normals.Contains (mesh.normals[i])) {
  77.                     normals.Add (mesh.normals[i]);
  78.                     noIndex.Add (normals.Count - 1);
  79.                 }
  80.                 else {
  81.                     noIndex.Add (normals.IndexOf (mesh.normals[i]));
  82.                 }
  83.             }
  84.  
  85.             for (int i = 0; i < vertices.Count; i++) {
  86.                 tempV3 = vertices[i];
  87.                 text.AppendFormat ("v {0} {1} {2}\n", tempV3.x, tempV3.y, tempV3.z);
  88.             }
  89.  
  90.             text.Append ("\n");
  91.  
  92.             for (int i = 0; i < uv.Count; i++) {
  93.                 tempV2 = uv[i];
  94.                 text.AppendFormat ("vt {0} {1}\n", tempV2.x, tempV2.y);
  95.             }
  96.  
  97.             text.Append ("\n");
  98.  
  99.             for (int i = 0; i < normals.Count; i++) {
  100.                 tempV3 = normals[i];
  101.                 text.AppendFormat ("vn {0} {1} {2}\n", tempV3.x, tempV3.y, tempV3.z);
  102.             }
  103.  
  104.             text.Append ("\ns off\n\n"); // smoothing group, but unity doesn't support it :/
  105.  
  106.             for (int i = 0; i < mesh.triangles.Length; i += 3) {
  107.                 text.AppendFormat ("f {0}/{1}/{2} {3}/{4}/{5} {6}/{7}/{8}\n",
  108.                                     veIndex[ mesh.triangles[ i ] ] + 1,
  109.                                     uvIndex[ mesh.triangles[ i ] ] + 1,
  110.                                     noIndex[ mesh.triangles[ i ] ] + 1,
  111.  
  112.                                     veIndex[ mesh.triangles[ i + 1 ] ] + 1,
  113.                                     uvIndex[ mesh.triangles[ i + 1 ] ] + 1,
  114.                                     noIndex[ mesh.triangles[ i + 1 ] ] + 1,
  115.  
  116.                                     veIndex[ mesh.triangles[ i + 2 ] ] + 1,
  117.                                     uvIndex[ mesh.triangles[ i + 2 ] ] + 1,
  118.                                     noIndex[ mesh.triangles[ i + 2 ] ] + 1
  119.                                     );
  120.             }
  121.         }
  122.  
  123.         if (format == SaveFormat.QMO) {
  124.             throw new NotImplementedException ();
  125.         }
  126.  
  127.         return text.ToString ();
  128.     }
  129.  
  130.     /// <summary>
  131.     /// Load a Mesh from a file.
  132.     /// path : the path were the mesh will be loaded, WITHOUT THE EXTENSION.
  133.     /// format : format of mesh (obj/qmo).
  134.     /// </summary>
  135.  
  136.     public static void LoadFromFile (this Mesh mesh, string path, LoadFormat format) {
  137.         path = path + '.' + format.ToString ().ToLower ();
  138.  
  139.         try {
  140.             if (File.Exists (path)) {
  141.                 mesh.LoadFromStream (File.OpenText (path), format);
  142.             }
  143.             else {
  144.                 Debug.LogWarning ("This file doesn't exists, can't load mesh @ " + path);
  145.             }
  146.         }
  147.         catch (Exception ex) {
  148.             Debug.LogWarning ("Exception while loading mesh : " + ((mesh == null) ? "NULL_MESH" : mesh.name) + "\n@ " + path + "\nex: " + ex);
  149.         }
  150.     }
  151.  
  152.     /// <summary>
  153.     /// Load a Mesh from a TextReader (StringReader or StreamReader).
  154.     /// </summary>
  155.  
  156.     public static void LoadFromStream (this Mesh mesh, TextReader reader, LoadFormat format) {
  157.         string line;
  158.         int lineNumber = 0;
  159.  
  160.         string[] datas;
  161.         string[] v0Datas;
  162.         string[] v1Datas;
  163.         string[] v2Datas;
  164.         string[] v3Datas;
  165.  
  166.         Vector3 tempV3;
  167.         Vector2 tempV2;
  168.  
  169.         // "raw" data
  170.         List<Vector3> tempVertices = new List<Vector3> ();
  171.         List<Vector2> tempUV = new List<Vector2> ();
  172.         List<Vector3> tempNormals = new List<Vector3> ();
  173.  
  174.         // ordered data
  175.         List<Vector3> vertices = new List<Vector3> ();
  176.         List<Vector2> uv = new List<Vector2> ();
  177.         List<Vector3> normals = new List<Vector3> ();
  178.         List<int> triangles = new List<int> ();
  179.  
  180.         if (format == LoadFormat.OBJ) {
  181.             while ((line = reader.ReadLine()) != null) {
  182.                 lineNumber++;
  183.                 line = line.Replace ('\t', ' ');
  184.                 datas = line.Split (' ');
  185.  
  186.                 if (datas.Length == 0) continue;
  187.  
  188.                 // mesh name
  189.                 if (datas[0] == "o") {
  190.                     try {
  191.                         mesh.name = datas[1];
  192.                     }
  193.                     catch (Exception ex) {
  194.                         mesh.name = "undefined";
  195.                         Debug.LogWarning ("PARSE ERROR (name) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  196.                     }
  197.                 }
  198.  
  199.                 // vertex
  200.                 if (datas[0] == "v") {
  201.                     try {
  202.                         tempV3.x = float.Parse (datas[1]);
  203.                         tempV3.y = float.Parse (datas[2]);
  204.                         tempV3.z = float.Parse (datas[3]);
  205.  
  206.                         tempVertices.Add (tempV3);
  207.                     }
  208.                     catch (Exception ex) {
  209.                         tempVertices.Add (Vector3.zero);
  210.                         Debug.LogWarning ("PARSE ERROR (vertex) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  211.                     }
  212.                 }
  213.  
  214.                 // uv (vt = vertex texture)
  215.                 if (datas[0] == "vt") {
  216.                     try  {
  217.                         tempV2.x = float.Parse (datas[1]);
  218.                         tempV2.y = float.Parse (datas[2]);
  219.  
  220.                         tempUV.Add (tempV2);
  221.                     }
  222.                     catch (Exception ex) {
  223.                         tempUV.Add (Vector2.zero);
  224.                         Debug.LogWarning ("PARSE ERROR (uv) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  225.                     }
  226.                 }
  227.  
  228.                 // normal
  229.                 if (datas[0] == "vn") {
  230.                     try {
  231.                         tempV3.x = float.Parse (datas[1]);
  232.                         tempV3.y = float.Parse (datas[2]);
  233.                         tempV3.z = float.Parse (datas[3]);
  234.  
  235.                         tempNormals.Add (tempV3);
  236.                     }
  237.                     catch (Exception ex) {
  238.                         tempNormals.Add (Vector3.zero);
  239.                         Debug.LogWarning ("PARSE ERROR (normal) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  240.                     }
  241.                 }
  242.  
  243.                 // face
  244.                 if (datas[0] == "f") {
  245.  
  246.                     // triangle or quad
  247.                     if (datas.Length >= 4) {
  248.                         try {
  249.                             v0Datas = datas[1].Split ('/');
  250.                             v1Datas = datas[2].Split ('/');
  251.                             v2Datas = datas[3].Split ('/');
  252.  
  253.                             vertices.Add ( tempVertices[ int.Parse (v0Datas[0]) - 1 ] );
  254.                             vertices.Add ( tempVertices[ int.Parse (v1Datas[0]) - 1 ] );
  255.                             vertices.Add ( tempVertices[ int.Parse (v2Datas[0]) - 1 ] );
  256.  
  257.                             uv.Add ( tempUV[ int.Parse (v0Datas[1]) - 1 ] );
  258.                             uv.Add ( tempUV[ int.Parse (v1Datas[1]) - 1 ] );
  259.                             uv.Add ( tempUV[ int.Parse (v2Datas[1]) - 1 ] );
  260.  
  261.                             normals.Add ( tempNormals[ int.Parse (v0Datas[2]) - 1 ] );
  262.                             normals.Add ( tempNormals[ int.Parse (v1Datas[2]) - 1 ] );
  263.                             normals.Add ( tempNormals[ int.Parse (v2Datas[2]) - 1 ] );
  264.  
  265.                             int i = triangles.Count;
  266.                             triangles.Add (i);
  267.                             triangles.Add (i + 1);
  268.                             triangles.Add (i + 2);
  269.  
  270.                             if (datas.Length >= 5) {
  271.                                 v3Datas = datas[4].Split ('/');
  272.  
  273.                                 vertices.Add ( tempVertices[ int.Parse (v3Datas[0]) ] );
  274.                                 uv.Add ( tempUV[ int.Parse (v3Datas[1]) ] );
  275.                                 normals.Add ( tempNormals[ int.Parse (v3Datas[2]) ] );
  276.  
  277.                                 triangles.Add (i + 1);
  278.                                 triangles.Add (i + 2);
  279.                                 triangles.Add (i + 3);
  280.                             }
  281.                         }
  282.                         catch (Exception ex) {
  283.                             Debug.LogWarning ("PARSE ERROR (face:" + (datas.Length-1) + ") : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  284.                         }
  285.                     }
  286.                 }
  287.  
  288.                 // else it's :
  289.                 // - a comment (#)
  290.                 // - a smoothing group (s on or s off), but unity doesn't support it
  291.                 // - a unsupported instruction (ex : mtl)
  292.             }
  293.  
  294.             mesh.Clear ();
  295.             mesh.vertices = vertices.ToArray ();
  296.             mesh.uv = uv.ToArray ();
  297.             mesh.normals = normals.ToArray ();
  298.             mesh.triangles = triangles.ToArray ();
  299.         }
  300.  
  301.         if (format == LoadFormat.QMO) {
  302.             throw new NotImplementedException ();
  303.         }
  304.  
  305.         reader.Close ();
  306.     }
  307. // NEW CODE
  308.    
  309. // OLD CODE (simpler but surely faster, WARNING : can load only .obj saved with this code (can have issue when loading .obj from other softwares))
  310.     public static string SimpleSaveToText (this Mesh mesh) { return mesh.SimpleSaveToText (SaveFormat.OBJ); }
  311.    
  312.     /// <summary>
  313.     /// Save a Mesh to a text.
  314.     /// sFormat : format of the text (obj/qmo). Optional : default .obj.
  315.     /// </summary>
  316.  
  317.     public static string SimpleSaveToText (this Mesh mesh, SaveFormat sFormat) {
  318.         StringBuilder text = new StringBuilder ();
  319.        
  320.         if (sFormat == SaveFormat.OBJ) {
  321.             text.AppendFormat("# ModelisaTools exported obj file\n\no {0}\n\n", mesh.name);
  322.            
  323.             foreach (Vector3 v in mesh.vertices) {
  324.                 text.AppendFormat ("v {0} {1} {2}\n", v.x, v.y, v.z);
  325.             }
  326.  
  327.             text.Append ("\n");
  328.  
  329.             foreach (Vector2 u in mesh.uv) {
  330.                 text.AppendFormat ("vt {0} {1}\n", u.x, u.y);
  331.             }
  332.  
  333.             text.Append ("\n");
  334.  
  335.             foreach (Vector3 n in mesh.normals) {
  336.                 text.AppendFormat ("vn {0} {1} {2}\n", n.x, n.y, n.z);
  337.             }
  338.            
  339.             text.Append ("\ns off\n\n"); // smoothing group, but unity doesn't support it :/
  340.            
  341.             for (int i = 0; i < mesh.triangles.Length; i += 3) {
  342.                 text.AppendFormat ("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", mesh.triangles[i]+1, mesh.triangles[i+1]+1, mesh.triangles[i+2]+1);
  343.             }
  344.         }
  345.        
  346.         if (sFormat == SaveFormat.QMO) {
  347.             throw new NotImplementedException ();
  348.         }
  349.        
  350.         return text.ToString ();
  351.     }
  352.    
  353.     public static void SimpleSaveToFile (this Mesh mesh, string path) { mesh.SimpleSaveToFile (path, SaveFormat.OBJ, false); }
  354.     public static void SimpleSaveToFile (this Mesh mesh, string path, SaveFormat sFormat) { mesh.SimpleSaveToFile (path, sFormat, false); }
  355.     public static void SimpleSaveToFile (this Mesh mesh, string path, bool overwrite) { mesh.SimpleSaveToFile (path, SaveFormat.OBJ, overwrite); }
  356.    
  357.     /// <summary>
  358.     /// Save a Mesh to a file.
  359.     /// path : the path were the mesh will be created WITHOUT THE EXTENSION.
  360.     /// sFormat : format of the file (obj/qmo). Optional : default .obj.
  361.     /// overwrite : if the file already exists, should it overwrite ? Optional : default false.
  362.     /// </summary>
  363.  
  364.     public static void SimpleSaveToFile (this Mesh mesh, string path, SaveFormat sFormat, bool overwrite) {
  365.         path = path + '.' + sFormat.ToString ().ToLower ();
  366.  
  367.         try {
  368.             if (!File.Exists (path) || overwrite) {
  369.                 File.WriteAllText (path, mesh.SimpleSaveToText (sFormat));
  370.             }
  371.             else {
  372.                 Debug.LogWarning ("This file already exists, can't save mesh : " + mesh.name + ", or set overwrite to true.\n@" + path);
  373.             }
  374.         }
  375.         catch (Exception ex) {
  376.             Debug.LogWarning ("Exception while saving mesh : " + mesh.name + "\n@ " + path + "\nex: " + ex);
  377.         }
  378.     }
  379.  
  380.     public static void SimpleLoadFromFile (this Mesh mesh, string path) { mesh.SimpleLoadFromFile (path, LoadFormat.Auto); }
  381.  
  382.     /// <summary>
  383.     /// Load a Mesh from a file.
  384.     /// path : the path were the mesh will be loaded, WITH THE EXTENSION if lFormat is AUTO, and WITHOUT if lFormat is : OBJ, QMO.
  385.     /// lFormat : format of mesh (obj/qmo). Optional : default AUTO
  386.     /// </summary>
  387.  
  388.     public static void SimpleLoadFromFile (this Mesh mesh, string path, LoadFormat lFormat) {
  389.         if (lFormat != LoadFormat.Auto) {
  390.             path = path + '.' + lFormat.ToString ().ToLower ();
  391.         }
  392.  
  393.         try {
  394.             if (File.Exists (path)) {
  395.                 string extension = Path.GetExtension (path);
  396.                 LoadFormat format;
  397.                 if (extension == ".obj") {
  398.                     format = LoadFormat.OBJ;
  399.                 }
  400.                 else if (extension == ".qmo") {
  401.                     format = LoadFormat.QMO;
  402.                 }
  403.                 else {
  404.                     format = LoadFormat.Auto;
  405.                 }
  406.                 mesh.SimpleLoadFromStream (File.OpenText (path), format);
  407.             }
  408.             else {
  409.                 Debug.LogWarning ("This file doesn't exists, can't load mesh @ " + path);
  410.             }
  411.         }
  412.         catch (Exception ex) {
  413.             Debug.LogWarning ("Exception while loading mesh : " + mesh.name + "\n@ " + path + "\nex: " + ex);
  414.         }
  415.     }
  416.  
  417.     /// <summary>
  418.     /// Load a Mesh from a TextReader (StringReader or StreamReader).
  419.     /// </summary>
  420.  
  421.     public static void SimpleLoadFromStream (this Mesh mesh, TextReader reader, LoadFormat lFormat) {
  422.         string line;
  423.         int lineNumber = 0;
  424.         string[] datas;
  425.         Vector3 tempVector3;
  426.         Vector2 tempVector2;
  427.         List<Vector3> vertices = new List<Vector3> ();
  428.         List<Vector2> uv = new List<Vector2> ();
  429.         List<Vector3> normals = new List<Vector3> ();
  430.         List<int> triangles = new List<int> ();
  431.  
  432.         if (lFormat == LoadFormat.Auto) {
  433.             Debug.LogWarning ("Can't load mesh : " + mesh.name + ", format is not supported.");
  434.             return;
  435.         }
  436.  
  437.         if (lFormat == LoadFormat.OBJ) {
  438.             while ((line = reader.ReadLine()) != null) {
  439.  
  440.                 datas = line.Split (' '); // so datas[0] == o || v || vt || vn || f || ...
  441.  
  442.                 // mesh name
  443.                 if (line.StartsWith ("o")) {
  444.                     mesh.name = datas[1];
  445.                 }
  446.  
  447.                 // vertex
  448.                 if (line.StartsWith ("v ")) {
  449.                     try {
  450.                         tempVector3.x = float.Parse (datas[1]);
  451.                         tempVector3.y = float.Parse (datas[2]);
  452.                         tempVector3.z = float.Parse (datas[3]);
  453.                        
  454.                         vertices.Add (tempVector3);
  455.                     }
  456.                     catch (Exception ex) {
  457.                         Debug.LogWarning ("PARSE ERROR (vertex) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  458.                         vertices.Add (Vector3.zero);
  459.                     }
  460.                 }
  461.  
  462.                 // uv - texture coordinate
  463.                 if (line.StartsWith ("vt")) {
  464.                     try {
  465.                         tempVector2.x = float.Parse (datas[1]);
  466.                         tempVector2.y = float.Parse (datas[2]);
  467.                        
  468.                         uv.Add (tempVector2);
  469.                     }
  470.                     catch (Exception ex) {
  471.                         Debug.LogWarning ("PARSE ERROR (uv) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  472.                         uv.Add (Vector2.zero);
  473.                     }
  474.                 }
  475.  
  476.                 // normal
  477.                 if (line.StartsWith ("vn")) {
  478.                     try {
  479.                         tempVector3.x = float.Parse (datas[1]);
  480.                         tempVector3.y = float.Parse (datas[2]);
  481.                         tempVector3.z = float.Parse (datas[3]);
  482.                        
  483.                         normals.Add (tempVector3);
  484.                     }
  485.                     catch (Exception ex) {
  486.                         Debug.LogWarning ("PARSE ERROR (normal) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  487.                         normals.Add (Vector3.zero);
  488.                     }
  489.                 }
  490.  
  491.                 // triangle (face)
  492.                 if (line.StartsWith ("f")) {
  493.                     try {
  494.                         triangles.Add (int.Parse (datas[1].Split ('/')[0]) - 1);
  495.                         triangles.Add (int.Parse (datas[2].Split ('/')[0]) - 1);
  496.                         triangles.Add (int.Parse (datas[3].Split ('/')[0]) - 1);
  497.                     }
  498.                     catch (Exception ex) {
  499.                         Debug.LogWarning ("PARSE ERROR (triangle) : line " + lineNumber + " while loading mesh : " + mesh.name + "\n" + ex);
  500.                         triangles.Add (1);
  501.                         triangles.Add (2);
  502.                         triangles.Add (3);
  503.                         // beurk beurk, but we preserve vertex/face order
  504.                     }
  505.                 }
  506.  
  507.                 // else it's :
  508.                 //  _ a comment (#...)
  509.                 //  _ a smoothing group, but unity doesn't support it (s on/s off)
  510.                 //  _ a unsupported operation (ex : mtl)
  511.  
  512.                 lineNumber++;
  513.             }
  514.  
  515.             mesh.Clear ();
  516.             mesh.vertices = vertices.ToArray ();
  517.             mesh.uv = uv.ToArray ();
  518.             mesh.normals = normals.ToArray ();
  519.             mesh.triangles = triangles.ToArray ();
  520.         }
  521.  
  522.         if (lFormat == LoadFormat.QMO) {
  523.             //
  524.         }
  525.  
  526.         reader.Close ();
  527.     }
  528.  
  529.     /// <summary>
  530.     /// Load a Mesh from a String (internally convert into a StringReader and call LoadFromStream).
  531.     /// lFormat : format of mesh (obj/qmo)
  532.     /// </summary>
  533.  
  534.     public static void SimpleLoadFromText (this Mesh mesh, string text, LoadFormat lFormat) {
  535.         mesh.SimpleLoadFromStream (new StringReader (text), lFormat);
  536.     }
  537. // OLD CODE
  538. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement