ObjImporter

From Unify Community Wiki
Revision as of 01:27, 1 March 2011 by Capnbishop (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Author: el anónimo

Description

This is a simple utility class for importing .obj files into a Unity mesh at runtime.

ObjExporter.cs

<csharp>/* This version of ObjImporter first reads through the entire file, getting a count of how large

* the final arrays will be, and then uses standard arrays for everything (as opposed to ArrayLists
* or any other fancy things). 
*/

using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text;

public class ObjImporter {

   private struct meshStruct
   {
       public Vector3[] vertices;
       public Vector3[] normals;
       public Vector2[] uv;
       public Vector2[] uv1;
       public Vector2[] uv2;
       public int[] triangles;
       public int[] faceVerts;
       public int[] faceUVs;
       public Vector3[] faceData;
       public string name;
       public string fileName;
   }
   
   // Use this for initialization

public Mesh ImportFile (string filePath) {

       meshStruct newMesh = createMeshStruct(filePath);
       populateMeshStruct(ref newMesh);
       Vector3[] newVerts = new Vector3[newMesh.faceData.Length];
       Vector2[] newUVs = new Vector2[newMesh.faceData.Length];
       Vector3[] newNormals = new Vector3[newMesh.faceData.Length];
       int i = 0;
       /* The following foreach loops through the facedata and assigns the appropriate vertex, uv, or normal
        * for the appropriate Unity mesh array.
        */
       foreach (Vector3 v in newMesh.faceData)            
       {
           newVerts[i] = newMesh.vertices[(int)v.x - 1];
           if (v.y >= 1)
               newUVs[i] = newMesh.uv[(int)v.y - 1];
           
           if (v.z >= 1)
               newNormals[i] = newMesh.normals[(int)v.z - 1];
           i++;
       }

Mesh mesh = new Mesh();

       mesh.vertices = newVerts;     
       mesh.uv = newUVs;        
       mesh.normals = newNormals;
       mesh.triangles = newMesh.triangles;
       mesh.RecalculateBounds();
       mesh.Optimize();

return mesh; }

   private static meshStruct createMeshStruct(string filename)
   {
       int triangles = 0;
       int vertices = 0;
       int vt = 0;
       int vn = 0;
       int face = 0;
       meshStruct mesh = new meshStruct();
       mesh.fileName = filename;
       StreamReader stream = File.OpenText(filename);
       string entireText = stream.ReadToEnd();
       stream.Close();
       using (StringReader reader = new StringReader(entireText))
       {
           string currentText = reader.ReadLine();
           char[] splitIdentifier = { ' ' };
           string[] brokenString;
           while (currentText != null)
           {
               if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ")
                   && !currentText.StartsWith("vn "))
               {
                   currentText = reader.ReadLine();
                   if (currentText != null)
                   {
                       currentText = currentText.Replace("  ", " ");
                   }
               }
               else
               {
                   currentText = currentText.Trim();                           //Trim the current line
                   brokenString = currentText.Split(splitIdentifier, 50);      //Split the line into an array, separating the original line by blank spaces
                   switch (brokenString[0])
                   {
                       case "v":
                           vertices++;
                           break;
                       case "vt":
                           vt++;
                           break;
                       case "vn":
                           vn++;
                           break;
                       case "f":
                           face = face + brokenString.Length - 1;
                           triangles = triangles + 3 * (brokenString.Length - 2); /*brokenString.Length is 3 or greater since a face must have at least
                                                                                    3 vertices.  For each additional vertice, there is an additional
                                                                                    triangle in the mesh (hence this formula).*/
                           break;
                   }
                   currentText = reader.ReadLine();
                   if (currentText != null)
                   {
                       currentText = currentText.Replace("  ", " ");
                   }
               }
           }
       }
       mesh.triangles = new int[triangles];
       mesh.vertices = new Vector3[vertices];
       mesh.uv = new Vector2[vt];
       mesh.normals = new Vector3[vn];
       mesh.faceData = new Vector3[face];
       return mesh;
   }
   private static void populateMeshStruct(ref meshStruct mesh)
   {
       StreamReader stream = File.OpenText(mesh.fileName);
       string entireText = stream.ReadToEnd();
       stream.Close();
       using (StringReader reader = new StringReader(entireText))
       {
           string currentText = reader.ReadLine();
           
           char[] splitIdentifier = { ' ' };
           char[] splitIdentifier2 = { '/' };
           string[] brokenString;
           string[] brokenBrokenString;
           int f = 0;
           int f2 = 0;
           int v = 0;
           int vn = 0;
           int vt = 0;
           int vt1 = 0;
           int vt2 = 0;
           while (currentText != null)
           {
               if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ") &&
                   !currentText.StartsWith("vn ") && !currentText.StartsWith("g ") && !currentText.StartsWith("usemtl ") &&
                   !currentText.StartsWith("mtllib ") && !currentText.StartsWith("vt1 ") && !currentText.StartsWith("vt2 ") &&
                   !currentText.StartsWith("vc ") && !currentText.StartsWith("usemap "))
               {
                   currentText = reader.ReadLine();
                   if (currentText != null)
                   {
                       currentText = currentText.Replace("  ", " ");
                   }
               }
               else
               {
                   currentText = currentText.Trim();
                   brokenString = currentText.Split(splitIdentifier, 50);
                   switch (brokenString[0])
                   {
                       case "g":
                           break;
                       case "usemtl":
                           break;
                       case "usemap":
                           break;
                       case "mtllib":
                           break;
                       case "v":
                           mesh.vertices[v] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
                                                    System.Convert.ToSingle(brokenString[3]));
                           v++;
                           break;
                       case "vt":
                           mesh.uv[vt] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                           vt++;
                           break;
                       case "vt1":
                           mesh.uv[vt1] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                           vt1++;
                           break;
                       case "vt2":
                           mesh.uv[vt2] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
                           vt2++;
                           break;
                       case "vn":
                           mesh.normals[vn] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
                                                   System.Convert.ToSingle(brokenString[3]));
                           vn++;
                           break;
                       case "vc":
                           break;
                       case "f":
                       
                           int j = 1;
                           List<int> intArray = new List<int>();
                           while (j < brokenString.Length && ("" + brokenString[j]).Length > 0)
                           {
                               Vector3 temp = new Vector3();
                               brokenBrokenString = brokenString[j].Split(splitIdentifier2, 3);    //Separate the face into individual components (vert, uv, normal)
                               temp.x = System.Convert.ToInt32(brokenBrokenString[0]);
                               if (brokenBrokenString.Length > 1)                                  //Some .obj files skip UV and normal
                               {
                                   if (brokenBrokenString[1] != "")                                    //Some .obj files skip the uv and not the normal
                                   {
                                       temp.y = System.Convert.ToInt32(brokenBrokenString[1]);
                                   }
                                   temp.z = System.Convert.ToInt32(brokenBrokenString[2]);
                               }
                               j++;
                               
                               mesh.faceData[f2] = temp;
                               intArray.Add(f2);
                               f2++;
                           }
                           j = 1;
                           while (j + 2 < brokenString.Length)     //Create triangles out of the face data.  There will generally be more than 1 triangle per face.
                           {
                               mesh.triangles[f] = intArray[0];
                               f++;
                               mesh.triangles[f] = intArray[j];
                               f++;
                               mesh.triangles[f] = intArray[j+1];
                               f++;
                               
                               j++;
                           }
                           break;
                   }
                   currentText = reader.ReadLine();
                   if (currentText != null)
                   {
                       currentText = currentText.Replace("  ", " ");       //Some .obj files insert double spaces, this removes them.
                   }
               }
           }
       }
   }

}</csharp>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox