123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- using UnityEngine;
- using System.IO;
- using System.Collections.Generic;
- using System.Text;
- public class MegaCacheOBJMtl
- {
- public string name;
- public Color Ka;
- public Color Kd;
- public Color Ks;
- public Color Tf;
- public float Tr;
- public Color Ke;
- public float Ns;
- public float Ni;
- public float d;
- public int illum;
- public string map_Ka;
- public string map_Kd;
- public Texture2D Kdtexture;
- }
- public class MegaCacheObjImporter
- {
- class MegaCacheOBJFace
- {
- public int[] v = new int[4];
- public int[] uv = new int[4];
- public int[] n = new int[4];
- public bool quad = false;
- public int smthgrp;
- public int mtl;
- }
- class MegaCacheOBJMesh
- {
- public List<Vector3> vertices = new List<Vector3>();
- public List<Vector3> normals = new List<Vector3>();
- public List<Vector2> uv = new List<Vector2>();
- public List<Vector2> uv1 = new List<Vector2>();
- public List<Vector2> uv2 = new List<Vector2>();
- public List<MegaCacheOBJFace> faces = new List<MegaCacheOBJFace>();
- }
- static List<MegaCacheOBJMtl> mtls = new List<MegaCacheOBJMtl>();
- static List<MegaCacheFace> faces = new List<MegaCacheFace>();
- static int currentmtl;
- static int smthgrp;
- static int offset = 0;
- static int offsetmtl = 0;
- static MegaCacheOBJMtl loadmtl;
- static public void Init()
- {
- mtls.Clear();
- }
- static public int NumMtls()
- {
- return mtls.Count;
- }
- static public MegaCacheOBJMtl GetMtl(int i)
- {
- return mtls[i];
- }
- static string importpath;
- static public Mesh ImportFile(string filePath, float scale, bool adjust, bool tangents, bool loadmtls, bool optimize, bool recalcnormals)
- {
- #if UNITY_EDITOR
- faces.Clear();
- importpath = Path.GetDirectoryName(filePath);
- StreamReader stream = File.OpenText(filePath);
- string entireText = stream.ReadToEnd();
- stream.Close();
- MegaCacheOBJMesh newMesh = new MegaCacheOBJMesh();
- populateMeshStructNew(entireText, ref newMesh, loadmtls);
- Mesh mesh = new Mesh();
- int v1 = 0;
- int v2 = 1;
- int v3 = 2;
- int v4 = 3;
- currentmtl = 0;
- smthgrp = 0;
- for ( int i = 0; i < newMesh.vertices.Count; i++ )
- {
- newMesh.vertices[i] *= scale;
- if ( adjust )
- {
- Vector3 p = newMesh.vertices[i];
- p.x = -p.x;
- newMesh.vertices[i] = p;
- }
- }
- for ( int i = 0; i < newMesh.normals.Count; i++ )
- {
- Vector3 p = newMesh.normals[i];
- p.x = -p.x;
- newMesh.normals[i] = p;
- }
- Vector3 n1 = Vector3.forward;
- Vector3 n2 = Vector3.forward;
- Vector3 n3 = Vector3.forward;
- Vector3 n4 = Vector3.forward;
- if ( newMesh.normals.Count == 0 )
- recalcnormals = true;
- if ( newMesh.uv.Count == 0 )
- {
- for ( int t = 0; t < newMesh.faces.Count; t++ )
- {
- MegaCacheOBJFace f = newMesh.faces[t];
- if ( newMesh.normals.Count > 0 )
- {
- n1 = newMesh.normals[f.n[v1]];
- n2 = newMesh.normals[f.n[v2]];
- n3 = newMesh.normals[f.n[v3]];
- if ( f.quad )
- n4 = newMesh.normals[f.n[v4]];
- }
- if ( adjust )
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v3]], newMesh.vertices[f.v[v2]], n1, n3, n2, Vector3.zero, Vector3.zero, Vector3.zero, 1, f.mtl));
- else
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v2]], newMesh.vertices[f.v[v3]], n1, n2, n3, Vector3.zero, Vector3.zero, Vector3.zero, 1, f.mtl));
- if ( f.quad )
- {
- if ( adjust )
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v4]], newMesh.vertices[f.v[v3]], n1, n4, n3, Vector3.zero, Vector3.zero, Vector3.zero, 1, f.mtl));
- else
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v3]], newMesh.vertices[f.v[v4]], n1, n3, n4, Vector3.zero, Vector3.zero, Vector3.zero, 1, f.mtl));
- }
- }
- MegaCacheMeshConstructorOBJNoUV.Construct(faces, mesh, newMesh.vertices.ToArray(), false, recalcnormals, tangents);
- }
- else
- {
- for ( int t = 0; t < newMesh.faces.Count; t++ )
- {
- MegaCacheOBJFace f = newMesh.faces[t];
- if ( newMesh.normals.Count > 0 )
- {
- n1 = newMesh.normals[f.n[v1]];
- n2 = newMesh.normals[f.n[v2]];
- n3 = newMesh.normals[f.n[v3]];
- if ( f.quad )
- n4 = newMesh.normals[f.n[v4]];
- }
- if ( adjust )
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v3]], newMesh.vertices[f.v[v2]], n1, n3, n2, newMesh.uv[f.uv[v1]], newMesh.uv[f.uv[v3]], newMesh.uv[f.uv[v2]], 1, f.mtl));
- else
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v2]], newMesh.vertices[f.v[v3]], n1, n2, n3, newMesh.uv[f.uv[v1]], newMesh.uv[f.uv[v2]], newMesh.uv[f.uv[v3]], 1, f.mtl));
- if ( f.quad )
- {
- if ( adjust )
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v4]], newMesh.vertices[f.v[v3]], n1, n4, n3, newMesh.uv[f.uv[v1]], newMesh.uv[f.uv[v4]], newMesh.uv[f.uv[v3]], 1, f.mtl));
- else
- faces.Add(new MegaCacheFace(newMesh.vertices[f.v[v1]], newMesh.vertices[f.v[v3]], newMesh.vertices[f.v[v4]], n1, n3, n4, newMesh.uv[f.uv[v1]], newMesh.uv[f.uv[v3]], newMesh.uv[f.uv[v4]], 1, f.mtl));
- }
- }
- MegaCacheMeshConstructorOBJ.Construct(faces, mesh, newMesh.vertices.ToArray(), false, recalcnormals, tangents);
- }
- return mesh;
- #else
- return null;
- #endif
- }
- static public string ReadLine(string input)
- {
- StringBuilder sb = new StringBuilder();
- while ( true )
- {
- if ( offset >= input.Length )
- break;
- int ch = input[offset++];
- if ( ch == '\r' || ch == '\n' )
- {
- while ( offset < input.Length )
- {
- int ch1 = input[offset++];
- if ( ch1 != '\n' )
- {
- offset--;
- break;
- }
- }
- return sb.ToString();
- }
- sb.Append((char)ch);
- }
- if ( sb.Length > 0 )
- return sb.ToString();
- return null;
- }
- static public string ReadLineMtl(string input)
- {
- StringBuilder sb = new StringBuilder();
- while ( true )
- {
- if ( offsetmtl >= input.Length )
- break;
- int ch = input[offsetmtl++];
- if ( ch == '\r' || ch == '\n' )
- {
- while ( offsetmtl < input.Length )
- {
- int ch1 = input[offsetmtl++];
- if ( ch1 != '\n' )
- {
- offsetmtl--;
- break;
- }
- }
- return sb.ToString();
- }
- sb.Append((char)ch);
- }
- if ( sb.Length > 0 )
- return sb.ToString();
- return null;
- }
- static void populateMeshStructNew(string entireText, ref MegaCacheOBJMesh mesh, bool loadmtls)
- {
- offset = 0;
- string currentText = ReadLine(entireText);
- char[] splitIdentifier = { ' ' };
- char[] splitIdentifier2 = { '/' };
- string[] brokenString;
- string[] brokenBrokenString;
- //int smthgrp = -1;
- while ( currentText != null )
- {
- currentText = currentText.Trim();
- brokenString = currentText.Split(splitIdentifier, 50);
- switch ( brokenString[0] )
- {
- case "g": break;
- case "usemtl":
- brokenString[1] = brokenString[1].Replace(':', '_');
- if ( loadmtls )
- currentmtl = GetMtlID(brokenString[1]);
- else
- currentmtl = 0;
- break;
- case "usemap": break;
- case "mtllib":
- if ( loadmtls )
- {
- string p = importpath + "/" + brokenString[1];
- LoadMtlLib(p);
- }
-
- break;
- case "v": mesh.vertices.Add(new Vector3(float.Parse(brokenString[1]), float.Parse(brokenString[2]), float.Parse(brokenString[3]))); break;
- case "vt": mesh.uv.Add(new Vector2(float.Parse(brokenString[1]), float.Parse(brokenString[2]))); break;
- case "vt1": mesh.uv1.Add(new Vector2(float.Parse(brokenString[1]), float.Parse(brokenString[2]))); break;
- case "vt2": mesh.uv2.Add(new Vector2(float.Parse(brokenString[1]), float.Parse(brokenString[2]))); break;
- case "vn": mesh.normals.Add(new Vector3(float.Parse(brokenString[1]), float.Parse(brokenString[2]), float.Parse(brokenString[3]))); break;
- case "vc": break;
- case "f":
- int j = 1;
- MegaCacheOBJFace oface = new MegaCacheOBJFace();
- oface.mtl = currentmtl;
- oface.smthgrp = smthgrp;
- while ( j < brokenString.Length && ("" + brokenString[j]).Length > 0 )
- {
- if ( j > 4 )
- {
- Debug.LogError("OBJ file contains faces with more than 4 sides, importer only supports quads and tris!");
- return;
- }
- brokenBrokenString = brokenString[j].Split(splitIdentifier2, 3);
- if ( j == 4 )
- oface.quad = true;
- oface.v[j - 1] = int.Parse(brokenBrokenString[0]) - 1;
- if ( oface.v[j - 1] < 0 )
- oface.v[j - 1] = mesh.vertices.Count + oface.v[j - 1] + 1;
- if ( brokenBrokenString.Length > 1 )
- {
- if ( brokenBrokenString[1] != "" )
- {
- oface.uv[j - 1] = int.Parse(brokenBrokenString[1]) - 1;
- if ( oface.uv[j - 1] < 0 )
- oface.uv[j - 1] = mesh.uv.Count + oface.uv[j - 1] + 1;
- }
- if ( brokenBrokenString.Length > 2 )
- {
- oface.n[j - 1] = int.Parse(brokenBrokenString[2]) - 1;
- if ( oface.n[j - 1] < 0 )
- oface.n[j - 1] = mesh.normals.Count + oface.n[j - 1] + 1;
- }
- }
- j++;
- }
- mesh.faces.Add(oface);
- break;
- case "s":
- //if ( brokenString[1] == "off" )
- //smthgrp = -1;
- //else
- //smthgrp = int.Parse(brokenString[1]);
- break;
- }
- currentText = ReadLine(entireText);
- if ( currentText != null )
- currentText = currentText.Replace(" ", " ");
- }
- }
- static public void ImportMtl(string filePath)
- {
- LoadMtlLib(filePath);
- }
- static MegaCacheOBJMtl HaveMaterial(string name)
- {
- for ( int i = 0; i < mtls.Count; i++ )
- {
- if ( mtls[i].name == name )
- {
- return mtls[i];
- }
- }
- MegaCacheOBJMtl mtl = new MegaCacheOBJMtl();
- mtl.Ka = Color.white;
- mtl.Kd = Color.white;
- mtl.Ks = Color.white;
- mtl.Ke = Color.white;
- mtl.name = name;
- mtls.Add(mtl);
- return mtl;
- }
- static int GetMtlID(string name)
- {
- if ( mtls.Count > 0 )
- {
- for ( int i = 0; i < mtls.Count; i++ )
- {
- if ( mtls[i].name == name )
- {
- return i;
- }
- }
- Debug.Log("Missing Material " + name);
- }
- return 0;
- }
- #if false
- static public Texture2D LoadTexture(string filename)
- {
- Texture2D tex = null;
- if ( File.Exists(filename) )
- {
- byte[] buf = File.ReadAllBytes(filename);
- tex = new Texture2D(2, 2);
- tex.LoadImage(buf);
- }
- return tex;
- }
- #endif
- static void LoadMtlLib(string filename)
- {
- #if UNITY_EDITOR
- offsetmtl = 0;
- string path = Path.GetDirectoryName(filename);
- StreamReader stream = File.OpenText(filename);
- string entireText = stream.ReadToEnd();
- stream.Close();
- //using ( StringReader reader = new StringReader(entireText) )
- {
- //string currentText = reader.ReadLine();
- string currentText = ReadLineMtl(entireText);
- char[] splitIdentifier = { ' ' };
- string[] brokenString;
- while ( currentText != null )
- {
- currentText = currentText.Trim();
- brokenString = currentText.Split(splitIdentifier, 50);
- switch ( brokenString[0] )
- {
- case "newmtl":
- brokenString[1] = brokenString[1].Replace(':', '_');
- MegaCacheOBJMtl mtl = HaveMaterial(brokenString[1]);
- loadmtl = mtl;
- break;
- case "Ns":
- loadmtl.Ns = float.Parse(brokenString[1]);
- break;
- case "Ni":
- loadmtl.Ni = float.Parse(brokenString[1]);
- break;
- case "d":
- loadmtl.d = float.Parse(brokenString[1]);
- break;
- case "Tr":
- loadmtl.Tr = float.Parse(brokenString[1]);
- break;
- case "Tf":
- loadmtl.Tf.r = float.Parse(brokenString[1]);
- loadmtl.Tf.g = float.Parse(brokenString[2]);
- loadmtl.Tf.b = float.Parse(brokenString[3]);
- break;
- case "illum":
- loadmtl.illum = int.Parse(brokenString[1]);
- break;
- case "Ka":
- loadmtl.Ka.r = float.Parse(brokenString[1]);
- loadmtl.Ka.g = float.Parse(brokenString[2]);
- loadmtl.Ka.b = float.Parse(brokenString[3]);
- break;
- case "Kd":
- loadmtl.Kd.r = float.Parse(brokenString[1]);
- loadmtl.Kd.g = float.Parse(brokenString[2]);
- loadmtl.Kd.b = float.Parse(brokenString[3]);
- break;
- case "Ks":
- loadmtl.Ks.r = float.Parse(brokenString[1]);
- loadmtl.Ks.g = float.Parse(brokenString[2]);
- loadmtl.Ks.b = float.Parse(brokenString[3]);
- break;
- case "Ke":
- loadmtl.Ke.r = float.Parse(brokenString[1]);
- loadmtl.Ke.g = float.Parse(brokenString[2]);
- loadmtl.Ke.b = float.Parse(brokenString[3]);
- break;
- case "map_Ka":
- if ( brokenString.Length > 1 )
- loadmtl.map_Ka = brokenString[1];
- break;
- case "map_Kd":
- if ( brokenString.Length > 1 )
- {
- string dir = Path.GetDirectoryName(brokenString[1]);
- if ( dir.Length == 0 )
- loadmtl.map_Kd = path + "/" + brokenString[1];
- else
- loadmtl.map_Kd = brokenString[1];
- }
- break;
- }
- //currentText = reader.ReadLine();
- currentText = ReadLineMtl(entireText);
- if ( currentText != null )
- currentText = currentText.Replace(" ", " ");
- }
- }
- #endif
- }
- }
|