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

SourceForge.net Logo

©2005-2011 Laurent Ribon