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

SourceForge.net Logo

©2005-2011 Laurent Ribon