00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
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
00068 GLC_ColladaToWorld::~GLC_ColladaToWorld()
00069 {
00070
00071 m_pWorld= NULL;
00072 clear();
00073 }
00074
00076
00078
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
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
00095 m_FileSize= QFileInfo(m_FileName).size();
00096
00097 m_pStreamReader= new QXmlStreamReader(m_pFile);
00098
00099
00100 goToElement("COLLADA");
00101
00102
00103 QString version= readAttribute("version", true);
00104
00105
00106 goToElement("asset");
00107 while (endElementNotReached(m_pStreamReader, "asset"))
00108 {
00109 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00110 {
00111 const QStringRef currentElementName= m_pStreamReader->name();
00112 if (currentElementName == "up_axis")
00113 {
00114 const QString upAxis= getContent("up_axis");
00115 if (upAxis == "X_UP") m_pWorld->setUpVector(glc::X_AXIS);
00116 else if (upAxis == "Y_UP") m_pWorld->setUpVector(glc::Y_AXIS);
00117 else if (upAxis == "Z_UP") m_pWorld->setUpVector(glc::Z_AXIS);
00118 }
00119 }
00120 m_pStreamReader->readNext();
00121 }
00122
00123 while (endElementNotReached(m_pStreamReader, "COLLADA"))
00124 {
00125 if (QXmlStreamReader::StartElement == m_pStreamReader->tokenType())
00126 {
00127 const QStringRef currentElementName= m_pStreamReader->name();
00128 if (currentElementName == "library_images") loadLibraryImage();
00129 else if (currentElementName == "library_materials") loadLibraryMaterials();
00130 else if (currentElementName == "library_effects") loadLibraryEffects();
00131 else if (currentElementName == "library_geometries") loadLibraryGeometries();
00132 else if (currentElementName == "library_nodes") loadLibraryNodes();
00133 else if (currentElementName == "library_controllers") loadLibraryContollers();
00134 else if (currentElementName == "library_visual_scenes") loadVisualScenes();
00135 else if (currentElementName == "scene") loadScene();
00136 }
00137
00138 m_pStreamReader->readNext();
00139 }
00140
00141 linkTexturesToMaterials();
00142
00143
00144 createMesh();
00145
00146
00147 createSceneGraph();
00148
00149 emit currentQuantum(100);
00150
00151 return m_pWorld;
00152 }
00153
00155
00157
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
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
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
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
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
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
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
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
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
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
00286 m_TopLevelColladaNode.clear();
00287
00288
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
00301 m_StructInstanceHash.clear();
00302
00303 m_CurrentId.clear();
00304
00305 m_ListOfAttachedFileName.clear();
00306 }
00307
00308
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
00326 void GLC_ColladaToWorld::loadImage()
00327 {
00328
00329
00330 m_CurrentId= readAttribute("id", true);
00331 QString fileName;
00332
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
00349 if (!fileName.isEmpty())
00350 {
00351 m_ImageFileHash.insert(m_CurrentId, fileName);
00352 }
00353 }
00354
00355
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
00374 void GLC_ColladaToWorld::loadMaterial()
00375 {
00376
00377 m_CurrentId= readAttribute("id", true);
00378
00379 goToElement("instance_effect");
00380
00381
00382 const QString url= readAttribute("url", true).remove('#');
00383
00384
00385
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
00402 if (!url.isEmpty())
00403 {
00404
00405 m_MaterialLibHash.insert(m_CurrentId, url);
00406 }
00407
00408 }
00409
00410
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
00429 void GLC_ColladaToWorld::loadEffect()
00430 {
00431
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
00455 void GLC_ColladaToWorld::loadProfileCommon()
00456 {
00457
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
00473 void GLC_ColladaToWorld::loadNewParam()
00474 {
00475
00476
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
00492 void GLC_ColladaToWorld::loadSurface(const QString& sid)
00493 {
00494
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
00512 void GLC_ColladaToWorld::loadSampler2D(const QString& sid)
00513 {
00514
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
00532 void GLC_ColladaToWorld::loadTechnique()
00533 {
00534
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
00550 void GLC_ColladaToWorld::loadMaterialTechnique(const QString& elementName)
00551 {
00552
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
00573 void GLC_ColladaToWorld::loadCommonColorOrTexture(const QString& name)
00574 {
00575
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
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
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
00611 void GLC_ColladaToWorld::loadTransparency(const QString& name)
00612 {
00613
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
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
00646 void GLC_ColladaToWorld::loadShininess(const QString& name)
00647 {
00648
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
00675 QColor GLC_ColladaToWorld::readXmlColor()
00676 {
00677
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
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
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
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
00767 if (!id.isEmpty())
00768 {
00769 m_GeometryHash.insert(id, m_pMeshInfo);
00770 m_pMeshInfo= NULL;
00771 }
00772 }
00773
00774
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
00788
00789 }
00790
00791 m_pStreamReader->readNext();
00792 }
00793 checkForXmlError("Error occur while loading element : mesh");
00794 }
00795
00796
00797 void GLC_ColladaToWorld::loadVertexBulkData()
00798 {
00799
00800
00801 m_CurrentId= readAttribute("id", true);
00802
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
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
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
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
00883 void GLC_ColladaToWorld::loadVertices()
00884 {
00885
00886
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
00896 void GLC_ColladaToWorld::loadPolylist()
00897 {
00898
00899
00900 const int polygonCount= readAttribute("count", true).toInt();
00901
00902
00903 const QString materialId= readAttribute("material", false);
00904
00905
00906 QList<InputData> inputDataList;
00907
00908
00909 QList<int> vcountList;
00910
00911
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
00923 currentInput.m_Offset= readAttribute("offset", true).toInt();
00924
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
00931 currentInput.m_Source= readAttribute("source", true).remove('#');
00932
00933
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 {
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
00971 addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
00972
00973 updateProgressBar();
00974 }
00975
00976
00977 void GLC_ColladaToWorld::loadPolygons()
00978 {
00979
00980 const QString materialId= readAttribute("material", false);
00981
00982
00983 QList<InputData> inputDataList;
00984
00985
00986 QList<int> vcountList;
00987
00988
00989 int inputCount= 0;
00990
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
01002 currentInput.m_Offset= readAttribute("offset", true).toInt();
01003
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
01010 currentInput.m_Source= readAttribute("source", true).remove('#');
01011
01012
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 {
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
01032 vcountList.append(size / inputCount);
01033 }
01034 }
01035 }
01036 m_pStreamReader->readNext();
01037 }
01038
01039 addPolylistToCurrentMesh(inputDataList, vcountList, polyIndexList, materialId);
01040
01041 updateProgressBar();
01042 }
01043
01044
01045 void GLC_ColladaToWorld::addPolylistToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& vcountList, const QList<int>& polyIndexList, const QString& materialId)
01046 {
01047
01048
01049 const int polygonCount= vcountList.size();
01050 const int inputDataCount= inputDataList.size();
01051 const int polyIndexCount= polyIndexList.size();
01052
01053
01054 bool hasNormals= false;
01055 bool hasTexture= false;
01056
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
01077
01078
01079 QList<int> polygonIndex;
01080
01081
01082 for (int i= 0; i < polyIndexCount; i+= maxOffset + 1)
01083 {
01084
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
01094 polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01095 }
01096 else
01097 {
01098
01099 m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
01100
01101 polygonIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01102
01103
01104 for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01105 {
01106
01107 InputData currentInputData= inputDataList.at(dataIndex);
01108
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
01117 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride));
01118
01119 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(polyIndexList.at(i + currentInputData.m_Offset) * stride + 1));
01120
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
01127 if (!hasTexture)
01128 {
01129 m_pMeshInfo->m_Datas[TEXCOORD].append(0.0);
01130 }
01131
01132 }
01133 }
01134
01135
01136 const int indexOffset= m_pMeshInfo->m_Index.size();
01137
01138
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
01149 if (polygonSize > 3)
01150 {
01151 glc::triangulatePolygon(&onePolygonIndex, m_pMeshInfo->m_Datas.at(VERTEX));
01152 }
01153
01154
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
01169 if (!hasNormals)
01170 {
01171 qDebug() << "Compute Normals with offset " << indexOffset;
01172 computeNormalOfCurrentPrimitiveOfCurrentMesh(indexOffset);
01173 }
01174
01175
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
01183 void GLC_ColladaToWorld::computeNormalOfCurrentPrimitiveOfCurrentMesh(int indexOffset)
01184 {
01185 const QList<float>* pData= &(m_pMeshInfo->m_Datas.at(VERTEX));
01186
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
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
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
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
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
01236 void GLC_ColladaToWorld::loadTriangles()
01237 {
01238
01239
01240 const QString materialId= readAttribute("material", false);
01241
01242
01243 QList<InputData> inputDataList;
01244
01245
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
01257 currentInput.m_Offset= readAttribute("offset", true).toInt();
01258
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
01265 currentInput.m_Source= readAttribute("source", true).remove('#');
01266
01267
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 {
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
01294 addTrianglesToCurrentMesh(inputDataList, trianglesIndexList, materialId);
01295
01296 updateProgressBar();
01297
01298 }
01299
01300
01301 void GLC_ColladaToWorld::addTrianglesToCurrentMesh(const QList<InputData>& inputDataList, const QList<int>& trianglesIndexList, const QString& materialId)
01302 {
01303
01304
01305 const int inputDataCount= inputDataList.size();
01306 const int trianglesIndexCount= trianglesIndexList.size();
01307
01308
01309 bool hasNormals= false;
01310 bool hasTexture= false;
01311
01312
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
01333
01334
01335 QList<GLuint> trianglesIndex;
01336
01337
01338 for (int i= 0; i < trianglesIndexCount; i+= maxOffset + 1)
01339 {
01340
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
01350 trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01351 }
01352 else
01353 {
01354
01355 m_pMeshInfo->m_Mapping.insert(currentVertice, (m_pMeshInfo->m_FreeIndex)++);
01356
01357 trianglesIndex.append(m_pMeshInfo->m_Mapping.value(currentVertice));
01358
01359
01360 for (int dataIndex= 0; dataIndex < inputDataCount; ++dataIndex)
01361 {
01362
01363 InputData currentInputData= inputDataList.at(dataIndex);
01364
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
01373 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride));
01374
01375 m_pMeshInfo->m_Datas[currentInputData.m_Semantic].append(iBulkHash.value().at(trianglesIndexList.at(i + currentInputData.m_Offset) * stride + 1));
01376
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
01382 if (!hasTexture)
01383 {
01384 m_pMeshInfo->m_Datas[TEXCOORD].append(0.0);
01385 }
01386 }
01387 }
01388 }
01389
01390
01391 const int indexOffset= m_pMeshInfo->m_Index.size();
01392
01393
01394 m_pMeshInfo->m_Index.append(trianglesIndex);
01395
01396
01397 if (!hasNormals)
01398 {
01399 computeNormalOfCurrentPrimitiveOfCurrentMesh(indexOffset);
01400 }
01401
01402
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
01411 void GLC_ColladaToWorld::loadLibraryNodes()
01412 {
01413
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
01438 void GLC_ColladaToWorld::loadLibraryContollers()
01439 {
01440
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
01458 void GLC_ColladaToWorld::loadVisualScenes()
01459 {
01460
01461
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
01487 void GLC_ColladaToWorld::loadInstanceGeometry(ColladaNode* pNode)
01488 {
01489
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
01513 void GLC_ColladaToWorld::loadInstanceNode(ColladaNode* pNode)
01514 {
01515
01516 const QString url= readAttribute("url", true).remove('#');
01517 pNode->m_InstanceOffNodeIds.append(url);
01518 }
01519
01520
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
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
01568 GLC_ColladaToWorld::ColladaNode* GLC_ColladaToWorld::loadNode(ColladaNode* pParent)
01569 {
01570
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
01585 m_CurrentId= id;
01586
01587 ColladaNode* pNode= new ColladaNode(id, pParent);
01588
01589
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
01612 newId= readAttribute("name", false);
01613 }
01614
01615 GLC_ColladaToWorld::ColladaNode* pChildNode= loadNode(pNode);
01616 if (NULL != pNode)
01617 {
01618
01619 pNode->m_ChildNodes.append(pChildNode);
01620 }
01621 }
01622 }
01623 else if ((currentElementName == "instance_camera")
01624 || (currentElementName == "instance_light"))
01625 {
01626
01627 delete pNode;
01628 pNode= NULL;
01629 }
01630 }
01631 m_pStreamReader->readNext();
01632
01633 }
01634
01635 if (NULL != pNode)
01636 {
01637
01638 m_ColladaNodeHash.insert(id, pNode);
01639 }
01640 return pNode;
01641 }
01642
01643
01644
01645 void GLC_ColladaToWorld::translateNode(ColladaNode* pNode)
01646 {
01647
01648 Q_ASSERT(NULL != pNode);
01649
01650 QStringList translateStringList= getContent("translate").simplified().split(' ');
01651
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
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
01663 GLC_Matrix4x4 translationMatrix(translate[0], translate[1], translate[2]);
01664
01665 pNode->m_Matrix= pNode->m_Matrix * translationMatrix;
01666 }
01667
01668
01669 void GLC_ColladaToWorld::scaleNode(ColladaNode* pNode)
01670 {
01671
01672 Q_ASSERT(NULL != pNode);
01673
01674 QStringList scaleStringList= getContent("scale").simplified().split(' ');
01675
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
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
01687 GLC_Matrix4x4 scaleMatrix;
01688 scaleMatrix.setMatScaling(scale[0], scale[1], scale[2]);
01689 scaleMatrix.optimise();
01690
01691 pNode->m_Matrix= pNode->m_Matrix * scaleMatrix;
01692 }
01693
01694
01695 void GLC_ColladaToWorld::rotateNode(ColladaNode* pNode)
01696 {
01697
01698 Q_ASSERT(NULL != pNode);
01699
01700 QStringList rotateStringList= getContent("rotate").simplified().split(' ');
01701
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
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
01713 GLC_Vector3d rotationAxis(rotate[0], rotate[1], rotate[2]);
01714
01715 GLC_Matrix4x4 rotationMatrix(rotationAxis, rotate[3]);
01716
01717 pNode->m_Matrix= pNode->m_Matrix * rotationMatrix;
01718 }
01719
01720
01721 void GLC_ColladaToWorld::composeMatrixNode(ColladaNode* pNode)
01722 {
01723 Q_ASSERT(NULL != pNode);
01724
01725
01726 QStringList matrixStringList= getContent("matrix").simplified().split(' ');
01727
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
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
01749 GLC_Matrix4x4 currentMatrix(matrix);
01750 currentMatrix.optimise();
01751
01752
01753 pNode->m_Matrix= pNode->m_Matrix * currentMatrix;
01754 }
01755
01756
01757 void GLC_ColladaToWorld::loadScene()
01758 {
01759
01760 while (endElementNotReached(m_pStreamReader, "scene"))
01761 {
01762
01763 m_pStreamReader->readNext();
01764 }
01765 }
01766
01767
01768 void GLC_ColladaToWorld::linkTexturesToMaterials()
01769 {
01770
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
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
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
01832 void GLC_ColladaToWorld::createMesh()
01833 {
01834
01835 QHash<const QString, MeshInfo*>::iterator iMeshInfo= m_GeometryHash.begin();
01836 while (m_GeometryHash.constEnd() != iMeshInfo)
01837 {
01838 MeshInfo* pCurrentMeshInfo= iMeshInfo.value();
01839
01840
01841 pCurrentMeshInfo->m_pMesh->addVertice(pCurrentMeshInfo->m_Datas.at(VERTEX).toVector());
01842
01843 pCurrentMeshInfo->m_Datas[VERTEX].clear();
01844
01845
01846 pCurrentMeshInfo->m_pMesh->addNormals(pCurrentMeshInfo->m_Datas.at(NORMAL).toVector());
01847
01848 pCurrentMeshInfo->m_Datas[NORMAL].clear();
01849
01850
01851
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
01859 QHash<QString, MatOffsetSize>::iterator iMatInfo= pCurrentMeshInfo->m_Materials.begin();
01860 while (pCurrentMeshInfo->m_Materials.constEnd() != iMatInfo)
01861 {
01862
01863 QString materialId= iMatInfo.key();
01864 GLC_Material* pCurrentMaterial= NULL;
01865 if (m_MaterialInstanceMap.contains(materialId))
01866 {
01867
01868 materialId= m_MaterialInstanceMap.value(materialId);
01869 }
01870
01871 if (m_MaterialLibHash.contains(materialId))
01872 {
01873 materialId= m_MaterialLibHash.value(materialId);
01874
01875 }
01876 if (m_MaterialEffectHash.contains(materialId))
01877 {
01878
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
01890 const int offset= iMatInfo.value().m_Offset;
01891 const int size= iMatInfo.value().m_size;
01892
01893 QList<GLuint> triangles;
01894 for (int i= offset; i < (offset + size); ++i)
01895 {
01896 triangles.append(pCurrentMeshInfo->m_Index.at(i));
01897 }
01898
01899
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
01912 m_3DRepHash.insert(iMeshInfo.key(), pRep);
01913 ++iMeshInfo;
01914 }
01915 }
01916
01917
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
01925 if (NULL != pCurrentColladaNode)
01926 {
01927 GLC_StructOccurence* pOccurence= createOccurenceFromNode(pCurrentColladaNode);
01928 m_pWorld->rootOccurence()->addChild(pOccurence);
01929 }
01930 }
01931
01932
01933 m_pWorld->rootOccurence()->removeEmptyChildren();
01934 m_pWorld->rootOccurence()->updateChildrenAbsoluteMatrix();
01935
01936 }
01937
01938
01939 GLC_StructOccurence* GLC_ColladaToWorld::createOccurenceFromNode(ColladaNode* pNode)
01940 {
01941
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
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
01987 m_StructInstanceHash.insert(pNode->m_Id, pInstance);
01988
01989 pInstance->move(pNode->m_Matrix);
01990
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)
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)
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
02082 void GLC_ColladaToWorld::updateProgressBar()
02083 {
02084 qint64 currentOffset= m_pStreamReader->characterOffset();
02085
02086 int currentQuantumValue;
02087
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 }