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