GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_objtoworld.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  Version 2.0.0, packaged on July 2010.
6 
7  http://glc-lib.sourceforge.net
8 
9  GLC-lib is free software; you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13 
14  GLC-lib is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with GLC-lib; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 
23 *****************************************************************************/
24 
26 
27 
28 #include "glc_objtoworld.h"
29 #include "../sceneGraph/glc_world.h"
30 #include "glc_objmtlloader.h"
31 #include "../glc_fileformatexception.h"
32 #include "../maths/glc_geomtools.h"
33 #include "../sceneGraph/glc_structreference.h"
34 #include "../sceneGraph/glc_structinstance.h"
35 #include "../sceneGraph/glc_structoccurence.h"
36 #include <QTextStream>
37 #include <QFileInfo>
38 #include <QGLContext>
39 
41 // Constructor
44 : m_pWorld(NULL)
45 , m_FileName()
46 , m_pMtlLoader(NULL)
47 , m_CurrentLineNumber(0)
48 , m_pCurrentObjMesh(NULL)
49 , m_FaceType(notSet)
50 , m_CurrentMeshMaterials()
51 , m_CurrentMaterialName("GLC_Default")
52 , m_ListOfAttachedFileName()
53 , m_Positions()
54 , m_Normals()
55 , m_Texels()
56 , m_VerticeIndex(0)
57 , m_NormalIndex(0)
58 , m_TextureIndex(0)
59 , m_VerticeOffset(0)
60 , m_NormalOffset(0)
61 , m_TextureOffset(0)
62 , m_ResetIndex(false)
63 {
64 }
65 
67 {
68  clear();
69 }
70 
72 // Set Functions
74 
75 // Create an GLC_World from an input OBJ File
77 {
79  m_FileName= file.fileName();
81  // Test if the file exist and can be opened
83  if (!file.open(QIODevice::ReadOnly))
84  {
85  QString message(QString("GLC_ObjToWorld::CreateWorldFromObj File ") + m_FileName + QString(" doesn't exist"));
86  //qDebug() << message;
88  throw(fileFormatException);
89  }
90 
92  // Init member
94  m_pWorld= new GLC_World;
95 
96  // Create Working variables
97  int currentQuantumValue= 0;
98  int previousQuantumValue= 0;
99  int numberOfLine= 0;
100 
101  // Create the input file stream
102  QTextStream objStream(&file);
103 
104  // QString buffer
105  QString lineBuff;
106 
107  QString mtlLibLine;
108 
110  // Searching mtllib attribute
112  while (!objStream.atEnd() && !lineBuff.contains("mtllib"))
113  {
114  ++numberOfLine;
115  lineBuff= objStream.readLine();
116  if (lineBuff.contains("mtllib")) mtlLibLine= lineBuff;
117  }
118 
120  // Count the number of lines of the OBJ file
122  while (!objStream.atEnd())
123  {
124  ++numberOfLine;
125  objStream.readLine();
126  }
127 
129  // Reset the stream
131  objStream.resetStatus();
132  objStream.seek(0);
133 
135  // if mtl file found, load it
137  QString mtlLibFileName(getMtlLibFileName(mtlLibLine));
138  if (!mtlLibFileName.isEmpty())
139  {
140  m_pMtlLoader= new GLC_ObjMtlLoader(mtlLibFileName);
141  if (!m_pMtlLoader->loadMaterials())
142  {
143  delete m_pMtlLoader;
144  m_pMtlLoader= NULL;
145  if (!mtlLibLine.isEmpty())
146  {
147  QStringList stringList(m_FileName);
148  stringList.append("Open Material File : " + mtlLibFileName + " failed");
149  GLC_ErrorLog::addError(stringList);
150  }
151  }
152  else
153  {
154  // Update Attached file name list
155  m_ListOfAttachedFileName << mtlLibFileName;
157  }
158  }
159  else
160  {
161  //qDebug() << "GLC_ObjToWorld::CreateWorldFromObj: mtl file not found";
162  }
163 
165  // Read Buffer and create the world
167  emit currentQuantum(currentQuantumValue);
169  m_VerticeIndex= 0;
170  m_NormalIndex= 0;
171  m_TextureIndex= 0;
172 
173  m_VerticeOffset= 0;
174  m_NormalOffset= 0;
175  m_TextureOffset= 0;
176 
177  while (!objStream.atEnd())
178  {
180  lineBuff= objStream.readLine();
181 
182  mergeLines(&lineBuff, &objStream);
183 
184  scanLigne(lineBuff);
185  currentQuantumValue = static_cast<int>((static_cast<double>(m_CurrentLineNumber) / numberOfLine) * 100);
186  if (currentQuantumValue > previousQuantumValue)
187  {
188  emit currentQuantum(currentQuantumValue);
189  }
190  previousQuantumValue= currentQuantumValue;
191 
192  }
193  file.close();
194 
196 
198  if (m_pWorld->rootOccurence()->childCount() == 0)
199  {
200  QString message= "GLC_ObjToWorld::CreateWorldFromObj " + m_FileName + " No mesh found!";
202  clear();
203  throw(fileFormatException);
204  }
205  return m_pWorld;
206 
207 }
208 
210 // Private services functions
212 
213 // Return the name of the mtl file
215 {
216  // Search mtl file with the same name than the OBJ file Name
217  QString mtlFileName(m_FileName);
218  mtlFileName.replace(m_FileName.size() - 3, 3, "mtl");
219  QFile mtlFile(mtlFileName);
220  if (!mtlFile.exists())// mtl file with same name not found
221  {
222  QTextStream stream(&line);
223  QString header;
224  if ((stream >> header >> mtlFileName).status() == QTextStream::Ok)
225  {
226  // If There is spaces in the string to extracts
227  QString valueString2;
228  while ((stream >> valueString2).status() == QTextStream::Ok)
229  {
230  mtlFileName.append(" ");
231  mtlFileName.append(valueString2);
232  }
233  QFileInfo fileInfo(m_FileName);
234  mtlFileName= fileInfo.absolutePath() + QDir::separator() + mtlFileName;
235  }
236  else
237  {
238  // There is no mtl file to load
239  mtlFileName.clear();
240  }
241  }
242  return mtlFileName;
243 }
244 
245 // Scan a line previously extracted from OBJ file
246 void GLC_ObjToWorld::scanLigne(QString &line)
247 {
248  line= line.trimmed();
249  // Search Vertexs vectors
250  if (line.startsWith("v ")|| line.startsWith(QString("v") + QString(QChar(9))))
251  {
252  if (m_ResetIndex)
253  {
257 
258  m_VerticeIndex= 0;
259  m_TextureIndex= 0;
260  m_NormalIndex= 0;
261  m_ResetIndex= false;
262  }
263  line.remove(0,2); // Remove first 2 char
264  m_Positions.append(extract3dVect(line));
265  m_FaceType = notSet;
266  ++m_VerticeIndex;
267  }
268 
269  // Search texture coordinate vectors
270  else if (line.startsWith("vt ")|| line.startsWith(QString("vt") + QString(QChar(9))))
271  {
272  line.remove(0,3); // Remove first 3 char
273  m_Texels.append(extract2dVect(line));
274  m_FaceType = notSet;
275  ++m_TextureIndex;
276  }
277 
278  // Search normals vectors
279  else if (line.startsWith("vn ") || line.startsWith(QString("vn") + QString(QChar(9))))
280  {
281  line.remove(0,3); // Remove first 3 char
282  m_Normals.append(extract3dVect(line));
283  m_FaceType = notSet;
284  ++m_NormalIndex;
285  }
286 
287  // Search faces to update index
288  else if (line.startsWith("f ") || line.startsWith(QString("f") + QString(QChar(9))))
289  {
290  m_ResetIndex= true;
291  // If there is no group or object in the OBJ file
292  if (NULL == m_pCurrentObjMesh)
293  {
294  changeGroup("GLC_Default");
295  //qDebug() << "Default group " << line;
296  }
297  line.remove(0,2); // Remove first 2 char
298  extractFaceIndex(line);
299  }
300 
301  // Search Material
302  else if (line.startsWith("usemtl ") || line.startsWith(QString("usemtl") + QString(QChar(9))))
303  {
304  line.remove(0,7); // Remove first 7 char
305  setCurrentMaterial(line);
306  m_FaceType = notSet;
307  }
308 
309  // Search Group
310  else if (line.startsWith("g ") || line.startsWith("o ") || line.startsWith(QString("g") + QString(QChar(9)))
311  || line.startsWith(QString("o") + QString(QChar(9))))
312  {
313  m_FaceType = notSet;
314  line.remove(0,2); // Remove first 2 char
315  changeGroup(line);
316  }
317 
318 }
319 // Change current group
320 void GLC_ObjToWorld::changeGroup(QString line)
321 {
322  //qDebug() << "GLC_ObjToWorld::changeGroup at Line :" << line;
324  // Parse the line containing the group name
326  QTextStream stream(&line);
327  QString groupName;
328  if ((stream >> groupName).status() == QTextStream::Ok)
329  {
330  // If There is an space in the string to extracts
331  QString valueString2;
332  while ((stream >> valueString2).status() == QTextStream::Ok)
333  {
334  groupName.append(" ");
335  groupName.append(valueString2);
336  }
338  // If the groupName == "default" nothing to do
340  if("default" != groupName)
341  {
344  m_pCurrentObjMesh->m_pMesh->setName(groupName);
345 
346  }
347  }
348  else
349  {
350  QString message= "GLC_ObjToWorld::changeGroup " + m_FileName + " something is wrong!!";
351  message.append("\nAt line : ");
352  message.append(QString::number(m_CurrentLineNumber));
354  clear();
355  throw(fileFormatException);
356  }
357 
358 }
359 
360 // Extract a Vector from a string
361 QList<float> GLC_ObjToWorld::extract3dVect(QString &line)
362 {
363  float x=0.0f;
364  float y=0.0f;
365  float z=0.0f;
366 
367  QList<float> vectResult;
368  QTextStream stringVecteur(&line);
369 
370  QString xString, yString, zString;
371 
372  if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
373  {
374  bool xOk, yOk, zOk;
375  x= xString.toFloat(&xOk);
376  y= yString.toFloat(&yOk);
377  z= zString.toFloat(&zOk);
378  if (!(xOk && yOk && zOk))
379  {
380  QString message= "GLC_ObjToWorld::extract3dVect " + m_FileName + " failed to convert vector component to float";
381  message.append("\nAt ligne : ");
382  message.append(QString::number(m_CurrentLineNumber));
383  QStringList stringList(m_FileName);
384  stringList.append(message);
385  GLC_ErrorLog::addError(stringList);
386 
387  //GLC_FileFormatException fileFormatException(message, m_FileName);
388  //clear();
389  //throw(fileFormatException);
390  }
391  else
392  {
393  vectResult << x << y << z;
394  }
395  }
396 
397  return vectResult;
398 
399 }
400 
401 // Extract a Vector from a string
402 QList<float> GLC_ObjToWorld::extract2dVect(QString &line)
403 {
404  float x=0.0f;
405  float y=0.0f;
406  QList<float> vectResult;
407  QTextStream stringVecteur(&line);
408 
409  QString xString, yString;
410 
411  if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
412  {
413  bool xOk, yOk;
414  x= xString.toFloat(&xOk);
415  y= yString.toFloat(&yOk);
416  if (!(xOk && yOk))
417  {
418  QString message= "GLC_ObjToWorld::extract2dVect " + m_FileName + " failed to convert vector component to double";
419  message.append("\nAt ligne : ");
420  message.append(QString::number(m_CurrentLineNumber));
422  clear();
423  throw(fileFormatException);
424  }
425  vectResult << x << y;
426  }
427 
428  return vectResult;
429 }
430 
431 // Extract a face from a string
433 {
434  QString buff;
435 
436  int coordinateIndex;
437  int normalIndex;
438  int textureCoordinateIndex;
439 
440  QList<GLuint> currentFaceIndex;
442  // Parse the line containing face index
444  QTextStream streamFace(&line);
445  while ((!streamFace.atEnd()))
446  {
447  streamFace >> buff;
448  extractVertexIndex(buff, coordinateIndex, normalIndex, textureCoordinateIndex);
449 
450  ObjVertice currentVertice(coordinateIndex, normalIndex, textureCoordinateIndex);
451  if (m_pCurrentObjMesh->m_ObjVerticeIndexMap.contains(currentVertice))
452  {
453  currentFaceIndex.append(m_pCurrentObjMesh->m_ObjVerticeIndexMap.value(currentVertice));
454  }
455  else
456  {
457  // Add Vertex to the mesh bulk data
458  m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3));
459  m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3 + 1));
460  m_pCurrentObjMesh->m_Positions.append(m_Positions.value(coordinateIndex * 3 + 2));
461  if (-1 != normalIndex)
462  {
463  // Add Normal to the mesh bulk data
464  m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3));
465  m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3 + 1));
466  m_pCurrentObjMesh->m_Normals.append(m_Normals.value(normalIndex * 3 + 2));
467  }
468  else
469  {
470  // Add Null Normal to the mesh bulk data
471  m_pCurrentObjMesh->m_Normals.append(0.0f);
472  m_pCurrentObjMesh->m_Normals.append(0.0f);
473  m_pCurrentObjMesh->m_Normals.append(0.0f);
474  }
475  if (-1 != textureCoordinateIndex)
476  {
477  // Add texture coordinate to the mesh bulk data
478  m_pCurrentObjMesh->m_Texels.append(m_Texels.value(textureCoordinateIndex * 2));
479  m_pCurrentObjMesh->m_Texels.append(m_Texels.value(textureCoordinateIndex * 2 + 1));
480  }
481  else if (!m_pCurrentObjMesh->m_Texels.isEmpty())
482  {
483  // Add epmty texture coordinate
484  m_pCurrentObjMesh->m_Texels.append(0.0f);
485  m_pCurrentObjMesh->m_Texels.append(0.0f);
486  }
487  // Add the index to current face index
488  currentFaceIndex.append(m_pCurrentObjMesh->m_NextFreeIndex);
489  // Add ObjVertice to ObjVertice Map
491  // Increment next free index
493  }
494 
495  }
497  // Check the number of face's vertex
499  const int size= currentFaceIndex.size();
500  if (size < 3)
501  {
502  QStringList stringList(m_FileName);
503  stringList.append("GLC_ObjToWorld::extractFaceIndex Face with less than 3 vertex found");
504  GLC_ErrorLog::addError(stringList);
505  return;
506  }
508  // Add the face to the current mesh
511  {
512  if (size > 3)
513  {
515  }
516  m_pCurrentObjMesh->m_Index.append(currentFaceIndex);
517  }
518  else if (m_FaceType != notSet)
519  {
520  if (size > 3)
521  {
523  }
524  // Comput the face normal
525  if (currentFaceIndex.size() < 3) return;
526  GLC_Vector3df normal= computeNormal(currentFaceIndex.at(0), currentFaceIndex.at(1), currentFaceIndex.at(2));
527 
528  // Add Face normal to bulk data
529  QSet<GLuint> indexSet= currentFaceIndex.toSet();
530  QSet<GLuint>::iterator iIndexSet= indexSet.begin();
531  while (indexSet.constEnd() != iIndexSet)
532  {
533  m_pCurrentObjMesh->m_Normals[*iIndexSet * 3]= normal.x();
534  m_pCurrentObjMesh->m_Normals[*iIndexSet * 3 + 1]= normal.y();
535  m_pCurrentObjMesh->m_Normals[*iIndexSet * 3 + 2]= normal.z();
536 
537  ++iIndexSet;
538  }
539 
540  m_pCurrentObjMesh->m_Index.append(currentFaceIndex);
541 
542  }
543  else
544  {
545  QString message= "GLC_ObjToWorld::extractFaceIndex " + m_FileName + " unknow face type";
546  message.append("\nAt line : ");
547  message.append(QString::number(m_CurrentLineNumber));
549  clear();
550  throw(fileFormatException);
551  }
552 }
555 {
556  QTextStream streamString(&line);
557  QString materialName;
558 
559  if (!((streamString >> materialName).status() == QTextStream::Ok))
560  {
561  QString message= "GLC_ObjToWorld::SetCurrentMaterial " + m_FileName + " : failed to extract materialName";
562  message.append("\nAt line : ");
563  message.append(QString::number(m_CurrentLineNumber));
565  clear();
566  throw(fileFormatException);
567  }
569  // Check if the material is already loaded from the current mesh
571  if ((NULL != m_pMtlLoader) && m_pMtlLoader->contains(materialName))
572  {
573  if (NULL == m_pCurrentObjMesh)
574  {
575  changeGroup("GLC_Default");
576  }
577  Q_ASSERT(NULL != m_pCurrentObjMesh->m_pLastOffsetSize);
578 
580  {
581  // Update last material offsetSize
583  }
584  else
585  {
586  QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
587  while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
588  {
589  if (iMat.value() == m_pCurrentObjMesh->m_pLastOffsetSize)
590  {
591  iMat= m_pCurrentObjMesh->m_Materials.erase(iMat);
592  }
593  else
594  {
595  ++iMat;
596  }
597  }
598  }
599  // Create this material offsetSize
600  MatOffsetSize* pMatOffsetSize= new MatOffsetSize();
601  pMatOffsetSize->m_Offset= m_pCurrentObjMesh->m_Index.size();
602  // Update current Obj mesh
603  m_pCurrentObjMesh->m_pLastOffsetSize= pMatOffsetSize;
604  m_pCurrentObjMesh->m_Materials.insertMulti(materialName, pMatOffsetSize);
605  // Update current material name
606  m_CurrentMaterialName= materialName;
607  }
608 
609 }
610 // Extract a vertex from a string
611 void GLC_ObjToWorld::extractVertexIndex(QString line, int &Coordinate, int &Normal, int &TextureCoordinate)
612 {
613  if (m_FaceType == notSet)
614  {
615  setObjType(line);
616  }
617 
619  {
620  // Replace "/" with " "
621  line.replace('/', ' ');
622  QTextStream streamVertex(&line);
623  QString coordinateString, textureCoordinateString, normalString;
624  if ((streamVertex >> coordinateString >> textureCoordinateString >> normalString).status() == QTextStream::Ok)
625  {
626  bool coordinateOk, textureCoordinateOk, normalOk;
627  Coordinate= coordinateString.toInt(&coordinateOk);
628  --Coordinate;
629  TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
630  --TextureCoordinate;
631  Normal= normalString.toInt(&normalOk);
632  --Normal;
633  if (!(coordinateOk && textureCoordinateOk && normalOk))
634  {
635  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " failed to convert String to int";
636  message.append("\nAt line : ");
637  message.append(QString::number(m_CurrentLineNumber));
639  clear();
640  throw(fileFormatException);
641  }
642  else if (Coordinate < 0)
643  {
644  Coordinate= m_VerticeIndex + m_VerticeOffset + Coordinate + 1;
645  Normal= m_NormalIndex + m_NormalOffset + Normal + 1;
646  TextureCoordinate= m_TextureIndex + m_TextureOffset + TextureCoordinate + 1;
647  }
648  }
649  else
650  {
651  QString message= "GLC_ObjToWorld::extractVertexIndex Obj file " + m_FileName + " type is not supported";
652  message.append("\nAt line : ");
653  message.append(QString::number(m_CurrentLineNumber));
655  clear();
656  throw(fileFormatException);
657  }
658 
659  }
660  else if (m_FaceType == coordinateAndTexture)
661  {
662  // Replace "/" with " "
663  line.replace('/', ' ');
664  QTextStream streamVertex(&line);
665  QString coordinateString, textureCoordinateString;
666  if ((streamVertex >> coordinateString >> textureCoordinateString).status() == QTextStream::Ok)
667  {
668  bool coordinateOk, textureCoordinateOk;
669  Coordinate= coordinateString.toInt(&coordinateOk);
670  --Coordinate;
671  TextureCoordinate= textureCoordinateString.toInt(&textureCoordinateOk);
672  --TextureCoordinate;
673  Normal= -1;
674  if (!(coordinateOk && textureCoordinateOk))
675  {
676  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + "failed to convert String to int";
677  message.append("\nAt line : ");
678  message.append(QString::number(m_CurrentLineNumber));
680  clear();
681  throw(fileFormatException);
682  }
683  else if (Coordinate < 0)
684  {
685  Coordinate= m_VerticeIndex + m_VerticeOffset + Coordinate + 1;
686  TextureCoordinate= m_TextureIndex + m_TextureOffset + TextureCoordinate + 1;
687  }
688  }
689  else
690  {
691  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " this Obj file type is not supported";
692  message.append("\nAt line : ");
693  message.append(QString::number(m_CurrentLineNumber));
695  clear();
696  throw(fileFormatException);
697  }
698  }
699  else if (m_FaceType == coordinateAndNormal)
700  {
701  // Replace "/" with " "
702  line.replace('/', ' ');
703  QTextStream streamVertex(&line);
704  QString coordinateString, normalString;
705  if ((streamVertex >> coordinateString >> normalString).status() == QTextStream::Ok)
706  {
707  bool coordinateOk, normalOk;
708  Coordinate= coordinateString.toInt(&coordinateOk);
709  --Coordinate;
710  TextureCoordinate= -1;
711  Normal= normalString.toInt(&normalOk);
712  --Normal;
713  if (!(coordinateOk && normalOk))
714  {
715  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " failed to convert String to int";
716  message.append("\nAt line : ");
717  message.append(QString::number(m_CurrentLineNumber));
719  clear();
720  throw(fileFormatException);
721  }
722  else if (Coordinate < 0)
723  {
724  Coordinate= m_VerticeIndex + m_VerticeOffset + Coordinate + 1;
725  Normal= m_NormalIndex + m_NormalOffset + Normal + 1;
726  }
727 
728  }
729  else
730  {
731  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " this Obj file type is not supported";
732  message.append("\nAt line : ");
733  message.append(QString::number(m_CurrentLineNumber));
735  clear();
736  throw(fileFormatException);
737  }
738  }
739  else if (m_FaceType == coordinate)
740  {
741  QTextStream streamVertex(&line);
742  QString coordinateString;
743  if ((streamVertex >> coordinateString).status() == QTextStream::Ok)
744  {
745  bool coordinateOk;
746  Coordinate= coordinateString.toInt(&coordinateOk);
747  --Coordinate;
748  TextureCoordinate= -1;
749  Normal= -1;
750  if (!coordinateOk)
751  {
752  QString message= "GLC_ObjToWorld::extractVertexIndex " + m_FileName + " failed to convert String to int";
753  message.append("\nAt line : ");
754  message.append(QString::number(m_CurrentLineNumber));
756  clear();
757  throw(fileFormatException);
758  }
759  else if (Coordinate < 0)
760  {
761  Coordinate= m_VerticeIndex + m_VerticeOffset + Coordinate + 1;
762  }
763  }
764  else
765  {
766  QString message= "GLC_ObjToWorld::extractVertexIndex Obj " + m_FileName + " file type is not supported";
767  message.append("\nAt line : ");
768  message.append(QString::number(m_CurrentLineNumber));
770  clear();
771  throw(fileFormatException);
772  }
773  }
774  else
775  {
776  QString message= "GLC_ObjToWorld::extractVertexIndex OBJ file " + m_FileName + " not reconize";
777  message.append("\nAt line : ");
778  message.append(QString::number(m_CurrentLineNumber));
780  clear();
781  throw(fileFormatException);
782  }
783 
784 }
785 
786 // set the OBJ File type
787 void GLC_ObjToWorld::setObjType(QString& ligne)
788 {
789  const QRegExp coordinateOnlyRegExp("^[-+]?\\d{1,}$"); // ex. 10
790  const QRegExp coordinateTextureNormalRegExp("^[-+]?\\d{1,}/[-+]?\\d{1,}/[-+]?\\d{1,}$"); // ex. 10/30/54
791  const QRegExp coordinateNormalRegExp("^[-+]?\\d{1,}//[-+]?\\d{1,}$"); // ex. 10//54
792  const QRegExp coordinateTextureRegExp("^[-+]?\\d{1,}/[-+]?\\d{1,}$"); // ex. 10/56
793 
794  if (coordinateTextureNormalRegExp.exactMatch(ligne))
795  {
797  }
798  else if (coordinateTextureRegExp.exactMatch(ligne))
799  {
801  }
802  else if (coordinateNormalRegExp.exactMatch(ligne))
803  {
805  }
806  else if (coordinateOnlyRegExp.exactMatch(ligne))
807  {
809  }
810  else
811  {
812  QString message= "GLC_ObjToWorld::setObjType OBJ file " + m_FileName + " not reconize";
813  message.append("\nAt line : ");
814  message.append(QString::number(m_CurrentLineNumber));
816  clear();
817  throw(fileFormatException);
818  }
819 }
820 
821 // compute face normal
822 GLC_Vector3df GLC_ObjToWorld::computeNormal(GLuint index1, GLuint index2, GLuint index3)
823 {
824  double xn, yn, zn;
825 
826  // Vertex 1
827  xn= m_pCurrentObjMesh->m_Positions.at(index1 * 3);
828  yn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 1);
829  zn= m_pCurrentObjMesh->m_Positions.at(index1 * 3 + 2);
830  const GLC_Vector3d vect1(xn, yn, zn);
831 
832  // Vertex 2
833  xn= m_pCurrentObjMesh->m_Positions.at(index2 * 3);
834  yn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 1);
835  zn= m_pCurrentObjMesh->m_Positions.at(index2 * 3 + 2);
836  const GLC_Vector3d vect2(xn, yn, zn);
837 
838  // Vertex 3
839  xn= m_pCurrentObjMesh->m_Positions.at(index3 * 3);
840  yn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 1);
841  zn= m_pCurrentObjMesh->m_Positions.at(index3 * 3 + 2);
842  const GLC_Vector3d vect3(xn, yn, zn);
843 
844  const GLC_Vector3d edge1(vect3 - vect2);
845  const GLC_Vector3d edge2(vect1 - vect2);
846 
847  GLC_Vector3d normal(edge1 ^ edge2);
848  normal.normalize();
849 
850  return normal.toVector3df();
851 }
852 
853 // clear objToWorld allocate memmory
855 {
856  m_CurrentMeshMaterials.clear();
857  m_ListOfAttachedFileName.clear();
858 
859  if (NULL != m_pMtlLoader)
860  {
861  delete m_pMtlLoader;
862  m_pMtlLoader= NULL;
863  }
864  if (NULL != m_pCurrentObjMesh)
865  {
866  delete m_pCurrentObjMesh;
867  m_pCurrentObjMesh= NULL;
868  }
869 
870 }
871 // Merge Mutli line in one
872 void GLC_ObjToWorld::mergeLines(QString* pLineBuff, QTextStream* p0bjStream)
873 {
874  if (pLineBuff->endsWith(QChar('\\')))
875  {
876  pLineBuff->replace(QChar('\\'), QChar(' '));
877  pLineBuff->append(p0bjStream->readLine());
879  mergeLines(pLineBuff, p0bjStream);
880  }
881 }
882 
883 // Add the current Obj mesh to the world
885 {
886  if (NULL != m_pCurrentObjMesh)
887  {
888  if (!m_pCurrentObjMesh->m_Positions.isEmpty())
889  {
893  m_pCurrentObjMesh->m_Normals.clear();
894  if (!m_pCurrentObjMesh->m_Texels.isEmpty())
895  {
897  m_pCurrentObjMesh->m_Texels.clear();
898  }
899  QHash<QString, MatOffsetSize*>::iterator iMat= m_pCurrentObjMesh->m_Materials.begin();
900  while (m_pCurrentObjMesh->m_Materials.constEnd() != iMat)
901  {
902  GLC_Material* pCurrentMaterial= NULL;
903  if ((NULL != m_pMtlLoader) && (m_pMtlLoader->contains(iMat.key())))
904  {
905  pCurrentMaterial= m_pMtlLoader->material(iMat.key());
906  }
907  // Create the list of triangles to add to the mesh
908  const int offset= iMat.value()->m_Offset;
909  int size= iMat.value()->m_size;
910  if (0 == size)
911  {
912  size= m_pCurrentObjMesh->m_Index.size() - offset;
913  }
914  //qDebug() << "Offset : " << offset << " size : " << size;
915  QList<GLuint> triangles;
916  for (int i= offset; i < (offset + size); ++i)
917  {
918  triangles.append(m_pCurrentObjMesh->m_Index.at(i));
919  }
920  // Add the list of triangle to the mesh
921  if (!triangles.isEmpty())
922  {
923  m_pCurrentObjMesh->m_pMesh->addTriangles(pCurrentMaterial, triangles);
924  }
925 
926  ++iMat;
927  }
928  if (m_pCurrentObjMesh->m_pMesh->faceCount(0) > 0)
929  {
933  }
934  else
935  {
936  delete m_pCurrentObjMesh->m_pMesh;
937  }
938 
939  }
940  else
941  {
942  delete m_pCurrentObjMesh->m_pMesh;
943  }
944 
945  delete m_pCurrentObjMesh;
946  m_pCurrentObjMesh= NULL;
947  }
948 }
949 
950 

©2005-2013 Laurent Ribon