glc_mesh.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 
00003  This file is part of the GLC-lib library.
00004  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
00005  http://glc-lib.sourceforge.net
00006 
00007  GLC-lib is free software; you can redistribute it and/or modify
00008  it under the terms of the GNU Lesser General Public License as published by
00009  the Free Software Foundation; either version 3 of the License, or
00010  (at your option) any later version.
00011 
00012  GLC-lib is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU Lesser General Public License for more details.
00016 
00017  You should have received a copy of the GNU Lesser General Public License
00018  along with GLC-lib; if not, write to the Free Software
00019  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021 *****************************************************************************/
00022 
00024 
00025 #include "glc_mesh.h"
00026 #include "../glc_renderstatistics.h"
00027 #include "../glc_context.h"
00028 
00029 // Class chunk id
00030 quint32 GLC_Mesh::m_ChunkId= 0xA701;
00031 
00032 GLC_Mesh::GLC_Mesh()
00033 :GLC_Geometry("Mesh", false)
00034 , m_NextPrimitiveLocalId(1)
00035 , m_PrimitiveGroups()
00036 , m_DefaultMaterialId(0)
00037 , m_NumberOfVertice(0)
00038 , m_NumberOfNormals(0)
00039 , m_ColorPearVertex(false)
00040 , m_MeshData()
00041 , m_CurrentLod(0)
00042 {
00043 
00044 }
00045 
00046 GLC_Mesh::GLC_Mesh(const GLC_Mesh& mesh)
00047 :GLC_Geometry(mesh)
00048 , m_NextPrimitiveLocalId(mesh.m_NextPrimitiveLocalId)
00049 , m_PrimitiveGroups(mesh.m_PrimitiveGroups)
00050 , m_DefaultMaterialId(mesh.m_DefaultMaterialId)
00051 , m_NumberOfVertice(mesh.m_NumberOfVertice)
00052 , m_NumberOfNormals(mesh.m_NumberOfNormals)
00053 , m_ColorPearVertex(mesh.m_ColorPearVertex)
00054 , m_MeshData(mesh.m_MeshData)
00055 , m_CurrentLod(0)
00056 {
00057         // Make a copy of m_PrimitiveGroups with new material id
00058         PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
00059         while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
00060         {
00061                 LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
00062                 m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
00063 
00064                 LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
00065                 while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
00066                 {
00067                         GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
00068                         pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
00069 
00070                         ++iPrimitiveGroup;
00071                 }
00072 
00073                 ++iPrimitiveGroups;
00074         }
00075 
00076 }
00077 
00078 // Overload "=" operator
00079 GLC_Mesh& GLC_Mesh::operator=(const GLC_Mesh& mesh)
00080 {
00081         if (this != &mesh)
00082         {
00083                 // Call the operator of the super class
00084                 GLC_Geometry::operator=(mesh);
00085 
00086                 // Clear the mesh
00087                 clearMeshWireAndBoundingBox();
00088 
00089                 // Copy members
00090                 m_NextPrimitiveLocalId= mesh.m_NextPrimitiveLocalId;
00091                 m_PrimitiveGroups= mesh.m_PrimitiveGroups;
00092                 m_DefaultMaterialId= mesh.m_DefaultMaterialId;
00093                 m_NumberOfVertice= mesh.m_NumberOfVertice;
00094                 m_NumberOfNormals= mesh.m_NumberOfNormals;
00095                 m_ColorPearVertex= mesh.m_ColorPearVertex;
00096                 m_MeshData= mesh.m_MeshData;
00097                 m_CurrentLod= 0;
00098 
00099                 // Make a copy of m_PrimitiveGroups with new material id
00100                 PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
00101                 while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
00102                 {
00103                         LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
00104                         m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
00105 
00106                         LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
00107                         while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
00108                         {
00109                                 GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
00110                                 pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
00111 
00112                                 ++iPrimitiveGroup;
00113                         }
00114 
00115                         ++iPrimitiveGroups;
00116                 }
00117         }
00118 
00119         return *this;
00120 }
00121 
00122 // Destructor
00123 GLC_Mesh::~GLC_Mesh()
00124 {
00125         PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00126         while (iGroups != m_PrimitiveGroups.constEnd())
00127         {
00128                 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00129                 while (iGroup != iGroups.value()->constEnd())
00130                 {
00131                         delete iGroup.value();
00132 
00133                         ++iGroup;
00134                 }
00135                 delete iGroups.value();
00136                 ++iGroups;
00137         }
00138 }
00139 
00141 // Get Functions
00143 // Return the class Chunk ID
00144 quint32 GLC_Mesh::chunckID()
00145 {
00146         return m_ChunkId;
00147 }
00148 
00149 // Get number of faces
00150 unsigned int GLC_Mesh::faceCount(int lod) const
00151 {
00152         return m_MeshData.trianglesCount(lod);
00153 }
00154 
00155 // Get number of vertex
00156 unsigned int GLC_Mesh::VertexCount() const
00157 {
00158         return m_NumberOfVertice;
00159 }
00160 
00161 // return the mesh bounding box
00162 const GLC_BoundingBox& GLC_Mesh::boundingBox()
00163 {
00164         if (NULL == m_pBoundingBox)
00165         {
00166                 //qDebug() << "GLC_Mesh2::boundingBox create boundingBox";
00167                 m_pBoundingBox= new GLC_BoundingBox();
00168 
00169                 if (m_MeshData.positionVectorHandle()->isEmpty())
00170                 {
00171                         qDebug() << "GLC_Mesh::boundingBox empty m_Positions";
00172                 }
00173                 else
00174                 {
00175                         GLfloatVector* pVertexVector= m_MeshData.positionVectorHandle();
00176                         const int max= pVertexVector->size();
00177                         for (int i= 0; i < max; i= i + 3)
00178                         {
00179                                 GLC_Vector3d vector((*pVertexVector)[i], (*pVertexVector)[i + 1], (*pVertexVector)[i + 2]);
00180                                 m_pBoundingBox->combine(vector);
00181                         }
00182                 }
00183                 // Combine with the wiredata bounding box
00184                 m_pBoundingBox->combine(m_WireData.boundingBox());
00185         }
00186         return *m_pBoundingBox;
00187 
00188 }
00189 
00190 // Return a copy of the Mesh as GLC_Geometry pointer
00191 GLC_Geometry* GLC_Mesh::clone() const
00192 {
00193         return new GLC_Mesh(*this);
00194 }
00195 
00196 // Return true if the mesh contains triangles
00197 bool GLC_Mesh::containsTriangles(int lod, GLC_uint materialId) const
00198 {
00199         // Check if the lod exist and material exists
00200         Q_ASSERT(m_PrimitiveGroups.contains(lod));
00201         if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00202         else return m_PrimitiveGroups.value(lod)->value(materialId)->containsTriangles();
00203 }
00204 
00205 // Return the specified index
00206 QVector<GLuint> GLC_Mesh::getTrianglesIndex(int lod, GLC_uint materialId) const
00207 {
00208         // Check if the mesh contains triangles
00209         Q_ASSERT(containsTriangles(lod, materialId));
00210 
00211         GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00212 
00213         int offset= 0;
00214         if (vboIsUsed())
00215         {
00216                 offset= static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->trianglesIndexOffset()) / sizeof(GLuint));
00217         }
00218         else
00219         {
00220                 offset= pPrimitiveGroup->trianglesIndexOffseti();
00221         }
00222         const int size= pPrimitiveGroup->trianglesIndexSize();
00223 
00224         QVector<GLuint> resultIndex(size);
00225 
00226         memcpy((void*)resultIndex.data(), &(m_MeshData.indexVector(lod).data())[offset], size * sizeof(GLuint));
00227 
00228         return resultIndex;
00229 }
00230 
00231 // Return the number of triangles
00232 int GLC_Mesh::numberOfTriangles(int lod, GLC_uint materialId) const
00233 {
00234         // Check if the lod exist and material exists
00235         if (!m_PrimitiveGroups.contains(lod))return 0;
00236         else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00237         else return m_PrimitiveGroups.value(lod)->value(materialId)->trianglesIndexSize();
00238 }
00239 
00240 // Return true if the mesh contains trips
00241 bool GLC_Mesh::containsStrips(int lod, GLC_uint materialId) const
00242 {
00243         // Check if the lod exist and material exists
00244         if (!m_PrimitiveGroups.contains(lod))return false;
00245         else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00246         else return m_PrimitiveGroups.value(lod)->value(materialId)->containsStrip();
00247 
00248 }
00249 
00250 // Return the strips index
00251 QList<QVector<GLuint> > GLC_Mesh::getStripsIndex(int lod, GLC_uint materialId) const
00252 {
00253         // Check if the mesh contains trips
00254         Q_ASSERT(containsStrips(lod, materialId));
00255 
00256         GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00257 
00258         QList<int> offsets;
00259         QList<int> sizes;
00260         int stripsCount;
00261 
00262         if (vboIsUsed())
00263         {
00264                 stripsCount= pPrimitiveGroup->stripsOffset().size();
00265                 for (int i= 0; i < stripsCount; ++i)
00266                 {
00267                         offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->stripsOffset().at(i)) / sizeof(GLuint)));
00268                         sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
00269                 }
00270         }
00271         else
00272         {
00273                 stripsCount= pPrimitiveGroup->stripsOffseti().size();
00274                 for (int i= 0; i < stripsCount; ++i)
00275                 {
00276                         offsets.append(static_cast<int>(pPrimitiveGroup->stripsOffseti().at(i)));
00277                         sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
00278                 }
00279 
00280         }
00281         // The result list of vector
00282         QList<QVector<GLuint> > result;
00283         // The copy of the mesh Data LOD index vector
00284         QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
00285         for (int i= 0; i < stripsCount; ++i)
00286         {
00287                 QVector<GLuint> currentStrip(sizes.at(i));
00288                 memcpy((void*)currentStrip.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
00289                 result.append(currentStrip);
00290         }
00291 
00292         return result;
00293 }
00294 
00295 // Return the number of strips
00296 int GLC_Mesh::numberOfStrips(int lod, GLC_uint materialId) const
00297 {
00298         // Check if the lod exist and material exists
00299         if (!m_PrimitiveGroups.contains(lod))return 0;
00300         else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00301         else return m_PrimitiveGroups.value(lod)->value(materialId)->stripsSizes().size();
00302 }
00303 
00304 // Return true if the mesh contains fans
00305 bool GLC_Mesh::containsFans(int lod, GLC_uint materialId) const
00306 {
00307         // Check if the lod exist and material exists
00308         if (!m_PrimitiveGroups.contains(lod))return false;
00309         else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
00310         else return m_PrimitiveGroups.value(lod)->value(materialId)->containsFan();
00311 
00312 }
00313 
00315 int GLC_Mesh::numberOfFans(int lod, GLC_uint materialId) const
00316 {
00317         // Check if the lod exist and material exists
00318         if(!m_PrimitiveGroups.contains(lod))return 0;
00319         else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
00320         else return m_PrimitiveGroups.value(lod)->value(materialId)->fansSizes().size();
00321 }
00322 
00323 // Return the strips index
00324 QList<QVector<GLuint> > GLC_Mesh::getFansIndex(int lod, GLC_uint materialId) const
00325 {
00326         // Check if the mesh contains trips
00327         Q_ASSERT(containsFans(lod, materialId));
00328 
00329         GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
00330 
00331         QList<int> offsets;
00332         QList<int> sizes;
00333         int fansCount;
00334 
00335         if (vboIsUsed())
00336         {
00337                 fansCount= pPrimitiveGroup->fansOffset().size();
00338                 for (int i= 0; i < fansCount; ++i)
00339                 {
00340                         offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->fansOffset().at(i)) / sizeof(GLuint)));
00341                         sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
00342                 }
00343         }
00344         else
00345         {
00346                 fansCount= pPrimitiveGroup->fansOffseti().size();
00347                 for (int i= 0; i < fansCount; ++i)
00348                 {
00349                         offsets.append(static_cast<int>(pPrimitiveGroup->fansOffseti().at(i)));
00350                         sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
00351                 }
00352 
00353         }
00354         // The result list of vector
00355         QList<QVector<GLuint> > result;
00356         // The copy of the mesh Data LOD index vector
00357         QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
00358         for (int i= 0; i < fansCount; ++i)
00359         {
00360                 QVector<GLuint> currentFan(sizes.at(i));
00361                 memcpy((void*)currentFan.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
00362                 result.append(currentFan);
00363         }
00364 
00365         return result;
00366 }
00367 
00368 GLC_Mesh* GLC_Mesh::createMeshOfGivenLod(int lodIndex)
00369 {
00370         Q_ASSERT(m_MeshData.lodCount() > lodIndex);
00371 
00372         copyVboToClientSide();
00373         GLC_Mesh* pLodMesh= new GLC_Mesh;
00374         pLodMesh->setName(this->name() + "-LOD-" + QString::number(lodIndex));
00375         QHash<GLuint, GLuint> sourceToTargetIndexMap;
00376         QHash<GLuint, GLuint> tagetToSourceIndexMap;
00377         int maxIndex= -1;
00378 
00379         int targetLod= 0;
00380         copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, targetLod);
00381 
00382         copyBulkData(pLodMesh, tagetToSourceIndexMap, maxIndex);
00383 
00384         pLodMesh->finish();
00385 
00386         releaseVboClientSide(false);
00387 
00388         return pLodMesh;
00389 }
00390 
00391 GLC_Mesh* GLC_Mesh::createMeshFromGivenLod(int lodIndex)
00392 {
00393         const int lodCount= m_MeshData.lodCount();
00394         Q_ASSERT(lodCount > lodIndex);
00395 
00396         copyVboToClientSide();
00397         GLC_Mesh* pLodMesh= new GLC_Mesh;
00398         pLodMesh->setName(this->name() + "-LOD-" + QString::number(lodIndex));
00399         QHash<GLuint, GLuint> sourceToTargetIndexMap;
00400         QHash<GLuint, GLuint> tagetToSourceIndexMap;
00401         int maxIndex= -1;
00402 
00403         if ((lodCount - lodIndex) > 1)
00404         {
00405                 int targetLod= 1;
00406                 for (int i= lodIndex + 1; i < lodCount; ++i)
00407                 {
00408                         copyIndex(i, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, targetLod);
00409                         ++targetLod;
00410                 }
00411                 copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, 0);
00412         }
00413         else
00414         {
00415                 copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, 0);
00416         }
00417 
00418 
00419         copyBulkData(pLodMesh, tagetToSourceIndexMap, maxIndex);
00420 
00421         pLodMesh->finish();
00422 
00423         releaseVboClientSide(false);
00424 
00425         return pLodMesh;
00426 }
00427 GLC_Mesh& GLC_Mesh::transformVertice(const GLC_Matrix4x4& matrix)
00428 {
00429         if (matrix.type() != GLC_Matrix4x4::Identity)
00430         {
00431                 delete m_pBoundingBox;
00432                 m_pBoundingBox= NULL;
00433                 copyVboToClientSide();
00434                 const int stride= 3;
00435                 GLfloatVector* pVectPos= m_MeshData.positionVectorHandle();
00436                 const GLC_Matrix4x4 rotationMatrix= matrix.rotationMatrix();
00437                 GLfloatVector* pVectNormal= m_MeshData.normalVectorHandle();
00438                 const int verticeCount= pVectPos->size() / stride;
00439                 for (int i= 0; i < verticeCount; ++i)
00440                 {
00441                         GLC_Vector3d newPos(pVectPos->at(stride * i), pVectPos->at(stride * i + 1), pVectPos->at(stride * i + 2));
00442                         newPos= matrix * newPos;
00443                         pVectPos->operator[](stride * i)= static_cast<GLfloat>(newPos.x());
00444                         pVectPos->operator[](stride * i + 1)= static_cast<GLfloat>(newPos.y());
00445                         pVectPos->operator[](stride * i + 2)= static_cast<GLfloat>(newPos.z());
00446 
00447                         GLC_Vector3d newNormal(pVectNormal->at(stride * i), pVectNormal->at(stride * i + 1), pVectNormal->at(stride * i + 2));
00448                         newNormal= rotationMatrix * newNormal;
00449                         pVectNormal->operator[](stride * i)= static_cast<GLfloat>(newNormal.x());
00450                         pVectNormal->operator[](stride * i + 1)= static_cast<GLfloat>(newNormal.y());
00451                         pVectNormal->operator[](stride * i + 2)= static_cast<GLfloat>(newNormal.z());
00452                 }
00453                 releaseVboClientSide(true);
00454         }
00455 
00456         return *this;
00457 }
00458 
00459 double GLC_Mesh::volume()
00460 {
00461         double resultVolume= 0.0;
00462 
00463         if (!m_MeshData.isEmpty())
00464         {
00465                 IndexList triangleIndex;
00466                 QList<GLC_Material*> materials= materialSet().toList();
00467                 const int materialsCount= materials.count();
00468                 for (int i= 0; i < materialsCount; ++i)
00469                 {
00470                         GLC_uint materialId= materials.at(i)->id();
00471                         if (containsTriangles(0, materialId))
00472                         {
00473                                 triangleIndex.append(getTrianglesIndex(0, materialId).toList());
00474                         }
00475                         if (containsStrips(0, materialId))
00476                         {
00477                                 triangleIndex.append(equivalentTrianglesIndexOfstripsIndex(0, materialId));
00478                         }
00479                         if (containsFans(0, materialId))
00480                         {
00481                                 triangleIndex.append(equivalentTrianglesIndexOfFansIndex(0, materialId));
00482                         }
00483                 }
00484 
00485                 GLfloatVector vertices= m_MeshData.positionVector();
00486                 Q_ASSERT((triangleIndex.count() % 3) == 0);
00487                 const int triangleCount= triangleIndex.count() / 3;
00488                 for (int i= 0; i < triangleCount; ++i)
00489                 {
00490                         const int index= i * 3;
00491                         const double v1x= vertices.at(triangleIndex.at(index) * 3);
00492                         const double v1y= vertices.at(triangleIndex.at(index) * 3 + 1);
00493                         const double v1z= vertices.at(triangleIndex.at(index) * 3 + 2);
00494 
00495                         const double v2x= vertices.at(triangleIndex.at(index + 1) * 3);
00496                         const double v2y= vertices.at(triangleIndex.at(index + 1) * 3 + 1);
00497                         const double v2z= vertices.at(triangleIndex.at(index + 1) * 3 + 2);
00498 
00499                         const double v3x= vertices.at(triangleIndex.at(index + 2) * 3);
00500                         const double v3y= vertices.at(triangleIndex.at(index + 2) * 3 + 1);
00501                         const double v3z= vertices.at(triangleIndex.at(index + 2) * 3 + 2);
00502 
00503                         resultVolume+= ((v2y - v1y) * (v3z - v1z) - (v2z - v1z) * (v3y - v1y)) * (v1x + v2x + v3x);
00504                 }
00505 
00506                 resultVolume= resultVolume / 6.0;
00507         }
00508 
00509         return resultVolume;
00510 }
00511 
00513 // Set Functions
00515 
00516 // Clear the content of the mesh and super class GLC_Geometry
00517 void GLC_Mesh::clear()
00518 {
00519         // Clear the mesh content
00520         clearMeshWireAndBoundingBox();
00521 
00522         // Clear the super class GLC_Geometry
00523         GLC_Geometry::clear();
00524 }
00525 
00526 
00527 // Clear the content off the mesh and makes it empty
00528 void GLC_Mesh::clearMeshWireAndBoundingBox()
00529 {
00530         // Reset primitive local id
00531         m_NextPrimitiveLocalId= 1;
00532 
00533         // Remove all primitive groups
00534         PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
00535         while (iGroups != m_PrimitiveGroups.constEnd())
00536         {
00537                 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
00538                 while (iGroup != iGroups.value()->constEnd())
00539                 {
00540                         delete iGroup.value();
00541 
00542                         ++iGroup;
00543                 }
00544                 delete iGroups.value();
00545                 ++iGroups;
00546         }
00547         m_PrimitiveGroups.clear();
00548 
00549         m_DefaultMaterialId= 0;
00550         m_NumberOfVertice= 0;
00551         m_NumberOfNormals= 0;
00552         m_IsSelected= false;
00553         m_ColorPearVertex= false;
00554         // Clear data of the mesh
00555         m_MeshData.clear();
00556         m_CurrentLod= 0;
00557 
00558         GLC_Geometry::clearWireAndBoundingBox();
00559 }
00560 
00561 // Add triangles
00562 GLC_uint GLC_Mesh::addTriangles(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00563 {
00564         GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00565         Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00566         Q_ASSERT(!indexList.isEmpty());
00567 
00568         GLC_uint id= 0;
00569         if (0 == lod)
00570         {
00571                 id= m_NextPrimitiveLocalId++;
00572         }
00573         m_MeshData.trianglesAdded(lod, indexList.size() / 3);
00574 
00575         m_PrimitiveGroups.value(lod)->value(groupId)->addTriangles(indexList, id);
00576 
00577         // Invalid the geometry
00578         m_GeometryIsValid = false;
00579 
00580         return id;
00581 }
00582 
00583 // Add triangles Strip ans return his id
00584 GLC_uint GLC_Mesh::addTrianglesStrip(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00585 {
00586         GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00587         Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00588         Q_ASSERT(!indexList.isEmpty());
00589 
00590         GLC_uint id= 0;
00591         if (0 == lod)
00592         {
00593                 id= m_NextPrimitiveLocalId++;
00594         }
00595         m_MeshData.trianglesAdded(lod, indexList.size() - 2);
00596 
00597         m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesStrip(indexList, id);
00598 
00599         // Invalid the geometry
00600         m_GeometryIsValid = false;
00601 
00602         return id;
00603 }
00604 // Add triangles Fan
00605 GLC_uint GLC_Mesh::addTrianglesFan(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
00606 {
00607         GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
00608         Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
00609         Q_ASSERT(!indexList.isEmpty());
00610 
00611         GLC_uint id= 0;
00612         if (0 == lod)
00613         {
00614                 id= m_NextPrimitiveLocalId++;
00615         }
00616         m_MeshData.trianglesAdded(lod, indexList.size() - 2);
00617         m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesFan(indexList, id);
00618 
00619         // Invalid the geometry
00620         m_GeometryIsValid = false;
00621 
00622         return id;
00623 }
00624 
00625 // Reverse mesh normal
00626 void GLC_Mesh::reverseNormals()
00627 {
00628         GLfloatVector* pNormalVector= m_MeshData.normalVectorHandle();
00629         if (pNormalVector->isEmpty())
00630         {
00631                 (*m_MeshData.normalVectorHandle())= m_MeshData.normalVector();
00632         }
00633         const int size= pNormalVector->size();
00634         for (int i= 0; i < size; ++i)
00635         {
00636                 (*pNormalVector)[i]= - pNormalVector->at(i);
00637         }
00638         if (vboIsUsed())
00639         {
00640                 m_MeshData.fillVbo(GLC_MeshData::GLC_Normal);
00641                 m_MeshData.useVBO(false, GLC_MeshData::GLC_Normal);
00642         }
00643 }
00644 
00645 // Copy index list in a vector for Vertex Array Use
00646 void GLC_Mesh::finish()
00647 {
00648         boundingBox();
00649 
00650         m_MeshData.finishLod();
00651 
00652         moveIndexToMeshDataLod();
00653 
00654         //qDebug() << "Mesh mem size= " << memmorySize();
00655 }
00656 
00657 
00658 // Set the lod Index
00659 void GLC_Mesh::setCurrentLod(const int value)
00660 {
00661         if (value)
00662         {
00663                 const int numberOfLod= m_MeshData.lodCount() - 1;
00664                 // Clamp value to number of load
00665                 m_CurrentLod= qRound(static_cast<int>((static_cast<double>(value) / 100.0) * numberOfLod));
00666         }
00667         else
00668         {
00669                 m_CurrentLod= 0;
00670         }
00671 }
00672 // Replace the Master material
00673 void GLC_Mesh::replaceMasterMaterial(GLC_Material* pMat)
00674 {
00675         if (hasMaterial())
00676         {
00677                 GLC_uint oldId= firstMaterial()->id();
00678                 replaceMaterial(oldId, pMat);
00679         }
00680         else
00681         {
00682                 addMaterial(pMat);
00683         }
00684 }
00685 
00686 // Replace the material specified by id with another one
00687 void GLC_Mesh::replaceMaterial(const GLC_uint oldId, GLC_Material* pMat)
00688 {
00689         Q_ASSERT(containsMaterial(oldId));
00690         Q_ASSERT(!containsMaterial(pMat->id()) || (pMat->id() == oldId));
00691 
00692         if (pMat->id() != oldId)
00693         {
00694                 // Iterate over Level of detail
00695                 PrimitiveGroupsHash::const_iterator iGroups= m_PrimitiveGroups.constBegin();
00696                 while (m_PrimitiveGroups.constEnd() != iGroups)
00697                 {
00698                         LodPrimitiveGroups* pPrimitiveGroups= iGroups.value();
00699                         // Iterate over material group
00700                         LodPrimitiveGroups::iterator iGroup= pPrimitiveGroups->begin();
00701                         while (pPrimitiveGroups->constEnd() != iGroup)
00702                         {
00703                                 if (iGroup.key() == oldId)
00704                                 {
00705                                         GLC_PrimitiveGroup* pGroup= iGroup.value();
00706                                         // Erase old group pointer
00707                                         pPrimitiveGroups->erase(iGroup);
00708                                         // Change the group ID
00709                                         pGroup->setId(pMat->id());
00710                                         // Add the group with  new ID
00711                                         pPrimitiveGroups->insert(pMat->id(), pGroup);
00712                                         iGroup= pPrimitiveGroups->end();
00713                                 }
00714                                 else
00715                                 {
00716                                         ++iGroup;
00717                                 }
00718                         }
00719                         ++iGroups;
00720                 }
00721         }
00722 
00723         if (pMat != m_MaterialHash.value(oldId))
00724         {
00725                 // Remove old material
00726                 removeMaterial(oldId);
00727 
00728                 addMaterial(pMat);
00729         }
00730 
00731 }
00732 
00733 void GLC_Mesh::copyVboToClientSide()
00734 {
00735         m_MeshData.copyVboToClientSide();
00736         GLC_Geometry::copyVboToClientSide();
00737 }
00738 
00739 void GLC_Mesh::releaseVboClientSide(bool update)
00740 {
00741         m_MeshData.releaseVboClientSide(update);
00742         GLC_Geometry::releaseVboClientSide(update);
00743 }
00744 
00745 void GLC_Mesh::setVboUsage(bool usage)
00746 {
00747         if (!isEmpty())
00748         {
00749                 GLC_Geometry::setVboUsage(usage);
00750                 m_MeshData.setVboUsage(usage);
00751         }
00752 }
00753 
00754 // Load the mesh from binary data stream
00755 void GLC_Mesh::loadFromDataStream(QDataStream& stream, const MaterialHash& materialHash, const QHash<GLC_uint, GLC_uint>& materialIdMap)
00756 {
00757         quint32 chunckId;
00758         stream >> chunckId;
00759         Q_ASSERT(chunckId == m_ChunkId);
00760 
00761         // The mesh name
00762         QString meshName;
00763         stream >> meshName;
00764         setName(meshName);
00765 
00766         // The wire data
00767         stream >> GLC_Geometry::m_WireData;
00768 
00769         // The mesh next primitive local id
00770         GLC_uint localId;
00771         stream >> localId;
00772         setNextPrimitiveLocalId(localId);
00773 
00774         // Retrieve geom mesh data
00775         stream >> m_MeshData;
00776 
00777         // Retrieve primitiveGroupLodList
00778         QList<int> primitiveGroupLodList;
00779         stream >> primitiveGroupLodList;
00780 
00781         // Retrieve primitiveGroup list
00782         QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
00783         stream >> primitiveListOfGroupList;
00784 
00785         // Construct mesh primitiveGroupHash
00786         const int lodCount= primitiveGroupLodList.size();
00787         for (int i= 0; i < lodCount; ++i)
00788         {
00789                 GLC_Mesh::LodPrimitiveGroups* pCurrentPrimitiveGroup= new GLC_Mesh::LodPrimitiveGroups();
00790                 m_PrimitiveGroups.insert(primitiveGroupLodList.at(i), pCurrentPrimitiveGroup);
00791                 const int groupCount= primitiveListOfGroupList.at(i).size();
00792                 for (int iGroup= 0; iGroup < groupCount; ++iGroup)
00793                 {
00794                         Q_ASSERT(materialIdMap.contains(primitiveListOfGroupList.at(i).at(iGroup).id()));
00795                         const GLC_uint newId= materialIdMap.value(primitiveListOfGroupList.at(i).at(iGroup).id());
00796                         // Test if the mesh contains the material
00797                         if (!containsMaterial(newId))
00798                         {
00799                                 addMaterial(materialHash.value(newId));
00800                         }
00801                         GLC_PrimitiveGroup* pGroup= new GLC_PrimitiveGroup(primitiveListOfGroupList.at(i).at(iGroup), newId);
00802 
00803                         Q_ASSERT(! m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->contains(newId));
00804                         m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->insert(newId, pGroup);
00805                 }
00806         }
00807         stream >> m_NumberOfVertice;
00808         stream >> m_NumberOfNormals;
00809 
00810         finishSerialized();
00811 }
00812 
00813 // Save the mesh to binary data stream
00814 void GLC_Mesh::saveToDataStream(QDataStream& stream) const
00815 {
00816         quint32 chunckId= m_ChunkId;
00817         stream << chunckId;
00818 
00819         // The mesh name
00820         stream << name();
00821 
00822         // The wire data
00823         stream << m_WireData;
00824 
00825         // The mesh next primitive local id
00826         stream << nextPrimitiveLocalId();
00827 
00828         // Mesh data serialisation
00829         stream << m_MeshData;
00830 
00831         // Primitive groups serialisation
00832         QList<int> primitiveGroupLodList;
00833         QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
00834 
00835         GLC_Mesh::PrimitiveGroupsHash::const_iterator iGroupsHash= m_PrimitiveGroups.constBegin();
00836         while (m_PrimitiveGroups.constEnd() != iGroupsHash)
00837         {
00838                 primitiveGroupLodList.append(iGroupsHash.key());
00839                 QList<GLC_PrimitiveGroup> primitiveGroupList;
00840                 GLC_Mesh::LodPrimitiveGroups::const_iterator iGroups= iGroupsHash.value()->constBegin();
00841                 while (iGroupsHash.value()->constEnd() != iGroups)
00842                 {
00843                         primitiveGroupList.append(*(iGroups.value()));
00844                         ++iGroups;
00845                 }
00846                 primitiveListOfGroupList.append(primitiveGroupList);
00847                 ++iGroupsHash;
00848         }
00849         stream << primitiveGroupLodList;
00850         stream << primitiveListOfGroupList;
00851 
00852         stream << m_NumberOfVertice;
00853         stream << m_NumberOfNormals;
00854 }
00855 
00857 // OpenGL Functions
00859 
00860 // Virtual interface for OpenGL Geometry set up.
00861 void GLC_Mesh::glDraw(const GLC_RenderProperties& renderProperties)
00862 {
00863 
00864         Q_ASSERT(m_GeometryIsValid || !m_MeshData.positionSizeIsSet());
00865 
00866         const bool vboIsUsed= GLC_Geometry::vboIsUsed()  && GLC_State::vboSupported();
00867 
00868         if (m_IsSelected && (renderProperties.renderingMode() == glc::PrimitiveSelected) && !GLC_State::isInSelectionMode()
00869         && !renderProperties.setOfSelectedPrimitiveIdIsEmpty())
00870         {
00871                 m_CurrentLod= 0;
00872         }
00873 
00874         if (vboIsUsed)
00875         {
00876                 m_MeshData.createVBOs();
00877 
00878                 // Create VBO and IBO
00879                 if (!m_GeometryIsValid && !m_MeshData.positionSizeIsSet())
00880                 {
00881                         fillVbosAndIbos();
00882                 }
00883 
00884                 // Activate mesh VBOs and IBO of the current LOD
00885                 activateVboAndIbo();
00886         }
00887         else
00888         {
00889                 if (!m_GeometryIsValid)
00890                 {
00891                         m_MeshData.initPositionSize();
00892                 }
00893                 activateVertexArray();
00894         }
00895 
00896         if (GLC_State::isInSelectionMode())
00897         {
00898                 if (renderProperties.renderingMode() == glc::PrimitiveSelection)
00899                 {
00900                         primitiveSelectionRenderLoop(vboIsUsed);
00901                 }
00902                 else if (renderProperties.renderingMode() == glc::BodySelection)
00903                 {
00904                         bodySelectionRenderLoop(vboIsUsed);
00905                 }
00906                 else
00907                 {
00908                         normalRenderLoop(renderProperties, vboIsUsed);
00909                 }
00910         }
00911         else if (m_IsSelected)
00912         {
00913                 if (renderProperties.renderingMode() == glc::PrimitiveSelected)
00914                 {
00915                         if (!renderProperties.setOfSelectedPrimitiveIdIsEmpty())
00916                         {
00917                                 primitiveSelectedRenderLoop(renderProperties, vboIsUsed);
00918                         }
00919                         else
00920                         {
00921                                 m_IsSelected= false;
00922                                 if ((m_CurrentLod == 0) && (renderProperties.savedRenderingMode() == glc::OverwritePrimitiveMaterial) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
00923                                         primitiveRenderLoop(renderProperties, vboIsUsed);
00924                                 else
00925                                         normalRenderLoop(renderProperties, vboIsUsed);
00926                                 m_IsSelected= true;
00927                         }
00928                 }
00929                 else
00930                 {
00931                         normalRenderLoop(renderProperties, vboIsUsed);
00932                 }
00933         }
00934         else
00935         {
00936                 // Choose the accurate render loop
00937                 switch (renderProperties.renderingMode())
00938                 {
00939                 case glc::NormalRenderMode:
00940                         normalRenderLoop(renderProperties, vboIsUsed);
00941                         break;
00942                 case glc::OverwriteMaterial:
00943                         OverwriteMaterialRenderLoop(renderProperties, vboIsUsed);
00944                         break;
00945                 case glc::OverwriteTransparency:
00946                         OverwriteTransparencyRenderLoop(renderProperties, vboIsUsed);
00947                         break;
00948                 case glc::OverwriteTransparencyAndMaterial:
00949                         OverwriteTransparencyAndMaterialRenderLoop(renderProperties, vboIsUsed);
00950                         break;
00951                 case glc::OverwritePrimitiveMaterial:
00952                         if ((m_CurrentLod == 0) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
00953                                 primitiveRenderLoop(renderProperties, vboIsUsed);
00954                         else
00955                                 normalRenderLoop(renderProperties, vboIsUsed);
00956                         break;
00957                 default:
00958                         Q_ASSERT(false);
00959                         break;
00960                 }
00961         }
00962 
00963 
00964         // Restore client state
00965 
00966         if (m_ColorPearVertex && !m_IsSelected && !GLC_State::isInSelectionMode())
00967         {
00968                 glDisableClientState(GL_COLOR_ARRAY);
00969                 glDisable(GL_COLOR_MATERIAL);
00970         }
00971 
00972         glDisableClientState(GL_VERTEX_ARRAY);
00973         glDisableClientState(GL_NORMAL_ARRAY);
00974         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00975 
00976         if (vboIsUsed)
00977         {
00978                 QGLBuffer::release(QGLBuffer::IndexBuffer);
00979                 QGLBuffer::release(QGLBuffer::VertexBuffer);
00980         }
00981 
00982         // Draw mesh's wire if necessary
00983         if ((renderProperties.renderingFlag() == glc::WireRenderFlag) && !m_WireData.isEmpty() && !GLC_Geometry::typeIsWire())
00984         {
00985                 if (!GLC_State::isInSelectionMode())
00986                 {
00987                         GLC_Context::current()->glcEnableLighting(false);
00988                         // Set polyline colors
00989                         GLfloat color[4]= {static_cast<float>(m_WireColor.redF()),
00990                                                                         static_cast<float>(m_WireColor.greenF()),
00991                                                                         static_cast<float>(m_WireColor.blueF()),
00992                                                                         static_cast<float>(m_WireColor.alphaF())};
00993 
00994                         glColor4fv(color);
00995                         m_WireData.glDraw(renderProperties, GL_LINE_STRIP);
00996                         GLC_Context::current()->glcEnableLighting(true);
00997                 }
00998                 else
00999                 {
01000                         m_WireData.glDraw(renderProperties, GL_LINE_STRIP);
01001                 }
01002         }
01003 
01004         // Update statistics
01005         GLC_RenderStatistics::addBodies(1);
01006         GLC_RenderStatistics::addTriangles(m_MeshData.trianglesCount(m_CurrentLod));
01007 }
01008 
01010 // Private services Functions
01012 
01013 // Set the current material
01014 GLC_uint GLC_Mesh::setCurrentMaterial(GLC_Material* pMaterial, int lod, double accuracy)
01015 {
01016 
01017         // Test if a primitive group hash exists for the specified lod
01018         if (!m_PrimitiveGroups.contains(lod))
01019         {
01020                 m_PrimitiveGroups.insert(lod, new LodPrimitiveGroups());
01021 
01022                 m_MeshData.appendLod(accuracy);
01023         }
01024 
01025         GLC_uint returnId;
01026         if (NULL == pMaterial)
01027         {
01028                 returnId= m_DefaultMaterialId; // Default material id
01029 
01030                 // Test if the material has been already load
01031                 if (m_DefaultMaterialId == 0)
01032                 {
01033                         pMaterial= new GLC_Material();
01034                         // Add the material to the mesh
01035                         addMaterial(pMaterial);
01036                         m_DefaultMaterialId= pMaterial->id();
01037                         returnId= m_DefaultMaterialId;
01038 
01039                 }
01040                 // Test if a primitive group for this material exist
01041                 if (!m_PrimitiveGroups.value(lod)->contains(returnId))
01042                 {
01043                         m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
01044                 }
01045         }
01046         else
01047         {
01048                 returnId= pMaterial->id();
01049                 // Test if the material has been already load
01050                 if (!containsMaterial(returnId))
01051                 {
01052                         // Add the material to the mesh
01053                         addMaterial(pMaterial);
01054                         m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
01055 
01056                 }
01057                 else if (!m_PrimitiveGroups.value(lod)->contains(returnId))
01058                 {
01059                         // Add the material to the group
01060                         m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
01061                 }
01062         }
01063 
01064         return returnId;
01065 }
01066 
01067 // Fill VBOs and IBOs
01068 void GLC_Mesh::fillVbosAndIbos()
01069 {
01070         // Fill VBO of vertices
01071         m_MeshData.fillVbo(GLC_MeshData::GLC_Vertex);
01072 
01073         // Fill VBO of normals
01074         m_MeshData.fillVbo(GLC_MeshData::GLC_Normal);
01075 
01076         // Fill VBO of texel if needed
01077         m_MeshData.fillVbo(GLC_MeshData::GLC_Texel);
01078 
01079         // Fill VBO of color if needed
01080         m_MeshData.fillVbo(GLC_MeshData::GLC_Color);
01081 
01082         // Fill a lod IBO
01083         m_MeshData.fillLodIbo();
01084 
01085 }
01086 // set primitive group offset
01087 void GLC_Mesh::finishSerialized()
01088 {
01089         PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
01090         while (iGroups != m_PrimitiveGroups.constEnd())
01091         {
01092                 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
01093                 while (iGroup != iGroups.value()->constEnd())
01094                 {
01095                         iGroup.value()->computeVboOffset();
01096                         ++iGroup;
01097                 }
01098                 ++iGroups;
01099         }
01100 }
01101 /*
01102 // Move Indexs from the primitive groups to the mesh Data LOD and Set IBOs offsets
01103 void GLC_Mesh::finishVbo()
01104 {
01105         PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
01106         while (iGroups != m_PrimitiveGroups.constEnd())
01107         {
01108                 int currentLod= iGroups.key();
01109                 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
01110                 while (iGroup != iGroups.value()->constEnd())
01111                 {
01112                         // Add group triangles index to mesh Data LOD triangles index vector
01113                         if (iGroup.value()->containsTriangles())
01114                         {
01115                                 iGroup.value()->setTrianglesOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
01116                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
01117                         }
01118 
01119                         // Add group strip index to mesh Data LOD strip index vector
01120                         if (iGroup.value()->containsStrip())
01121                         {
01122                                 iGroup.value()->setBaseTrianglesStripOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
01123                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
01124                         }
01125 
01126                         // Add group fan index to mesh Data LOD fan index vector
01127                         if (iGroup.value()->containsFan())
01128                         {
01129                                 iGroup.value()->setBaseTrianglesFanOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
01130                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
01131                         }
01132 
01133                         iGroup.value()->finish();
01134                         ++iGroup;
01135                 }
01136                 ++iGroups;
01137 
01138         }
01139 }
01140 */
01141 
01142 // Move Indexs from the primitive groups to the mesh Data LOD and Set Index offsets
01143 void GLC_Mesh::moveIndexToMeshDataLod()
01144 {
01145         //qDebug() << "GLC_Mesh::moveIndexToMeshDataLod()";
01146         PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
01147         while (iGroups != m_PrimitiveGroups.constEnd())
01148         {
01149                 int currentLod= iGroups.key();
01150                 LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
01151                 while (iGroup != iGroups.value()->constEnd())
01152                 {
01153                         // Add group triangles index to mesh Data LOD triangles index vector
01154                         if (iGroup.value()->containsTriangles())
01155                         {
01156                                 iGroup.value()->setTrianglesOffseti(m_MeshData.indexVectorSize(currentLod));
01157                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
01158                         }
01159 
01160                         // Add group strip index to mesh Data LOD strip index vector
01161                         if (iGroup.value()->containsStrip())
01162                         {
01163                                 iGroup.value()->setBaseTrianglesStripOffseti(m_MeshData.indexVectorSize(currentLod));
01164                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
01165                         }
01166 
01167                         // Add group fan index to mesh Data LOD fan index vector
01168                         if (iGroup.value()->containsFan())
01169                         {
01170                                 iGroup.value()->setBaseTrianglesFanOffseti(m_MeshData.indexVectorSize(currentLod));
01171                                 (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
01172                         }
01173 
01174                         iGroup.value()->computeVboOffset();
01175                         iGroup.value()->finish();
01176                         ++iGroup;
01177                 }
01178                 ++iGroups;
01179         }
01180 }
01181 
01182 // The normal display loop
01183 void GLC_Mesh::normalRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01184 {
01185         const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01186         if ((!m_IsSelected || !isTransparent) || GLC_State::isInSelectionMode())
01187         {
01188                 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01189                 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01190                 {
01191                         GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01192                         GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01193 
01194                         // Test if the current material is renderable
01195                         bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01196 
01197                         // Choose the material to render
01198                         if ((materialIsrenderable || m_IsSelected) && !GLC_State::isInSelectionMode())
01199                 {
01200                                 // Execute current material
01201                                 pCurrentMaterial->glExecute();
01202 
01203                                 if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01204                         }
01205 
01206                         // Choose the primitives to render
01207                         if (m_IsSelected || GLC_State::isInSelectionMode() || materialIsrenderable)
01208                         {
01209 
01210                                 if (vboIsUsed)
01211                                 {
01212                                         vboDrawPrimitivesOf(pCurrentGroup);
01213                                 }
01214                                 else
01215                                 {
01216                                         vertexArrayDrawPrimitivesOf(pCurrentGroup);
01217                                 }
01218                         }
01219 
01220                         ++iGroup;
01221                 }
01222         }
01223 }
01224 
01225 //  The overwrite material render loop
01226 void GLC_Mesh::OverwriteMaterialRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01227 {
01228         // Get the overwrite material
01229         GLC_Material* pOverwriteMaterial= renderProperties.overwriteMaterial();
01230         Q_ASSERT(NULL != pOverwriteMaterial);
01231         pOverwriteMaterial->glExecute();
01232         if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01233 
01234         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01235         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01236         {
01237                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01238 
01239                 // Test if the current material is renderable
01240                 bool materialIsrenderable = (pOverwriteMaterial->isTransparent() == (renderProperties.renderingFlag() == glc::TransparentRenderFlag));
01241 
01242                 // Choose the primitives to render
01243                 if (m_IsSelected || materialIsrenderable)
01244                 {
01245 
01246                         if (vboIsUsed)
01247                                 vboDrawPrimitivesOf(pCurrentGroup);
01248                         else
01249                                 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01250                 }
01251 
01252                 ++iGroup;
01253         }
01254 }
01255 // The overwrite transparency render loop
01256 void GLC_Mesh::OverwriteTransparencyRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01257 {
01258         // Get transparency value
01259         const float alpha= renderProperties.overwriteTransparency();
01260         Q_ASSERT(-1.0f != alpha);
01261 
01262         // Test if the current material is renderable
01263         bool materialIsrenderable = (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01264 
01265         if (materialIsrenderable || m_IsSelected)
01266         {
01267                 LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01268                 while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01269                 {
01270                         GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01271                         GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01272 
01273                         // Execute current material
01274                         pCurrentMaterial->glExecute(alpha);
01275 
01276                         if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01277 
01278                         // Choose the primitives to render
01279                         if (m_IsSelected || materialIsrenderable)
01280                         {
01281 
01282                                 if (vboIsUsed)
01283                                         vboDrawPrimitivesOf(pCurrentGroup);
01284                                 else
01285                                         vertexArrayDrawPrimitivesOf(pCurrentGroup);
01286                         }
01287                         ++iGroup;
01288                 }
01289         }
01290 }
01291 
01292 void GLC_Mesh::OverwriteTransparencyAndMaterialRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01293 {
01294         // Get transparency value
01295         const float alpha= renderProperties.overwriteTransparency();
01296         Q_ASSERT(-1.0f != alpha);
01297 
01298         // Get the overwrite material
01299         GLC_Material* pOverwriteMaterial= renderProperties.overwriteMaterial();
01300         Q_ASSERT(NULL != pOverwriteMaterial);
01301         pOverwriteMaterial->glExecute(alpha);
01302         if (m_IsSelected) GLC_SelectionMaterial::glExecute();
01303 
01304         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01305         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01306         {
01307                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01308 
01309                 // Test if the current material is renderable
01310                 bool materialIsrenderable = (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01311 
01312                 // Choose the primitives to render
01313                 if (m_IsSelected || materialIsrenderable)
01314                 {
01315 
01316                         if (vboIsUsed)
01317                                 vboDrawPrimitivesOf(pCurrentGroup);
01318                         else
01319                                 vertexArrayDrawPrimitivesOf(pCurrentGroup);
01320                 }
01321 
01322                 ++iGroup;
01323         }
01324 }
01325 
01326 // The body selection render loop
01327 void GLC_Mesh::bodySelectionRenderLoop(bool vboIsUsed)
01328 {
01329         Q_ASSERT(GLC_State::isInSelectionMode());
01330 
01331         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01332         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01333         {
01334                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01335 
01336                 if (vboIsUsed)
01337                         vboDrawPrimitivesOf(pCurrentGroup);
01338                 else
01339                         vertexArrayDrawPrimitivesOf(pCurrentGroup);
01340 
01341                 ++iGroup;
01342         }
01343 }
01344 
01345 // The primitive selection render loop
01346 void GLC_Mesh::primitiveSelectionRenderLoop(bool vboIsUsed)
01347 {
01348         Q_ASSERT(GLC_State::isInSelectionMode());
01349 
01350         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01351 
01352         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01353         {
01354                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01355 
01356                 if (vboIsUsed)
01357                         vboDrawInSelectionModePrimitivesOf(pCurrentGroup);
01358                 else
01359                         vertexArrayDrawInSelectionModePrimitivesOf(pCurrentGroup);
01360 
01361                 ++iGroup;
01362         }
01363 }
01364 
01365 // The primitive rendeder loop
01366 void GLC_Mesh::primitiveRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01367 {
01368         const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01369         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01370         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01371         {
01372                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01373                 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01374 
01375                 // Test if the current material is renderable
01376                 const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01377 
01378                 if (materialIsrenderable)
01379                 {
01380                         pCurrentMaterial->glExecute();
01381                 }
01382                 if (vboIsUsed)
01383                         vboDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
01384                 else
01385                         vertexArrayDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
01386 
01387                 ++iGroup;
01388         }
01389 }
01390 
01391 // The primitive Selected render loop
01392 void GLC_Mesh::primitiveSelectedRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
01393 {
01394         const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
01395         LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
01396         while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
01397         {
01398                 GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
01399                 GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
01400 
01401                 // Test if the current material is renderable
01402                 const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
01403 
01404                 if (materialIsrenderable)
01405                 {
01406                         pCurrentMaterial->glExecute();
01407                 }
01408 
01409                 if (vboIsUsed)
01410                         vboDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
01411                 else
01412                         vertexArrayDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
01413 
01414                 ++iGroup;
01415         }
01416 }
01417 
01418 void GLC_Mesh::copyIndex(int lodIndex, GLC_Mesh* pLodMesh, QHash<GLuint, GLuint>& sourceToTargetIndexMap, QHash<GLuint, GLuint>& tagetToSourceIndexMap, int& maxIndex, int targetLod)
01419 {
01421         QList<GLuint> materialId= m_PrimitiveGroups.value(lodIndex)->keys();
01422 
01423         const int materialCount= materialId.size();
01424         for (int i= 0; i < materialCount; ++i)
01425         {
01426                 GLuint currentMaterialId= materialId.at(i);
01427                 GLC_Material* pCurrentMaterial= GLC_Geometry::material(currentMaterialId);
01428 
01429                 // Triangles
01430                 if (containsTriangles(lodIndex, currentMaterialId))
01431                 {
01432                         QVector<GLuint> sourceTriangleIndex= getTrianglesIndex(lodIndex, currentMaterialId);
01433                         QList<GLuint> targetTriangleIndex;
01434                         const int triangleIndexCount= sourceTriangleIndex.size();
01435                         for (int i= 0; i < triangleIndexCount; ++i)
01436                         {
01437                                 const GLuint currentIndex= sourceTriangleIndex.at(i);
01438                                 if (!sourceToTargetIndexMap.contains(currentIndex))
01439                                 {
01440                                         sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
01441                                         tagetToSourceIndexMap.insert(maxIndex, currentIndex);
01442                                         targetTriangleIndex.append(maxIndex);
01443                                 }
01444                                 else
01445                                 {
01446                                         targetTriangleIndex.append(sourceToTargetIndexMap.value(currentIndex));
01447                                 }
01448                         }
01449                         pLodMesh->addTriangles(pCurrentMaterial, targetTriangleIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
01450                 }
01451 
01452                 //Triangles strips
01453                 if (containsStrips(lodIndex, currentMaterialId))
01454                 {
01455                         QList<QVector<GLuint> > sourceStripIndex= getStripsIndex(lodIndex, currentMaterialId);
01456                         const int stripCount= sourceStripIndex.size();
01457                         for (int stripIndex= 0; stripIndex < stripCount; ++stripIndex)
01458                         {
01459 
01460                                 QVector<GLuint> sourceTriangleStripIndex= sourceStripIndex.at(stripIndex);
01461                                 QList<GLuint> targetTriangleStripIndex;
01462                                 const int triangleStripIndexCount= sourceTriangleStripIndex.size();
01463                                 for (int i= 0; i < triangleStripIndexCount; ++i)
01464                                 {
01465                                         const GLuint currentIndex= sourceTriangleStripIndex.at(i);
01466                                         if (!sourceToTargetIndexMap.contains(currentIndex))
01467                                         {
01468                                                 sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
01469                                                 tagetToSourceIndexMap.insert(maxIndex, currentIndex);
01470                                                 targetTriangleStripIndex.append(maxIndex);
01471                                         }
01472                                         else
01473                                         {
01474                                                 targetTriangleStripIndex.append(sourceToTargetIndexMap.value(currentIndex));
01475                                         }
01476                                 }
01477                                 pLodMesh->addTrianglesStrip(pCurrentMaterial, targetTriangleStripIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
01478                         }
01479                 }
01480                 //Triangles fans
01481                 if (containsFans(lodIndex, currentMaterialId))
01482                 {
01483                         QList<QVector<GLuint> > sourceFanIndex= getFansIndex(lodIndex, currentMaterialId);
01484                         const int fanCount= sourceFanIndex.size();
01485                         for (int fanIndex= 0; fanIndex < fanCount; ++fanIndex)
01486                         {
01487 
01488                                 QVector<GLuint> sourceTriangleFanIndex= sourceFanIndex.at(fanIndex);
01489                                 QList<GLuint> targetTriangleFanIndex;
01490                                 const int triangleFanIndexCount= sourceTriangleFanIndex.size();
01491                                 for (int i= 0; i < triangleFanIndexCount; ++i)
01492                                 {
01493                                         const GLuint currentIndex= sourceTriangleFanIndex.at(i);
01494                                         if (!sourceToTargetIndexMap.contains(currentIndex))
01495                                         {
01496                                                 sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
01497                                                 tagetToSourceIndexMap.insert(maxIndex, currentIndex);
01498                                                 targetTriangleFanIndex.append(maxIndex);
01499                                         }
01500                                         else
01501                                         {
01502                                                 targetTriangleFanIndex.append(sourceToTargetIndexMap.value(currentIndex));
01503                                         }
01504                                 }
01505                                 pLodMesh->addTrianglesFan(pCurrentMaterial, targetTriangleFanIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
01506                         }
01507                 }
01508         }
01509 }
01510 
01511 void GLC_Mesh::copyBulkData(GLC_Mesh* pLodMesh, const QHash<GLuint, GLuint>& tagetToSourceIndexMap, int maxIndex)
01512 {
01513         GLfloatVector tempFloatVector;
01514         int stride= 3;
01515         // Extract position bulk data
01516         Q_ASSERT(!m_MeshData.positionVectorHandle()->isEmpty());
01517         tempFloatVector.resize(stride * (maxIndex + 1));
01518         for (int i= 0; i < maxIndex + 1; ++i)
01519         {
01520                 GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
01521                 GLfloat* pSource= &(m_MeshData.positionVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
01522 
01523                 memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
01524         }
01525         pLodMesh->addVertice(tempFloatVector);
01526         tempFloatVector.clear();
01527 
01528         // Extract normal bulk data
01529         Q_ASSERT(!m_MeshData.normalVectorHandle()->isEmpty());
01530         tempFloatVector.resize(stride * (maxIndex + 1));
01531         for (int i= 0; i < maxIndex + 1; ++i)
01532         {
01533                 GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
01534                 GLfloat* pSource= &(m_MeshData.normalVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
01535 
01536                 memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
01537         }
01538         pLodMesh->addNormals(tempFloatVector);
01539         tempFloatVector.clear();
01540 
01541         if (!m_MeshData.texelVectorHandle()->isEmpty())
01542         {
01543                 // Extract texel bulk data
01544                 stride= 2;
01545                 tempFloatVector.resize(stride * (maxIndex + 1));
01546 
01547                 for (int i= 0; i < maxIndex + 1; ++i)
01548                 {
01549                         GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
01550                         GLfloat* pSource= &(m_MeshData.texelVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
01551 
01552                         memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
01553                 }
01554                 pLodMesh->addTexels(tempFloatVector);
01555                 tempFloatVector.clear();
01556         }
01557 }
01558 
01559 IndexList GLC_Mesh::equivalentTrianglesIndexOfstripsIndex(int lodIndex, GLC_uint materialId)
01560 {
01561         IndexList trianglesIndex;
01562         if (containsStrips(lodIndex, materialId))
01563         {
01564                 const QList<QVector<GLuint> > stripsIndex= getStripsIndex(lodIndex, materialId);
01565                 const int stripCount= stripsIndex.count();
01566                 for (int i= 0; i < stripCount; ++i)
01567                 {
01568                         const QVector<GLuint> currentStripIndex= stripsIndex.at(i);
01569 
01570                         trianglesIndex.append(currentStripIndex.at(0));
01571                         trianglesIndex.append(currentStripIndex.at(1));
01572                         trianglesIndex.append(currentStripIndex.at(2));
01573                         const int stripSize= currentStripIndex.size();
01574                         for (int j= 3; j < stripSize; ++j)
01575                         {
01576                                 if ((j % 2) != 0)
01577                                 {
01578                                         trianglesIndex.append(currentStripIndex.at(j));
01579                                         trianglesIndex.append(currentStripIndex.at(j - 1));
01580                                         trianglesIndex.append(currentStripIndex.at(j - 2));
01581                                 }
01582                                 else
01583                                 {
01584                                         trianglesIndex.append(currentStripIndex.at(j));
01585                                         trianglesIndex.append(currentStripIndex.at(j - 2));
01586                                         trianglesIndex.append(currentStripIndex.at(j - 1));
01587                                 }
01588                         }
01589                 }
01590         }
01591         return trianglesIndex;
01592 }
01593 
01594 IndexList GLC_Mesh::equivalentTrianglesIndexOfFansIndex(int lodIndex, GLC_uint materialId)
01595 {
01596         IndexList trianglesIndex;
01597         if (containsFans(lodIndex, materialId))
01598         {
01599                 const QList<QVector<GLuint> > fanIndex= getFansIndex(lodIndex, materialId);
01600                 const int fanCount= fanIndex.count();
01601                 for (int i= 0; i < fanCount; ++i)
01602                 {
01603                         const QVector<GLuint> currentFanIndex= fanIndex.at(i);
01604                         const int size= currentFanIndex.size();
01605                         for (int j= 1; j < size - 1; ++j)
01606                         {
01607                                 trianglesIndex.append(currentFanIndex.first());
01608                                 trianglesIndex.append(currentFanIndex.at(j));
01609                                 trianglesIndex.append(currentFanIndex.at(j + 1));
01610                         }
01611                 }
01612         }
01613         return trianglesIndex;
01614 }
01615 

SourceForge.net Logo

©2005-2011 Laurent Ribon