GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_offtoworld.cpp
Go to the documentation of this file.
1 
2 /****************************************************************************
3 
4  This file is part of the GLC-lib library.
5  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
6  http://glc-lib.sourceforge.net
7 
8  GLC-lib is free software; you can redistribute it and/or modify
9  it under the terms of the GNU Lesser General Public License as published by
10  the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version.
12 
13  GLC-lib is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public License
19  along with GLC-lib; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 
22 *****************************************************************************/
23 
25 
26 #include "glc_offtoworld.h"
27 #include "../sceneGraph/glc_world.h"
28 #include "../glc_fileformatexception.h"
29 #include "../sceneGraph/glc_structreference.h"
30 #include "../sceneGraph/glc_structinstance.h"
31 #include "../sceneGraph/glc_structoccurence.h"
32 
33 #include <QTextStream>
34 #include <QFileInfo>
35 #include <QGLContext>
36 
38 : m_pWorld(NULL)
39 , m_FileName()
40 , m_CurrentLineNumber(0)
41 , m_pCurrentMesh(NULL)
42 , m_CurVertexIndex(0)
43 , m_NbrOfVertexs(0)
44 , m_NbrOfFaces(0)
45 , m_IsCoff(false)
46 , m_Is4off(false)
47 , m_PositionBulk()
48 , m_NormalBulk()
49 , m_ColorBulk()
50 , m_IndexList()
51 {
52 
53 }
54 
56 {
57  clear();
58 }
59 
61 // Set Functions
63 
64 // Create an GLC_World from an input OFF File
66 {
67  clear();
68  m_FileName= file.fileName();
70  // Test if the file exist and can be opened
72  if (!file.open(QIODevice::ReadOnly))
73  {
74  QString message(QString("GLC_OffToWorld::CreateWorldFromOff File ") + m_FileName + QString(" doesn't exist"));
76  throw(fileFormatException);
77  }
78 
80  // Init member
82  m_pWorld= new GLC_World;
83 
84  // Create Working variables
85  int currentQuantumValue= 0;
86  int previousQuantumValue= 0;
87 
88  // Create the input file stream
89  QTextStream offStream(&file);
90 
91  // QString buffer
92  QString lineBuff;
93 
95  // Check the OFF Header
97  // Check if the file begin with "OFF" or "COFF"
99  lineBuff= offStream.readLine();
100  lineBuff= lineBuff.trimmed();
101  if(offStream.atEnd() || (!lineBuff.startsWith("OFF") && !lineBuff.startsWith("COFF") && !lineBuff.startsWith("4OFF")))
102  {
103  QString message= "GLC_OffToWorld::CreateWorldFromOff : OFF or COFF header not found";
105  clear();
106  throw(fileFormatException);
107  }
108 
109  // Set the COFF flag
110  m_IsCoff= lineBuff.startsWith("COFF");
111 
112  // Set the 4OFF flag
113  m_Is4off= lineBuff.startsWith("4OFF");
114 
115  // Create the mesh
116  m_pCurrentMesh= new GLC_Mesh();
117 
118  // Set mesh color per vertex if needed
119  if (m_IsCoff)
120  {
122  }
123  // Get the number of vertex and faces and skip comments
125  lineBuff= offStream.readLine();
126  lineBuff= lineBuff.trimmed();
127  while(!offStream.atEnd() && lineBuff.startsWith(QChar('#')))
128  {
130  lineBuff= offStream.readLine();
131  lineBuff= lineBuff.trimmed();
132  }
134 
136  // Read Buffer and load vertexs
138  emit currentQuantum(currentQuantumValue);
139 
140  for (int currentVertex= 0; currentVertex < m_NbrOfVertexs; ++currentVertex)
141  {
142  // Check it the end of file has been reached
143  if(offStream.atEnd())
144  {
145  QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
146  message.append("\nAt ligne : ");
147  message.append(QString::number(m_CurrentLineNumber));
149  clear();
150  throw(fileFormatException);
151  }
152 
154  lineBuff= offStream.readLine();
155  // Skip empty line
156  while (lineBuff.isEmpty())
157  {
159  lineBuff= offStream.readLine();
160  }
161  // Add current vertex and color if needed to the mesh
162  extractVertex(lineBuff);
163 
164  // Update Current Quantum for progress bar usage.
165  currentQuantumValue = static_cast<int>((static_cast<double>(currentVertex) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
166  if (currentQuantumValue > previousQuantumValue)
167  {
168  emit currentQuantum(currentQuantumValue);
169  }
170  previousQuantumValue= currentQuantumValue;
171  }
172 
174  // Read Buffer and load faces
176  for (int currentFace= 0; currentFace < m_NbrOfFaces; ++currentFace)
177  {
178  // Check it the end of file has been reached
179  if(offStream.atEnd())
180  {
181  QString message= "GLC_OffToWorld::CreateWorldFromOff : This file seems to be incomplete";
182  message.append("\nAt ligne : ");
183  message.append(QString::number(m_CurrentLineNumber));
185  clear();
186  throw(fileFormatException);
187  }
188 
190  lineBuff= offStream.readLine();
191  while (lineBuff.isEmpty())
192  {
194  lineBuff= offStream.readLine();
195  }
196 
197  // Add current Face to the mesh
198  extractFaceIndex(lineBuff);
199 
200  // Update Current Quantum for progress bar usage.
201  currentQuantumValue = static_cast<int>((static_cast<double>(currentFace + m_NbrOfVertexs + 1) / (m_NbrOfVertexs + m_NbrOfFaces)) * 100);
202  if (currentQuantumValue > previousQuantumValue)
203  {
204  emit currentQuantum(currentQuantumValue);
205  }
206  previousQuantumValue= currentQuantumValue;
207 
208  }
209 
210  file.close();
211  // Compute mesh normals
212  computeNormal();
213 
216  if (!m_ColorBulk.isEmpty())
217  {
218  m_pCurrentMesh->addColors(m_ColorBulk.toVector());
219  }
221 
223  GLC_3DRep* pRep= new GLC_3DRep(m_pCurrentMesh);
224  m_pCurrentMesh= NULL;
226 
227  return m_pWorld;
228 }
229 
231 // Private services Functions
233 
234 // clear offToWorld allocate memmory and reset member
236 {
237  if (NULL != m_pCurrentMesh)
238  {
239  delete m_pCurrentMesh;
240  m_pCurrentMesh= NULL;
241  }
242  m_pWorld= NULL;
243  m_FileName.clear();
245  m_pCurrentMesh= NULL;
246  m_CurVertexIndex= 0;
247  m_NbrOfVertexs= 0;
248  m_NbrOfFaces= 0;
249  m_IsCoff= false;
250  m_Is4off= false;
251  m_PositionBulk.clear();
252  m_NormalBulk.clear();
253  m_ColorBulk.clear();
254 }
255 
256 // Extract a Vertex from a string and add color component if needed
257 void GLC_OffToWorld::extractVertex(QString &line)
258 {
259 
260  QTextStream stringVecteur(&line);
261 
262  QString xString, yString, zString;
263 
264  if (((stringVecteur >> xString >> yString >> zString).status() == QTextStream::Ok))
265  {
266  bool xOk, yOk, zOk;
267  m_PositionBulk.append(xString.toFloat(&xOk));
268  m_PositionBulk.append(yString.toFloat(&yOk));
269  m_PositionBulk.append(zString.toFloat(&zOk));
270  if (!(xOk && yOk && zOk))
271  {
272  QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex component to float";
273  message.append("\nAt ligne : ");
274  message.append(QString::number(m_CurrentLineNumber));
276  clear();
277  throw(fileFormatException);
278  }
279  if (m_Is4off)
280  {
281  QString wString;
282  if (((stringVecteur >> wString).status() == QTextStream::Ok))
283  {
284  float w;
285  bool wOk;
286  w= wString.toFloat(&wOk);
287  if (!wOk)
288  {
289  QString message= "GLC_OffToWorld::extractVertex : failed to convert vertex fourth component to float";
290  message.append("\nAt ligne : ");
291  message.append(QString::number(m_CurrentLineNumber));
293  clear();
294  throw(fileFormatException);
295  }
296  const int lastValue= m_PositionBulk.size() - 1;
297  m_PositionBulk[lastValue - 2]= m_PositionBulk.at(lastValue - 2) / w;
298  m_PositionBulk[lastValue - 1]= m_PositionBulk.at(lastValue - 1) / w;
299  m_PositionBulk[lastValue]= m_PositionBulk.at(lastValue) / w;
300  }
301  else
302  {
303  QString message= "GLC_OffToWorld::extractVertex : failed to read vector fourth component";
304  message.append("\nAt ligne : ");
305  message.append(QString::number(m_CurrentLineNumber));
307  clear();
308  throw(fileFormatException);
309  }
310  }
311 
312  // Test if the file is a COFF
313  if (m_IsCoff)
314  {
315  QString rString, gString, bString, aString;
316 
317  if (((stringVecteur >> rString >> gString >> bString >> aString).status() == QTextStream::Ok))
318  {
319  bool rOk, gOk, bOk, aOk;
320  m_ColorBulk.append(rString.toFloat(&rOk));
321  m_ColorBulk.append(gString.toFloat(&gOk));
322  m_ColorBulk.append(bString.toFloat(&bOk));
323  m_ColorBulk.append(aString.toFloat(&aOk));
324  if (!(rOk && gOk && bOk && aOk))
325  {
326  QString message= "GLC_OffToWorld::extractVertex : failed to convert color component to float";
327  message.append("\nAt ligne : ");
328  message.append(QString::number(m_CurrentLineNumber));
330  clear();
331  throw(fileFormatException);
332  }
333  }
334  else
335  {
336  QString message= "GLC_OffToWorld::extractVertex : failed to read vertex color";
337  message.append("\nAt ligne : ");
338  message.append(QString::number(m_CurrentLineNumber));
340  clear();
341  throw(fileFormatException);
342  }
343  }
344 
345  }
346  else
347  {
348  QString message= "GLC_OffToWorld::extractVertex : failed to read vector component";
349  message.append("\nAt ligne : ");
350  message.append(QString::number(m_CurrentLineNumber));
352  clear();
353  throw(fileFormatException);
354  }
355 
356 }
357 
358 // Extract Number off Vertex and faces
360 {
361  QTextStream stringVecteur(&line);
362 
363  QString xString, yString;
364 
365  if (((stringVecteur >> xString >> yString).status() == QTextStream::Ok))
366  {
367  bool xOk, yOk;
368  m_NbrOfVertexs= xString.toInt(&xOk);
369  m_NbrOfFaces= yString.toInt(&yOk);
370  if (!(xOk && yOk))
371  {
372  QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to convert text to int";
373  message.append("\nAt ligne : ");
374  message.append(QString::number(m_CurrentLineNumber));
376  clear();
377  throw(fileFormatException);
378  }
379  }
380  else
381  {
382  QString message= "GLC_OffToWorld::extractNbrVertexsAndNbrFaces : failed to extract nbr of vertexs/faces";
383  message.append("\nAt ligne : ");
384  message.append(QString::number(m_CurrentLineNumber));
386  clear();
387  throw(fileFormatException);
388 
389  }
390 }
391 
392 // Extract a face from a string
394 {
395  QString buff;
396 
397  QList<GLuint> indexList;
398 
400  // Parse the line containing face index
402  QTextStream streamFace(&line);
403  // Get the number of vertex
404  if((streamFace >> buff).status() != QTextStream::Ok)
405  {
406  QString message= "GLC_OffToWorld::extractFaceIndex failed to extract number of vertex index";
407  message.append("\nAt line : ");
408  message.append(QString::number(m_CurrentLineNumber));
409  message.append(QString("\n") + line);
411  clear();
412  throw(fileFormatException);
413  }
414  bool conversionOk;
415  // Convert the QString Number of vertex to int
416  int numberOfVertex= buff.toInt(&conversionOk);
417  if (!conversionOk)
418  {
419  QString message= "GLC_OffToWorld::extractFaceIndex failed to convert String to int";
420  message.append("\nAt line : ");
421  message.append(QString::number(m_CurrentLineNumber));
423  clear();
424  throw(fileFormatException);
425  }
426  // Extract the face's vertexs index
427  for (int i= 0; i < numberOfVertex; ++i)
428  {
429  // Get a vertex index
430  if((streamFace >> buff).status() != QTextStream::Ok)
431  {
432  QString message= "GLC_OffToWorld::extractFaceIndex failed to extract vertex index";
433  message.append("\nAt line : ");
434  message.append(QString::number(m_CurrentLineNumber));
436  clear();
437  throw(fileFormatException);
438  }
439  // Convert the QString vertex index into int
440  int index= buff.toInt(&conversionOk);
441  if (conversionOk)
442  {
443  indexList.append(index);
444  }
445  else
446  {
447  QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to int";
448  message.append("\nAt line : ");
449  message.append(QString::number(m_CurrentLineNumber));
451  clear();
452  throw(fileFormatException);
453  }
454  }
455 
456  // Trying to read face color
457  QString rString, gString, bString;
458  if((streamFace >> rString >> gString >> bString).status() == QTextStream::Ok)
459  {
460  // Fill color bulk data if needed
461  if (m_ColorBulk.isEmpty())
462  {
463  const int size= m_PositionBulk.size() / 3 * 4;
464  for (int i= 0; i < size; ++i)
465  {
466  m_PositionBulk.append(0.0);
467  }
468  }
469  float r, g, b;
470  bool rOk, gOk, bOk;
471  r= rString.toFloat(&rOk);
472  g= gString.toFloat(&gOk);
473  b= bString.toFloat(&bOk);
474  if (!rOk || !gOk || !bOk)
475  {
476  QString message= "GLC_ObjToWorld::extractFaceIndex failed to convert String to float";
477  message.append("\nAt line : ");
478  message.append(QString::number(m_CurrentLineNumber));
480  clear();
481  throw(fileFormatException);
482  }
483  for (int i= 0; i < numberOfVertex; ++i)
484  {
485  m_ColorBulk[indexList[i] * 4]= r;
486  m_ColorBulk[indexList[i] * 4 + 1]= g;
487  m_ColorBulk[indexList[i] * 4 + 2]= b;
488  m_ColorBulk[indexList[i] * 4 + 3]= 1.0f;
489  }
490  }
491 
492  // Add the face to index List
493  m_IndexList.append(indexList);
494 }
495 
496 // compute face normal
498 {
499  //qDebug() << "GLC_OffToWorld::computeNormal";
500  //qDebug() << "Position size= " << m_PositionBulk.size();
501  //qDebug() << "Normal size= " << m_NormalBulk.size();
502  const QList<float>* pData= &m_PositionBulk;
503  // Fill the list of normal
504  QList<float>* pNormal= &m_NormalBulk;
505  const int normalCount= pData->size();
506  for (int i= 0; i < normalCount; ++i)
507  {
508  pNormal->append(0.0f);
509  }
510  // Compute the normals and add them to the current mesh info
511  const int size= m_IndexList.size();
512  double xn, yn, zn;
513 
514 
515  for (int i= 0; i < size; i+=3)
516  {
517  // Vertex 1
518  xn= pData->at(m_IndexList.at(i) * 3);
519  yn= pData->at(m_IndexList.at(i) * 3 + 1);
520  zn= pData->at(m_IndexList.at(i) * 3 + 2);
521  const GLC_Vector3d vect1(xn, yn, zn);
522 
523  // Vertex 2
524  xn= pData->at(m_IndexList.at(i + 1) * 3);
525  yn= pData->at(m_IndexList.at(i + 1) * 3 + 1);
526  zn= pData->at(m_IndexList.at(i + 1) * 3 + 2);
527  const GLC_Vector3d vect2(xn, yn, zn);
528 
529  // Vertex 3
530  xn= pData->at(m_IndexList.at(i + 2) * 3);
531  yn= pData->at(m_IndexList.at(i + 2) * 3 + 1);
532  zn= pData->at(m_IndexList.at(i + 2) * 3 + 2);
533  const GLC_Vector3d vect3(xn, yn, zn);
534 
535  const GLC_Vector3d edge1(vect3 - vect2);
536  const GLC_Vector3d edge2(vect1 - vect2);
537 
538  GLC_Vector3d normal(edge1 ^ edge2);
539  normal.normalize();
540 
541  GLC_Vector3df curNormal= normal.toVector3df();
542  for (int curVertex= 0; curVertex < 3; ++curVertex)
543  {
544  (*pNormal)[m_IndexList.at(i + curVertex) * 3]= curNormal.x();
545  (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 1]= curNormal.y();
546  (*pNormal)[m_IndexList.at(i + curVertex) * 3 + 2]= curNormal.z();
547  }
548  }
549 
550 }
551 

©2005-2013 Laurent Ribon