GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_colladatoworld.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  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  *****************************************************************************/
22 
23 #include "glc_colladatoworld.h"
24 #include "../sceneGraph/glc_world.h"
25 #include "../glc_fileformatexception.h"
26 #include "../maths/glc_geomtools.h"
27 #include "../glc_factory.h"
28 #include "glc_xmlutil.h"
29 
30 static QString prefixNodeId= "GLC_LIB_COLLADA_ID_";
31 static int currentNodeId= 0;
32 
33 using namespace glcXmlUtil;
34 
35 // Default constructor
37 : QObject()
38 , m_pWorld(NULL)
39 , m_pStreamReader(NULL)
40 , m_FileName()
41 , m_pFile(NULL)
42 , m_ImageFileHash()
43 , m_MaterialLibHash()
44 , m_SurfaceImageHash()
45 , m_MaterialEffectHash()
46 , m_pCurrentMaterial(NULL)
47 , m_TextureToMaterialHash()
48 , m_BulkDataHash()
49 , m_DataAccessorHash()
50 , m_VerticesSourceHash()
51 , m_pMeshInfo(NULL)
52 , m_GeometryHash()
53 , m_ColladaNodeHash()
54 , m_TopLevelColladaNode()
55 , m_MaterialInstanceMap()
56 , m_3DRepHash()
57 , m_StructInstanceHash()
58 , m_CurrentId()
59 , m_FileSize(0)
60 , m_CurrentOffset(0)
61 , m_ListOfAttachedFileName()
62 , m_TransparentIsRgbZero(false)
63 {
64  currentNodeId= 0;
65 }
66 
67 // Destructor
69 {
70  // Normal ends, world has not to be deleted
71  m_pWorld= NULL;
72  clear();
73 }
74 
76 // Set Functions
78 // Create an GLC_World from an input Collada File
80 {
81  m_pWorld= new GLC_World();
82  m_FileName= file.fileName();
83  m_pFile= &file;
84 
86  // Test if the file exist and can be opened
88  if (!m_pFile->open(QIODevice::ReadOnly))
89  {
90  QString message(QString("GLC_ColladaToWorld::CreateWorldFromCollada File ") + m_FileName + QString(" doesn't exist"));
92  throw(fileFormatException);
93  }
94  // Get the file size
95  m_FileSize= QFileInfo(m_FileName).size();
96 
97  m_pStreamReader= new QXmlStreamReader(m_pFile);
98 
99  // Go to the collada root Element
100  goToElement("COLLADA");
101 
102  // Read the collada version
103  QString version= readAttribute("version", true);
104 
105  // Go to the asset Element to get the Up vector
106  goToElement("asset");
107  while (endElementNotReached(m_pStreamReader, "asset"))
108  {
109  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
110  {
111  const QStringRef currentElementName= m_pStreamReader->name();
112  if (currentElementName == "up_axis")
113  {
114  const QString upAxis= getContent("up_axis");
115  if (upAxis == "X_UP") m_pWorld->setUpVector(glc::X_AXIS);
116  else if (upAxis == "Y_UP") m_pWorld->setUpVector(glc::Y_AXIS);
117  else if (upAxis == "Z_UP") m_pWorld->setUpVector(glc::Z_AXIS);
118  }
119  }
120  m_pStreamReader->readNext();
121  }
122 
123  while (endElementNotReached(m_pStreamReader, "COLLADA"))
124  {
125  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
126  {
127  const QStringRef currentElementName= m_pStreamReader->name();
128  if (currentElementName == "library_images") loadLibraryImage();
129  else if (currentElementName == "library_materials") loadLibraryMaterials();
130  else if (currentElementName == "library_effects") loadLibraryEffects();
131  else if (currentElementName == "library_geometries") loadLibraryGeometries();
132  else if (currentElementName == "library_nodes") loadLibraryNodes();
133  else if (currentElementName == "library_controllers") loadLibraryContollers();
134  else if (currentElementName == "library_visual_scenes") loadVisualScenes();
135  else if (currentElementName == "scene") loadScene();
136  }
137 
138  m_pStreamReader->readNext();
139  }
140 
141  m_pFile->close();
142  m_pFile= NULL;
143 
144  // Link the textures to materials
146 
147  // Create the mesh and link them to material
148  createMesh();
149 
150  // Create the scene graph struct
152 
153  emit currentQuantum(100);
154 
155  return m_pWorld;
156 }
157 
159 // Private services Functions
161 // Go to Element
162 void GLC_ColladaToWorld::goToElement(const QString& elementName)
163 {
164  while(startElementNotReached(m_pStreamReader, elementName))
165  {
166  m_pStreamReader->readNext();
167  }
168  checkForXmlError(QString("Element ") + elementName + QString(" Not Found"));
169 }
170 
171 // Go to the end Element of a xml
172 void GLC_ColladaToWorld::goToEndElement(const QString& elementName)
173 {
174  while(endElementNotReached(m_pStreamReader, elementName))
175  {
176  m_pStreamReader->readNext();
177  }
178  checkForXmlError(QString("End Element ") + elementName + QString(" Not Found"));
179 }
180 
181 // Return the content of an element
182 QString GLC_ColladaToWorld::getContent(const QString& element)
183 {
184  QString Content;
185  while(endElementNotReached(m_pStreamReader, element))
186  {
187  m_pStreamReader->readNext();
188  if (m_pStreamReader->isCharacters() && !m_pStreamReader->text().isEmpty())
189  {
190  Content+= m_pStreamReader->text().toString();
191  }
192  }
193 
194  return Content.simplified();
195 }
196 
197 // Read the specified attribute
198 QString GLC_ColladaToWorld::readAttribute(const QString& name, bool required)
199 {
200  QString attributeValue;
201  if (required && !m_pStreamReader->attributes().hasAttribute(name))
202  {
203  QString message(QString("required attribute ") + name + QString(" Not found"));
205  clear();
206  throw(fileFormatException);
207  }
208  else
209  {
210  attributeValue= m_pStreamReader->attributes().value(name).toString();
211  }
212  return attributeValue;
213 }
214 
215 // Check for XML error
216 void GLC_ColladaToWorld::checkForXmlError(const QString& info)
217 {
218  if (m_pStreamReader->atEnd() || m_pStreamReader->hasError())
219  {
221  clear();
222  throw(fileFormatException);
223  }
224 }
225 // Throw an exception with the specified text
226 void GLC_ColladaToWorld::throwException(const QString& message)
227 {
229  clear();
230  throw(fileFormatException);
231 }
232 
233 // Clear memmory
235 {
236  delete m_pWorld;
237  m_pWorld= NULL;
238 
239 
240  delete m_pStreamReader;
241  m_pStreamReader= NULL;
242 
243  if (m_pFile != NULL) m_pFile->close();
244  m_pFile= NULL;
245 
246  m_ImageFileHash.clear();
247  m_MaterialLibHash.clear();
248  m_SurfaceImageHash.clear();
249 
250  // Clear the material effect hash table
251  MaterialHash::iterator iMat= m_MaterialEffectHash.begin();
252  while (iMat != m_MaterialEffectHash.constEnd())
253  {
254  if (iMat.value()->isUnused()) delete iMat.value();
255  ++iMat;
256  }
257  m_MaterialEffectHash.clear();
258 
259  delete m_pCurrentMaterial;
260  m_pCurrentMaterial= NULL;
261 
262  m_TextureToMaterialHash.clear();
263 
264  m_BulkDataHash.clear();
265  m_DataAccessorHash.clear();
266 
267  m_VerticesSourceHash.clear();
268 
269  delete m_pMeshInfo;
270  m_pMeshInfo= NULL;
271 
272  // Delete all geometry from the geometry hash
273  QHash<const QString, MeshInfo*>::iterator iGeomHash= m_GeometryHash.begin();
274  while (m_GeometryHash.constEnd() != iGeomHash)
275  {
276  delete iGeomHash.value();
277  ++iGeomHash;
278  }
279  m_GeometryHash.clear();
280 
281  // Delete all collada node from the colalda node hash
282  QHash<const QString, ColladaNode*>::iterator iColladaNode= m_ColladaNodeHash.begin();
283  while (m_ColladaNodeHash.constEnd() != iColladaNode)
284  {
285  delete iColladaNode.value();
286  ++iColladaNode;
287  }
288  m_ColladaNodeHash.clear();
289 
290  // Clear the list of top level node (Not must not to be deleted)
291  m_TopLevelColladaNode.clear();
292 
293  // Clear the material instance map
294  m_MaterialInstanceMap.clear();
295 
297  QHash<const QString, GLC_3DRep*>::iterator i3DRep= m_3DRepHash.begin();
298  while (m_3DRepHash.constEnd() != i3DRep)
299  {
300  delete i3DRep.value();
301  ++i3DRep;
302  }
303  m_3DRepHash.clear();
304 
305  // Clear instance Hash table
306  m_StructInstanceHash.clear();
307 
308  m_CurrentId.clear();
309 
310  m_ListOfAttachedFileName.clear();
311 }
312 
313 // Load library_images element
315 {
316  while (endElementNotReached(m_pStreamReader, "library_images"))
317  {
318  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
319  {
320  const QStringRef currentElementName= m_pStreamReader->name();
321  if (currentElementName == "image") loadImage();
322  }
323  m_pStreamReader->readNext();
324 
326  }
327  checkForXmlError("Error occur while loading element : library_images");
328 }
329 
330 // Load image element
332 {
333  //qDebug() << "GLC_ColladaToWorld::loadImage()";
334  // load image id
335  m_CurrentId= readAttribute("id", true);
336  QString fileName;
337  // Trying to find external image fileName
338  while (endElementNotReached(m_pStreamReader, "image"))
339  {
340  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
341  {
342  const QStringRef currentElementName= m_pStreamReader->name();
343  if (currentElementName == "init_from")
344  {
345  fileName= getContent("init_from");
346  }
347  }
348  m_pStreamReader->readNext();
349  }
350 
351  checkForXmlError("Error occur while loading element : image");
352 
353  // Add the image in the image fileName Hash table
354  if (!fileName.isEmpty())
355  {
356  m_ImageFileHash.insert(m_CurrentId, fileName);
357  }
358 }
359 
360 // Load library_materials element
362 {
363  while (endElementNotReached(m_pStreamReader, "library_materials"))
364  {
365  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
366  {
367  const QStringRef currentElementName= m_pStreamReader->name();
368  if (currentElementName == "material") loadMaterial();
369  }
370  m_pStreamReader->readNext();
371 
373  }
374  checkForXmlError("Error occur while loading element : library_materials");
375 
376 }
377 
378 // Load a material
380 {
381  // load material id
382  m_CurrentId= readAttribute("id", true);
383 
384  goToElement("instance_effect");
385 
386  // Load instance effect url
387  const QString url= readAttribute("url", true).remove('#');
388  //qDebug() << "instance effect URL : " << url;
389 
390  // Read instance effect parameters
391  while (endElementNotReached(m_pStreamReader, "instance_effect"))
392  {
393  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
394  {
395  const QStringRef currentElementName= m_pStreamReader->name();
396  if (currentElementName == "setparam")
397  {
398  qDebug() << "GLC_ColladaToWorld::loadMaterial : setparam found";
399  }
400  }
401  m_pStreamReader->readNext();
402  }
403 
404  checkForXmlError("Error occur while loading element : material");
405 
406  // Add the image in the image fileName Hash table
407  if (!url.isEmpty())
408  {
409  //qDebug() << "insert material : " << m_CurrentId << " url: " << url;
410  m_MaterialLibHash.insert(m_CurrentId, url);
411  }
412 
413 }
414 
415 // Load library_effects element
417 {
418  while (endElementNotReached(m_pStreamReader, "library_effects"))
419  {
420  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
421  {
422  const QStringRef currentElementName= m_pStreamReader->name();
423  if (currentElementName == "effect") loadEffect();
424  }
425  m_pStreamReader->readNext();
426 
428  }
429  checkForXmlError("Error occur while loading element : library_effects");
430 
431 }
432 
433 // Load an effect
435 {
436  // load effect id
437  const QString id= readAttribute("id", true);
438  m_CurrentId= id;
441 
442  while (endElementNotReached(m_pStreamReader, "effect"))
443  {
444  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
445  {
446  const QStringRef currentElementName= m_pStreamReader->name();
447  if (currentElementName == "profile_COMMON") loadProfileCommon();
448  }
449  m_pStreamReader->readNext();
450  }
451 
452  checkForXmlError("Error occur while loading element : effect");
453 
455  m_pCurrentMaterial= NULL;
456 
457 }
458 
459 // Load profile_COMMON
461 {
462  //qDebug() << "GLC_ColladaToWorld::loadProfileCommon";
463  while (endElementNotReached(m_pStreamReader, "profile_COMMON"))
464  {
465  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
466  {
467  const QStringRef currentElementName= m_pStreamReader->name();
468  if (currentElementName == "image") loadImage();
469  else if (currentElementName == "newparam") loadNewParam();
470  else if (currentElementName == "technique") loadTechnique();
471  }
472  m_pStreamReader->readNext();
473  }
474  checkForXmlError("Error occur while loading element : profile_COMMON");
475 }
476 
477 // Load a new param of the common profile
479 {
480  //qDebug() << "GLC_ColladaToWorld::loadNewParam";
481  // load param sid
482  const QString sid= m_CurrentId + "::" + readAttribute("sid", true);
483  while (endElementNotReached(m_pStreamReader, "newparam"))
484  {
485  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
486  {
487  const QStringRef currentElementName= m_pStreamReader->name();
488  if (currentElementName == "surface") loadSurface(sid);
489  else if (currentElementName == "sampler2D") loadSampler2D(sid);
490  }
491  m_pStreamReader->readNext();
492  }
493  checkForXmlError("Error occur while loading element : profile_COMMON");
494 }
495 
496 // Load a surface
497 void GLC_ColladaToWorld::loadSurface(const QString& sid)
498 {
499  //qDebug() << "GLC_ColladaToWorld::loadSurface sid=" << sid ;
500  while (endElementNotReached(m_pStreamReader, "surface"))
501  {
502  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
503  {
504  const QStringRef currentElementName= m_pStreamReader->name();
505  if (currentElementName == "init_from")
506  {
507  const QString imageId= getContent("init_from");
508  m_SurfaceImageHash.insert(sid, imageId);
509  }
510  }
511  m_pStreamReader->readNext();
512  }
513  checkForXmlError("Error occur while loading element : surface");
514 }
515 
516 // Load Sampler 2D
517 void GLC_ColladaToWorld::loadSampler2D(const QString& sid)
518 {
519  //qDebug() << "GLC_ColladaToWorld::loadSampler2D sid= " << sid;
520  while (endElementNotReached(m_pStreamReader, "sampler2D"))
521  {
522  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
523  {
524  const QStringRef currentElementName= m_pStreamReader->name();
525  if (currentElementName == "source")
526  {
527  const QString source= m_CurrentId + "::" + getContent("source");
528  m_Sampler2DSurfaceHash.insert(sid, source);
529  }
530  }
531  m_pStreamReader->readNext();
532  }
533  checkForXmlError("Error occur while loading element : sampler2D");
534 }
535 
536 // Load technique
538 {
539  //qDebug() << "GLC_ColladaToWorld::loadTechnique";
540  while (endElementNotReached(m_pStreamReader, "technique"))
541  {
542  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
543  {
544  const QStringRef currentElementName= m_pStreamReader->name();
545  if (currentElementName == "phong") loadMaterialTechnique(currentElementName.toString());
546  if (currentElementName == "lambert") loadMaterialTechnique(currentElementName.toString());
547  if (currentElementName == "blinn") loadMaterialTechnique(currentElementName.toString());
548  }
549  m_pStreamReader->readNext();
550  }
551  checkForXmlError("Error occur while loading element : technique");
552 }
553 
554 // load phong material
555 void GLC_ColladaToWorld::loadMaterialTechnique(const QString& elementName)
556 {
557  //qDebug() << "GLC_ColladaToWorld::loadMaterialTechnique";
558  while (endElementNotReached(m_pStreamReader, elementName))
559  {
560  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
561  {
562  const QStringRef currentElementName= m_pStreamReader->name();
563  if ((currentElementName == "emission")
564  || (currentElementName == "ambient")
565  || (currentElementName == "diffuse")
566  ||(currentElementName == "specular"))
567  loadCommonColorOrTexture(currentElementName.toString());
568  else if (currentElementName == "transparent") loadTransparent();
569  else if (currentElementName == "transparency") loadTransparency(currentElementName.toString());
570  else if (currentElementName == "shininess") loadShininess(currentElementName.toString());
571  }
572  m_pStreamReader->readNext();
573  }
574  checkForXmlError("Error occur while loading element : " + elementName);
575 }
576 
577 // load common color or texture
579 {
580  //qDebug() << "GLC_ColladaToWorld::loadCommonColorOrTexture " << name;
581  Q_ASSERT(NULL != m_pCurrentMaterial);
582 
584  {
585  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
586  {
587  const QStringRef currentElementName= m_pStreamReader->name();
588  if (currentElementName == "color")
589  {
590  if (name == "emission") m_pCurrentMaterial->setEmissiveColor(readXmlColor());
591  else if (name == "ambient") m_pCurrentMaterial->setAmbientColor(readXmlColor());
592  else if (name == "diffuse") m_pCurrentMaterial->setDiffuseColor(readXmlColor());
593  else if (name == "specular") m_pCurrentMaterial->setSpecularColor(readXmlColor());
594  }
595  else if (currentElementName == "texture")
596  {
597  //qDebug() << "Load texture " << name;
598  const QString sid = m_CurrentId + "::" + readAttribute("texture", true);
600  }
601  }
602  m_pStreamReader->readNext();
603  }
604  checkForXmlError("Error occur while loading element : " + name);
605 }
606 
607 // Load transparent
609 {
610  const QString opaque= readAttribute("opaque", false);
611  if (opaque == "RGB_ZERO") m_TransparentIsRgbZero= true;
612  else m_TransparentIsRgbZero= false;
613 }
614 
615 // Load transparency
616 void GLC_ColladaToWorld::loadTransparency(const QString& name)
617 {
618  //qDebug() << "GLC_ColladaToWorld::loadTransparency";
619  Q_ASSERT(NULL != m_pCurrentMaterial);
621  {
622  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
623  {
624  const QStringRef currentElementName= m_pStreamReader->name();
625  if (currentElementName == "float")
626  {
627  bool stringToFloatOk= false;
628  const QString alphaString= getContent("float");
629  float alpha;
631  {
632  alpha= alphaString.toFloat(&stringToFloatOk);
633  }
634  else
635  {
636  alpha= 1.0f - alphaString.toFloat(&stringToFloatOk);
637  }
638  // A material mustn't be invisible (no sense)
639  if (qFuzzyCompare(alpha, 0.0f)) alpha= 1.0f;
640 
642  if (!stringToFloatOk) throwException("Error while trying to convert :" + alphaString + " to float");
643  }
644  }
645  m_pStreamReader->readNext();
646  }
647  checkForXmlError("Error occur while loading element : " + name);
648 }
649 
650 // Load shininess
651 void GLC_ColladaToWorld::loadShininess(const QString& name)
652 {
653  //qDebug() << "GLC_ColladaToWorld::loadShininess";
654  Q_ASSERT(NULL != m_pCurrentMaterial);
656  {
657  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
658  {
659  const QStringRef currentElementName= m_pStreamReader->name();
660  if (currentElementName == "float")
661  {
662  bool stringToFloatOk= false;
663  const QString shininessString= getContent("float");
664  const float shininess= shininessString.toFloat(&stringToFloatOk);
665  if (!stringToFloatOk)
666  {
667  QStringList stringList(m_FileName);
668  stringList.append("Error while trying to convert :" + shininessString + " to float");
669  GLC_ErrorLog::addError(stringList);
670  }
671  else m_pCurrentMaterial->setShininess(shininess);
672  }
673  }
674  m_pStreamReader->readNext();
675  }
676  checkForXmlError("Error occur while loading element : " + name);
677 }
678 
679 // Read a xml Color
681 {
682  //qDebug() << "GLC_ColladaToWorld::readXmlColor()";
683  QColor resultColor;
684 
685  QString colorString= getContent("color");
686  QStringList colors= colorString.split(' ');
687  if(colors.size() == 4)
688  {
689  bool okRed, okGreen, okBlue, okAlpha;
690  const float red= colors.at(0).toFloat(&okRed);
691  const float green= colors.at(1).toFloat(&okGreen);
692  const float blue= colors.at(2).toFloat(&okBlue);
693  const float alpha= colors.at(3).toFloat(&okAlpha);
694  if (okRed && okGreen && okBlue && okAlpha)
695  {
696  resultColor.setRedF(red);
697  resultColor.setGreenF(green);
698  resultColor.setBlueF(blue);
699  resultColor.setAlphaF(alpha);
700  }
701  else
702  {
703  QString info= "Error occur while reading xml color : " + colorString;
704  qDebug() << info << " " << m_FileName;
705  GLC_FileFormatException fileFormatException(info, m_FileName, GLC_FileFormatException::WrongFileFormat);
706  clear();
707  throw(fileFormatException);
708  }
709  }
710  else
711  {
712  QString info= "Error occur while reading xml color : " + colorString;
713  qDebug() << info << " " << m_FileName;
714  GLC_FileFormatException fileFormatException(info, m_FileName, GLC_FileFormatException::WrongFileFormat);
715  clear();
716  throw(fileFormatException);
717  }
718 
719  return resultColor;
720 }
721 
722 // Load library_geometries element
724 {
725  while (endElementNotReached(m_pStreamReader, "library_geometries"))
726  {
727  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
728  {
729  const QStringRef currentElementName= m_pStreamReader->name();
730  if (currentElementName == "geometry") loadGeometry();
731  }
732 
733  m_pStreamReader->readNext();
734 
736  }
737  checkForXmlError("Error occur while loading element : library_geometries");
738 }
739 
740 // Load an geometry element
742 {
743  delete m_pMeshInfo;
744  m_pMeshInfo= new MeshInfo();
746 
747  const QString id= readAttribute("id", false);
748  m_CurrentId= id;
749  if (!id.isEmpty())
750  {
752  //qDebug() << "Loading geometry : " << id;
753  }
754  else
755  {
756  qDebug() << "Geometry without id found !!";
757  }
758 
759  while (endElementNotReached(m_pStreamReader, "geometry"))
760  {
761  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
762  {
763  const QStringRef currentElementName= m_pStreamReader->name();
764  if (currentElementName == "mesh") loadMesh();
765  }
766 
767  m_pStreamReader->readNext();
768  }
769  checkForXmlError("Error occur while loading element : geometry");
770 
771  // Add the current mesh info to the geometry hash
772  if (!id.isEmpty())
773  {
774  m_GeometryHash.insert(id, m_pMeshInfo);
775  m_pMeshInfo= NULL;
776  }
777 }
778 
779 // Load a mesh
781 {
782  while (endElementNotReached(m_pStreamReader, "mesh"))
783  {
784  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
785  {
786  const QStringRef currentElementName= m_pStreamReader->name();
787  if (currentElementName == "source") loadVertexBulkData();
788  else if (currentElementName == "vertices") loadVertices();
789  else if (currentElementName == "polylist") loadPolylist();
790  else if (currentElementName == "polygons") loadPolygons();
791  else if (currentElementName == "triangles") loadTriangles();
792  //else if (currentElementName == "trifans") loadTriFans();
793  //else if (currentElementName == "tristrips") loadTriStrip();
794  }
795 
796  m_pStreamReader->readNext();
797  }
798  checkForXmlError("Error occur while loading element : mesh");
799 }
800 
801 // Load Vertex bulk data
803 {
804  //qDebug() << "GLC_ColladaToWorld::loadVertexBulkData()";
805  // load Vertex Bulk data id
806  m_CurrentId= readAttribute("id", true);
807  //qDebug() << "id=" << m_CurrentId;
808  QList<float> vertices;
809 
810  while (endElementNotReached(m_pStreamReader, "source"))
811  {
812  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
813  {
814  const QStringRef currentElementName= m_pStreamReader->name();
815  if ((currentElementName == "float_array"))
816  {
817  int count= readAttribute("count", true).toInt();
818  QString array= getContent("float_array");
819  QStringList list= array.split(' ');
820  // Check the array size
821  if (count != list.size()) throwException("float_array size not match");
822 
823  for (int i= 0; i < count; ++i)
824  {
825  vertices.append(list.at(i).toFloat());
826  }
827  }
828  else if (currentElementName == "technique_common") loadTechniqueCommon();
829  }
830 
831  m_pStreamReader->readNext();
832  }
833  checkForXmlError("Error occur while loading element : source");
834  m_BulkDataHash.insert(m_CurrentId, vertices);
835 
837 }
838 
840 {
841  //qDebug() << "GLC_ColladaToWorld::loadTechniqueCommon()";
842 
843  while (endElementNotReached(m_pStreamReader, "technique_common"))
844  {
845  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
846  {
847  const QStringRef currentElementName= m_pStreamReader->name();
848  if ((currentElementName == "accessor")) loadAccessor();
849  }
850 
851  m_pStreamReader->readNext();
852  }
853  checkForXmlError("Error occur while loading element : technique_common");
854 
855 }
856 
858 {
859  //qDebug() << "GLC_ColladaToWorld::loadAccessor()";
860  Accessor accessor;
861  const QString count= readAttribute("count", true);
862  const QString offset= readAttribute("offset", false);
863  const QString stride= readAttribute("stride", false);
864  bool conversionOk;
865  accessor.m_Count= count.toUInt(&conversionOk);
866  if (conversionOk)
867  {
868  if (!offset.isEmpty())
869  {
870  accessor.m_Offset= offset.toUInt(&conversionOk);
871  }
872  if (!stride.isEmpty())
873  {
874  accessor.m_Stride= stride.toUInt(&conversionOk);
875  }
876  }
877 
878  while (endElementNotReached(m_pStreamReader, "accessor"))
879  {
880  m_pStreamReader->readNext();
881  }
882  checkForXmlError("Error occur while loading element : technique_common");
883 
884  m_DataAccessorHash.insert(m_CurrentId, accessor);
885 }
886 
887 // Load attributes and identity of mesh vertices
889 {
890  //qDebug() << "GLC_ColladaToWorld::loadVertices()";
891  // load Vertices id
892  m_CurrentId= readAttribute("id", true);
893 
894  goToElement("input");
895  const QString source= readAttribute("source", true).remove('#');
896  m_VerticesSourceHash.insert(m_CurrentId, source);
897  checkForXmlError("Error occur while loading element : vertices");
898 }
899 
900 // Load polygons or polylist
902 {
903  //qDebug() << "GLC_ColladaToWorld::loadPolylist()";
904  // The number of polygon
905  const int polygonCount= readAttribute("count", true).toInt();
906 
907  // The material id
908  const QString materialId= readAttribute("material", false);
909 
910  // Offsets and data source list
911  QList<InputData> inputDataList;
912 
913  // Polygon number of vertice list
914  QList<int> vcountList;
915 
916  // Polygon index list
917  QList<int> polyIndexList;
918 
919  while (endElementNotReached(m_pStreamReader, "polylist"))
920  {
921  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
922  {
923  const QStringRef currentElementName= m_pStreamReader->name();
924  if ((currentElementName == "input") && vcountList.isEmpty())
925  {
926  InputData currentInput;
927  // Get input data offset
928  currentInput.m_Offset= readAttribute("offset", true).toInt();
929  // Get input data semantic
930  const QString semantic= readAttribute("semantic", true);
931  if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
932  else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
933  else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
934  else throwException("Source semantic :" + semantic + "Not supported");
935  // Get input data source id
936  currentInput.m_Source= readAttribute("source", true).remove('#');
937 
938  // Bypasss vertices indirection
939  if (m_VerticesSourceHash.contains(currentInput.m_Source))
940  {
941  currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
942  }
943  inputDataList.append(currentInput);
944  }
945  else if ((currentElementName == "vcount") && (inputDataList.size() > 0))
946  {
947  QString vcountString= getContent("vcount");
948  QStringList vcountStringList= vcountString.split(' ');
949  if (vcountStringList.size() != polygonCount) throwException("vcount size not match");
950  bool toIntOK;
951  for (int i= 0; i < polygonCount; ++i)
952  {
953  vcountList.append(vcountStringList.at(i).toInt(&toIntOK));
954  if (!toIntOK) throwException("Unable to convert string :" + vcountStringList.at(i) + " To int");
955  }
956  }
957  else if ((currentElementName == "p") && !vcountList.isEmpty() && polyIndexList.isEmpty())
958  {
959  { // Fill index List
960  QString pString= getContent("p");
961  QStringList pStringList= pString.split(' ');
962  bool toIntOK;
963  const int size= pStringList.size();
964  for (int i= 0; i < size; ++i)
965  {
966  polyIndexList.append(pStringList.at(i).toInt(&toIntOK));
967  if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
968  }
969  }
970 
971  }
972  }
973  m_pStreamReader->readNext();
974  }
975  // Add the polylist to the current mesh
976  addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
977 
979 }
980 
981 // Load Polygons
983 {
984  // The material id
985  const QString materialId= readAttribute("material", false);
986 
987  // Offsets and data source list
988  QList<InputData> inputDataList;
989 
990  // Polygon number of vertice list
991  QList<int> vcountList;
992 
993  // The input number
994  int inputCount= 0;
995  // Polygon index list
996  QList<int> polyIndexList;
997  while (endElementNotReached(m_pStreamReader, "polygons"))
998  {
999  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1000  {
1001  const QStringRef currentElementName= m_pStreamReader->name();
1002  if ((currentElementName == "input") && vcountList.isEmpty())
1003  {
1004  ++inputCount;
1005  InputData currentInput;
1006  // Get input data offset
1007  currentInput.m_Offset= readAttribute("offset", true).toInt();
1008  // Get input data semantic
1009  const QString semantic= readAttribute("semantic", true);
1010  if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
1011  else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
1012  else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
1013  else throwException("Source semantic :" + semantic + "Not supported");
1014  // Get input data source id
1015  currentInput.m_Source= readAttribute("source", true).remove('#');
1016 
1017  // Bypasss vertices indirection
1018  if (m_VerticesSourceHash.contains(currentInput.m_Source))
1019  {
1020  currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
1021  }
1022  inputDataList.append(currentInput);
1023  }
1024  else if (currentElementName == "p")
1025  {
1026  { // Fill index List
1027  QString pString= getContent("p");
1028  QStringList pStringList= pString.split(' ');
1029  bool toIntOK;
1030  const int size= pStringList.size();
1031  for (int i= 0; i < size; ++i)
1032  {
1033  polyIndexList.append(pStringList.at(i).toInt(&toIntOK));
1034  if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
1035  }
1036  // Add the polygon size in vcountList
1037  vcountList.append(size / inputCount);
1038  }
1039  }
1040  }
1041  m_pStreamReader->readNext();
1042  }
1043  // Add the polylist to the current mesh
1044  addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
1045 
1047 }
1048 
1049 // Add the polylist to the current mesh
1050 void GLC_ColladaToWorld::addPolylistToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& vcountList, const QList<int>& polyIndexList, const QString& materialId)
1051 {
1052  //qDebug() << "GLC_ColladaToWorld::addPolylistToCurrentMesh";
1053 
1054  const int polygonCount= vcountList.size();
1055  const int inputDataCount= inputDataList.size();
1056  const int polyIndexCount= polyIndexList.size();
1057 
1058  // Flag to know if the polylist has normal
1059  bool hasNormals= false;
1060  bool hasTexture= false;
1061  // Check the existance of data source
1062  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1063  {
1064  const QString source= inputDataList.at(dataIndex).m_Source;
1065  if ( !m_BulkDataHash.contains(source))
1066  {
1067  throwException(" Source : " + source + " Not found");
1068  }
1069  if (inputDataList.at(dataIndex).m_Semantic == NORMAL) hasNormals= true;
1070  if (inputDataList.at(dataIndex).m_Semantic == TEXCOORD) hasTexture= true;
1071  }
1072 
1073  int maxOffset= 0;
1074  for (int i= 0; i < inputDataCount; ++i)
1075  {
1076  if (inputDataList.at(i).m_Offset > maxOffset)
1077  {
1078  maxOffset= inputDataList.at(i).m_Offset;
1079  }
1080  }
1081  //qDebug() << " Max Offset :" << maxOffset;
1082 
1083  // the polygonIndex of the polylist
1084  QList<int> polygonIndex;
1085 
1086  // Fill the mapping, bulk data and index list of the current mesh info
1087  for (int i= 0; i < polyIndexCount; i+= maxOffset + 1)
1088  {
1089  // Create and set the current vertice index
1090  ColladaVertice currentVertice;
1091  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1092  {
1093  currentVertice.m_Values[inputDataList.at(dataIndex).m_Semantic]= polyIndexList.at(i + inputDataList.at(dataIndex).m_Offset);
1094  }
1095 
1096  if (m_pMeshInfo->m_Mapping.contains(currentVertice))
1097  {
1098  // Add the the index to the polygon index
1099  polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
1100  }
1101  else
1102  {
1103  // Add the current vertice to the current mesh info mapping hash table and increment the freeIndex
1104  m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
1105  // Add the the index to the polygon index
1106  polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
1107 
1108  // Add the bulk data associated to the current vertice to the current mesh info
1109  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1110  {
1111  // The current input data
1112  InputData currentInputData= inputDataList.at(dataIndex);
1113  // QHash iterator on the right QList<float>
1114  BulkDataHash::const_iterator iBulkHash= m_BulkDataHash.find(currentInputData.m_Source);
1115  int stride;
1116  if (m_DataAccessorHash.contains(currentInputData.m_Source))
1117  {
1118  stride= m_DataAccessorHash.value(currentInputData.m_Source).m_Stride;
1119  }
1120  else if (currentInputData.m_Semantic != TEXCOORD) stride= 3; else stride= 2;
1121  // Firts value
1122  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride));
1123  // Second value
1124  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride + 1));
1125  // Fird value
1126  if (currentInputData.m_Semantic != TEXCOORD)
1127  {
1128  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride + 2));
1129  }
1130  }
1131  // Avoid problem wich occur with mesh containing materials with and without texture
1132  if (!hasTexture)
1133  {
1134  m_pMeshInfo->m_Datas[TEXCOORD].append(0.0);
1135  }
1136 
1137  }
1138  }
1139 
1140  // Save mesh info index offset
1141  const int indexOffset= m_pMeshInfo->m_Index.size();
1142  // Triangulate the polygons of the polylist
1143  // Input polygon index must start from 0 and succesive : (0 1 2 3 4)
1144  QList<GLuint> onePolygonIndex;
1145  for (int i= 0; i < polygonCount; ++i)
1146  {
1147  const int polygonSize= vcountList.at(i);
1148  Q_ASSERT(polygonSize > 2);
1149  for (int i= 0; i < polygonSize; ++i)
1150  {
1151  onePolygonIndex.append(polygonIndex.takeFirst());
1152  }
1153  // Triangulate the current polygon if the polygon as more than 3 vertice
1154  if (polygonSize > 3)
1155  {
1156  glc::triangulatePolygon(&onePolygonIndex, m_pMeshInfo->m_Datas.at(VERTEX));
1157  }
1158  // Add index to the mesh info
1159  //Q_ASSERT(not onePolygonIndex.isEmpty());
1160  if (!onePolygonIndex.isEmpty())
1161  {
1162  m_pMeshInfo->m_Index.append(onePolygonIndex);
1163  }
1164  else
1165  {
1166  QStringList stringList(m_FileName);
1167  stringList.append("Unable to triangulate a polygon of " + m_pMeshInfo->m_pMesh->name());
1168  GLC_ErrorLog::addError(stringList);
1169  }
1170  onePolygonIndex.clear();
1171  }
1172 
1173  // Check if normal computation is needed
1174  if (!hasNormals)
1175  {
1176  qDebug() << "Compute Normals with offset " << indexOffset;
1178  }
1179 
1180  // Add material the current mesh info
1181  MatOffsetSize matInfo;
1182  matInfo.m_Offset= indexOffset;
1183  matInfo.m_size= m_pMeshInfo->m_Index.size() - indexOffset;
1184  m_pMeshInfo->m_Materials.insert(materialId, matInfo);
1185 
1186 }
1187 // Compute Normals for the current primitive element of the current mesh
1189 {
1190  const QList<float>* pData= &(m_pMeshInfo->m_Datas.at(VERTEX));
1191  // Fill the list of normal
1192  QList<float>* pNormal= &(m_pMeshInfo->m_Datas[NORMAL]);
1193  const int normalOffset= pNormal->size();
1194  const int normalCount= pData->size() - normalOffset;
1195  for (int i= 0; i < normalCount; ++i)
1196  {
1197  pNormal->append(0.0f);
1198  }
1199  // Compute the normals and add them to the current mesh info
1200  const int size= m_pMeshInfo->m_Index.size() - indexOffset;
1201  double xn, yn, zn;
1202 
1203 
1204  for (int i= indexOffset; i < size; i+=3)
1205  {
1206  // Vertex 1
1207  xn= pData->at(m_pMeshInfo->m_Index.at(i) * 3);
1208  yn= pData->at(m_pMeshInfo->m_Index.at(i) * 3 + 1);
1209  zn= pData->at(m_pMeshInfo->m_Index.at(i) * 3 + 2);
1210  const GLC_Vector3d vect1(xn, yn, zn);
1211 
1212  // Vertex 2
1213  xn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3);
1214  yn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3 + 1);
1215  zn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3 + 2);
1216  const GLC_Vector3d vect2(xn, yn, zn);
1217 
1218  // Vertex 3
1219  xn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3);
1220  yn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3 + 1);
1221  zn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3 + 2);
1222  const GLC_Vector3d vect3(xn, yn, zn);
1223 
1224  const GLC_Vector3d edge1(vect3 - vect2);
1225  const GLC_Vector3d edge2(vect1 - vect2);
1226 
1227  GLC_Vector3d normal(edge1 ^ edge2);
1228  normal.normalize();
1229 
1230  GLC_Vector3df curNormal= normal.toVector3df();
1231  for (int curVertex= 0; curVertex < 3; ++curVertex)
1232  {
1233  (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3]= curNormal.x();
1234  (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3 + 1]= curNormal.y();
1235  (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3 + 2]= curNormal.z();
1236  }
1237  }
1238 }
1239 
1240 // Load triangles
1242 {
1243  //qDebug() << "GLC_ColladaToWorld::loadTriangles()";
1244  // The material id
1245  const QString materialId= readAttribute("material", false);
1246 
1247  // Offsets and data source list
1248  QList<InputData> inputDataList;
1249 
1250  // triangle index list
1251  QList<int> trianglesIndexList;
1252 
1253  while (endElementNotReached(m_pStreamReader, "triangles"))
1254  {
1255  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1256  {
1257  const QStringRef currentElementName= m_pStreamReader->name();
1258  if ((currentElementName == "input") && trianglesIndexList.isEmpty())
1259  {
1260  InputData currentInput;
1261  // Get input data offset
1262  currentInput.m_Offset= readAttribute("offset", true).toInt();
1263  // Get input data semantic
1264  const QString semantic= readAttribute("semantic", true);
1265  if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
1266  else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
1267  else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
1268  else throwException("Source semantic :" + semantic + "Not supported");
1269  // Get input data source id
1270  currentInput.m_Source= readAttribute("source", true).remove('#');
1271 
1272  // Bypasss vertices indirection
1273  if (m_VerticesSourceHash.contains(currentInput.m_Source))
1274  {
1275  currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
1276  }
1277  inputDataList.append(currentInput);
1278  }
1279  else if ((currentElementName == "p") && trianglesIndexList.isEmpty())
1280  {
1281  { // Fill index List
1282  QString pString= getContent("p");
1283  QStringList pStringList= pString.split(' ');
1284  bool toIntOK;
1285  const int size= pStringList.size();
1286  for (int i= 0; i < size; ++i)
1287  {
1288  trianglesIndexList.append(pStringList.at(i).toInt(&toIntOK));
1289  if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
1290  }
1291  }
1292 
1293  }
1294  }
1295  m_pStreamReader->readNext();
1296  }
1297 
1298  // Add the polylist to the current mesh
1299  addTrianglesToCurrentMesh(inputDataList, trianglesIndexList, materialId);
1300 
1302 
1303 }
1304 
1305 // Add the triangles to current mesh
1306 void GLC_ColladaToWorld::addTrianglesToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& trianglesIndexList, const QString& materialId)
1307 {
1308  //qDebug() << "GLC_ColladaToWorld::addTrianglesToCurrentMesh";
1309 
1310  const int inputDataCount= inputDataList.size();
1311  const int trianglesIndexCount= trianglesIndexList.size();
1312 
1313  // Flag to know if the polylist has normal
1314  bool hasNormals= false;
1315  bool hasTexture= false;
1316 
1317  // Check the existance of data source
1318  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1319  {
1320  const QString source= inputDataList.at(dataIndex).m_Source;
1321  if ( !m_BulkDataHash.contains(source))
1322  {
1323  throwException(" Source : " + source + " Not found");
1324  }
1325  if (inputDataList.at(dataIndex).m_Semantic == NORMAL) hasNormals= true;
1326  if (inputDataList.at(dataIndex).m_Semantic == TEXCOORD) hasTexture= true;
1327  }
1328 
1329  int maxOffset= 0;
1330  for (int i= 0; i < inputDataCount; ++i)
1331  {
1332  if (inputDataList.at(i).m_Offset > maxOffset)
1333  {
1334  maxOffset= inputDataList.at(i).m_Offset;
1335  }
1336  }
1337  //qDebug() << " Triangles Max Offset :" << maxOffset;
1338 
1339  // the polygonIndex of the polylist
1340  QList<GLuint> trianglesIndex;
1341 
1342  // Fill the mapping, bulk data and index list of the current mesh info
1343  for (int i= 0; i < trianglesIndexCount; i+= maxOffset + 1)
1344  {
1345  // Create and set the current vertice index
1346  ColladaVertice currentVertice;
1347  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1348  {
1349  currentVertice.m_Values[inputDataList.at(dataIndex).m_Semantic]= trianglesIndexList.at(i + inputDataList.at(dataIndex).m_Offset);
1350  }
1351 
1352  if (m_pMeshInfo->m_Mapping.contains(currentVertice))
1353  {
1354  // Add the the index to the triangles index
1355  trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
1356  }
1357  else
1358  {
1359  // Add the current vertice to the current mesh info mapping hash table and increment the freeIndex
1360  m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
1361  // Add the the index to the triangles index
1362  trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
1363 
1364  // Add the bulk data associated to the current vertice to the current mesh info
1365  for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
1366  {
1367  // The current input data
1368  InputData currentInputData= inputDataList.at(dataIndex);
1369  // QHash iterator on the right QList<float>
1370  BulkDataHash::const_iterator iBulkHash= m_BulkDataHash.find(currentInputData.m_Source);
1371  int stride;
1372  if (m_DataAccessorHash.contains(currentInputData.m_Source))
1373  {
1374  stride= m_DataAccessorHash.value(currentInputData.m_Source).m_Stride;
1375  }
1376  else if (currentInputData.m_Semantic != TEXCOORD) stride= 3; else stride= 2;
1377  // Firts value
1378  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride));
1379  // Second value
1380  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride + 1));
1381  // Fird value
1382  if (currentInputData.m_Semantic != TEXCOORD)
1383  {
1384  m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride + 2));
1385  }
1386  // Avoid problem wich occur with mesh containing materials with and without texture
1387  if (!hasTexture)
1388  {
1389  m_pMeshInfo->m_Datas[TEXCOORD].append(0.0);
1390  }
1391  }
1392  }
1393  }
1394 
1395  // Save mesh info index offset
1396  const int indexOffset= m_pMeshInfo->m_Index.size();
1397 
1398  // Add index to the mesh info
1399  m_pMeshInfo->m_Index.append(trianglesIndex);
1400 
1401  // Check if normal computation is needed
1402  if (!hasNormals)
1403  {
1405  }
1406 
1407  // Add material the current mesh info
1408  MatOffsetSize matInfo;
1409  matInfo.m_Offset= indexOffset;
1410  matInfo.m_size= m_pMeshInfo->m_Index.size() - indexOffset;
1411  m_pMeshInfo->m_Materials.insertMulti(materialId, matInfo);
1412 
1413 }
1414 
1415 // Load the library nodes
1417 {
1418  //qDebug() << "GLC_ColladaToWorld::loadLibraryNodes";
1419 
1420  while (endElementNotReached(m_pStreamReader, "library_nodes"))
1421  {
1422  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1423  {
1424  const QStringRef currentElementName= m_pStreamReader->name();
1425  if ((currentElementName == "node"))
1426  {
1428  if (NULL != pNode)
1429  {
1430 
1431  }
1432  }
1433  }
1434 
1436 
1437  m_pStreamReader->readNext();
1438  }
1439  checkForXmlError("Error occur while loading element : library_nodes");
1440 }
1441 
1442 // Load the library controllers
1444 {
1445  //qDebug() << "GLC_ColladaToWorld::loadLibraryContollers";
1446 
1447  while (endElementNotReached(m_pStreamReader, "library_controllers"))
1448  {
1449  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1450  {
1451  const QStringRef currentElementName= m_pStreamReader->name();
1452  if ((currentElementName == "controller")) loadController();
1453  }
1454 
1456 
1457  m_pStreamReader->readNext();
1458  }
1459  checkForXmlError("Error occur while loading element : library_controllers");
1460 }
1461 
1462 // Load library_visual_scenes element
1464 {
1465  //qDebug() << "GLC_ColladaToWorld::loadVisualScenes";
1466  // The element library visual scene must contains a visual scene element
1467  goToElement("visual_scene");
1468 
1469  while (endElementNotReached(m_pStreamReader, "visual_scene"))
1470  {
1471  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1472  {
1473  const QStringRef currentElementName= m_pStreamReader->name();
1474  if (currentElementName == "node")
1475  {
1477  if (NULL != pNode)
1478  {
1479  m_TopLevelColladaNode.append(pNode);
1480  }
1481  }
1482  }
1483 
1485 
1486  m_pStreamReader->readNext();
1487  }
1488  checkForXmlError("Error occur while loading element : visual_scene");
1489 }
1490 
1491 // Load an instance geometry
1493 {
1494  //qDebug() << "GLC_ColladaToWorld::loadInstanceGeometry";
1495 
1496  const QString url= readAttribute("url", true).remove('#');
1497  pNode->m_InstanceGeometryIDs.append(url);
1498 
1499  while (endElementNotReached(m_pStreamReader, "instance_geometry"))
1500  {
1501  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1502  {
1503  const QStringRef currentElementName= m_pStreamReader->name();
1504  if ((currentElementName == "instance_material"))
1505  {
1506  const QString target= readAttribute("target", true).remove('#');
1507  const QString symbol= readAttribute("symbol", true);
1508  m_MaterialInstanceMap.insert(symbol, target);
1509  }
1510 
1511  }
1512  m_pStreamReader->readNext();
1513  }
1514  checkForXmlError("Error occur while loading element : instance_geometry");
1515 }
1516 
1517 // Load an instance of node
1519 {
1520  //qDebug() << "GLC_ColladaToWorld::loadInstanceNode";
1521  const QString url= readAttribute("url", true).remove('#');
1522  pNode->m_InstanceOffNodeIds.append(url);
1523 }
1524 
1525 // Load an instance Controller
1527 {
1528  const QString url= readAttribute("url", true).remove('#');
1529  pNode->m_InstanceOffNodeIds.append(url);
1530 
1531  while (endElementNotReached(m_pStreamReader, "instance_controller"))
1532  {
1533  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1534  {
1535  const QStringRef currentElementName= m_pStreamReader->name();
1536  if ((currentElementName == "instance_material"))
1537  {
1538  const QString target= readAttribute("target", true).remove('#');
1539  const QString symbol= readAttribute("symbol", true);
1540  m_MaterialInstanceMap.insert(symbol, target);
1541  }
1542  }
1543  m_pStreamReader->readNext();
1544  }
1545  checkForXmlError("Error occur while loading element : instance_controller");
1546 }
1547 
1548 // Load a collada controller node
1550 {
1551 
1552  m_CurrentId= readAttribute("id", true);
1553  while (endElementNotReached(m_pStreamReader, "controller"))
1554  {
1555  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1556  {
1557  const QStringRef currentElementName= m_pStreamReader->name();
1558  if ((currentElementName == "skin"))
1559  {
1560  const QString source= readAttribute("source", true).remove('#');
1561  ColladaNode* pNode= new ColladaNode(m_CurrentId, NULL);
1562  pNode->m_InstanceGeometryIDs.append(source);
1563  m_ColladaNodeHash.insert(m_CurrentId, pNode);
1564  }
1565  }
1566  m_pStreamReader->readNext();
1567  }
1568  checkForXmlError("Error occur while loading element : controller");
1569 
1570 }
1571 
1572 // Load a Collada Node element
1574 {
1575  //qDebug() << "GLC_ColladaToWorld::loadNode";
1576 
1577 
1578  QString id= readAttribute("id", false);
1579  if (id.isEmpty())
1580  {
1581  id= readAttribute("name", false);
1582  }
1583  if (id.isEmpty())
1584  {
1585  id= prefixNodeId + QString::number(++currentNodeId);
1586  }
1587 
1588  qint64 currentOffset= m_pStreamReader->characterOffset();
1589  //qDebug() << "Load Node " << id;
1590  m_CurrentId= id;
1591  // The node
1592  ColladaNode* pNode= new ColladaNode(id, pParent);
1593  // To avoid infinite call
1594  //m_pStreamReader->readNext();
1595 
1596  while (endElementNotReached(m_pStreamReader, "node"))
1597  {
1598  if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
1599  {
1600  const QStringRef currentElementName= m_pStreamReader->name();
1601 
1602  if ((currentElementName == "translate")) translateNode(pNode);
1603  else if ((currentElementName == "scale")) scaleNode(pNode);
1604  else if ((currentElementName == "rotate")) rotateNode(pNode);
1605  else if ((currentElementName == "matrix")) composeMatrixNode(pNode);
1606  else if ((currentElementName == "instance_geometry")) loadInstanceGeometry(pNode);
1607  else if ((currentElementName == "instance_node")) loadInstanceNode(pNode);
1608  else if ((currentElementName == "instance_controller")) loadInstanceController(pNode);
1609  else if ((currentElementName == "node"))
1610  {
1611  if (currentOffset != m_pStreamReader->characterOffset())
1612  {
1613  QString newId= readAttribute("id", false);
1614  if (newId.isEmpty())
1615  {
1616  //qDebug() << "Child ReadAttribute name";
1617  newId= readAttribute("name", false);
1618  }
1619  //qDebug() << "New ID = " << newId;
1620  GLC_ColladaToWorld::ColladaNode* pChildNode= loadNode(pNode);
1621  if (NULL != pNode)
1622  {
1623  //qDebug() << "Add child";
1624  pNode->m_ChildNodes.append(pChildNode);
1625  }
1626  }
1627  }
1628  else if ((currentElementName == "instance_camera")
1629  || (currentElementName == "instance_light"))
1630  {
1631  // Node type not supported
1632  delete pNode;
1633  pNode= NULL;
1634  }
1635  }
1636  m_pStreamReader->readNext();
1637 
1638  }
1639 
1640  if (NULL != pNode)
1641  {
1642  // Add the collada node to the collada node hash table
1643  m_ColladaNodeHash.insert(id, pNode);
1644  }
1645  return pNode;
1646 }
1647 
1648 
1649 // Translate the node
1651 {
1652  //qDebug() << "Translate Node";
1653  Q_ASSERT(NULL != pNode);
1654  // Load translation values
1655  QStringList translateStringList= getContent("translate").simplified().split(' ');
1656  // A translation must contains 3 string
1657  const int size= translateStringList.size();
1658  if (translateStringList.size() != 3) throwException("Translate element must contains 3 floats and it's contains :" + QString::number(translateStringList.size()));
1659  // Convert the string to double
1660  double translate[3];
1661  bool toFloatOk= false;
1662  for (int i= 0; i < size; ++i)
1663  {
1664  translate[i]= static_cast<double>(translateStringList.at(i).toFloat(&toFloatOk));
1665  if (!toFloatOk) throwException("The number :" + translateStringList.at(i) + "Is not a float");
1666  }
1667  // Built the translation matrix
1668  GLC_Matrix4x4 translationMatrix(translate[0], translate[1], translate[2]);
1669  // Update the node matrix
1670  pNode->m_Matrix= pNode->m_Matrix * translationMatrix;
1671 }
1672 
1673 // Scale the node
1675 {
1676  //qDebug() << "Scale Node";
1677  Q_ASSERT(NULL != pNode);
1678  // Load scale values
1679  QStringList scaleStringList= getContent("scale").simplified().split(' ');
1680  // A scale must contains 3 string
1681  const int size= scaleStringList.size();
1682  if (scaleStringList.size() != 3) throwException("Scale element must contains 3 floats and it's contains :" + QString::number(scaleStringList.size()));
1683  // Convert the string to double
1684  double scale[3];
1685  bool toFloatOk= false;
1686  for (int i= 0; i < size; ++i)
1687  {
1688  scale[i]= static_cast<double>(scaleStringList.at(i).toFloat(&toFloatOk));
1689  if (!toFloatOk) throwException("The number :" + scaleStringList.at(i) + "Is not a float");
1690  }
1691  // Built the translation matrix
1692  GLC_Matrix4x4 scaleMatrix;
1693  scaleMatrix.setMatScaling(scale[0], scale[1], scale[2]);
1694  scaleMatrix.optimise();
1695  // Update the node matrix
1696  pNode->m_Matrix= pNode->m_Matrix * scaleMatrix;
1697 }
1698 
1699 // Rotate the node
1701 {
1702  //qDebug() << "Rotate Node";
1703  Q_ASSERT(NULL != pNode);
1704  // Load rotate values
1705  QStringList rotateStringList= getContent("rotate").simplified().split(' ');
1706  // A rotate must contains 4 string (Axis Vector 3 + Angle)
1707  const int size= rotateStringList.size();
1708  if (rotateStringList.size() != 4) throwException("Rotate element must contains 4 floats and it's contains :" + QString::number(rotateStringList.size()));
1709  // Convert the string to double
1710  double rotate[4];
1711  bool toFloatOk= false;
1712  for (int i= 0; i < size; ++i)
1713  {
1714  rotate[i]= static_cast<double>(rotateStringList.at(i).toFloat(&toFloatOk));
1715  if (!toFloatOk) throwException("The number :" + rotateStringList.at(i) + "Is not a float");
1716  }
1717  // Rotation vector
1718  GLC_Vector3d rotationAxis(rotate[0], rotate[1], rotate[2]);
1719  // Built the rotation matrix
1720  GLC_Matrix4x4 rotationMatrix(rotationAxis, rotate[3]);
1721  // Update the node matrix
1722  pNode->m_Matrix= pNode->m_Matrix * rotationMatrix;
1723 }
1724 
1725 // Compose Node matrix
1727 {
1728  Q_ASSERT(NULL != pNode);
1729 
1730  // Load matrix values
1731  QStringList matrixStringList= getContent("matrix").simplified().split(' ');
1732  // A rotate must contains 16 string 4 x 4 Matrix
1733  const int size= matrixStringList.size();
1734  if (size != 16) throwException("Matrix element must contains 16 floats and it's contains :" + QString::number(size));
1735  // Convert the string to double
1736  double matrix[16];
1737  bool toFloatOk= false;
1738  for (int i= 0; i < 4; ++i)
1739  {
1740  matrix[i]= static_cast<double>(matrixStringList.at(i * 4).toFloat(&toFloatOk));
1741  if (!toFloatOk) throwException("The number :" + matrixStringList.at(i) + "Is not a float");
1742 
1743  matrix[i + 4]= static_cast<double>(matrixStringList.at(i * 4 + 1).toFloat(&toFloatOk));
1744  if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 1) + "Is not a float");
1745 
1746  matrix[i + 8]= static_cast<double>(matrixStringList.at(i * 4 + 2).toFloat(&toFloatOk));
1747  if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 2) + "Is not a float");
1748 
1749  matrix[i + 12]= static_cast<double>(matrixStringList.at(i * 4 + 3).toFloat(&toFloatOk));
1750  if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 3) + "Is not a float");
1751 
1752  }
1753  // Built the matrix
1754  GLC_Matrix4x4 currentMatrix(matrix);
1755  currentMatrix.optimise();
1756 
1757  // Update the node matrix
1758  pNode->m_Matrix= pNode->m_Matrix * currentMatrix;
1759 }
1760 
1761 // Load scene element
1763 {
1764  //qDebug() << "GLC_ColladaToWorld::loadScene";
1765  while (endElementNotReached(m_pStreamReader, "scene"))
1766  {
1767  // Nothing to do
1768  m_pStreamReader->readNext();
1769  }
1770 }
1771 
1772 // Link texture to material
1774 {
1775  // Iterate throuth the the texture id to material hash
1776  MaterialHash::iterator iMat= m_TextureToMaterialHash.begin();
1777  while (iMat != m_TextureToMaterialHash.constEnd())
1778  {
1779  GLC_Material* pCurrentMaterial= iMat.value();
1780  const QString textureId= iMat.key();
1781 
1782  // Check that the texture is present
1783  if (m_Sampler2DSurfaceHash.contains(textureId))
1784  {
1785  const QString surfaceId= m_Sampler2DSurfaceHash.value(textureId);
1786  if (m_SurfaceImageHash.contains(surfaceId))
1787  {
1788  const QString imageFileId= m_SurfaceImageHash.value(surfaceId);
1789  }
1790  }
1791  if (m_Sampler2DSurfaceHash.contains(textureId) && m_SurfaceImageHash.contains(m_Sampler2DSurfaceHash.value(textureId))
1792  && m_ImageFileHash.contains(m_SurfaceImageHash.value(m_Sampler2DSurfaceHash.value(textureId))))
1793  {
1794  const QString imageFileName= m_ImageFileHash.value(m_SurfaceImageHash.value(m_Sampler2DSurfaceHash.value(textureId)));
1795  QString fullImageFileName= QFileInfo(m_FileName).absolutePath() + QDir::separator() + imageFileName;
1796  if (QFileInfo(fullImageFileName).exists())
1797  {
1798  m_ListOfAttachedFileName << fullImageFileName;
1799  GLC_Texture* pTexture= new GLC_Texture(fullImageFileName);
1800  pCurrentMaterial->setTexture(pTexture);
1801  }
1802  else if (QFileInfo(m_FileName).absolutePath() != QFileInfo(fullImageFileName).absolutePath())
1803  {
1804  // Trying to find image in collada file path
1805  QString fullImageFileName= QFileInfo(m_FileName).absolutePath() + QDir::separator() + QFileInfo(imageFileName).fileName();
1806  if (QFileInfo(fullImageFileName).exists())
1807  {
1808  m_ListOfAttachedFileName << fullImageFileName;
1809  GLC_Texture* pTexture= new GLC_Texture(fullImageFileName);
1810  pCurrentMaterial->setTexture(pTexture);
1811  }
1812  else
1813  {
1814  QStringList stringList(m_FileName);
1815  stringList.append(imageFileName + " Not found");
1816  GLC_ErrorLog::addError(stringList);
1817  }
1818  }
1819  else
1820  {
1821  QStringList stringList(m_FileName);
1822  stringList.append(imageFileName + " Not found");
1823  GLC_ErrorLog::addError(stringList);
1824  }
1825 
1826  }
1827  else
1828  {
1829  QStringList stringList(m_FileName);
1830  stringList.append("Texture : " + textureId + " Not found");
1831  GLC_ErrorLog::addError(stringList);
1832  }
1833  ++iMat;
1834  }
1835 }
1836 // Create mesh and link them to material
1838 {
1839  //qDebug() << "GLC_ColladaToWorld::createMesh()";
1840  QHash<const QString, MeshInfo*>::iterator iMeshInfo= m_GeometryHash.begin();
1841  while (m_GeometryHash.constEnd() != iMeshInfo)
1842  {
1843  MeshInfo* pCurrentMeshInfo= iMeshInfo.value();
1844  // Add Bulk Data to the mesh
1845  // Add vertice
1846  pCurrentMeshInfo->m_pMesh->addVertice(pCurrentMeshInfo->m_Datas.at(VERTEX).toVector());
1847  //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[VERTEX].size() << " Vertice";
1848  pCurrentMeshInfo->m_Datas[VERTEX].clear();
1849 
1850  // Add Normal
1851  pCurrentMeshInfo->m_pMesh->addNormals(pCurrentMeshInfo->m_Datas.at(NORMAL).toVector());
1852  //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[NORMAL].size() << " Normal";
1853  pCurrentMeshInfo->m_Datas[NORMAL].clear();
1854 
1855  // Add texel if necessary
1856  //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[TEXCOORD].size() << " texel";
1857  if (!pCurrentMeshInfo->m_Datas.at(TEXCOORD).isEmpty())
1858  {
1859  pCurrentMeshInfo->m_pMesh->addTexels(pCurrentMeshInfo->m_Datas.at(TEXCOORD).toVector());
1860  pCurrentMeshInfo->m_Datas[TEXCOORD].clear();
1861  }
1862 
1863  // Add face index and material to the mesh
1864  QHash<QString, MatOffsetSize>::iterator iMatInfo= pCurrentMeshInfo->m_Materials.begin();
1865  while (pCurrentMeshInfo->m_Materials.constEnd() != iMatInfo)
1866  {
1867  // Trying to find the material
1868  QString materialId= iMatInfo.key();
1869  GLC_Material* pCurrentMaterial= NULL;
1870  if (m_MaterialInstanceMap.contains(materialId))
1871  {
1872  //qDebug() << "Map " << materialId << " to " << m_MaterialInstanceMap.value(materialId);
1873  materialId= m_MaterialInstanceMap.value(materialId);
1874  }
1875  //qDebug() << "MaterialLibHash size : " << m_MaterialLibHash.size();
1876  if (m_MaterialLibHash.contains(materialId))
1877  {
1878  materialId= m_MaterialLibHash.value(materialId);
1879  //qDebug() << "Material id " << materialId;
1880  }
1881  if (m_MaterialEffectHash.contains(materialId))
1882  {
1883  //qDebug() << "Material " << materialId << " find";
1884  pCurrentMaterial= m_MaterialEffectHash.value(materialId);
1885  Q_ASSERT(NULL != pCurrentMaterial);
1886  }
1887  else
1888  {
1889  QStringList stringList(m_FileName);
1890  stringList.append("Material " + materialId + " Not found");
1891  GLC_ErrorLog::addError(stringList);
1892  }
1893 
1894  // Create the list of triangles to add to the mesh
1895  const int offset= iMatInfo.value().m_Offset;
1896  const int size= iMatInfo.value().m_size;
1897  //qDebug() << "Offset : " << offset << " size : " << size;
1898  QList<GLuint> triangles;
1899  for (int i= offset; i < (offset + size); ++i)
1900  {
1901  triangles.append(pCurrentMeshInfo->m_Index.at(i));
1902  }
1903  //qDebug() << "Add " << triangles.size() << " elment to the triangle index";
1904  // Add the list of triangle to the mesh
1905  if (!triangles.isEmpty())
1906  {
1907  pCurrentMeshInfo->m_pMesh->addTriangles(pCurrentMaterial, triangles);
1908  }
1909 
1910  ++iMatInfo;
1911  }
1912  pCurrentMeshInfo->m_pMesh->finish();
1913  GLC_3DRep* pRep= new GLC_3DRep(pCurrentMeshInfo->m_pMesh);
1914  pCurrentMeshInfo->m_pMesh= NULL;
1915  pRep->clean();
1916  //qDebug() << "Insert Rep : " << iMeshInfo.key();
1917  m_3DRepHash.insert(iMeshInfo.key(), pRep);
1918  ++iMeshInfo;
1919  }
1920 }
1921 
1922 // Create the scene graph struct
1924 {
1925  const int topLevelNodeCount= m_TopLevelColladaNode.size();
1926  for (int i= 0; i < topLevelNodeCount; ++i)
1927  {
1928  ColladaNode* pCurrentColladaNode= m_TopLevelColladaNode.at(i);
1929  //qDebug() << "Top level node is : " << pCurrentColladaNode->m_Id;
1930  if (NULL != pCurrentColladaNode)
1931  {
1932  GLC_StructOccurence* pOccurence= createOccurenceFromNode(pCurrentColladaNode);
1933  m_pWorld->rootOccurence()->addChild(pOccurence);
1934  }
1935  }
1936 
1937  // Update position
1940 
1941 }
1942 
1943 // Create Occurence tree from node tree
1945 {
1946  //qDebug() << "GLC_ColladaToWorld::createOccurenceFromNode";
1947  Q_ASSERT(NULL != pNode);
1948  GLC_StructInstance* pInstance= NULL;
1949  GLC_StructOccurence* pOccurence= NULL;
1950  if (!pNode->m_InstanceGeometryIDs.isEmpty())
1951  {
1952  if (m_StructInstanceHash.contains(pNode->m_Id))
1953  {
1954  pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
1955  pInstance->move(pNode->m_Matrix);
1956  //qDebug() << "Instance move with this matrix :" << pNode->m_Matrix.toString();
1957  pOccurence= new GLC_StructOccurence(pInstance);
1958  }
1959  else
1960  {
1961  const int size= pNode->m_InstanceGeometryIDs.size();
1962  GLC_3DRep* pRep= NULL;
1963  for (int i= 0; i < size; ++i)
1964  {
1965  const QString geometryId= pNode->m_InstanceGeometryIDs.at(i);
1966  if (NULL == pRep)
1967  {
1968  pRep= new GLC_3DRep(*(m_3DRepHash.value(geometryId)));
1969  }
1970  else
1971  {
1972  pRep->merge(m_3DRepHash.value(geometryId));
1973  }
1974  }
1975  if (NULL != pRep)
1976  {
1977  GLC_StructReference* pStructRef= NULL;
1978  if (pRep->isEmpty())
1979  {
1980  QStringList stringList(m_FileName);
1981  stringList.append("Empty rep : " + pRep->name());
1982  GLC_ErrorLog::addError(stringList);
1983  delete pRep;
1984  pRep= NULL;
1985  }
1986  else
1987  {
1988  pStructRef= new GLC_StructReference(pRep);
1989  pInstance= new GLC_StructInstance(pStructRef);
1990 
1991  // Save instance in instance hash Table
1992  m_StructInstanceHash.insert(pNode->m_Id, pInstance);
1993 
1994  pInstance->move(pNode->m_Matrix);
1995  //qDebug() << "Instance move with this matrix :" << pNode->m_Matrix.toString();
1996  pOccurence= new GLC_StructOccurence(pInstance);
1997  }
1998 
1999  }
2000  else
2001  {
2002  QStringList stringList(m_FileName);
2003  stringList.append("Geometry Id Not found");
2004  GLC_ErrorLog::addError(stringList);
2005  }
2006  }
2007  }
2008  if (!pNode->m_ChildNodes.isEmpty())
2009  {
2010  if (NULL == pOccurence) // The node hasn't geometry -> Create an occurence
2011  {
2012  if (m_StructInstanceHash.contains(pNode->m_Id))
2013  {
2014  pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
2015  }
2016  else
2017  {
2018  GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
2019  pInstance= new GLC_StructInstance(pStructRef);
2020  }
2021 
2022  pInstance->move(pNode->m_Matrix);
2023  pOccurence= new GLC_StructOccurence(pInstance);
2024  }
2025 
2026  const int size= pNode->m_ChildNodes.size();
2027  for (int i= 0; i < size; ++i)
2028  {
2029  if (NULL != pNode->m_ChildNodes.at(i))
2030  {
2031  pOccurence->addChild(createOccurenceFromNode(pNode->m_ChildNodes.at(i)));
2032  }
2033  }
2034  }
2035  if (!pNode->m_InstanceOffNodeIds.isEmpty())
2036  {
2037  if (NULL == pOccurence) // The node hasn't geometry and childs -> Create an occurence
2038  {
2039  if (m_StructInstanceHash.contains(pNode->m_Id))
2040  {
2041  pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
2042  }
2043  else
2044  {
2045  GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
2046  pInstance= new GLC_StructInstance(pStructRef);
2047  }
2048 
2049  pInstance->move(pNode->m_Matrix);
2050  pOccurence= new GLC_StructOccurence(pInstance);
2051  }
2052 
2053  const int size= pNode->m_InstanceOffNodeIds.size();
2054  for (int i= 0; i < size; ++i)
2055  {
2056  if (m_ColladaNodeHash.contains(pNode->m_InstanceOffNodeIds.at(i)))
2057  {
2058  pOccurence->addChild(createOccurenceFromNode(m_ColladaNodeHash.value(pNode->m_InstanceOffNodeIds.at(i))));
2059  }
2060  else
2061  {
2062  const QString errorMsg= "Instance Node : " + pNode->m_InstanceOffNodeIds.at(i) + "Not Found";
2063  throwException(errorMsg);
2064  }
2065  }
2066  }
2067  if (NULL == pOccurence)
2068  {
2069  if (m_StructInstanceHash.contains(pNode->m_Id))
2070  {
2071  pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
2072  }
2073  else
2074  {
2075  GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
2076  pInstance= new GLC_StructInstance(pStructRef);
2077  }
2078 
2079  pInstance->move(pNode->m_Matrix);
2080  pOccurence= new GLC_StructOccurence(pInstance);
2081  }
2082 
2083  return pOccurence;
2084 }
2085 
2086 // Update progress bar
2088 {
2089  qint64 currentOffset= m_pStreamReader->characterOffset();
2090 
2091  int currentQuantumValue;
2092  // Progrees bar indicator
2093  currentQuantumValue = static_cast<int>((static_cast<double>(currentOffset) / m_FileSize) * 100);
2094  if (currentQuantumValue > m_CurrentOffset)
2095  {
2096  emit currentQuantum(currentQuantumValue);
2097  m_CurrentOffset= currentQuantumValue;
2098  }
2099 
2100 }

©2005-2013 Laurent Ribon