00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00026
00027 #include "glc_mesh.h"
00028 #include "../glc_renderstatistics.h"
00029
00030
00031 quint32 GLC_Mesh::m_ChunkId= 0xA701;
00032
00033 GLC_Mesh::GLC_Mesh()
00034 :GLC_Geometry("Mesh", false)
00035 , m_NextPrimitiveLocalId(1)
00036 , m_PrimitiveGroups()
00037 , m_DefaultMaterialId(0)
00038 , m_NumberOfVertice(0)
00039 , m_NumberOfNormals(0)
00040 , m_ColorPearVertex(false)
00041 , m_MeshData()
00042 , m_CurrentLod(0)
00043 {
00044
00045 }
00046
00047 GLC_Mesh::GLC_Mesh(const GLC_Mesh& mesh)
00048 :GLC_Geometry(mesh)
00049 , m_NextPrimitiveLocalId(mesh.m_NextPrimitiveLocalId)
00050 , m_PrimitiveGroups(mesh.m_PrimitiveGroups)
00051 , m_DefaultMaterialId(mesh.m_DefaultMaterialId)
00052 , m_NumberOfVertice(mesh.m_NumberOfVertice)
00053 , m_NumberOfNormals(mesh.m_NumberOfNormals)
00054 , m_ColorPearVertex(mesh.m_ColorPearVertex)
00055 , m_MeshData(mesh.m_MeshData)
00056 , m_CurrentLod(0)
00057 {
00058
00059 PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
00060 while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
00061 {
00062 LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
00063 m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
00064
00065 LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
00066 while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
00067 {
00068 GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
00069 pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
00070
00071 ++iPrimitiveGroup;
00072 }
00073
00074 ++iPrimitiveGroups;
00075 }
00076
00077 }
00078
00079
00080 GLC_Mesh& GLC_Mesh::operator=(const GLC_Mesh& mesh)
00081 {
00082 if (this != &mesh)
00083 {
00084
00085 GLC_Geometry::operator=(mesh);
00086
00087
00088 clearMeshWireAndBoundingBox();
00089
00090
00091 m_NextPrimitiveLocalId= mesh.m_NextPrimitiveLocalId;
00092 m_PrimitiveGroups= mesh.m_PrimitiveGroups;
00093 m_DefaultMaterialId= mesh.m_DefaultMaterialId;
00094 m_NumberOfVertice= mesh.m_NumberOfVertice;
00095 m_NumberOfNormals= mesh.m_NumberOfNormals;
00096 m_ColorPearVertex= mesh.m_ColorPearVertex;
00097 m_MeshData= mesh.m_MeshData;
00098 m_CurrentLod= 0;
00099
00100
00101 PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
00102 while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
00103 {
00104 LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
00105 m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
00106
00107 LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
00108 while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
00109 {
00110 GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
00111 pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
00112
00113 ++iPrimitiveGroup;
00114 }
00115
00116 ++iPrimitiveGroups;
00117 }
00118 }
00119
00120 return *this;
00121 }
00122
00123
00124 GLC_Mesh::~GLC_Mesh()
00125 {
00126 PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00127 while (iGroups != m_PrimitiveGroups.constEnd())
00128 {
00129 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00130 while (iGroup != iGroups.value()->constEnd())
00131 {
00132 delete iGroup.value();
00133
00134 ++iGroup;
00135 }
00136 delete iGroups.value();
00137 ++iGroups;
00138 }
00139 }
00140
00142
00144
00145 quint32 GLC_Mesh::chunckID()
00146 {
00147 return m_ChunkId;
00148 }
00149
00150
00151 unsigned int GLC_Mesh::faceCount(int lod) const
00152 {
00153 return m_MeshData.trianglesCount(lod);
00154 }
00155
00156
00157 unsigned int GLC_Mesh::VertexCount() const
00158 {
00159 return m_NumberOfVertice;
00160 }
00161
00162
00163 const GLC_BoundingBox& GLC_Mesh::boundingBox()
00164 {
00165 if (NULL == m_pBoundingBox)
00166 {
00167
00168 m_pBoundingBox= new GLC_BoundingBox();
00169
00170 if (m_MeshData.positionVectorHandle()->isEmpty())
00171 {
00172 qDebug() << "GLC_ExtendedMesh::getBoundingBox empty m_Positions";
00173 }
00174 else
00175 {
00176 GLfloatVector* pVertexVector= m_MeshData.positionVectorHandle();
00177 const int max= pVertexVector->size();
00178 for (int i= 0; i < max; i= i + 3)
00179 {
00180 GLC_Vector3d vector((*pVertexVector)[i], (*pVertexVector)[i + 1], (*pVertexVector)[i + 2]);
00181 m_pBoundingBox->combine(vector);
00182 }
00183 }
00184
00185 m_pBoundingBox->combine(m_WireData.boundingBox());
00186 }
00187 return *m_pBoundingBox;
00188
00189 }
00190
00191
00192 GLC_Geometry* GLC_Mesh::clone() const
00193 {
00194 return new GLC_Mesh(*this);
00195 }
00196
00197
00198 bool GLC_Mesh::containsTriangles(int lod, GLC_uint materialId) const
00199 {
00200
00201 Q_ASSERT(m_PrimitiveGroups.contains(lod));
00202 if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00203 else return m_PrimitiveGroups.value(lod)->value(materialId)->containsTriangles();
00204 }
00205
00206
00207 QVector<GLuint> GLC_Mesh::getTrianglesIndex(int lod, GLC_uint materialId) const
00208 {
00209
00210 Q_ASSERT(containsTriangles(lod, materialId));
00211
00212 GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00213
00214 int offset= 0;
00215 if (GLC_State::vboUsed())
00216 {
00217 offset= static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->trianglesIndexOffset()) / sizeof(GLuint));
00218 }
00219 else
00220 {
00221 offset= pPrimitiveGroup->trianglesIndexOffseti();
00222 }
00223 const int size= pPrimitiveGroup->trianglesIndexSize();
00224
00225 QVector<GLuint> resultIndex(size);
00226
00227 memcpy((void*)resultIndex.data(), &(m_MeshData.indexVector(lod).data())[offset], size * sizeof(GLuint));
00228
00229 return resultIndex;
00230 }
00231
00232
00233 int GLC_Mesh::numberOfTriangles(int lod, GLC_uint materialId) const
00234 {
00235
00236 if (!m_PrimitiveGroups.contains(lod))return 0;
00237 else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00238 else return m_PrimitiveGroups.value(lod)->value(materialId)->trianglesIndexSize();
00239 }
00240
00241
00242 bool GLC_Mesh::containsStrips(int lod, GLC_uint materialId) const
00243 {
00244
00245 if (!m_PrimitiveGroups.contains(lod))return false;
00246 else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00247 else return m_PrimitiveGroups.value(lod)->value(materialId)->containsStrip();
00248
00249 }
00250
00251
00252 QList<QVector<GLuint> > GLC_Mesh::getStripsIndex(int lod, GLC_uint materialId) const
00253 {
00254
00255 Q_ASSERT(containsStrips(lod, materialId));
00256
00257 GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00258
00259 QList<int> offsets;
00260 QList<int> sizes;
00261 int stripsCount;
00262
00263 if (GLC_State::vboUsed())
00264 {
00265 stripsCount= pPrimitiveGroup->stripsOffset().size();
00266 for (int i= 0; i < stripsCount; ++i)
00267 {
00268 offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->stripsOffset().at(i)) / sizeof(GLuint)));
00269 sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
00270 }
00271 }
00272 else
00273 {
00274 stripsCount= pPrimitiveGroup->stripsOffseti().size();
00275 for (int i= 0; i < stripsCount; ++i)
00276 {
00277 offsets.append(static_cast<int>(pPrimitiveGroup->stripsOffseti().at(i)));
00278 sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
00279 }
00280
00281 }
00282
00283 QList<QVector<GLuint> > result;
00284
00285 QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
00286 for (int i= 0; i < stripsCount; ++i)
00287 {
00288 QVector<GLuint> currentStrip(sizes.at(i));
00289 memcpy((void*)currentStrip.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
00290 result.append(currentStrip);
00291 }
00292
00293 return result;
00294 }
00295
00296
00297 int GLC_Mesh::numberOfStrips(int lod, GLC_uint materialId) const
00298 {
00299
00300 if (!m_PrimitiveGroups.contains(lod))return 0;
00301 else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00302 else return m_PrimitiveGroups.value(lod)->value(materialId)->stripsSizes().size();
00303 }
00304
00305
00306 bool GLC_Mesh::containsFans(int lod, GLC_uint materialId) const
00307 {
00308
00309 if (!m_PrimitiveGroups.contains(lod))return false;
00310 else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00311 else return m_PrimitiveGroups.value(lod)->value(materialId)->containsFan();
00312
00313 }
00314
00316 int GLC_Mesh::numberOfFans(int lod, GLC_uint materialId) const
00317 {
00318
00319 if(!m_PrimitiveGroups.contains(lod))return 0;
00320 else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00321 else return m_PrimitiveGroups.value(lod)->value(materialId)->fansSizes().size();
00322 }
00323
00324
00325 QList<QVector<GLuint> > GLC_Mesh::getFansIndex(int lod, GLC_uint materialId) const
00326 {
00327
00328 Q_ASSERT(containsFans(lod, materialId));
00329
00330 GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00331
00332 QList<int> offsets;
00333 QList<int> sizes;
00334 int fansCount;
00335
00336 if (GLC_State::vboUsed())
00337 {
00338 fansCount= pPrimitiveGroup->fansOffset().size();
00339 for (int i= 0; i < fansCount; ++i)
00340 {
00341 offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->fansOffset().at(i)) / sizeof(GLuint)));
00342 sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
00343 }
00344 }
00345 else
00346 {
00347 fansCount= pPrimitiveGroup->fansOffseti().size();
00348 for (int i= 0; i < fansCount; ++i)
00349 {
00350 offsets.append(static_cast<int>(pPrimitiveGroup->fansOffseti().at(i)));
00351 sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
00352 }
00353
00354 }
00355
00356 QList<QVector<GLuint> > result;
00357
00358 QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
00359 for (int i= 0; i < fansCount; ++i)
00360 {
00361 QVector<GLuint> currentFan(sizes.at(i));
00362 memcpy((void*)currentFan.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
00363 result.append(currentFan);
00364 }
00365
00366 return result;
00367 }
00368
00370
00372
00373
00374 void GLC_Mesh::clear()
00375 {
00376
00377 clearMeshWireAndBoundingBox();
00378
00379
00380 GLC_Geometry::clear();
00381 }
00382
00383
00384
00385 void GLC_Mesh::clearMeshWireAndBoundingBox()
00386 {
00387
00388 m_NextPrimitiveLocalId= 1;
00389
00390
00391 PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00392 while (iGroups != m_PrimitiveGroups.constEnd())
00393 {
00394 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00395 while (iGroup != iGroups.value()->constEnd())
00396 {
00397 delete iGroup.value();
00398
00399 ++iGroup;
00400 }
00401 delete iGroups.value();
00402 ++iGroups;
00403 }
00404 m_PrimitiveGroups.clear();
00405
00406 m_DefaultMaterialId= 0;
00407 m_NumberOfVertice= 0;
00408 m_NumberOfNormals= 0;
00409 m_IsSelected= false;
00410 m_ColorPearVertex= false;
00411
00412 m_MeshData.clear();
00413 m_CurrentLod= 0;
00414
00415 GLC_Geometry::clearWireAndBoundingBox();
00416 }
00417
00418
00419 GLC_uint GLC_Mesh::addTriangles(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00420 {
00421 GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00422 Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00423 Q_ASSERT(!indexList.isEmpty());
00424
00425 GLC_uint id= 0;
00426 if (0 == lod)
00427 {
00428 id= m_NextPrimitiveLocalId++;
00429 }
00430 m_MeshData.trianglesAdded(lod, indexList.size() / 3);
00431
00432 m_PrimitiveGroups.value(lod)->value(groupId)->addTriangles(indexList, id);
00433
00434
00435 m_GeometryIsValid = false;
00436
00437 return id;
00438 }
00439
00440
00441 GLC_uint GLC_Mesh::addTrianglesStrip(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00442 {
00443 GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00444 Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00445 Q_ASSERT(!indexList.isEmpty());
00446
00447 GLC_uint id= 0;
00448 if (0 == lod)
00449 {
00450 id= m_NextPrimitiveLocalId++;
00451 }
00452 m_MeshData.trianglesAdded(lod, indexList.size() - 2);
00453
00454 m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesStrip(indexList, id);
00455
00456
00457 m_GeometryIsValid = false;
00458
00459 return id;
00460 }
00461
00462 GLC_uint GLC_Mesh::addTrianglesFan(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00463 {
00464 GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00465 Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00466 Q_ASSERT(!indexList.isEmpty());
00467
00468 GLC_uint id= 0;
00469 if (0 == lod)
00470 {
00471 id= m_NextPrimitiveLocalId++;
00472 }
00473 m_MeshData.trianglesAdded(lod, indexList.size() - 2);
00474 m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesFan(indexList, id);
00475
00476
00477 m_GeometryIsValid = false;
00478
00479 return id;
00480 }
00481
00482
00483 void GLC_Mesh::reverseNormals()
00484 {
00485 GLfloatVector* pNormalVector= m_MeshData.normalVectorHandle();
00486 if (pNormalVector->isEmpty())
00487 {
00488 (*m_MeshData.normalVectorHandle())= m_MeshData.normalVector();
00489 }
00490 const int size= pNormalVector->size();
00491 for (int i= 0; i < size; ++i)
00492 {
00493 (*pNormalVector)[i]= - pNormalVector->at(i);
00494 }
00495
00496 m_GeometryIsValid = false;
00497 }
00498
00499
00500 void GLC_Mesh::finish()
00501 {
00502 boundingBox();
00503
00504 m_MeshData.finishLod();
00505
00506 if (GLC_State::vboUsed())
00507 {
00508 finishVbo();
00509 }
00510 else
00511 {
00512 finishNonVbo();
00513 }
00514
00515
00516 }
00517
00518
00519
00520 void GLC_Mesh::setCurrentLod(const int value)
00521 {
00522 if (value)
00523 {
00524 const int numberOfLod= m_MeshData.lodCount() - 1;
00525
00526 m_CurrentLod= qRound(static_cast<int>((static_cast<double>(value) / 100.0) * numberOfLod));
00527 }
00528 else
00529 {
00530 m_CurrentLod= 0;
00531 }
00532 }
00533
00534 void GLC_Mesh::replaceMasterMaterial(GLC_Material* pMat)
00535 {
00536 if (hasMaterial())
00537 {
00538 GLC_uint oldId= firstMaterial()->id();
00539 replaceMaterial(oldId, pMat);
00540 }
00541 else
00542 {
00543 addMaterial(pMat);
00544 }
00545 }
00546
00547
00548 void GLC_Mesh::replaceMaterial(const GLC_uint oldId, GLC_Material* pMat)
00549 {
00550 Q_ASSERT(containsMaterial(oldId));
00551 Q_ASSERT(!containsMaterial(pMat->id()) || (pMat->id() == oldId));
00552
00553 if (pMat->id() != oldId)
00554 {
00555
00556 PrimitiveGroupsHash::const_iterator iGroups= m_PrimitiveGroups.constBegin();
00557 while (m_PrimitiveGroups.constEnd() != iGroups)
00558 {
00559 LodPrimitiveGroups* pPrimitiveGroups= iGroups.value();
00560
00561 LodPrimitiveGroups::iterator iGroup= pPrimitiveGroups->begin();
00562 while (pPrimitiveGroups->constEnd() != iGroup)
00563 {
00564 if (iGroup.key() == oldId)
00565 {
00566 GLC_PrimitiveGroup* pGroup= iGroup.value();
00567
00568 pPrimitiveGroups->erase(iGroup);
00569
00570 pGroup->setId(pMat->id());
00571
00572 pPrimitiveGroups->insert(pMat->id(), pGroup);
00573 iGroup= pPrimitiveGroups->end();
00574 }
00575 else
00576 {
00577 ++iGroup;
00578 }
00579 }
00580 ++iGroups;
00581 }
00582 }
00583
00584 if (pMat != m_MaterialHash.value(oldId))
00585 {
00586
00587 removeMaterial(oldId);
00588
00589 addMaterial(pMat);
00590 }
00591
00592 }
00593
00594 void GLC_Mesh::copyVboToClientSide()
00595 {
00596 m_MeshData.copyVboToClientSide();
00597 GLC_Geometry::copyVboToClientSide();
00598 }
00599
00600 void GLC_Mesh::releaseVboClientSide(bool update)
00601 {
00602 m_MeshData.releaseVboClientSide(update);
00603 GLC_Geometry::releaseVboClientSide(update);
00604 }
00605
00606
00607 void GLC_Mesh::loadFromDataStream(QDataStream& stream, const MaterialHash& materialHash, const QHash<GLC_uint, GLC_uint>& materialIdMap)
00608 {
00609 quint32 chunckId;
00610 stream >> chunckId;
00611 Q_ASSERT(chunckId == m_ChunkId);
00612
00613
00614 QString meshName;
00615 stream >> meshName;
00616 setName(meshName);
00617
00618
00619 stream >> GLC_Geometry::m_WireData;
00620
00621
00622 GLC_uint localId;
00623 stream >> localId;
00624 setNextPrimitiveLocalId(localId);
00625
00626
00627 stream >> m_MeshData;
00628
00629
00630 QList<int> primitiveGroupLodList;
00631 stream >> primitiveGroupLodList;
00632
00633
00634 QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
00635 stream >> primitiveListOfGroupList;
00636
00637
00638 const int lodCount= primitiveGroupLodList.size();
00639 for (int i= 0; i < lodCount; ++i)
00640 {
00641 GLC_Mesh::LodPrimitiveGroups* pCurrentPrimitiveGroup= new GLC_Mesh::LodPrimitiveGroups();
00642 m_PrimitiveGroups.insert(primitiveGroupLodList.at(i), pCurrentPrimitiveGroup);
00643 const int groupCount= primitiveListOfGroupList.at(i).size();
00644 for (int iGroup= 0; iGroup < groupCount; ++iGroup)
00645 {
00646 Q_ASSERT(materialIdMap.contains(primitiveListOfGroupList.at(i).at(iGroup).id()));
00647 const GLC_uint newId= materialIdMap.value(primitiveListOfGroupList.at(i).at(iGroup).id());
00648
00649 if (!containsMaterial(newId))
00650 {
00651 addMaterial(materialHash.value(newId));
00652 }
00653 GLC_PrimitiveGroup* pGroup= new GLC_PrimitiveGroup(primitiveListOfGroupList.at(i).at(iGroup), newId);
00654
00655 Q_ASSERT(! m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->contains(newId));
00656 m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->insert(newId, pGroup);
00657 }
00658 }
00659 stream >> m_NumberOfVertice;
00660 stream >> m_NumberOfNormals;
00661
00662 finishSerialized();
00663
00664 }
00665
00666
00667 void GLC_Mesh::saveToDataStream(QDataStream& stream) const
00668 {
00669 quint32 chunckId= m_ChunkId;
00670 stream << chunckId;
00671
00672
00673 stream << name();
00674
00675
00676 stream << m_WireData;
00677
00678
00679 stream << nextPrimitiveLocalId();
00680
00681
00682 stream << m_MeshData;
00683
00684
00685 QList<int> primitiveGroupLodList;
00686 QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
00687
00688 GLC_Mesh::PrimitiveGroupsHash::const_iterator iGroupsHash= m_PrimitiveGroups.constBegin();
00689 while (m_PrimitiveGroups.constEnd() != iGroupsHash)
00690 {
00691 primitiveGroupLodList.append(iGroupsHash.key());
00692 QList<GLC_PrimitiveGroup> primitiveGroupList;
00693 GLC_Mesh::LodPrimitiveGroups::const_iterator iGroups= iGroupsHash.value()->constBegin();
00694 while (iGroupsHash.value()->constEnd() != iGroups)
00695 {
00696 primitiveGroupList.append(*(iGroups.value()));
00697 ++iGroups;
00698 }
00699 primitiveListOfGroupList.append(primitiveGroupList);
00700 ++iGroupsHash;
00701 }
00702 stream << primitiveGroupLodList;
00703 stream << primitiveListOfGroupList;
00704
00705 stream << m_NumberOfVertice;
00706 stream << m_NumberOfNormals;
00707 }
00708
00710
00712
00713
00714 void GLC_Mesh::glDraw(const GLC_RenderProperties& renderProperties)
00715 {
00716 Q_ASSERT(m_GeometryIsValid || !m_MeshData.normalVectorHandle()->isEmpty());
00717
00718 const bool vboIsUsed= GLC_State::vboUsed();
00719
00720 if (m_IsSelected && (renderProperties.renderingMode() == glc::PrimitiveSelected) && !GLC_State::isInSelectionMode()
00721 && !renderProperties.setOfSelectedPrimitiveIdIsEmpty())
00722 {
00723 m_CurrentLod= 0;
00724 }
00725
00726 if (vboIsUsed)
00727 {
00728 m_MeshData.createVBOs();
00729
00730
00731 if (!m_GeometryIsValid && !m_MeshData.positionVectorHandle()->isEmpty())
00732 {
00733 fillVbosAndIbos();
00734 }
00735 else if (!m_GeometryIsValid && !m_MeshData.normalVectorHandle()->isEmpty())
00736 {
00737
00738 m_MeshData.useVBO(true, GLC_MeshData::GLC_Normal);
00739
00740 GLfloatVector* pNormalVector= m_MeshData.normalVectorHandle();
00741 const GLsizei dataNbr= static_cast<GLsizei>(pNormalVector->size());
00742 const GLsizeiptr dataSize= dataNbr * sizeof(GLfloat);
00743 glBufferData(GL_ARRAY_BUFFER, dataSize, pNormalVector->data(), GL_STATIC_DRAW);
00744 m_MeshData.normalVectorHandle()->clear();
00745 }
00746
00747
00748 activateVboAndIbo();
00749 }
00750 else
00751 {
00752 activateVertexArray();
00753 }
00754
00755 if (GLC_State::isInSelectionMode())
00756 {
00757 if (renderProperties.renderingMode() == glc::PrimitiveSelection)
00758 {
00759 primitiveSelectionRenderLoop(vboIsUsed);
00760 }
00761 else if (renderProperties.renderingMode() == glc::BodySelection)
00762 {
00763 bodySelectionRenderLoop(vboIsUsed);
00764 }
00765 else
00766 {
00767 normalRenderLoop(renderProperties, vboIsUsed);
00768 }
00769 }
00770 else if (m_IsSelected)
00771 {
00772 if (renderProperties.renderingMode() == glc::PrimitiveSelected)
00773 {
00774 if (!renderProperties.setOfSelectedPrimitiveIdIsEmpty())
00775 {
00776 primitiveSelectedRenderLoop(renderProperties, vboIsUsed);
00777 }
00778 else
00779 {
00780 m_IsSelected= false;
00781 if ((m_CurrentLod == 0) && (renderProperties.savedRenderingMode() == glc::OverwritePrimitiveMaterial) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
00782 primitiveRenderLoop(renderProperties, vboIsUsed);
00783 else
00784 normalRenderLoop(renderProperties, vboIsUsed);
00785 m_IsSelected= true;
00786 }
00787 }
00788 else
00789 {
00790 normalRenderLoop(renderProperties, vboIsUsed);
00791 }
00792 }
00793 else
00794 {
00795
00796 switch (renderProperties.renderingMode())
00797 {
00798 case glc::NormalRenderMode:
00799 normalRenderLoop(renderProperties, vboIsUsed);
00800 break;
00801 case glc::OverwriteMaterial:
00802 OverwriteMaterialRenderLoop(renderProperties, vboIsUsed);
00803 break;
00804 case glc::OverwriteTransparency:
00805 OverwriteTransparencyRenderLoop(renderProperties, vboIsUsed);
00806 break;
00807 case glc::OverwritePrimitiveMaterial:
00808 if ((m_CurrentLod == 0) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
00809 primitiveRenderLoop(renderProperties, vboIsUsed);
00810 else
00811 normalRenderLoop(renderProperties, vboIsUsed);
00812 break;
00813 default:
00814 Q_ASSERT(false);
00815 break;
00816 }
00817 }
00818
00819
00820
00821 if (vboIsUsed)
00822 {
00823 m_MeshData.useIBO(false);
00824 m_MeshData.useVBO(false, GLC_MeshData::GLC_Normal);
00825 }
00826
00827 if (m_ColorPearVertex && !m_IsSelected && !GLC_State::isInSelectionMode())
00828 {
00829 glDisableClientState(GL_COLOR_ARRAY);
00830 glDisable(GL_COLOR_MATERIAL);
00831 }
00832
00833 glDisableClientState(GL_VERTEX_ARRAY);
00834 glDisableClientState(GL_NORMAL_ARRAY);
00835 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00836
00837
00838 if ((renderProperties.renderingFlag() == glc::WireRenderFlag) && !m_WireData.isEmpty() && !GLC_Geometry::typeIsWire())
00839 {
00840 if (!GLC_State::isInSelectionMode())
00841 {
00842 glDisable(GL_LIGHTING);
00843
00844 GLfloat color[4]= {static_cast<float>(m_WireColor.redF()),
00845 static_cast<float>(m_WireColor.greenF()),
00846 static_cast<float>(m_WireColor.blueF()),
00847 static_cast<float>(m_WireColor.alphaF())};
00848
00849 glColor4fv(color);
00850 m_WireData.glDraw(renderProperties);
00851 glEnable(GL_LIGHTING);
00852 }
00853 else
00854 {
00855 m_WireData.glDraw(renderProperties);
00856 }
00857 }
00858
00859
00860 GLC_RenderStatistics::addBodies(1);
00861 GLC_RenderStatistics::addTriangles(m_MeshData.trianglesCount(m_CurrentLod));
00862 }
00863
00865
00867
00868
00869 GLC_uint GLC_Mesh::setCurrentMaterial(GLC_Material* pMaterial, int lod, double accuracy)
00870 {
00871
00872
00873 if (!m_PrimitiveGroups.contains(lod))
00874 {
00875 m_PrimitiveGroups.insert(lod, new LodPrimitiveGroups());
00876
00877 m_MeshData.appendLod(accuracy);
00878 }
00879
00880 GLC_uint returnId;
00881 if (NULL == pMaterial)
00882 {
00883 returnId= m_DefaultMaterialId;
00884
00885
00886 if (m_DefaultMaterialId == 0)
00887 {
00888 pMaterial= new GLC_Material();
00889
00890 addMaterial(pMaterial);
00891 m_DefaultMaterialId= pMaterial->id();
00892 returnId= m_DefaultMaterialId;
00893
00894 }
00895
00896 if (!m_PrimitiveGroups.value(lod)->contains(returnId))
00897 {
00898 m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
00899 }
00900 }
00901 else
00902 {
00903 returnId= pMaterial->id();
00904
00905 if (!containsMaterial(returnId))
00906 {
00907
00908 addMaterial(pMaterial);
00909 m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
00910
00911 }
00912 else if (!m_PrimitiveGroups.value(lod)->contains(returnId))
00913 {
00914
00915 m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
00916 }
00917 }
00918
00919 return returnId;
00920 }
00921
00922
00923 void GLC_Mesh::fillVbosAndIbos()
00924 {
00925
00926 m_MeshData.fillVbo(GLC_MeshData::GLC_Vertex);
00927
00928
00929 m_MeshData.fillVbo(GLC_MeshData::GLC_Normal);
00930
00931
00932 m_MeshData.fillVbo(GLC_MeshData::GLC_Texel);
00933
00934
00935 m_MeshData.fillVbo(GLC_MeshData::GLC_Color);
00936
00937 const int lodNumber= m_MeshData.lodCount();
00938 for (int i= 0; i < lodNumber; ++i)
00939 {
00940
00941 if (!m_MeshData.indexVectorHandle(i)->isEmpty())
00942 {
00943 QVector<GLuint>* pIndexVector= m_MeshData.indexVectorHandle(i);
00944 m_MeshData.useIBO(true, i);
00945 const GLsizei indexNbr= static_cast<GLsizei>(pIndexVector->size());
00946 const GLsizeiptr indexSize = indexNbr * sizeof(GLuint);
00947 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexSize, pIndexVector->data(), GL_STATIC_DRAW);
00948 }
00949 }
00950
00951 m_MeshData.finishVbo();
00952
00953 }
00954
00955 void GLC_Mesh::finishSerialized()
00956 {
00957 if (GLC_State::vboUsed())
00958 {
00959 PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00960 while (iGroups != m_PrimitiveGroups.constEnd())
00961 {
00962 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00963 while (iGroup != iGroups.value()->constEnd())
00964 {
00965 iGroup.value()->changeToVboMode();
00966 ++iGroup;
00967 }
00968 ++iGroups;
00969 }
00970 }
00971 }
00972
00973
00974 void GLC_Mesh::finishVbo()
00975 {
00976 PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00977 while (iGroups != m_PrimitiveGroups.constEnd())
00978 {
00979 int currentLod= iGroups.key();
00980 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00981 while (iGroup != iGroups.value()->constEnd())
00982 {
00983
00984 if (iGroup.value()->containsTriangles())
00985 {
00986 iGroup.value()->setTrianglesOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
00987 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
00988 }
00989
00990
00991 if (iGroup.value()->containsStrip())
00992 {
00993 iGroup.value()->setBaseTrianglesStripOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
00994 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
00995 }
00996
00997
00998 if (iGroup.value()->containsFan())
00999 {
01000 iGroup.value()->setBaseTrianglesFanOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
01001 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
01002 }
01003
01004 iGroup.value()->finish();
01005 ++iGroup;
01006 }
01007 ++iGroups;
01008
01009 }
01010 }
01011
01012
01013 void GLC_Mesh::finishNonVbo()
01014 {
01015
01016 PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
01017 while (iGroups != m_PrimitiveGroups.constEnd())
01018 {
01019 int currentLod= iGroups.key();
01020 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
01021 while (iGroup != iGroups.value()->constEnd())
01022 {
01023
01024 if (iGroup.value()->containsTriangles())
01025 {
01026 iGroup.value()->setTrianglesOffseti(m_MeshData.indexVectorSize(currentLod));
01027 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
01028 }
01029
01030
01031 if (iGroup.value()->containsStrip())
01032 {
01033 iGroup.value()->setBaseTrianglesStripOffseti(m_MeshData.indexVectorSize(currentLod));
01034 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
01035 }
01036
01037
01038 if (iGroup.value()->containsFan())
01039 {
01040 iGroup.value()->setBaseTrianglesFanOffseti(m_MeshData.indexVectorSize(currentLod));
01041 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
01042 }
01043
01044 iGroup.value()->finish();
01045 ++iGroup;
01046 }
01047 ++iGroups;
01048 }
01049 }
01050
01051
01052 void GLC_Mesh::normalRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01053 {
01054 const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01055 if ((!m_IsSelected || !isTransparent) || GLC_State::isInSelectionMode())
01056 {
01057 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01058 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01059 {
01060 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01061 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01062
01063
01064 bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01065
01066
01067 if ((materialIsrenderable || m_IsSelected) && !GLC_State::isInSelectionMode())
01068 {
01069
01070 pCurrentMaterial->glExecute();
01071
01072 if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01073 }
01074
01075
01076 if (m_IsSelected || GLC_State::isInSelectionMode() || materialIsrenderable)
01077 {
01078
01079 if (vboIsUsed)
01080 vboDrawPrimitivesOf(pCurrentGroup);
01081 else
01082 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01083 }
01084
01085 ++iGroup;
01086 }
01087 }
01088 }
01089
01090
01091 void GLC_Mesh::OverwriteMaterialRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01092 {
01093
01094 GLC_Material* pOverwriteMaterial= renderProperties.overwriteMaterial();
01095 Q_ASSERT(NULL != pOverwriteMaterial);
01096 pOverwriteMaterial->glExecute();
01097 if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01098
01099 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01100 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01101 {
01102 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01103
01104
01105 bool materialIsrenderable = (pOverwriteMaterial->isTransparent() == (renderProperties.renderingFlag() == glc::TransparentRenderFlag));
01106
01107
01108 if (m_IsSelected || materialIsrenderable)
01109 {
01110
01111 if (vboIsUsed)
01112 vboDrawPrimitivesOf(pCurrentGroup);
01113 else
01114 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01115 }
01116
01117 ++iGroup;
01118 }
01119 }
01120
01121 void GLC_Mesh::OverwriteTransparencyRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01122 {
01123
01124 const float alpha= renderProperties.overwriteTransparency();
01125 Q_ASSERT(-1.0f != alpha);
01126
01127
01128 bool materialIsrenderable = (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01129
01130 if (materialIsrenderable || m_IsSelected)
01131 {
01132 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01133 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01134 {
01135 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01136 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01137
01138
01139 pCurrentMaterial->glExecute(alpha);
01140
01141 if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01142
01143
01144 if (m_IsSelected || materialIsrenderable)
01145 {
01146
01147 if (vboIsUsed)
01148 vboDrawPrimitivesOf(pCurrentGroup);
01149 else
01150 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01151 }
01152 ++iGroup;
01153 }
01154 }
01155 }
01156
01157
01158 void GLC_Mesh::bodySelectionRenderLoop(bool vboIsUsed)
01159 {
01160 Q_ASSERT(GLC_State::isInSelectionMode());
01161
01162 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01163 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01164 {
01165 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01166
01167 if (vboIsUsed)
01168 vboDrawPrimitivesOf(pCurrentGroup);
01169 else
01170 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01171
01172 ++iGroup;
01173 }
01174 }
01175
01176
01177 void GLC_Mesh::primitiveSelectionRenderLoop(bool vboIsUsed)
01178 {
01179 Q_ASSERT(GLC_State::isInSelectionMode());
01180
01181 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01182
01183 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01184 {
01185 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01186
01187 if (vboIsUsed)
01188 vboDrawInSelectionModePrimitivesOf(pCurrentGroup);
01189 else
01190 vertexArrayDrawInSelectionModePrimitivesOf(pCurrentGroup);
01191
01192 ++iGroup;
01193 }
01194 }
01195
01196
01197 void GLC_Mesh::primitiveRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01198 {
01199 const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01200 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01201 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01202 {
01203 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01204 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01205
01206
01207 const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01208
01209 if (materialIsrenderable)
01210 {
01211 pCurrentMaterial->glExecute();
01212 }
01213 if (vboIsUsed)
01214 vboDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
01215 else
01216 vertexArrayDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
01217
01218 ++iGroup;
01219 }
01220 }
01221
01222
01223 void GLC_Mesh::primitiveSelectedRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01224 {
01225 const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01226 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01227 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01228 {
01229 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01230 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01231
01232
01233 const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01234
01235 if (materialIsrenderable)
01236 {
01237 pCurrentMaterial->glExecute();
01238 }
01239
01240 if (vboIsUsed)
01241 vboDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
01242 else
01243 vertexArrayDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
01244
01245 ++iGroup;
01246 }
01247 }
01248