UnityMol  0.9.6-875
UnityMol viewer / In developement
OBJ.cs
Go to the documentation of this file.
1 
66 // this code is from http://www.everyday3d.com/blog/index.php/2010/05/24/loading-3d-models-runtime-unity3d/
67 // which was released under the MIT license
68 // Modified by Da silva franck IBPC Paris
69 // to open .obj file in a local Disk
70 
71 using UnityEngine;
72 using System;
73 using System.Collections;
74 using System.Collections.Generic;
75 using System.Globalization;
76 using System.Text;
77 using System.Text.RegularExpressions;
78 using System.IO;
79 using System.Net;
80 using Molecule.Model;
81 using Molecule.Control;
82 using System.Xml;
83 using UI;
84 public class OBJ : MonoBehaviour {
85 
86  public string objPath;
87  private TextReader sr;
88  private TextReader mtl_reader = null;
89  int compteurvertice = 0;
90 
91  /* OBJ file tags */
92  private const string O = "o";
93  private const string G = "g";
94  private const string V = "v";
95  private const string VT = "vt";
96  private const string VN = "vn";
97  private const string F = "f";
98  private const string MTL = "mtllib";
99  private const string UML = "usemtl";
100 
101  /* MTL file tags */
102  private const string NML = "newmtl";
103  private const string NS = "Ns"; // Shininess
104  private const string KA = "Ka"; // Ambient component (not supported)
105  private const string KD = "Kd"; // Diffuse component
106  private const string KS = "Ks"; // Specular component
107  private const string D = "d"; // Transparency (not supported)
108  private const string TR = "Tr"; // Same as 'd'
109  private const string ILLUM = "illum"; // Illumination model. 1 - diffuse, 2 - specular
110  private const string MAP_KD = "map_Kd"; // Diffuse texture (other textures are not supported)
111 
112 // private string basepath;
113  private string mtllib;
115 
116 
117  public OBJ (){
118  buffer = new GeometryBuffer ();
119  sr = null;
120  mtl_reader = null;
121  }
122 
123  //Construct from the file content
124  public OBJ(TextReader reader) : this()
125  {
126  sr = reader;
127  mtl_reader = null;
128  }
129  //Construct from the file content
130  public OBJ(TextReader reader, TextReader mtl_reader) : this(reader)
131  {
132  this.mtl_reader = mtl_reader;
133  }
134 
135  //Construct from a file path
136  public OBJ(string path) : this()
137  {
138  sr = new StreamReader(path);
139  mtl_reader = null;
140  }
141 
142  //Construct from a file path
143  public OBJ(string path, string mtl_path) : this(path)
144  {
145  mtl_reader = new StreamReader(mtl_path);
146  }
147 
148 
149  public void Load() {
150  string text;
151  using (sr)
152  {
153  text = sr.ReadToEnd();
154  }
155 
156  SetGeometryData(text);
157 
158  if(hasMaterials && mtl_reader != null) {
159 // Debug.Log("J'ai du matos");
160 // loader = new WWW(basepath + mtllib);
161 // yield return loader;
162  //string[] mtlpath = objPath.Split("."[0]);
163  //sr=new StreamReader(mtlpath[0]+".mtl");
164  using (mtl_reader)
165  {
166  text = mtl_reader.ReadToEnd();
167 // Debug.Log("Jai lu du matos");
168 
169  }
170 
171  SetMaterialData(text);
172 
173  foreach(MaterialData m in materialData) {
174 
175  if(m.diffuseTexPath != null) {
176  // Debug.Log(m.diffuseTexPath+"Oups");
177 // WWW texloader = new WWW(basepath + m.diffuseTexPath);
178  WWW texloader = new WWW(m.diffuseTexPath);
179 // yield return texloader;
180  m.diffuseTex = texloader.texture;
181  }
182  }
183  }
184 
185  Build();
186 
187  }
188 
189  private void SetGeometryData(string data) {
190  string[] lines = data.Split("\n".ToCharArray());
191 
192  for(int i = 0; i < lines.Length; i++) {
193  string l = lines[i];
194 
195  if(l.IndexOf("#") != -1) l = l.Substring(0, l.IndexOf("#"));
196  string[] p = l.Split(" ".ToCharArray());
197 
198  switch(p[0]) {
199  case O:
200  buffer.PushObject(p[1].Trim());
201  break;
202  case G:
203  buffer.PushGroup(p[1].Trim());
204  break;
205  case V:
206  //Unity has a left-handed coordinates system while Molecular OBJs are right-handed
207  //So we have to negate the X coordinates
208  buffer.PushVertex( new Vector3( -cf(p[1]), cf(p[2]), cf(p[3]) ) );
209  compteurvertice++;
210  break;
211  case VT:
212  buffer.PushUV( new Vector2( cf(p[1]), cf(p[2]) ));
213  break;
214  case VN:
215  //Unity has a left-handed coordinates system while Molecular OBJs are right-handed
216  //So we have to negate the X coordinates
217  //Here it affects only light ! The winding reverse is in GeometryBuffer::PopulateMeshes
218  Vector3 norm = new Vector3( -cf(p[1]), cf(p[2]), cf(p[3]) );
219  norm.Normalize();
220  buffer.PushNormal( norm );
221  break;
222  case F:
223  for(int j = 1; j < p.Length; j++) {
224  string[] c = p[j].Trim().Split("/".ToCharArray());
225 // Debug.Log("" +p[j]);
226  FaceIndices fi = new FaceIndices();
227  fi.vi = ci(c[0])-1;
228  if(c.Length > 1 && c[1] != "") fi.vu = ci(c[1])-1;
229  if(c.Length > 2 && c[2] != "") fi.vn = ci(c[2])-1;
230 // Debug.Log("vi "+fi.vi+" vu "+fi.vu+ " vn "+fi.vn);
231  buffer.PushFace(fi);
232  }
233  break;
234  case MTL:
235  if(mtl_reader != null)
236  mtllib = p[1].Trim();
237  break;
238  case UML:
239  if(mtl_reader != null)
240  buffer.PushMaterialName(p[1].Trim());
241  break;
242  }
243  }
244 
245  // buffer.Trace();
246  }
247 
248  // via profiler, discovered that Convert.ToSingle and Convert.ToInt32
249  // are very slow... so using float.Parse and int.Parse instead!
250  //
251  // memory usage during obj loading went down from 56 MB to 6.8 MB (8.2x improvement)
252  // and load time went down 1742ms to 514ms (3.4x improvement)
253 
254  /*
255  private float cf(string v) {
256  return Convert.ToSingle(v.Trim(), new CultureInfo("en-US"));
257  }
258 
259  private int ci(string v) {
260  return Convert.ToInt32(v.Trim(), new CultureInfo("en-US"));
261  }
262  */
263 
264  private float cf(string v) {
265  return float.Parse(v);
266  }
267 
268  private int ci(string v) {
269  return int.Parse(v);
270  }
271 
272 
273  private bool hasMaterials {
274  get {
275  return mtllib != null;
276  }
277  }
278 
279  /* ############## MATERIALS */
280  private List<MaterialData> materialData;
281  private class MaterialData {
282  public string name;
283  public Color ambient;
284  public Color diffuse;
285  public Color specular;
286  public float shininess;
287  public float alpha;
288  public int illumType;
289  public string diffuseTexPath;
290  public Texture2D diffuseTex;
291  }
292 
293  private void SetMaterialData(string data) {
294  string[] lines = data.Split("\n".ToCharArray());
295 
296  materialData = new List<MaterialData>();
297  MaterialData current = new MaterialData();
298 
299  for(int i = 0; i < lines.Length; i++) {
300  string l = lines[i];
301 
302  if(l.IndexOf("#") != -1) l = l.Substring(0, l.IndexOf("#"));
303  string[] p = l.Split(" ".ToCharArray());
304 
305  switch(p[0]) {
306  case NML:
307  current = new MaterialData();
308  current.name = p[1].Trim();
309  materialData.Add(current);
310  break;
311  case KA:
312  current.ambient = gc(p);
313  break;
314  case KD:
315  current.diffuse = gc(p);
316  break;
317  case KS:
318  current.specular = gc(p);
319  break;
320  case NS:
321  current.shininess = cf(p[1]) / 1000;
322  break;
323  case D:
324  case TR:
325  current.alpha = cf(p[1]);
326  break;
327  case MAP_KD:
328  current.diffuseTexPath = p[1].Trim();
329  break;
330  case ILLUM:
331  current.illumType = ci(p[1]);
332  break;
333 
334  }
335  }
336  }
337 
338  private Material GetMaterial(MaterialData md) {
339  Material m;
340 
341 
342  // commenter le 24
343 
344  if(md.illumType == 2) {
345  m = new Material(Shader.Find("Bumped Specular cut"));
346 // m = new Material(Shader.Find("Diffuse"));
347  m.SetColor("_Color", Color.black);
348  m.SetFloat("_Shininess", md.shininess);
349 // m.SetFloat("_Shininess", 10);
350  } else {
351  m = new Material(Shader.Find("Diffuse"));
352  }
353 
354  m.SetColor("_Color", md.diffuse);
355 
356  if(md.diffuseTex != null) m.SetTexture("_MainTex", md.diffuseTex);
357 
358  return m;
359  }
360 
361  private Color gc(string[] p) {
362  return new Color( cf(p[1]), cf(p[2]), cf(p[3]) );
363  }
364 
365  private void Build() {
366  Dictionary<string, Material> materials = new Dictionary<string, Material>();
367  Material m;
368 
370 
371  if(hasMaterials && mtl_reader != null) {
372  Debug.Log("Obj import :: MATERIAL read");
373  foreach(MaterialData md in materialData) {
374  materials.Add(md.name, GetMaterial(md));
375  }
376  } else {
377  Debug.Log("Obj import :: NO MATERIAL read");
378  m = new Material(Shader.Find("Mat Cap Cut"));
379  materials.Add("default", m);
380  m.SetTexture("_MatCap", (Texture)Resources.Load("lit_spheres/divers/daphz1"));
381  }
382 
383  GameObject[] ms = new GameObject[buffer.numObjects];
384 
385  for(int i = 0; i < buffer.numObjects; i++) {
386  GameObject go = new GameObject();
387  go.name="SurfaceOBJ";
388  man.addSurface(go);
389  go.transform.parent = man.getParentGameObject().transform;
390  go.AddComponent(typeof(MeshFilter));
391  go.AddComponent(typeof(MeshRenderer));
392  ms[i] = go;
393  }
394 
395  // Debug.Log("nb vertice :" + compteurvertice);
396  buffer.PopulateMeshes(ms, materials);
397 
399  }
400 }
void PushObject(string name)
const string NS
Definition: OBJ.cs:103
const string KD
Definition: OBJ.cs:105
const string KA
Definition: OBJ.cs:104
OBJ()
Definition: OBJ.cs:117
const string ILLUM
Definition: OBJ.cs:109
const string MTL
Definition: OBJ.cs:98
int ci(string v)
Definition: OBJ.cs:268
string mtllib
Definition: OBJ.cs:113
const string O
Definition: OBJ.cs:92
void PushGroup(string name)
void SetGeometryData(string data)
Definition: OBJ.cs:189
void PushNormal(Vector3 v)
OBJ(TextReader reader, TextReader mtl_reader)
Definition: OBJ.cs:130
TextReader sr
Definition: OBJ.cs:87
Color ambient
Definition: OBJ.cs:283
const string F
Definition: OBJ.cs:97
const string UML
Definition: OBJ.cs:99
void PushMaterialName(string name)
void SetMaterialData(string data)
Definition: OBJ.cs:293
float shininess
Definition: OBJ.cs:286
void PushUV(Vector2 v)
const string V
Definition: OBJ.cs:94
GeometryBuffer buffer
Definition: OBJ.cs:114
const string TR
Definition: OBJ.cs:108
string diffuseTexPath
Definition: OBJ.cs:289
Color gc(string[] p)
Definition: OBJ.cs:361
bool hasMaterials
Definition: OBJ.cs:273
OBJ(TextReader reader)
Definition: OBJ.cs:124
float cf(string v)
Definition: OBJ.cs:264
void PopulateMeshes(GameObject[] gs, Dictionary< string, Material > mats)
const string MAP_KD
Definition: OBJ.cs:110
void Load()
Definition: OBJ.cs:149
const string VN
Definition: OBJ.cs:96
const string D
Definition: OBJ.cs:107
const string KS
Definition: OBJ.cs:106
void PushFace(FaceIndices f)
void Build()
Definition: OBJ.cs:365
const string VT
Definition: OBJ.cs:95
Texture2D diffuseTex
Definition: OBJ.cs:290
TextReader mtl_reader
Definition: OBJ.cs:88
Color specular
Definition: OBJ.cs:285
Definition: OBJ.cs:84
GameObject getParentGameObject()
const string NML
Definition: OBJ.cs:102
Material GetMaterial(MaterialData md)
Definition: OBJ.cs:338
void PushVertex(Vector3 v)
const string G
Definition: OBJ.cs:93
OBJ(string path)
Definition: OBJ.cs:136
Color diffuse
Definition: OBJ.cs:284
static SurfaceManager getSurfaceManager()
Definition: UnityMolMain.cs:24
float alpha
Definition: OBJ.cs:287
OBJ(string path, string mtl_path)
Definition: OBJ.cs:143
int compteurvertice
Definition: OBJ.cs:89
List< MaterialData > materialData
Definition: OBJ.cs:280
void addSurface(GameObject surface)
string objPath
Definition: OBJ.cs:86
static bool surfaceInitialized
int illumType
Definition: OBJ.cs:288
string name
Definition: OBJ.cs:282
Definition: GUIDisplay.cs:66