glc_colladatoworld.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  Version 2.0.0 Beta 1, packaged on April 2010.
00006 
00007  http://glc-lib.sourceforge.net
00008 
00009  GLC-lib is free software; you can redistribute it and/or modify
00010  it under the terms of the GNU General Public License as published by
00011  the Free Software Foundation; either version 2 of the License, or
00012  (at your option) any later version.
00013 
00014  GLC-lib is distributed in the hope that it will be useful,
00015  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  GNU General Public License for more details.
00018 
00019  You should have received a copy of the GNU General Public License
00020  along with GLC-lib; if not, write to the Free Software
00021  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023  *****************************************************************************/
00024 
00025 #include "glc_colladatoworld.h"
00026 #include "../sceneGraph/glc_world.h"
00027 #include "../glc_fileformatexception.h"
00028 #include "../maths/glc_geomtools.h"
00029 #include "../glc_factory.h"
00030 
00031 // Default constructor
00032 GLC_ColladaToWorld::GLC_ColladaToWorld(const QGLContext* pContext)
00033 : QObject()
00034 , m_pWorld(NULL)
00035 , m_pQGLContext(pContext)
00036 , m_pStreamReader(NULL)
00037 , m_FileName()
00038 , m_pFile()
00039 , m_ImageFileHash()
00040 , m_MaterialLibHash()
00041 , m_SurfaceImageHash()
00042 , m_MaterialEffectHash()
00043 , m_pCurrentMaterial(NULL)
00044 , m_TextureToMaterialHash()
00045 , m_BulkDataHash()
00046 , m_VerticesSourceHash()
00047 , m_pMeshInfo(NULL)
00048 , m_GeometryHash()
00049 , m_ColladaNodeHash()
00050 , m_TopLevelColladaNode()
00051 , m_MaterialInstanceMap()
00052 , m_3DRepHash()
00053 , m_StructInstanceHash()
00054 , m_CurrentId()
00055 , m_FileSize(0)
00056 , m_CurrentOffset(0)
00057 , m_ListOfAttachedFileName()
00058 , m_TransparentIsRgbZero(false)
00059 {
00060 
00061 }
00062 
00063 // Destructor
00064 GLC_ColladaToWorld::~GLC_ColladaToWorld()
00065 {
00066         // Normal ends, wold has not to be deleted
00067         m_pWorld= NULL;
00068         clear();
00069 }
00070 
00072 // Set Functions
00074 // Create an GLC_World from an input Collada File
00075 GLC_World* GLC_ColladaToWorld::CreateWorldFromCollada(QFile &file)
00076 {
00077         m_pWorld= new GLC_World();
00078         m_FileName= file.fileName();
00079         m_pFile= &file;
00080 
00082         // Test if the file exist and can be opened
00084         if (!m_pFile->open(QIODevice::ReadOnly))
00085         {
00086                 QString message(QString("GLC_ColladaToWorld::CreateWorldFromCollada File ") + m_FileName + QString(" doesn't exist"));
00087                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::FileNotFound);
00088                 throw(fileFormatException);
00089         }
00090         // Get the file size
00091         m_FileSize= QFileInfo(m_FileName).size();
00092 
00093         m_pStreamReader= new QXmlStreamReader(m_pFile);
00094 
00095         // Go to the collada root Element
00096         goToElement("COLLADA");
00097 
00098         // Read the collada version
00099         QString version= readAttribute("version", true);
00100 
00101         // Go to the asset Element to get the Up vector
00102         goToElement("asset");
00103         while (endElementNotReached("asset"))
00104         {
00105                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00106                 {
00107                         const QStringRef currentElementName= m_pStreamReader->name();
00108                         if (currentElementName == "up_axis")
00109                         {
00110                                 const QString upAxis= getContent("up_axis");
00111                                 if (upAxis == "X_UP") m_pWorld->setUpVector(glc::X_AXIS);
00112                                 else if (upAxis == "Y_UP") m_pWorld->setUpVector(glc::Y_AXIS);
00113                                 else if (upAxis == "Z_UP") m_pWorld->setUpVector(glc::Z_AXIS);
00114                         }
00115                 }
00116                 m_pStreamReader->readNext();
00117         }
00118 
00119         while (endElementNotReached("COLLADA"))
00120         {
00121                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00122                 {
00123                         const QStringRef currentElementName= m_pStreamReader->name();
00124                         if (currentElementName == "library_images") loadLibraryImage();
00125                         else if (currentElementName == "library_materials") loadLibraryMaterials();
00126                         else if (currentElementName == "library_effects") loadLibraryEffects();
00127                         else if (currentElementName == "library_geometries") loadLibraryGeometries();
00128                         else if (currentElementName == "library_nodes") loadLibraryNodes();
00129                         else if (currentElementName == "library_controllers") loadLibraryContollers();
00130                         else if (currentElementName == "library_visual_scenes") loadVisualScenes();
00131                         else if (currentElementName == "scene") loadScene();
00132                 }
00133 
00134                 m_pStreamReader->readNext();
00135         }
00136         // Link the textures to materials
00137         linkTexturesToMaterials();
00138 
00139         // Create the mesh and link them to material
00140         createMesh();
00141 
00142         // Create the scene graph struct
00143         createSceneGraph();
00144 
00145         emit currentQuantum(100);
00146 
00147         return m_pWorld;
00148 }
00149 
00151 // Private services Functions
00153 // Go to Element
00154 void GLC_ColladaToWorld::goToElement(const QString& elementName)
00155 {
00156         while(startElementNotReached(elementName))
00157         {
00158                 m_pStreamReader->readNext();
00159         }
00160         checkForXmlError(QString("Element ") + elementName + QString(" Not Found"));
00161 }
00162 
00163 // Go to the end Element of a xml
00164 void GLC_ColladaToWorld::goToEndElement(const QString& elementName)
00165 {
00166         while(endElementNotReached(elementName))
00167         {
00168                 m_pStreamReader->readNext();
00169         }
00170         checkForXmlError(QString("End Element ") + elementName + QString(" Not Found"));
00171 }
00172 
00173 // Return the content of an element
00174 QString GLC_ColladaToWorld::getContent(const QString& element)
00175 {
00176         QString Content;
00177         while(endElementNotReached(element))
00178         {
00179                 m_pStreamReader->readNext();
00180                 if (m_pStreamReader->isCharacters() && !m_pStreamReader->text().isEmpty())
00181                 {
00182                         Content+= m_pStreamReader->text().toString();
00183                 }
00184         }
00185 
00186         return Content.simplified();
00187 }
00188 
00189 // Read the specified attribute
00190 QString GLC_ColladaToWorld::readAttribute(const QString& name, bool required)
00191 {
00192         QString attributeValue;
00193         if (required && !m_pStreamReader->attributes().hasAttribute(name))
00194         {
00195                 QString message(QString("required attribute ") + name + QString(" Not found"));
00196                 qDebug() << message;
00197                 GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00198                 clear();
00199                 throw(fileFormatException);
00200         }
00201         else
00202         {
00203                 attributeValue= m_pStreamReader->attributes().value(name).toString();
00204         }
00205         return attributeValue;
00206 }
00207 
00208 // Check for XML error
00209 void GLC_ColladaToWorld::checkForXmlError(const QString& info)
00210 {
00211         if (m_pStreamReader->atEnd() || m_pStreamReader->hasError())
00212         {
00213                 qDebug() << info << " " << m_FileName;
00214                 GLC_FileFormatException fileFormatException(info, m_FileName, GLC_FileFormatException::WrongFileFormat);
00215                 clear();
00216                 throw(fileFormatException);
00217         }
00218 }
00219 // Throw an exception with the specified text
00220 void GLC_ColladaToWorld::throwException(const QString& message)
00221 {
00222         qDebug() << message;
00223         GLC_FileFormatException fileFormatException(message, m_FileName, GLC_FileFormatException::WrongFileFormat);
00224         clear();
00225         throw(fileFormatException);
00226 }
00227 
00228 // Clear memmory
00229 void GLC_ColladaToWorld::clear()
00230 {
00231         delete m_pWorld;
00232         m_pWorld= NULL;
00233 
00234         delete m_pStreamReader;
00235         m_pStreamReader= NULL;
00236 
00237         if (NULL != m_pFile) m_pFile->close();
00238         m_pFile= NULL;
00239 
00240         m_ImageFileHash.clear();
00241         m_MaterialLibHash.clear();
00242         m_SurfaceImageHash.clear();
00243 
00244         // Clear the material effect hash table
00245         MaterialHash::iterator iMat= m_MaterialEffectHash.begin();
00246         while (iMat != m_MaterialEffectHash.constEnd())
00247         {
00248                 if (iMat.value()->isUnused()) delete iMat.value();
00249                 ++iMat;
00250         }
00251         m_MaterialEffectHash.clear();
00252 
00253         delete m_pCurrentMaterial;
00254         m_pCurrentMaterial= NULL;
00255 
00256         m_TextureToMaterialHash.clear();
00257 
00258         m_BulkDataHash.clear();
00259 
00260         m_VerticesSourceHash.clear();
00261 
00262         delete m_pMeshInfo;
00263         m_pMeshInfo= NULL;
00264 
00265         // Delete all geometry from the geometry hash
00266         QHash<const QString, MeshInfo*>::iterator iGeomHash= m_GeometryHash.begin();
00267         while (m_GeometryHash.constEnd() != iGeomHash)
00268         {
00269                 delete iGeomHash.value();
00270                 ++iGeomHash;
00271         }
00272         m_GeometryHash.clear();
00273 
00274         // Delete all collada node from the colalda node hash
00275         QHash<const QString, ColladaNode*>::iterator iColladaNode= m_ColladaNodeHash.begin();
00276         while (m_ColladaNodeHash.constEnd() != iColladaNode)
00277         {
00278                 delete iColladaNode.value();
00279                 ++iColladaNode;
00280         }
00281         m_ColladaNodeHash.clear();
00282 
00283         // Clear the list of top level node (Not must not to be deleted)
00284         m_TopLevelColladaNode.clear();
00285 
00286         // Clear the material instance map
00287         m_MaterialInstanceMap.clear();
00288 
00290         QHash<const QString, GLC_3DRep*>::iterator i3DRep= m_3DRepHash.begin();
00291         while (m_3DRepHash.constEnd() != i3DRep)
00292         {
00293                 delete i3DRep.value();
00294                 ++i3DRep;
00295         }
00296         m_3DRepHash.clear();
00297 
00298         // Clear instance Hash table
00299         m_StructInstanceHash.clear();
00300 
00301         m_CurrentId.clear();
00302 
00303         m_ListOfAttachedFileName.clear();
00304 }
00305 
00306 // Load library_images element
00307 void GLC_ColladaToWorld::loadLibraryImage()
00308 {
00309         while (endElementNotReached("library_images"))
00310         {
00311                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00312                 {
00313                         const QStringRef currentElementName= m_pStreamReader->name();
00314                         if (currentElementName == "image") loadImage();
00315                 }
00316                 m_pStreamReader->readNext();
00317 
00318                 updateProgressBar();
00319         }
00320         checkForXmlError("Error occur while loading element : library_images");
00321 }
00322 
00323 // Load image element
00324 void GLC_ColladaToWorld::loadImage()
00325 {
00326         //qDebug() << "GLC_ColladaToWorld::loadImage()";
00327         // load image id
00328         m_CurrentId= readAttribute("id", true);
00329         QString fileName;
00330         // Trying to find external image fileName
00331         while (endElementNotReached("image"))
00332         {
00333                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00334                 {
00335                         const QStringRef currentElementName= m_pStreamReader->name();
00336                         if (currentElementName == "init_from")
00337                         {
00338                                 fileName= getContent("init_from");
00339                         }
00340                 }
00341                 m_pStreamReader->readNext();
00342         }
00343 
00344         checkForXmlError("Error occur while loading element : image");
00345 
00346         // Add the image in the image fileName Hash table
00347         if (!fileName.isEmpty())
00348         {
00349                 m_ImageFileHash.insert(m_CurrentId, fileName);
00350         }
00351 }
00352 
00353 // Load library_materials element
00354 void GLC_ColladaToWorld::loadLibraryMaterials()
00355 {
00356         while (endElementNotReached("library_materials"))
00357         {
00358                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00359                 {
00360                         const QStringRef currentElementName= m_pStreamReader->name();
00361                         if (currentElementName == "material") loadMaterial();
00362                 }
00363                 m_pStreamReader->readNext();
00364 
00365                 updateProgressBar();
00366         }
00367         checkForXmlError("Error occur while loading element : library_materials");
00368 
00369 }
00370 
00371 // Load a material
00372 void GLC_ColladaToWorld::loadMaterial()
00373 {
00374         // load material id
00375         m_CurrentId= readAttribute("id", true);
00376 
00377         goToElement("instance_effect");
00378 
00379         // Load instance effect url
00380         const QString url= readAttribute("url", true).remove('#');
00381         //qDebug() << "instance effect URL : " << url;
00382 
00383         // Read instance effect parameters
00384         while (endElementNotReached("instance_effect"))
00385         {
00386                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00387                 {
00388                         const QStringRef currentElementName= m_pStreamReader->name();
00389                         if (currentElementName == "setparam")
00390                         {
00391                                 qDebug() << "GLC_ColladaToWorld::loadMaterial : setparam found";
00392                         }
00393                 }
00394                 m_pStreamReader->readNext();
00395         }
00396 
00397         checkForXmlError("Error occur while loading element : material");
00398 
00399         // Add the image in the image fileName Hash table
00400         if (!url.isEmpty())
00401         {
00402                 //qDebug() << "insert material : " << m_CurrentId << " url: " << url;
00403                 m_MaterialLibHash.insert(m_CurrentId, url);
00404         }
00405 
00406 }
00407 
00408 // Load library_effects element
00409 void GLC_ColladaToWorld::loadLibraryEffects()
00410 {
00411         while (endElementNotReached("library_effects"))
00412         {
00413                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00414                 {
00415                         const QStringRef currentElementName= m_pStreamReader->name();
00416                         if (currentElementName == "effect") loadEffect();
00417                 }
00418                 m_pStreamReader->readNext();
00419 
00420                 updateProgressBar();
00421         }
00422         checkForXmlError("Error occur while loading element : library_effects");
00423 
00424 }
00425 
00426 // Load an effect
00427 void GLC_ColladaToWorld::loadEffect()
00428 {
00429         // load effect id
00430         const QString id= readAttribute("id", true);
00431         m_CurrentId= id;
00432         m_pCurrentMaterial= new GLC_Material();
00433         m_pCurrentMaterial->setName(id);
00434 
00435         while (endElementNotReached("effect"))
00436         {
00437                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00438                 {
00439                         const QStringRef currentElementName= m_pStreamReader->name();
00440                         if (currentElementName == "profile_COMMON") loadProfileCommon();
00441                 }
00442                 m_pStreamReader->readNext();
00443         }
00444 
00445         checkForXmlError("Error occur while loading element : effect");
00446 
00447         m_MaterialEffectHash.insert(id, m_pCurrentMaterial);
00448         m_pCurrentMaterial= NULL;
00449 
00450 }
00451 
00452 // Load profile_COMMON
00453 void GLC_ColladaToWorld::loadProfileCommon()
00454 {
00455         //qDebug() << "GLC_ColladaToWorld::loadProfileCommon";
00456         while (endElementNotReached("profile_COMMON"))
00457         {
00458                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00459                 {
00460                         const QStringRef currentElementName= m_pStreamReader->name();
00461                         if (currentElementName == "image") loadImage();
00462                         else if (currentElementName == "newparam") loadNewParam();
00463                         else if (currentElementName == "technique") loadTechnique();
00464                 }
00465                 m_pStreamReader->readNext();
00466         }
00467         checkForXmlError("Error occur while loading element : profile_COMMON");
00468 }
00469 
00470 // Load a new param of the common profile
00471 void GLC_ColladaToWorld::loadNewParam()
00472 {
00473         //qDebug() << "GLC_ColladaToWorld::loadNewParam";
00474         // load param sid
00475         const QString sid= m_CurrentId + "::" + readAttribute("sid", true);
00476         while (endElementNotReached("newparam"))
00477         {
00478                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00479                 {
00480                         const QStringRef currentElementName= m_pStreamReader->name();
00481                         if (currentElementName == "surface") loadSurface(sid);
00482                         else if (currentElementName == "sampler2D") loadSampler2D(sid);
00483                 }
00484                 m_pStreamReader->readNext();
00485         }
00486         checkForXmlError("Error occur while loading element : profile_COMMON");
00487 }
00488 
00489 // Load a surface
00490 void GLC_ColladaToWorld::loadSurface(const QString& sid)
00491 {
00492         //qDebug() << "GLC_ColladaToWorld::loadSurface sid=" << sid ;
00493         while (endElementNotReached("surface"))
00494         {
00495                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00496                 {
00497                         const QStringRef currentElementName= m_pStreamReader->name();
00498                         if (currentElementName == "init_from")
00499                         {
00500                                 const QString imageId= getContent("init_from");
00501                                 m_SurfaceImageHash.insert(sid, imageId);
00502                         }
00503                 }
00504                 m_pStreamReader->readNext();
00505         }
00506         checkForXmlError("Error occur while loading element : surface");
00507 }
00508 
00509 // Load Sampler 2D
00510 void GLC_ColladaToWorld::loadSampler2D(const QString& sid)
00511 {
00512         //qDebug() << "GLC_ColladaToWorld::loadSampler2D sid= " << sid;
00513         while (endElementNotReached("sampler2D"))
00514         {
00515                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00516                 {
00517                         const QStringRef currentElementName= m_pStreamReader->name();
00518                         if (currentElementName == "source")
00519                         {
00520                                 const QString source= m_CurrentId + "::" + getContent("source");
00521                                 m_Sampler2DSurfaceHash.insert(sid, source);
00522                         }
00523                 }
00524                 m_pStreamReader->readNext();
00525         }
00526         checkForXmlError("Error occur while loading element : sampler2D");
00527 }
00528 
00529 // Load technique
00530 void GLC_ColladaToWorld::loadTechnique()
00531 {
00532         //qDebug() << "GLC_ColladaToWorld::loadTechnique";
00533         while (endElementNotReached("technique"))
00534         {
00535                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00536                 {
00537                         const QStringRef currentElementName= m_pStreamReader->name();
00538                         if (currentElementName == "phong") loadMaterialTechnique(currentElementName.toString());
00539                         if (currentElementName == "lambert") loadMaterialTechnique(currentElementName.toString());
00540                         if (currentElementName == "blinn") loadMaterialTechnique(currentElementName.toString());
00541                 }
00542                 m_pStreamReader->readNext();
00543         }
00544         checkForXmlError("Error occur while loading element : technique");
00545 }
00546 
00547 // load phong material
00548 void GLC_ColladaToWorld::loadMaterialTechnique(const QString& elementName)
00549 {
00550         //qDebug() << "GLC_ColladaToWorld::loadMaterialTechnique";
00551         while (endElementNotReached(elementName))
00552         {
00553                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00554                 {
00555                         const QStringRef currentElementName= m_pStreamReader->name();
00556                         if ((currentElementName == "emission")
00557                                         || (currentElementName == "ambient")
00558                                         || (currentElementName == "diffuse")
00559                                         ||(currentElementName == "specular"))
00560                                 loadCommonColorOrTexture(currentElementName.toString());
00561                         else if (currentElementName == "transparent") loadTransparent();
00562                         else if (currentElementName == "transparency") loadTransparency(currentElementName.toString());
00563                         else if (currentElementName == "shininess") loadShininess(currentElementName.toString());
00564                 }
00565                 m_pStreamReader->readNext();
00566         }
00567         checkForXmlError("Error occur while loading element : " + elementName);
00568 }
00569 
00570 // load common color or texture
00571 void GLC_ColladaToWorld::loadCommonColorOrTexture(const QString& name)
00572 {
00573         //qDebug() << "GLC_ColladaToWorld::loadCommonColorOrTexture " << name;
00574         Q_ASSERT(NULL != m_pCurrentMaterial);
00575 
00576         while (endElementNotReached(name))
00577         {
00578                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00579                 {
00580                         const QStringRef currentElementName= m_pStreamReader->name();
00581                         if (currentElementName == "color")
00582                         {
00583                                 if (name == "emission") m_pCurrentMaterial->setLightEmission(readXmlColor());
00584                                 else if (name == "ambient") m_pCurrentMaterial->setAmbientColor(readXmlColor());
00585                                 else if (name == "diffuse") m_pCurrentMaterial->setDiffuseColor(readXmlColor());
00586                                 else if (name == "specular") m_pCurrentMaterial->setSpecularColor(readXmlColor());
00587                         }
00588                         else if (currentElementName == "texture")
00589                         {
00590                                 //qDebug() << "Load texture " << name;
00591                                 const QString sid = m_CurrentId + "::" + readAttribute("texture", true);
00592                                 m_TextureToMaterialHash.insert(sid, m_pCurrentMaterial);
00593                         }
00594                 }
00595                 m_pStreamReader->readNext();
00596         }
00597         checkForXmlError("Error occur while loading element : " + name);
00598 }
00599 
00600 // Load transparent
00601 void GLC_ColladaToWorld::loadTransparent()
00602 {
00603         const QString opaque= readAttribute("opaque", false);
00604         if (opaque == "RGB_ZERO") m_TransparentIsRgbZero= true;
00605         else m_TransparentIsRgbZero= false;
00606 }
00607 
00608 // Load transparency
00609 void GLC_ColladaToWorld::loadTransparency(const QString& name)
00610 {
00611         //qDebug() << "GLC_ColladaToWorld::loadTransparency";
00612         Q_ASSERT(NULL != m_pCurrentMaterial);
00613         while (endElementNotReached(name))
00614         {
00615                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00616                 {
00617                         const QStringRef currentElementName= m_pStreamReader->name();
00618                         if (currentElementName == "float")
00619                         {
00620                                 bool stringToFloatOk= false;
00621                                 const QString alphaString= getContent("float");
00622                                 float alpha;
00623                                 if (m_TransparentIsRgbZero)
00624                                 {
00625                                         alpha= alphaString.toFloat(&stringToFloatOk);
00626                                 }
00627                                 else
00628                                 {
00629                                         alpha= 1.0f - alphaString.toFloat(&stringToFloatOk);
00630                                 }
00631                                 // A material mustn't be invisible (no sense)
00632                                 if (qFuzzyCompare(alpha, 0.0f)) alpha= 1.0f;
00633 
00634                                 m_pCurrentMaterial->setOpacity(alpha);
00635                                 if (!stringToFloatOk) throwException("Error while trying to convert :" + alphaString + " to float");
00636                         }
00637                 }
00638                 m_pStreamReader->readNext();
00639         }
00640         checkForXmlError("Error occur while loading element : " + name);
00641 }
00642 
00643 // Load shininess
00644 void GLC_ColladaToWorld::loadShininess(const QString& name)
00645 {
00646         //qDebug() << "GLC_ColladaToWorld::loadShininess";
00647         Q_ASSERT(NULL != m_pCurrentMaterial);
00648         while (endElementNotReached(name))
00649         {
00650                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00651                 {
00652                         const QStringRef currentElementName= m_pStreamReader->name();
00653                         if (currentElementName == "float")
00654                         {
00655                                 bool stringToFloatOk= false;
00656                                 const QString shininessString= getContent("float");
00657                                 const float shininess= shininessString.toFloat(&stringToFloatOk);
00658                                 if (!stringToFloatOk) qDebug() << QString("Error while trying to convert :" + shininessString + " to float");
00659                                 else m_pCurrentMaterial->setShininess(shininess);
00660                         }
00661                 }
00662                 m_pStreamReader->readNext();
00663         }
00664         checkForXmlError("Error occur while loading element : " + name);
00665 }
00666 
00667 // Read a xml Color
00668 QColor GLC_ColladaToWorld::readXmlColor()
00669 {
00670         //qDebug() << "GLC_ColladaToWorld::readXmlColor()";
00671         QColor resultColor;
00672 
00673         QString colorString= getContent("color");
00674         QStringList colors= colorString.split(' ');
00675         if(colors.size() == 4)
00676         {
00677                 bool okRed, okGreen, okBlue, okAlpha;
00678                 const float red= colors.at(0).toFloat(&okRed);
00679                 const float green= colors.at(1).toFloat(&okGreen);
00680                 const float blue= colors.at(2).toFloat(&okBlue);
00681                 const float alpha= colors.at(3).toFloat(&okAlpha);
00682                 if (okRed && okGreen && okBlue && okAlpha)
00683                 {
00684                         resultColor.setRedF(red);
00685                         resultColor.setGreenF(green);
00686                         resultColor.setBlueF(blue);
00687                         resultColor.setAlphaF(alpha);
00688                 }
00689                 else
00690                 {
00691                         QString info= "Error occur while reading xml color : " + colorString;
00692                         qDebug() << info << " " << m_FileName;
00693                         GLC_FileFormatException fileFormatException(info, m_FileName, GLC_FileFormatException::WrongFileFormat);
00694                         clear();
00695                         throw(fileFormatException);
00696                 }
00697         }
00698         else
00699         {
00700                 QString info= "Error occur while reading xml color : " + colorString;
00701                 qDebug() << info << " " << m_FileName;
00702                 GLC_FileFormatException fileFormatException(info, m_FileName, GLC_FileFormatException::WrongFileFormat);
00703                 clear();
00704                 throw(fileFormatException);
00705         }
00706 
00707         return resultColor;
00708 }
00709 
00710 // Load library_geometries element
00711 void GLC_ColladaToWorld::loadLibraryGeometries()
00712 {
00713         while (endElementNotReached("library_geometries"))
00714         {
00715                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00716                 {
00717                         const QStringRef currentElementName= m_pStreamReader->name();
00718                         if (currentElementName == "geometry") loadGeometry();
00719                 }
00720 
00721                 m_pStreamReader->readNext();
00722 
00723                 updateProgressBar();
00724         }
00725         checkForXmlError("Error occur while loading element : library_geometries");
00726 }
00727 
00728 // Load an geometry element
00729 void GLC_ColladaToWorld::loadGeometry()
00730 {
00731         delete m_pMeshInfo;
00732         m_pMeshInfo= new MeshInfo();
00733         m_pMeshInfo->m_pMesh= new GLC_Mesh;
00734 
00735         const QString id= readAttribute("id", false);
00736         m_CurrentId= id;
00737         if (!id.isEmpty())
00738         {
00739                 m_pMeshInfo->m_pMesh->setName(id);
00740                 //qDebug() << "Loading geometry : " << id;
00741         }
00742         else
00743         {
00744                 qDebug() << "Geometry without id found !!";
00745         }
00746 
00747         while (endElementNotReached("geometry"))
00748         {
00749                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00750                 {
00751                         const QStringRef currentElementName= m_pStreamReader->name();
00752                         if (currentElementName == "mesh") loadMesh();
00753                 }
00754 
00755                 m_pStreamReader->readNext();
00756         }
00757         checkForXmlError("Error occur while loading element : geometry");
00758 
00759         // Add the current mesh info to the geometry hash
00760         if (!id.isEmpty())
00761         {
00762                 m_GeometryHash.insert(id, m_pMeshInfo);
00763                 m_pMeshInfo= NULL;
00764         }
00765 }
00766 
00767 // Load a mesh
00768 void GLC_ColladaToWorld::loadMesh()
00769 {
00770         while (endElementNotReached("mesh"))
00771         {
00772                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00773                 {
00774                         const QStringRef currentElementName= m_pStreamReader->name();
00775                         if (currentElementName == "source") loadVertexBulkData();
00776                         else if (currentElementName == "vertices") loadVertices();
00777                         else if (currentElementName == "polylist") loadPolylist();
00778                         else if (currentElementName == "polygons") loadPolygons();
00779                         else if (currentElementName == "triangles") loadTriangles();
00780                         //else if (currentElementName == "trifans") loadTriFans();
00781                         //else if (currentElementName == "tristrips") loadTriStrip();
00782                 }
00783 
00784                 m_pStreamReader->readNext();
00785         }
00786         checkForXmlError("Error occur while loading element : mesh");
00787 }
00788 
00789 // Load Vertex bulk data
00790 void GLC_ColladaToWorld::loadVertexBulkData()
00791 {
00792         //qDebug() << "GLC_ColladaToWorld::loadVertexBulkData()";
00793         // load Vertex Bulk data id
00794         m_CurrentId= readAttribute("id", true);
00795         //qDebug() << "id=" << m_CurrentId;
00796         QList<float> vertices;
00797 
00798         while (endElementNotReached("source"))
00799         {
00800                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00801                 {
00802                         const QStringRef currentElementName= m_pStreamReader->name();
00803                         if ((currentElementName == "float_array"))
00804                         {
00805                                 int count= readAttribute("count", true).toInt();
00806                                 QString array= getContent("float_array");
00807                                 QStringList list= array.split(' ');
00808                                 // Check the array size
00809                                 if (count != list.size()) throwException("float_array size not match");
00810 
00811                                 for (int i= 0; i < count; ++i)
00812                                 {
00813                                         vertices.append(list.at(i).toFloat());
00814                                 }
00815                         }
00816                         else if (currentElementName == "technique_common")
00817                         {
00818 
00819                         }
00820                 }
00821 
00822                 m_pStreamReader->readNext();
00823         }
00824         checkForXmlError("Error occur while loading element : source");
00825         m_BulkDataHash.insert(m_CurrentId, vertices);
00826 
00827         updateProgressBar();
00828 }
00829 
00830 // Load attributes and identity of mesh vertices
00831 void GLC_ColladaToWorld::loadVertices()
00832 {
00833         //qDebug() << "GLC_ColladaToWorld::loadVertices()";
00834         // load Vertices id
00835         m_CurrentId= readAttribute("id", true);
00836 
00837         goToElement("input");
00838         const QString source= readAttribute("source", true).remove('#');
00839         m_VerticesSourceHash.insert(m_CurrentId, source);
00840         checkForXmlError("Error occur while loading element : vertices");
00841 }
00842 
00843 // Load polygons or polylist
00844 void GLC_ColladaToWorld::loadPolylist()
00845 {
00846         //qDebug() << "GLC_ColladaToWorld::loadPolylist()";
00847         // The number of polygon
00848         const int polygonCount= readAttribute("count", true).toInt();
00849 
00850         // The material id
00851         const QString materialId= readAttribute("material", false);
00852 
00853         // Offsets and data source list
00854         QList<InputData> inputDataList;
00855 
00856         // Polygon number of vertice list
00857         QList<int> vcountList;
00858 
00859         // Polygon index list
00860         QList<int> polyIndexList;
00861 
00862         while (endElementNotReached("polylist"))
00863         {
00864                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00865                 {
00866                         const QStringRef currentElementName= m_pStreamReader->name();
00867                         if ((currentElementName == "input") && vcountList.isEmpty())
00868                         {
00869                                 InputData currentInput;
00870                                 // Get input data offset
00871                                 currentInput.m_Offset= readAttribute("offset", true).toInt();
00872                                 // Get input data semantic
00873                                 const QString semantic= readAttribute("semantic", true);
00874                                 if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
00875                                 else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
00876                                 else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
00877                                 else throwException("Source semantic :" + semantic + "Not supported");
00878                                 // Get input data source id
00879                                 currentInput.m_Source= readAttribute("source", true).remove('#');
00880 
00881                                 // Bypasss vertices indirection
00882                                 if (m_VerticesSourceHash.contains(currentInput.m_Source))
00883                                 {
00884                                         currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
00885                                 }
00886                                 inputDataList.append(currentInput);
00887                         }
00888                         else if ((currentElementName == "vcount") && (inputDataList.size() > 0))
00889                         {
00890                                 QString vcountString= getContent("vcount");
00891                                 QStringList vcountStringList= vcountString.split(' ');
00892                                 if (vcountStringList.size() != polygonCount) throwException("vcount size not match");
00893                                 bool toIntOK;
00894                                 for (int i= 0; i < polygonCount; ++i)
00895                                 {
00896                                         vcountList.append(vcountStringList.at(i).toInt(&toIntOK));
00897                                         if (!toIntOK) throwException("Unable to convert string :" + vcountStringList.at(i) + " To int");
00898                                 }
00899                         }
00900                         else if ((currentElementName == "p") && !vcountList.isEmpty() && polyIndexList.isEmpty())
00901                         {
00902                                 { // Fill index List
00903                                         QString pString= getContent("p");
00904                                         QStringList pStringList= pString.split(' ');
00905                                         bool toIntOK;
00906                                         const int size= pStringList.size();
00907                                         for (int i= 0; i < size; ++i)
00908                                         {
00909                                                 polyIndexList.append(pStringList.at(i).toInt(&toIntOK));
00910                                                 if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
00911                                         }
00912                                 }
00913 
00914                         }
00915                 }
00916                 m_pStreamReader->readNext();
00917         }
00918         // Add the polylist to the current mesh
00919         addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
00920 
00921         updateProgressBar();
00922 }
00923 
00924 // Load Polygons
00925 void GLC_ColladaToWorld::loadPolygons()
00926 {
00927         // The material id
00928         const QString materialId= readAttribute("material", false);
00929 
00930         // Offsets and data source list
00931         QList<InputData> inputDataList;
00932 
00933         // Polygon number of vertice list
00934         QList<int> vcountList;
00935 
00936         // The input number
00937         int inputCount= 0;
00938         // Polygon index list
00939         QList<int> polyIndexList;
00940         while (endElementNotReached("polygons"))
00941         {
00942                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00943                 {
00944                         const QStringRef currentElementName= m_pStreamReader->name();
00945                         if ((currentElementName == "input") && vcountList.isEmpty())
00946                         {
00947                                 ++inputCount;
00948                                 InputData currentInput;
00949                                 // Get input data offset
00950                                 currentInput.m_Offset= readAttribute("offset", true).toInt();
00951                                 // Get input data semantic
00952                                 const QString semantic= readAttribute("semantic", true);
00953                                 if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
00954                                 else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
00955                                 else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
00956                                 else throwException("Source semantic :" + semantic + "Not supported");
00957                                 // Get input data source id
00958                                 currentInput.m_Source= readAttribute("source", true).remove('#');
00959 
00960                                 // Bypasss vertices indirection
00961                                 if (m_VerticesSourceHash.contains(currentInput.m_Source))
00962                                 {
00963                                         currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
00964                                 }
00965                                 inputDataList.append(currentInput);
00966                         }
00967                         else if (currentElementName == "p")
00968                         {
00969                                 { // Fill index List
00970                                         QString pString= getContent("p");
00971                                         QStringList pStringList= pString.split(' ');
00972                                         bool toIntOK;
00973                                         const int size= pStringList.size();
00974                                         for (int i= 0; i < size; ++i)
00975                                         {
00976                                                 polyIndexList.append(pStringList.at(i).toInt(&toIntOK));
00977                                                 if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
00978                                         }
00979                                         // Add the polygon size in vcountList
00980                                         vcountList.append(size / inputCount);
00981                                 }
00982                         }
00983                 }
00984                 m_pStreamReader->readNext();
00985         }
00986         // Add the polylist to the current mesh
00987         addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
00988 
00989         updateProgressBar();
00990 }
00991 
00992 // Add the polylist to the current mesh
00993 void GLC_ColladaToWorld::addPolylistToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& vcountList, const QList<int>& polyIndexList, const QString& materialId)
00994 {
00995         //qDebug() << "GLC_ColladaToWorld::addPolylistToCurrentMesh";
00996 
00997         const int polygonCount= vcountList.size();
00998         const int inputDataCount= inputDataList.size();
00999         const int polyIndexCount= polyIndexList.size();
01000 
01001         // Flag to know if the polylist has normal
01002         bool hasNormals= false;
01003 
01004         // Check the existance of data source
01005         for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01006         {
01007                 const QString source= inputDataList.at(dataIndex).m_Source;
01008                 if ( !m_BulkDataHash.contains(source))
01009                 {
01010                         throwException(" Source : " + source + " Not found");
01011                 }
01012                 if (inputDataList.at(dataIndex).m_Semantic == NORMAL) hasNormals= true;
01013         }
01014 
01015         int maxOffset= 0;
01016         for (int i= 0; i < inputDataCount; ++i)
01017         {
01018                 if (inputDataList.at(i).m_Offset > maxOffset)
01019                 {
01020                         maxOffset= inputDataList.at(i).m_Offset;
01021                 }
01022         }
01023         //qDebug() << " Max Offset :" << maxOffset;
01024 
01025         // the polygonIndex of the polylist
01026         QList<int> polygonIndex;
01027 
01028         // Fill the mapping, bulk data and index list of the current mesh info
01029         for (int i= 0; i < polyIndexCount; i+= maxOffset + 1)
01030         {
01031                 // Create and set the current vertice index
01032                 ColladaVertice currentVertice;
01033                 for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01034                 {
01035                         currentVertice.m_Values[inputDataList.at(dataIndex).m_Semantic]= polyIndexList.at(i + inputDataList.at(dataIndex).m_Offset);
01036                 }
01037 
01038                 if (m_pMeshInfo->m_Mapping.contains(currentVertice))
01039                 {
01040                         // Add the the index to the polygon index
01041                         polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01042                 }
01043                 else
01044                 {
01045                         // Add the current vertice to the current mesh info mapping hash table and increment the freeIndex
01046                         m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
01047                         // Add the the index to the polygon index
01048                         polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01049 
01050                         // Add the bulk data associated to the current vertice to the current mesh info
01051                         for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01052                         {
01053                                 // The current input data
01054                                 InputData currentInputData= inputDataList.at(dataIndex);
01055                                 // QHash iterator on the right QList<float>
01056                                 BulkDataHash::const_iterator iBulkHash= m_BulkDataHash.find(currentInputData.m_Source);
01057                                 int stride;
01058                                 if (currentInputData.m_Semantic != TEXCOORD) stride= 3; else stride= 2;
01059                                 // Firts value
01060                                 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride));
01061                                 // Second value
01062                                 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride + 1));
01063                                 // Fird value
01064                                 if (currentInputData.m_Semantic != TEXCOORD)
01065                                 {
01066                                         m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride + 2));
01067                                 }
01068                         }
01069                 }
01070         }
01071 
01072         // Save mesh info index offset
01073         const int indexOffset= m_pMeshInfo->m_Index.size();
01074         // Triangulate the polygons of the polylist
01075         // Input polygon index must start from 0 and succesive : (0 1 2 3 4)
01076         QList<GLuint> onePolygonIndex;
01077         for (int i= 0; i < polygonCount; ++i)
01078         {
01079                 const int polygonSize= vcountList.at(i);
01080                 Q_ASSERT(polygonSize > 2);
01081                 for (int i= 0; i < polygonSize; ++i)
01082                 {
01083                         onePolygonIndex.append(polygonIndex.takeFirst());
01084                 }
01085                 // Triangulate the current polygon if the polygon as more than 3 vertice
01086                 if (polygonSize > 3)
01087                 {
01088                         glc::triangulatePolygon(&onePolygonIndex, m_pMeshInfo->m_Datas.at(VERTEX));
01089                 }
01090                 // Add index to the mesh info
01091                 //Q_ASSERT(not onePolygonIndex.isEmpty());
01092                 if (!onePolygonIndex.isEmpty())
01093                 {
01094                         m_pMeshInfo->m_Index.append(onePolygonIndex);
01095                 }
01096                 else
01097                 {
01098                         qDebug() << QString("Unable to triangulate a polygon of " + m_pMeshInfo->m_pMesh->name());
01099                         //throwException("Unable to triangulate a polygon of " + m_pMeshInfo->m_pMesh->name());
01100                 }
01101                 onePolygonIndex.clear();
01102         }
01103 
01104         // Check if normal computation is needed
01105         if (!hasNormals)
01106         {
01107                 qDebug() << "Compute Normals with offset " << indexOffset;
01108                 computeNormalOfCurrentPrimitiveOfCurrentMesh(indexOffset);
01109         }
01110 
01111         // Add material the current mesh info
01112         MatOffsetSize matInfo;
01113         matInfo.m_Offset= indexOffset;
01114         matInfo.m_size= m_pMeshInfo->m_Index.size() - indexOffset;
01115         m_pMeshInfo->m_Materials.insert(materialId, matInfo);
01116 
01117 }
01118 // Compute Normals for the current primitive element of the current mesh
01119 void GLC_ColladaToWorld::computeNormalOfCurrentPrimitiveOfCurrentMesh(int indexOffset)
01120 {
01121         const QList<float>* pData= &(m_pMeshInfo->m_Datas.at(VERTEX));
01122         // Fill the list of normal
01123         QList<float>* pNormal= &(m_pMeshInfo->m_Datas[NORMAL]);
01124         const int normalOffset= pNormal->size();
01125         const int normalCount= pData->size() - normalOffset;
01126         for (int i= 0; i < normalCount; ++i)
01127         {
01128                 pNormal->append(0.0f);
01129         }
01130         // Compute the normals and add them to the current mesh info
01131         const int size= m_pMeshInfo->m_Index.size() - indexOffset;
01132         double xn, yn, zn;
01133 
01134 
01135         for (int i= indexOffset; i < size; i+=3)
01136         {
01137                 // Vertex 1
01138                 xn= pData->at(m_pMeshInfo->m_Index.at(i) * 3);
01139                 yn= pData->at(m_pMeshInfo->m_Index.at(i) * 3 + 1);
01140                 zn= pData->at(m_pMeshInfo->m_Index.at(i) * 3 + 2);
01141                 const GLC_Vector3d vect1(xn, yn, zn);
01142 
01143                 // Vertex 2
01144                 xn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3);
01145                 yn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3  + 1);
01146                 zn= pData->at(m_pMeshInfo->m_Index.at(i + 1) * 3 + 2);
01147                 const GLC_Vector3d vect2(xn, yn, zn);
01148 
01149                 // Vertex 3
01150                 xn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3);
01151                 yn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3 + 1);
01152                 zn= pData->at(m_pMeshInfo->m_Index.at(i + 2) * 3 + 2);
01153                 const GLC_Vector3d vect3(xn, yn, zn);
01154 
01155                 const GLC_Vector3d edge1(vect3 - vect2);
01156                 const GLC_Vector3d edge2(vect1 - vect2);
01157 
01158                 GLC_Vector3d normal(edge1 ^ edge2);
01159                 normal.normalize();
01160 
01161                 GLC_Vector3df curNormal= normal.toVector3df();
01162                 for (int curVertex= 0; curVertex < 3; ++curVertex)
01163                 {
01164                         (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3]= curNormal.X();
01165                         (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3 + 1]= curNormal.Y();
01166                         (*pNormal)[m_pMeshInfo->m_Index.at(i + curVertex) * 3 + 2]= curNormal.Z();
01167                 }
01168         }
01169 }
01170 
01171 // Load triangles
01172 void  GLC_ColladaToWorld::loadTriangles()
01173 {
01174         //qDebug() << "GLC_ColladaToWorld::loadTriangles()";
01175         // The material id
01176         const QString materialId= readAttribute("material", false);
01177 
01178         // Offsets and data source list
01179         QList<InputData> inputDataList;
01180 
01181         // triangle index list
01182         QList<int> trianglesIndexList;
01183 
01184         while (endElementNotReached("triangles"))
01185         {
01186                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01187                 {
01188                         const QStringRef currentElementName= m_pStreamReader->name();
01189                         if ((currentElementName == "input") && trianglesIndexList.isEmpty())
01190                         {
01191                                 InputData currentInput;
01192                                 // Get input data offset
01193                                 currentInput.m_Offset= readAttribute("offset", true).toInt();
01194                                 // Get input data semantic
01195                                 const QString semantic= readAttribute("semantic", true);
01196                                 if (semantic == "VERTEX") currentInput.m_Semantic= VERTEX;
01197                                 else if (semantic == "NORMAL") currentInput.m_Semantic= NORMAL;
01198                                 else if (semantic == "TEXCOORD") currentInput.m_Semantic= TEXCOORD;
01199                                 else throwException("Source semantic :" + semantic + "Not supported");
01200                                 // Get input data source id
01201                                 currentInput.m_Source= readAttribute("source", true).remove('#');
01202 
01203                                 // Bypasss vertices indirection
01204                                 if (m_VerticesSourceHash.contains(currentInput.m_Source))
01205                                 {
01206                                         currentInput.m_Source= m_VerticesSourceHash.value(currentInput.m_Source);
01207                                 }
01208                                 inputDataList.append(currentInput);
01209                         }
01210                         else if ((currentElementName == "p") && trianglesIndexList.isEmpty())
01211                         {
01212                                 { // Fill index List
01213                                         QString pString= getContent("p");
01214                                         QStringList pStringList= pString.split(' ');
01215                                         bool toIntOK;
01216                                         const int size= pStringList.size();
01217                                         for (int i= 0; i < size; ++i)
01218                                         {
01219                                                 trianglesIndexList.append(pStringList.at(i).toInt(&toIntOK));
01220                                                 if (!toIntOK) throwException("Unable to convert string :" + pStringList.at(i) + " To int");
01221                                         }
01222                                 }
01223 
01224                         }
01225                 }
01226                 m_pStreamReader->readNext();
01227         }
01228 
01229         // Add the polylist to the current mesh
01230         addTrianglesToCurrentMesh(inputDataList, trianglesIndexList, materialId);
01231 
01232         updateProgressBar();
01233 
01234 }
01235 
01236 // Add the triangles to current mesh
01237 void GLC_ColladaToWorld::addTrianglesToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& trianglesIndexList, const QString& materialId)
01238 {
01239         //qDebug() << "GLC_ColladaToWorld::addTrianglesToCurrentMesh";
01240 
01241         const int inputDataCount= inputDataList.size();
01242         const int trianglesIndexCount= trianglesIndexList.size();
01243 
01244         // Flag to know if the polylist has normal
01245         bool hasNormals= false;
01246 
01247         // Check the existance of data source
01248         for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01249         {
01250                 const QString source= inputDataList.at(dataIndex).m_Source;
01251                 if ( !m_BulkDataHash.contains(source))
01252                 {
01253                         throwException(" Source : " + source + " Not found");
01254                 }
01255                 if (inputDataList.at(dataIndex).m_Semantic == NORMAL) hasNormals= true;
01256         }
01257 
01258         int maxOffset= 0;
01259         for (int i= 0; i < inputDataCount; ++i)
01260         {
01261                 if (inputDataList.at(i).m_Offset > maxOffset)
01262                 {
01263                         maxOffset= inputDataList.at(i).m_Offset;
01264                 }
01265         }
01266         //qDebug() << " Triangles Max Offset :" << maxOffset;
01267 
01268         // the polygonIndex of the polylist
01269         QList<GLuint> trianglesIndex;
01270 
01271         // Fill the mapping, bulk data and index list of the current mesh info
01272         for (int i= 0; i < trianglesIndexCount; i+= maxOffset + 1)
01273         {
01274                 // Create and set the current vertice index
01275                 ColladaVertice currentVertice;
01276                 for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01277                 {
01278                         currentVertice.m_Values[inputDataList.at(dataIndex).m_Semantic]= trianglesIndexList.at(i + inputDataList.at(dataIndex).m_Offset);
01279                 }
01280 
01281                 if (m_pMeshInfo->m_Mapping.contains(currentVertice))
01282                 {
01283                         // Add the the index to the triangles index
01284                         trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01285                 }
01286                 else
01287                 {
01288                         // Add the current vertice to the current mesh info mapping hash table and increment the freeIndex
01289                         m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
01290                         // Add the the index to the triangles index
01291                         trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01292 
01293                         // Add the bulk data associated to the current vertice to the current mesh info
01294                         for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01295                         {
01296                                 // The current input data
01297                                 InputData currentInputData= inputDataList.at(dataIndex);
01298                                 // QHash iterator on the right QList<float>
01299                                 BulkDataHash::const_iterator iBulkHash= m_BulkDataHash.find(currentInputData.m_Source);
01300                                 int stride;
01301                                 if (currentInputData.m_Semantic != TEXCOORD) stride= 3; else stride= 2;
01302                                 // Firts value
01303                                 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride));
01304                                 // Second value
01305                                 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride + 1));
01306                                 // Fird value
01307                                 if (currentInputData.m_Semantic != TEXCOORD)
01308                                 {
01309                                         m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride + 2));
01310                                 }
01311                         }
01312                 }
01313         }
01314 
01315         // Save mesh info index offset
01316         const int indexOffset= m_pMeshInfo->m_Index.size();
01317 
01318         // Add index to the mesh info
01319         m_pMeshInfo->m_Index.append(trianglesIndex);
01320 
01321         // Check if normal computation is needed
01322         if (!hasNormals)
01323         {
01324                 computeNormalOfCurrentPrimitiveOfCurrentMesh(indexOffset);
01325         }
01326 
01327         // Add material the current mesh info
01328         MatOffsetSize matInfo;
01329         matInfo.m_Offset= indexOffset;
01330         matInfo.m_size= m_pMeshInfo->m_Index.size() - indexOffset;
01331         m_pMeshInfo->m_Materials.insertMulti(materialId, matInfo);
01332 
01333 }
01334 
01335 // Load the library nodes
01336 void GLC_ColladaToWorld::loadLibraryNodes()
01337 {
01338         //qDebug() << "GLC_ColladaToWorld::loadLibraryNodes";
01339 
01340         while (endElementNotReached("library_nodes"))
01341         {
01342                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01343                 {
01344                         const QStringRef currentElementName= m_pStreamReader->name();
01345                         if ((currentElementName == "node"))
01346                         {
01347                                 GLC_ColladaToWorld::ColladaNode* pNode= loadNode(NULL);
01348                                 if (NULL != pNode)
01349                                 {
01350 
01351                                 }
01352                         }
01353                 }
01354 
01355                 updateProgressBar();
01356 
01357                 m_pStreamReader->readNext();
01358         }
01359         checkForXmlError("Error occur while loading element : library_nodes");
01360 }
01361 
01362 // Load the library controllers
01363 void GLC_ColladaToWorld::loadLibraryContollers()
01364 {
01365         //qDebug() << "GLC_ColladaToWorld::loadLibraryContollers";
01366 
01367         while (endElementNotReached("library_controllers"))
01368         {
01369                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01370                 {
01371                         const QStringRef currentElementName= m_pStreamReader->name();
01372                         if ((currentElementName == "controller")) loadController();
01373                 }
01374 
01375                 updateProgressBar();
01376 
01377                 m_pStreamReader->readNext();
01378         }
01379         checkForXmlError("Error occur while loading element : library_controllers");
01380 }
01381 
01382 // Load library_visual_scenes element
01383 void GLC_ColladaToWorld::loadVisualScenes()
01384 {
01385         //qDebug() << "GLC_ColladaToWorld::loadVisualScenes";
01386         // The element library visual scene must contains a visual scene element
01387         goToElement("visual_scene");
01388 
01389         while (endElementNotReached("visual_scene"))
01390         {
01391                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01392                 {
01393                         const QStringRef currentElementName= m_pStreamReader->name();
01394                         if (currentElementName == "node")
01395                         {
01396                                 GLC_ColladaToWorld::ColladaNode* pNode= loadNode(NULL);
01397                                 if (NULL != pNode)
01398                                 {
01399                                         m_TopLevelColladaNode.append(pNode);
01400                                 }
01401                         }
01402                 }
01403 
01404                 updateProgressBar();
01405 
01406                 m_pStreamReader->readNext();
01407         }
01408         checkForXmlError("Error occur while loading element : visual_scene");
01409 }
01410 
01411 // Load an instance geometry
01412 void GLC_ColladaToWorld::loadInstanceGeometry(ColladaNode* pNode)
01413 {
01414         //qDebug() << "GLC_ColladaToWorld::loadInstanceGeometry";
01415 
01416         const QString url= readAttribute("url", true).remove('#');
01417         pNode->m_InstanceGeometryIDs.append(url);
01418 
01419         while (endElementNotReached("instance_geometry"))
01420         {
01421                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01422                 {
01423                         const QStringRef currentElementName= m_pStreamReader->name();
01424                         if ((currentElementName == "instance_material"))
01425                         {
01426                                 const QString target= readAttribute("target", true).remove('#');
01427                                 const QString symbol= readAttribute("symbol", true);
01428                                 m_MaterialInstanceMap.insert(symbol, target);
01429                         }
01430 
01431                 }
01432                 m_pStreamReader->readNext();
01433         }
01434         checkForXmlError("Error occur while loading element : instance_geometry");
01435 }
01436 
01437 // Load an instance of node
01438 void GLC_ColladaToWorld::loadInstanceNode(ColladaNode* pNode)
01439 {
01440         //qDebug() << "GLC_ColladaToWorld::loadInstanceNode";
01441         const QString url= readAttribute("url", true).remove('#');
01442         pNode->m_InstanceOffNodeIds.append(url);
01443 }
01444 
01445 // Load an instance Controller
01446 void GLC_ColladaToWorld::loadInstanceController(ColladaNode* pNode)
01447 {
01448         const QString url= readAttribute("url", true).remove('#');
01449         pNode->m_InstanceOffNodeIds.append(url);
01450 
01451         while (endElementNotReached("instance_controller"))
01452         {
01453                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01454                 {
01455                         const QStringRef currentElementName= m_pStreamReader->name();
01456                         if ((currentElementName == "instance_material"))
01457                         {
01458                                 const QString target= readAttribute("target", true).remove('#');
01459                                 const QString symbol= readAttribute("symbol", true);
01460                                 m_MaterialInstanceMap.insert(symbol, target);
01461                         }
01462                 }
01463                 m_pStreamReader->readNext();
01464         }
01465         checkForXmlError("Error occur while loading element : instance_controller");
01466 }
01467 
01468 // Load a collada controller node
01469 void GLC_ColladaToWorld::loadController()
01470 {
01471 
01472         m_CurrentId= readAttribute("id", true);
01473         while (endElementNotReached("controller"))
01474         {
01475                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01476                 {
01477                         const QStringRef currentElementName= m_pStreamReader->name();
01478                         if ((currentElementName == "skin"))
01479                         {
01480                                 const QString source= readAttribute("source", true).remove('#');
01481                                 ColladaNode* pNode= new ColladaNode(m_CurrentId, NULL);
01482                                 pNode->m_InstanceGeometryIDs.append(source);
01483                                 m_ColladaNodeHash.insert(m_CurrentId, pNode);
01484                         }
01485                 }
01486                 m_pStreamReader->readNext();
01487         }
01488         checkForXmlError("Error occur while loading element : controller");
01489 
01490 }
01491 
01492 // Load a Collada Node element
01493 GLC_ColladaToWorld::ColladaNode* GLC_ColladaToWorld::loadNode(ColladaNode* pParent)
01494 {
01495         //qDebug() << "GLC_ColladaToWorld::loadNode";
01496         QString id= readAttribute("id", false);
01497         if (id.isEmpty())
01498         {
01499                 id= readAttribute("name", true);
01500         }
01501         //qDebug() << "Load Node " << id;
01502         m_CurrentId= id;
01503         // The node
01504         ColladaNode* pNode= new ColladaNode(id, pParent);
01505         // To avoid infinite call
01506         //m_pStreamReader->readNext();
01507 
01508         while (endElementNotReached("node"))
01509         {
01510                 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
01511                 {
01512                         const QStringRef currentElementName= m_pStreamReader->name();
01513 
01514                         if ((currentElementName == "translate")) translateNode(pNode);
01515                         else if ((currentElementName == "scale")) scaleNode(pNode);
01516                         else if ((currentElementName == "rotate")) rotateNode(pNode);
01517                         else if ((currentElementName == "matrix")) composeMatrixNode(pNode);
01518                         else if ((currentElementName == "instance_geometry")) loadInstanceGeometry(pNode);
01519                         else if ((currentElementName == "instance_node")) loadInstanceNode(pNode);
01520                         else if ((currentElementName == "instance_controller")) loadInstanceController(pNode);
01521                         else if ((currentElementName == "node"))
01522                         {
01523                                 QString newId= readAttribute("id", false);
01524                                 if (newId.isEmpty())
01525                                 {
01526                                         //qDebug() << "Child ReadAttribute name";
01527                                         newId= readAttribute("name", true);
01528                                 }
01529                                 if (newId != id)
01530                                 {
01531                                         //qDebug() << "New ID = " << newId;
01532                                         GLC_ColladaToWorld::ColladaNode* pChildNode= loadNode(pNode);
01533                                         if (NULL != pNode)
01534                                         {
01535                                                 //qDebug() << "Add child";
01536                                                 pNode->m_ChildNodes.append(pChildNode);
01537                                         }
01538                                 }
01539                         }
01540                         else if ((currentElementName == "instance_camera")
01541                                         || (currentElementName == "instance_light"))
01542                         {
01543                                 // Node type not supported
01544                                 delete pNode;
01545                                 pNode= NULL;
01546                         }
01547                 }
01548                 m_pStreamReader->readNext();
01549 
01550         }
01551 
01552         if (NULL != pNode)
01553         {
01554                 // Add the collada node to the collada node hash table
01555                 m_ColladaNodeHash.insert(id, pNode);
01556         }
01557         return pNode;
01558 }
01559 
01560 
01561 // Translate the node
01562 void GLC_ColladaToWorld::translateNode(ColladaNode* pNode)
01563 {
01564         //qDebug() << "Translate Node";
01565         Q_ASSERT(NULL != pNode);
01566         // Load translation values
01567         QStringList translateStringList= getContent("translate").simplified().split(' ');
01568         // A translation must contains 3 string
01569         const int size= translateStringList.size();
01570         if (translateStringList.size() != 3) throwException("Translate element must contains 3 floats and it's contains :" + QString::number(translateStringList.size()));
01571         // Convert the string to double
01572         double translate[3];
01573         bool toFloatOk= false;
01574         for (int i= 0; i < size; ++i)
01575         {
01576                 translate[i]= static_cast<double>(translateStringList.at(i).toFloat(&toFloatOk));
01577                 if (!toFloatOk) throwException("The number :" + translateStringList.at(i) + "Is not a float");
01578         }
01579         // Built the translation matrix
01580         GLC_Matrix4x4 translationMatrix(translate[0], translate[1], translate[2]);
01581         // Update the node matrix
01582         pNode->m_Matrix= pNode->m_Matrix * translationMatrix;
01583 }
01584 
01585 // Scale the node
01586 void GLC_ColladaToWorld::scaleNode(ColladaNode* pNode)
01587 {
01588         //qDebug() << "Scale Node";
01589         Q_ASSERT(NULL != pNode);
01590         // Load scale values
01591         QStringList scaleStringList= getContent("scale").simplified().split(' ');
01592         // A scale must contains 3 string
01593         const int size= scaleStringList.size();
01594         if (scaleStringList.size() != 3) throwException("Scale element must contains 3 floats and it's contains :" + QString::number(scaleStringList.size()));
01595         // Convert the string to double
01596         double scale[3];
01597         bool toFloatOk= false;
01598         for (int i= 0; i < size; ++i)
01599         {
01600                 scale[i]= static_cast<double>(scaleStringList.at(i).toFloat(&toFloatOk));
01601                 if (!toFloatOk) throwException("The number :" + scaleStringList.at(i) + "Is not a float");
01602         }
01603         // Built the translation matrix
01604         GLC_Matrix4x4 scaleMatrix;
01605         scaleMatrix.setMatScaling(scale[0], scale[1], scale[2]);
01606         // Update the node matrix
01607         pNode->m_Matrix= pNode->m_Matrix * scaleMatrix;
01608 }
01609 
01610 // Rotate the node
01611 void GLC_ColladaToWorld::rotateNode(ColladaNode* pNode)
01612 {
01613         //qDebug() << "Rotate Node";
01614         Q_ASSERT(NULL != pNode);
01615         // Load rotate values
01616         QStringList rotateStringList= getContent("rotate").simplified().split(' ');
01617         // A rotate must contains 4 string (Axis Vector 3 + Angle)
01618         const int size= rotateStringList.size();
01619         if (rotateStringList.size() != 4) throwException("Rotate element must contains 4 floats and it's contains :" + QString::number(rotateStringList.size()));
01620         // Convert the string to double
01621         double rotate[4];
01622         bool toFloatOk= false;
01623         for (int i= 0; i < size; ++i)
01624         {
01625                 rotate[i]= static_cast<double>(rotateStringList.at(i).toFloat(&toFloatOk));
01626                 if (!toFloatOk) throwException("The number :" + rotateStringList.at(i) + "Is not a float");
01627         }
01628         // Rotation vector
01629         GLC_Vector3d rotationAxis(rotate[0], rotate[1], rotate[2]);
01630         // Built the rotation matrix
01631         GLC_Matrix4x4 rotationMatrix(rotationAxis, rotate[3]);
01632         // Update the node matrix
01633         pNode->m_Matrix= pNode->m_Matrix * rotationMatrix;
01634 }
01635 
01636 // Compose Node matrix
01637 void GLC_ColladaToWorld::composeMatrixNode(ColladaNode* pNode)
01638 {
01639         Q_ASSERT(NULL != pNode);
01640 
01641         // Load matrix values
01642         QStringList matrixStringList= getContent("matrix").simplified().split(' ');
01643         // A rotate must contains 16 string 4 x 4 Matrix
01644         const int size= matrixStringList.size();
01645         if (size != 16) throwException("Matrix element must contains 16 floats and it's contains :" + QString::number(size));
01646         // Convert the string to double
01647         double matrix[16];
01648         bool toFloatOk= false;
01649         for (int i= 0; i < 4; ++i)
01650         {
01651                 matrix[i]= static_cast<double>(matrixStringList.at(i * 4).toFloat(&toFloatOk));
01652                 if (!toFloatOk) throwException("The number :" + matrixStringList.at(i) + "Is not a float");
01653 
01654                 matrix[i + 4]= static_cast<double>(matrixStringList.at(i * 4 + 1).toFloat(&toFloatOk));
01655                 if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 1) + "Is not a float");
01656 
01657                 matrix[i + 8]= static_cast<double>(matrixStringList.at(i * 4 + 2).toFloat(&toFloatOk));
01658                 if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 2) + "Is not a float");
01659 
01660                 matrix[i + 12]= static_cast<double>(matrixStringList.at(i * 4 + 3).toFloat(&toFloatOk));
01661                 if (!toFloatOk) throwException("The number :" + matrixStringList.at(i * 4 + 3) + "Is not a float");
01662 
01663         }
01664         // Built the matrix
01665         GLC_Matrix4x4 currentMatrix(matrix);
01666         // Update the node matrix
01667         pNode->m_Matrix= pNode->m_Matrix * currentMatrix;
01668 }
01669 
01670 // Load scene element
01671 void GLC_ColladaToWorld::loadScene()
01672 {
01673         //qDebug() << "GLC_ColladaToWorld::loadScene";
01674         while (endElementNotReached("scene"))
01675         {
01676                 // Nothing to do
01677                 m_pStreamReader->readNext();
01678         }
01679 }
01680 
01681 // Link texture to material
01682 void GLC_ColladaToWorld::linkTexturesToMaterials()
01683 {
01684         // Iterate throuth the the texture id to material hash
01685         MaterialHash::iterator iMat= m_TextureToMaterialHash.begin();
01686         while (iMat != m_TextureToMaterialHash.constEnd())
01687         {
01688                 GLC_Material* pCurrentMaterial= iMat.value();
01689                 const QString textureId= iMat.key();
01690 
01691                 // Check that the texture is present
01692                 if (m_Sampler2DSurfaceHash.contains(textureId))
01693                 {
01694                         const QString surfaceId= m_Sampler2DSurfaceHash.value(textureId);
01695                         if (m_SurfaceImageHash.contains(surfaceId))
01696                         {
01697                                 const QString imageFileId=  m_SurfaceImageHash.value(surfaceId);
01698                         }
01699                 }
01700                 if (m_Sampler2DSurfaceHash.contains(textureId) && m_SurfaceImageHash.contains(m_Sampler2DSurfaceHash.value(textureId))
01701                                 && m_ImageFileHash.contains(m_SurfaceImageHash.value(m_Sampler2DSurfaceHash.value(textureId))))
01702                 {
01703                         const QString imageFileName= m_ImageFileHash.value(m_SurfaceImageHash.value(m_Sampler2DSurfaceHash.value(textureId)));
01704                         QString fullImageFileName= QFileInfo(m_FileName).absolutePath() + QDir::separator() + imageFileName;
01705                         if (QFileInfo(fullImageFileName).exists())
01706                         {
01707                                 m_ListOfAttachedFileName << fullImageFileName;
01708                                 GLC_Texture* pTexture= new GLC_Texture(m_pQGLContext, fullImageFileName);
01709                                 pCurrentMaterial->setTexture(pTexture);
01710                         }
01711                         else if (QFileInfo(m_FileName).absolutePath() != QFileInfo(fullImageFileName).absolutePath())
01712                         {
01713                                 // Trying to find image in collada file path
01714                                 QString fullImageFileName= QFileInfo(m_FileName).absolutePath() + QDir::separator() + QFileInfo(imageFileName).fileName();
01715                                 if (QFileInfo(fullImageFileName).exists())
01716                                 {
01717                                         m_ListOfAttachedFileName << fullImageFileName;
01718                                         GLC_Texture* pTexture= new GLC_Texture(m_pQGLContext, fullImageFileName);
01719                                         pCurrentMaterial->setTexture(pTexture);
01720                                 }
01721                                 else
01722                                 {
01723                                         qDebug() << imageFileName << " Not found";
01724                                 }
01725                         }
01726                         else
01727                         {
01728                                 qDebug() << imageFileName << " Not found";
01729                         }
01730 
01731                 }
01732                 else
01733                 {
01734                         qDebug() << "Texture : " << textureId << " Not found";
01735                 }
01736                 ++iMat;
01737         }
01738 }
01739 // Create mesh and link them to material
01740 void GLC_ColladaToWorld::createMesh()
01741 {
01742         //qDebug() << "GLC_ColladaToWorld::createMesh()";
01743         QHash<const QString, MeshInfo*>::iterator iMeshInfo= m_GeometryHash.begin();
01744         while (m_GeometryHash.constEnd() != iMeshInfo)
01745         {
01746                 MeshInfo* pCurrentMeshInfo= iMeshInfo.value();
01747                 // Add Bulk Data to the mesh
01748                 // Add vertice
01749                 pCurrentMeshInfo->m_pMesh->addVertice(pCurrentMeshInfo->m_Datas.at(VERTEX).toVector());
01750                 //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[VERTEX].size() << " Vertice";
01751                 pCurrentMeshInfo->m_Datas[VERTEX].clear();
01752 
01753                 // Add Normal
01754                 pCurrentMeshInfo->m_pMesh->addNormals(pCurrentMeshInfo->m_Datas.at(NORMAL).toVector());
01755                 //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[NORMAL].size() << " Normal";
01756                 pCurrentMeshInfo->m_Datas[NORMAL].clear();
01757 
01758                 // Add texel if necessary
01759                 //qDebug() << "Add " << pCurrentMeshInfo->m_Datas[TEXCOORD].size() << " texel";
01760                 if (!pCurrentMeshInfo->m_Datas.at(TEXCOORD).isEmpty())
01761                 {
01762                         pCurrentMeshInfo->m_pMesh->addTexels(pCurrentMeshInfo->m_Datas.at(TEXCOORD).toVector());
01763                         pCurrentMeshInfo->m_Datas[TEXCOORD].clear();
01764                 }
01765 
01766                 // Add face index and material to the mesh
01767                 QHash<QString, MatOffsetSize>::iterator iMatInfo= pCurrentMeshInfo->m_Materials.begin();
01768                 while (pCurrentMeshInfo->m_Materials.constEnd() != iMatInfo)
01769                 {
01770                         // Trying to find the material
01771                         QString materialId= iMatInfo.key();
01772                         GLC_Material* pCurrentMaterial= NULL;
01773                         if (m_MaterialInstanceMap.contains(materialId))
01774                         {
01775                                 //qDebug() << "Map " << materialId << " to " << m_MaterialInstanceMap.value(materialId);
01776                                 materialId= m_MaterialInstanceMap.value(materialId);
01777                         }
01778                         //qDebug() << "MaterialLibHash size : " << m_MaterialLibHash.size();
01779                         if (m_MaterialLibHash.contains(materialId))
01780                         {
01781                                 materialId= m_MaterialLibHash.value(materialId);
01782                                 //qDebug() << "Material id " << materialId;
01783                         }
01784                         if (m_MaterialEffectHash.contains(materialId))
01785                         {
01786                                 //qDebug() << "Material " << materialId << " find";
01787                                 pCurrentMaterial= m_MaterialEffectHash.value(materialId);
01788                                 Q_ASSERT(NULL != pCurrentMaterial);
01789                         }
01790                         else qDebug() << "Material " << materialId << " Not found";
01791 
01792                         // Create the list of triangles to add to the mesh
01793                         const int offset= iMatInfo.value().m_Offset;
01794                         const int size= iMatInfo.value().m_size;
01795                         //qDebug() << "Offset : " << offset << " size : " << size;
01796                         QList<GLuint> triangles;
01797                         for (int i= offset; i < (offset + size); ++i)
01798                         {
01799                                 triangles.append(pCurrentMeshInfo->m_Index.at(i));
01800                         }
01801                         //qDebug() << "Add " << triangles.size() << " elment to the triangle index";
01802                         // Add the list of triangle to the mesh
01803                         if (!triangles.isEmpty())
01804                         {
01805                                 pCurrentMeshInfo->m_pMesh->addTriangles(pCurrentMaterial, triangles);
01806                         }
01807 
01808                         ++iMatInfo;
01809                 }
01810                 pCurrentMeshInfo->m_pMesh->finish();
01811                 GLC_3DRep* pRep= new GLC_3DRep(pCurrentMeshInfo->m_pMesh);
01812                 pCurrentMeshInfo->m_pMesh= NULL;
01813                 pRep->clean();
01814                 //qDebug() << "Insert Rep : " << iMeshInfo.key();
01815                 m_3DRepHash.insert(iMeshInfo.key(), pRep);
01816                 ++iMeshInfo;
01817         }
01818 }
01819 
01820 // Create the scene graph struct
01821 void GLC_ColladaToWorld::createSceneGraph()
01822 {
01823         const int topLevelNodeCount= m_TopLevelColladaNode.size();
01824         for (int i= 0; i < topLevelNodeCount; ++i)
01825         {
01826                 ColladaNode* pCurrentColladaNode= m_TopLevelColladaNode.at(i);
01827                 //qDebug() << "Top level node is : " << pCurrentColladaNode->m_Id;
01828                 if (NULL != pCurrentColladaNode)
01829                 {
01830                         GLC_StructOccurence* pOccurence= createOccurenceFromNode(pCurrentColladaNode);
01831                         m_pWorld->rootOccurence()->addChild(pOccurence);
01832                 }
01833         }
01834 
01835         // Update position
01836         m_pWorld->rootOccurence()->removeEmptyChildren();
01837         m_pWorld->rootOccurence()->updateChildrenAbsoluteMatrix();
01838 
01839 }
01840 
01841 // Create Occurence tree from node tree
01842 GLC_StructOccurence* GLC_ColladaToWorld::createOccurenceFromNode(ColladaNode* pNode)
01843 {
01844         //qDebug() << "GLC_ColladaToWorld::createOccurenceFromNode";
01845         Q_ASSERT(NULL != pNode);
01846         GLC_StructInstance* pInstance= NULL;
01847         GLC_StructOccurence* pOccurence= NULL;
01848         if (!pNode->m_InstanceGeometryIDs.isEmpty())
01849         {
01850                 if (m_StructInstanceHash.contains(pNode->m_Id))
01851                 {
01852                         pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
01853                         pInstance->move(pNode->m_Matrix);
01854                         //qDebug() << "Instance move with this matrix :" << pNode->m_Matrix.toString();
01855                         pOccurence= new GLC_StructOccurence(pInstance);
01856                 }
01857                 else
01858                 {
01859                         const int size= pNode->m_InstanceGeometryIDs.size();
01860                         GLC_3DRep* pRep= NULL;
01861                         for (int i= 0; i < size; ++i)
01862                         {
01863                                 const QString geometryId= pNode->m_InstanceGeometryIDs.at(i);
01864                                 if (NULL == pRep)
01865                                 {
01866                                         pRep= new GLC_3DRep(*(m_3DRepHash.value(geometryId)));
01867                                 }
01868                                 else
01869                                 {
01870                                         pRep->merge(m_3DRepHash.value(geometryId));
01871                                 }
01872                         }
01873                         if (NULL != pRep)
01874                         {
01875                                 GLC_StructReference* pStructRef= NULL;
01876                                 if (pRep->isEmpty())
01877                                 {
01878                                         qDebug() << "Empty rep : " << pRep->name();
01879                                         delete pRep;
01880                                         pRep= NULL;
01881                                 }
01882                                 else
01883                                 {
01884                                         pStructRef= new GLC_StructReference(pRep);
01885                                         pInstance= new GLC_StructInstance(pStructRef);
01886 
01887                                         // Save instance in instance hash Table
01888                                         m_StructInstanceHash.insert(pNode->m_Id, pInstance);
01889 
01890                                         pInstance->move(pNode->m_Matrix);
01891                                         //qDebug() << "Instance move with this matrix :" << pNode->m_Matrix.toString();
01892                                         pOccurence= new GLC_StructOccurence(pInstance);
01893                                 }
01894 
01895                         }
01896                         else qDebug() << "Geometry Id Not found";
01897                 }
01898         }
01899         if (!pNode->m_ChildNodes.isEmpty())
01900         {
01901                 if (NULL == pOccurence) //  The node hasn't geometry -> Create an occurence
01902                 {
01903                         if (m_StructInstanceHash.contains(pNode->m_Id))
01904                         {
01905                                 pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
01906                         }
01907                         else
01908                         {
01909                                 GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
01910                                 pInstance= new GLC_StructInstance(pStructRef);
01911                         }
01912 
01913                         pInstance->move(pNode->m_Matrix);
01914                         pOccurence= new GLC_StructOccurence(pInstance);
01915                 }
01916 
01917                 const int size= pNode->m_ChildNodes.size();
01918                 for (int i= 0; i < size; ++i)
01919                 {
01920                         if (NULL != pNode->m_ChildNodes.at(i))
01921                         {
01922                                 pOccurence->addChild(createOccurenceFromNode(pNode->m_ChildNodes.at(i)));
01923                         }
01924                 }
01925         }
01926         if (!pNode->m_InstanceOffNodeIds.isEmpty())
01927         {
01928                 if (NULL == pOccurence) //  The node hasn't geometry and childs -> Create an occurence
01929                 {
01930                         if (m_StructInstanceHash.contains(pNode->m_Id))
01931                         {
01932                                 pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
01933                         }
01934                         else
01935                         {
01936                                 GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
01937                                 pInstance= new GLC_StructInstance(pStructRef);
01938                         }
01939 
01940                         pInstance->move(pNode->m_Matrix);
01941                         pOccurence= new GLC_StructOccurence(pInstance);
01942                 }
01943 
01944                 const int size= pNode->m_InstanceOffNodeIds.size();
01945                 for (int i= 0; i < size; ++i)
01946                 {
01947                         if (m_ColladaNodeHash.contains(pNode->m_InstanceOffNodeIds.at(i)))
01948                         {
01949                                 pOccurence->addChild(createOccurenceFromNode(m_ColladaNodeHash.value(pNode->m_InstanceOffNodeIds.at(i))));
01950                         }
01951                         else
01952                         {
01953                                 const QString errorMsg= "Instance Node : " + pNode->m_InstanceOffNodeIds.at(i) + "Not Found";
01954                                 throwException(errorMsg);
01955                         }
01956                 }
01957         }
01958         if (NULL == pOccurence)
01959         {
01960                 qDebug() << "Empty Node";
01961                 if (m_StructInstanceHash.contains(pNode->m_Id))
01962                 {
01963                         pInstance= new GLC_StructInstance(m_StructInstanceHash.value(pNode->m_Id));
01964                 }
01965                 else
01966                 {
01967                         GLC_StructReference* pStructRef= new GLC_StructReference(pNode->m_Id);
01968                         pInstance= new GLC_StructInstance(pStructRef);
01969                 }
01970 
01971                 pInstance->move(pNode->m_Matrix);
01972                 pOccurence= new GLC_StructOccurence(pInstance);
01973         }
01974 
01975         return pOccurence;
01976 }
01977 
01978 // Update progress bar
01979 void GLC_ColladaToWorld::updateProgressBar()
01980 {
01981         qint64 currentOffset= m_pStreamReader->characterOffset();
01982 
01983         int currentQuantumValue;
01984         // Progrees bar indicator
01985         currentQuantumValue = static_cast<int>((static_cast<double>(currentOffset) / m_FileSize) * 100);
01986         if (currentQuantumValue > m_CurrentOffset)
01987         {
01988                 emit currentQuantum(currentQuantumValue);
01989                 m_CurrentOffset= currentQuantumValue;
01990         }
01991 
01992 }

SourceForge.net Logo

©2005 Laurent Ribon