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

SourceForge.net Logo

©2005-2011 Laurent Ribon