GLC_lib  2.5.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
glc_mesh.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 
3  This file is part of the GLC-lib library.
4  Copyright (C) 2005-2008 Laurent Ribon (laumaya@users.sourceforge.net)
5  http://glc-lib.sourceforge.net
6 
7  GLC-lib is free software; you can redistribute it and/or modify
8  it under the terms of the GNU Lesser General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  GLC-lib is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public License
18  along with GLC-lib; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21 *****************************************************************************/
22 
24 
25 #include "glc_mesh.h"
26 #include "../glc_renderstatistics.h"
27 #include "../glc_context.h"
28 
29 // Class chunk id
30 quint32 GLC_Mesh::m_ChunkId= 0xA701;
31 
33 :GLC_Geometry("Mesh", false)
34 , m_NextPrimitiveLocalId(1)
35 , m_PrimitiveGroups()
36 , m_DefaultMaterialId(0)
37 , m_NumberOfVertice(0)
38 , m_NumberOfNormals(0)
39 , m_ColorPearVertex(false)
40 , m_MeshData()
41 , m_CurrentLod(0)
42 {
43 
44 }
45 
47 :GLC_Geometry(mesh)
48 , m_NextPrimitiveLocalId(mesh.m_NextPrimitiveLocalId)
49 , m_PrimitiveGroups(mesh.m_PrimitiveGroups)
50 , m_DefaultMaterialId(mesh.m_DefaultMaterialId)
51 , m_NumberOfVertice(mesh.m_NumberOfVertice)
52 , m_NumberOfNormals(mesh.m_NumberOfNormals)
53 , m_ColorPearVertex(mesh.m_ColorPearVertex)
54 , m_MeshData(mesh.m_MeshData)
55 , m_CurrentLod(0)
56 {
57  // Make a copy of m_PrimitiveGroups with new material id
58  PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
59  while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
60  {
61  LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
62  m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
63 
64  LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
65  while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
66  {
67  GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
68  pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
69 
70  ++iPrimitiveGroup;
71  }
72 
73  ++iPrimitiveGroups;
74  }
75 
76 }
77 
78 // Overload "=" operator
80 {
81  if (this != &mesh)
82  {
83  // Call the operator of the super class
85 
86  // Clear the mesh
88 
89  // Copy members
96  m_MeshData= mesh.m_MeshData;
97  m_CurrentLod= 0;
98 
99  // Make a copy of m_PrimitiveGroups with new material id
100  PrimitiveGroupsHash::const_iterator iPrimitiveGroups= mesh.m_PrimitiveGroups.constBegin();
101  while (mesh.m_PrimitiveGroups.constEnd() != iPrimitiveGroups)
102  {
103  LodPrimitiveGroups* pPrimitiveGroups= new LodPrimitiveGroups();
104  m_PrimitiveGroups.insert(iPrimitiveGroups.key(), pPrimitiveGroups);
105 
106  LodPrimitiveGroups::const_iterator iPrimitiveGroup= iPrimitiveGroups.value()->constBegin();
107  while (iPrimitiveGroups.value()->constEnd() != iPrimitiveGroup)
108  {
109  GLC_PrimitiveGroup* pPrimitiveGroup= new GLC_PrimitiveGroup(*(iPrimitiveGroup.value()), iPrimitiveGroup.key());
110  pPrimitiveGroups->insert(iPrimitiveGroup.key(), pPrimitiveGroup);
111 
112  ++iPrimitiveGroup;
113  }
114 
115  ++iPrimitiveGroups;
116  }
117  }
118 
119  return *this;
120 }
121 
122 // Destructor
124 {
125  PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
126  while (iGroups != m_PrimitiveGroups.constEnd())
127  {
128  LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
129  while (iGroup != iGroups.value()->constEnd())
130  {
131  delete iGroup.value();
132 
133  ++iGroup;
134  }
135  delete iGroups.value();
136  ++iGroups;
137  }
138 }
139 
141 // Get Functions
143 // Return the class Chunk ID
145 {
146  return m_ChunkId;
147 }
148 
149 // Get number of faces
150 unsigned int GLC_Mesh::faceCount(int lod) const
151 {
152  return m_MeshData.trianglesCount(lod);
153 }
154 
155 // Get number of vertex
156 unsigned int GLC_Mesh::VertexCount() const
157 {
158  return m_NumberOfVertice;
159 }
160 
161 // return the mesh bounding box
163 {
164  if (NULL == m_pBoundingBox)
165  {
166  //qDebug() << "GLC_Mesh2::boundingBox create boundingBox";
168 
169  if (m_MeshData.positionVectorHandle()->isEmpty())
170  {
171  qDebug() << "GLC_Mesh::boundingBox empty m_Positions";
172  }
173  else
174  {
176  const int max= pVertexVector->size();
177  for (int i= 0; i < max; i= i + 3)
178  {
179  GLC_Vector3d vector((*pVertexVector)[i], (*pVertexVector)[i + 1], (*pVertexVector)[i + 2]);
180  m_pBoundingBox->combine(vector);
181  }
182  }
183  // Combine with the wiredata bounding box
185  }
186  return *m_pBoundingBox;
187 
188 }
189 
190 // Return a copy of the Mesh as GLC_Geometry pointer
192 {
193  return new GLC_Mesh(*this);
194 }
195 
196 // Return true if the mesh contains triangles
197 bool GLC_Mesh::containsTriangles(int lod, GLC_uint materialId) const
198 {
199  // Check if the lod exist and material exists
200  Q_ASSERT(m_PrimitiveGroups.contains(lod));
201  if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
202  else return m_PrimitiveGroups.value(lod)->value(materialId)->containsTriangles();
203 }
204 
205 // Return the specified index
206 QVector<GLuint> GLC_Mesh::getTrianglesIndex(int lod, GLC_uint materialId) const
207 {
208  // Check if the mesh contains triangles
209  Q_ASSERT(containsTriangles(lod, materialId));
210 
211  GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
212 
213  int offset= 0;
214  if (vboIsUsed())
215  {
216  offset= static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->trianglesIndexOffset()) / sizeof(GLuint));
217  }
218  else
219  {
220  offset= pPrimitiveGroup->trianglesIndexOffseti();
221  }
222  const int size= pPrimitiveGroup->trianglesIndexSize();
223 
224  QVector<GLuint> resultIndex(size);
225 
226  memcpy((void*)resultIndex.data(), &(m_MeshData.indexVector(lod).data())[offset], size * sizeof(GLuint));
227 
228  return resultIndex;
229 }
230 
232 {
233  IndexList subject;
234  if (containsTriangles(lod, materialId))
235  {
236  subject= getTrianglesIndex(lod, materialId).toList();
237  }
238 
239  if (containsStrips(lod, materialId))
240  {
241  subject.append(equivalentTrianglesIndexOfstripsIndex(lod, materialId));
242  }
243 
244  if (containsFans(lod, materialId))
245  {
246  subject.append(equivalentTrianglesIndexOfFansIndex(lod, materialId));
247  }
248 
249  Q_ASSERT((subject.count() % 3) == 0);
250 
251  return subject;
252 }
253 
254 // Return the number of triangles
255 int GLC_Mesh::numberOfTriangles(int lod, GLC_uint materialId) const
256 {
257  // Check if the lod exist and material exists
258  if (!m_PrimitiveGroups.contains(lod))return 0;
259  else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
260  else return m_PrimitiveGroups.value(lod)->value(materialId)->trianglesIndexSize();
261 }
262 
263 // Return true if the mesh contains trips
264 bool GLC_Mesh::containsStrips(int lod, GLC_uint materialId) const
265 {
266  // Check if the lod exist and material exists
267  if (!m_PrimitiveGroups.contains(lod))return false;
268  else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
269  else return m_PrimitiveGroups.value(lod)->value(materialId)->containsStrip();
270 
271 }
272 
273 // Return the strips index
274 QList<QVector<GLuint> > GLC_Mesh::getStripsIndex(int lod, GLC_uint materialId) const
275 {
276  // Check if the mesh contains trips
277  Q_ASSERT(containsStrips(lod, materialId));
278 
279  GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
280 
281  QList<int> offsets;
282  QList<int> sizes;
283  int stripsCount;
284 
285  if (vboIsUsed())
286  {
287  stripsCount= pPrimitiveGroup->stripsOffset().size();
288  for (int i= 0; i < stripsCount; ++i)
289  {
290  offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->stripsOffset().at(i)) / sizeof(GLuint)));
291  sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
292  }
293  }
294  else
295  {
296  stripsCount= pPrimitiveGroup->stripsOffseti().size();
297  for (int i= 0; i < stripsCount; ++i)
298  {
299  offsets.append(static_cast<int>(pPrimitiveGroup->stripsOffseti().at(i)));
300  sizes.append(static_cast<int>(pPrimitiveGroup->stripsSizes().at(i)));
301  }
302 
303  }
304  // The result list of vector
305  QList<QVector<GLuint> > result;
306  // The copy of the mesh Data LOD index vector
307  QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
308  for (int i= 0; i < stripsCount; ++i)
309  {
310  QVector<GLuint> currentStrip(sizes.at(i));
311  memcpy((void*)currentStrip.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
312  result.append(currentStrip);
313  }
314 
315  return result;
316 }
317 
318 // Return the number of strips
319 int GLC_Mesh::numberOfStrips(int lod, GLC_uint materialId) const
320 {
321  // Check if the lod exist and material exists
322  if (!m_PrimitiveGroups.contains(lod))return 0;
323  else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
324  else return m_PrimitiveGroups.value(lod)->value(materialId)->stripsSizes().size();
325 }
326 
327 // Return true if the mesh contains fans
328 bool GLC_Mesh::containsFans(int lod, GLC_uint materialId) const
329 {
330  // Check if the lod exist and material exists
331  if (!m_PrimitiveGroups.contains(lod))return false;
332  else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return false;
333  else return m_PrimitiveGroups.value(lod)->value(materialId)->containsFan();
334 
335 }
336 
338 int GLC_Mesh::numberOfFans(int lod, GLC_uint materialId) const
339 {
340  // Check if the lod exist and material exists
341  if(!m_PrimitiveGroups.contains(lod))return 0;
342  else if (!m_PrimitiveGroups.value(lod)->contains(materialId)) return 0;
343  else return m_PrimitiveGroups.value(lod)->value(materialId)->fansSizes().size();
344 }
345 
347 {
348  GLC_Material* pSubject= NULL;
349 
350  if (!m_PrimitiveGroups.isEmpty())
351  {
352  LodPrimitiveGroups* pMasterLodPrimitiveGroup= m_PrimitiveGroups.value(lod);
353  LodPrimitiveGroups::const_iterator iGroup= pMasterLodPrimitiveGroup->constBegin();
354  while (iGroup != pMasterLodPrimitiveGroup->constEnd())
355  {
356  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
357  QList<GLC_uint> listOfId;
358 
359  listOfId.append(pCurrentGroup->triangleGroupId());
360  listOfId.append(pCurrentGroup->stripGroupId());
361  listOfId.append(pCurrentGroup->fanGroupId());
362  if (listOfId.contains(id))
363  {
364  const GLC_uint materialId= pCurrentGroup->id();
365  pSubject= this->material(materialId);
366  iGroup= pMasterLodPrimitiveGroup->constEnd();
367  }
368  else
369  {
370  ++iGroup;
371  }
372  }
373  }
374 
375  return pSubject;
376 }
377 
378 // Return the strips index
379 QList<QVector<GLuint> > GLC_Mesh::getFansIndex(int lod, GLC_uint materialId) const
380 {
381  // Check if the mesh contains trips
382  Q_ASSERT(containsFans(lod, materialId));
383 
384  GLC_PrimitiveGroup* pPrimitiveGroup= m_PrimitiveGroups.value(lod)->value(materialId);
385 
386  QList<int> offsets;
387  QList<int> sizes;
388  int fansCount;
389 
390  if (vboIsUsed())
391  {
392  fansCount= pPrimitiveGroup->fansOffset().size();
393  for (int i= 0; i < fansCount; ++i)
394  {
395  offsets.append(static_cast<int>(reinterpret_cast<GLsizeiptr>(pPrimitiveGroup->fansOffset().at(i)) / sizeof(GLuint)));
396  sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
397  }
398  }
399  else
400  {
401  fansCount= pPrimitiveGroup->fansOffseti().size();
402  for (int i= 0; i < fansCount; ++i)
403  {
404  offsets.append(static_cast<int>(pPrimitiveGroup->fansOffseti().at(i)));
405  sizes.append(static_cast<int>(pPrimitiveGroup->fansSizes().at(i)));
406  }
407 
408  }
409  // The result list of vector
410  QList<QVector<GLuint> > result;
411  // The copy of the mesh Data LOD index vector
412  QVector<GLuint> SourceIndex(m_MeshData.indexVector(lod));
413  for (int i= 0; i < fansCount; ++i)
414  {
415  QVector<GLuint> currentFan(sizes.at(i));
416  memcpy((void*)currentFan.data(), &(SourceIndex.data())[offsets.at(i)], sizes.at(i) * sizeof(GLuint));
417  result.append(currentFan);
418  }
419 
420  return result;
421 }
422 
423 QSet<GLC_uint> GLC_Mesh::setOfPrimitiveId() const
424 {
425  QList<GLC_uint> subject;
426  if (!m_PrimitiveGroups.isEmpty())
427  {
428  LodPrimitiveGroups* pMasterLodPrimitiveGroup= m_PrimitiveGroups.value(0);
429  LodPrimitiveGroups::const_iterator iGroup= pMasterLodPrimitiveGroup->constBegin();
430  while (iGroup != pMasterLodPrimitiveGroup->constEnd())
431  {
432  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
433  subject.append(pCurrentGroup->triangleGroupId());
434  subject.append(pCurrentGroup->stripGroupId());
435  subject.append(pCurrentGroup->fanGroupId());
436  ++iGroup;
437  }
438  }
439 
440  return QSet<GLC_uint>::fromList(subject);
441 }
442 
444 {
445  Q_ASSERT(m_MeshData.lodCount() > lodIndex);
446 
448  GLC_Mesh* pLodMesh= new GLC_Mesh;
449  pLodMesh->setName(this->name() + "-LOD-" + QString::number(lodIndex));
450  QHash<GLuint, GLuint> sourceToTargetIndexMap;
451  QHash<GLuint, GLuint> tagetToSourceIndexMap;
452  int maxIndex= -1;
453 
454  int targetLod= 0;
455  copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, targetLod);
456 
457  copyBulkData(pLodMesh, tagetToSourceIndexMap, maxIndex);
458 
459  pLodMesh->finish();
460 
461  releaseVboClientSide(false);
462 
463  return pLodMesh;
464 }
465 
467 {
468  const int lodCount= m_MeshData.lodCount();
469  Q_ASSERT(lodCount > lodIndex);
470 
472  GLC_Mesh* pLodMesh= new GLC_Mesh;
473  pLodMesh->setName(this->name() + "-LOD-" + QString::number(lodIndex));
474  QHash<GLuint, GLuint> sourceToTargetIndexMap;
475  QHash<GLuint, GLuint> tagetToSourceIndexMap;
476  int maxIndex= -1;
477 
478  if ((lodCount - lodIndex) > 1)
479  {
480  int targetLod= 1;
481  for (int i= lodIndex + 1; i < lodCount; ++i)
482  {
483  copyIndex(i, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, targetLod);
484  ++targetLod;
485  }
486  copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, 0);
487  }
488  else
489  {
490  copyIndex(lodIndex, pLodMesh, sourceToTargetIndexMap, tagetToSourceIndexMap, maxIndex, 0);
491  }
492 
493 
494  copyBulkData(pLodMesh, tagetToSourceIndexMap, maxIndex);
495 
496  pLodMesh->finish();
497 
498  releaseVboClientSide(false);
499 
500  return pLodMesh;
501 }
503 {
504  if (matrix.type() != GLC_Matrix4x4::Identity)
505  {
506  delete m_pBoundingBox;
507  m_pBoundingBox= NULL;
509  const int stride= 3;
511  const GLC_Matrix4x4 rotationMatrix= matrix.rotationMatrix();
513  const int verticeCount= pVectPos->size() / stride;
514  for (int i= 0; i < verticeCount; ++i)
515  {
516  GLC_Vector3d newPos(pVectPos->at(stride * i), pVectPos->at(stride * i + 1), pVectPos->at(stride * i + 2));
517  newPos= matrix * newPos;
518  pVectPos->operator[](stride * i)= static_cast<GLfloat>(newPos.x());
519  pVectPos->operator[](stride * i + 1)= static_cast<GLfloat>(newPos.y());
520  pVectPos->operator[](stride * i + 2)= static_cast<GLfloat>(newPos.z());
521 
522  GLC_Vector3d newNormal(pVectNormal->at(stride * i), pVectNormal->at(stride * i + 1), pVectNormal->at(stride * i + 2));
523  newNormal= rotationMatrix * newNormal;
524  pVectNormal->operator[](stride * i)= static_cast<GLfloat>(newNormal.x());
525  pVectNormal->operator[](stride * i + 1)= static_cast<GLfloat>(newNormal.y());
526  pVectNormal->operator[](stride * i + 2)= static_cast<GLfloat>(newNormal.z());
527  }
528  releaseVboClientSide(true);
529  }
530 
531  return *this;
532 }
533 
535 {
536  double resultVolume= 0.0;
537 
538  if (!m_MeshData.isEmpty())
539  {
540  IndexList triangleIndex;
541  QList<GLC_Material*> materials= materialSet().toList();
542  const int materialsCount= materials.count();
543  for (int i= 0; i < materialsCount; ++i)
544  {
545  GLC_uint materialId= materials.at(i)->id();
546  if (containsTriangles(0, materialId))
547  {
548  triangleIndex.append(getTrianglesIndex(0, materialId).toList());
549  }
550  if (containsStrips(0, materialId))
551  {
552  triangleIndex.append(equivalentTrianglesIndexOfstripsIndex(0, materialId));
553  }
554  if (containsFans(0, materialId))
555  {
556  triangleIndex.append(equivalentTrianglesIndexOfFansIndex(0, materialId));
557  }
558  }
559 
561  Q_ASSERT((triangleIndex.count() % 3) == 0);
562  const int triangleCount= triangleIndex.count() / 3;
563  for (int i= 0; i < triangleCount; ++i)
564  {
565  const int index= i * 3;
566  const double v1x= vertices.at(triangleIndex.at(index) * 3);
567  const double v1y= vertices.at(triangleIndex.at(index) * 3 + 1);
568  const double v1z= vertices.at(triangleIndex.at(index) * 3 + 2);
569 
570  const double v2x= vertices.at(triangleIndex.at(index + 1) * 3);
571  const double v2y= vertices.at(triangleIndex.at(index + 1) * 3 + 1);
572  const double v2z= vertices.at(triangleIndex.at(index + 1) * 3 + 2);
573 
574  const double v3x= vertices.at(triangleIndex.at(index + 2) * 3);
575  const double v3y= vertices.at(triangleIndex.at(index + 2) * 3 + 1);
576  const double v3z= vertices.at(triangleIndex.at(index + 2) * 3 + 2);
577 
578  resultVolume+= ((v2y - v1y) * (v3z - v1z) - (v2z - v1z) * (v3y - v1y)) * (v1x + v2x + v3x);
579  }
580 
581  resultVolume= resultVolume / 6.0;
582  }
583 
584  return resultVolume;
585 }
586 
588 // Set Functions
590 
591 // Clear the content of the mesh and super class GLC_Geometry
593 {
594  // Clear the mesh content
596 
597  // Clear the super class GLC_Geometry
599 }
600 
601 
602 // Clear the content off the mesh and makes it empty
604 {
605  // Reset primitive local id
607 
608  // Remove all primitive groups
609  PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
610  while (iGroups != m_PrimitiveGroups.constEnd())
611  {
612  LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
613  while (iGroup != iGroups.value()->constEnd())
614  {
615  delete iGroup.value();
616 
617  ++iGroup;
618  }
619  delete iGroups.value();
620  ++iGroups;
621  }
622  m_PrimitiveGroups.clear();
623 
627  m_IsSelected= false;
628  m_ColorPearVertex= false;
629  // Clear data of the mesh
630  m_MeshData.clear();
631  m_CurrentLod= 0;
632 
634 }
635 
636 // Add triangles
637 GLC_uint GLC_Mesh::addTriangles(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
638 {
639  GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
640  Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
641  Q_ASSERT(!indexList.isEmpty());
642 
643  GLC_uint id= 0;
644  if (0 == lod)
645  {
647  }
648  m_MeshData.trianglesAdded(lod, indexList.size() / 3);
649 
650  m_PrimitiveGroups.value(lod)->value(groupId)->addTriangles(indexList, id);
651 
652  // Invalid the geometry
653  m_GeometryIsValid = false;
654 
655  return id;
656 }
657 
658 // Add triangles Strip ans return his id
659 GLC_uint GLC_Mesh::addTrianglesStrip(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
660 {
661  GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
662  Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
663  Q_ASSERT(!indexList.isEmpty());
664 
665  GLC_uint id= 0;
666  if (0 == lod)
667  {
669  }
670  m_MeshData.trianglesAdded(lod, indexList.size() - 2);
671 
672  m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesStrip(indexList, id);
673 
674  // Invalid the geometry
675  m_GeometryIsValid = false;
676 
677  return id;
678 }
679 // Add triangles Fan
680 GLC_uint GLC_Mesh::addTrianglesFan(GLC_Material* pMaterial, const IndexList& indexList, const int lod, double accuracy)
681 {
682  GLC_uint groupId= setCurrentMaterial(pMaterial, lod, accuracy);
683  Q_ASSERT(m_PrimitiveGroups.value(lod)->contains(groupId));
684  Q_ASSERT(!indexList.isEmpty());
685 
686  GLC_uint id= 0;
687  if (0 == lod)
688  {
690  }
691  m_MeshData.trianglesAdded(lod, indexList.size() - 2);
692  m_PrimitiveGroups.value(lod)->value(groupId)->addTrianglesFan(indexList, id);
693 
694  // Invalid the geometry
695  m_GeometryIsValid = false;
696 
697  return id;
698 }
699 
700 // Reverse mesh normal
702 {
703  GLfloatVector* pNormalVector= m_MeshData.normalVectorHandle();
704  if (pNormalVector->isEmpty())
705  {
707  }
708  const int size= pNormalVector->size();
709  for (int i= 0; i < size; ++i)
710  {
711  (*pNormalVector)[i]= - pNormalVector->at(i);
712  }
713  if (vboIsUsed())
714  {
717  }
718 }
719 
720 // Copy index list in a vector for Vertex Array Use
722 {
723  if (m_MeshData.lodCount() > 0)
724  {
725  boundingBox();
726 
728 
730  }
731  else
732  {
733  clear();
734  }
735 
736  //qDebug() << "Mesh mem size= " << memmorySize();
737 }
738 
739 
740 // Set the lod Index
741 void GLC_Mesh::setCurrentLod(const int value)
742 {
743  if (value)
744  {
745  const int numberOfLod= m_MeshData.lodCount();
746  // Clamp value to number of load
747  m_CurrentLod= static_cast<int>((static_cast<double>(value) / 100.0) * numberOfLod);
748  if (m_CurrentLod >= numberOfLod) m_CurrentLod = numberOfLod - 1;
749  if (m_CurrentLod < 0) m_CurrentLod = 0;
750  }
751  else
752  {
753  m_CurrentLod= 0;
754  }
755 }
756 // Replace the Master material
758 {
759  if (hasMaterial())
760  {
761  GLC_uint oldId= firstMaterial()->id();
762  replaceMaterial(oldId, pMat);
763  }
764  else
765  {
766  addMaterial(pMat);
767  }
768 }
769 
770 // Replace the material specified by id with another one
772 {
773  Q_ASSERT(containsMaterial(oldId));
774  Q_ASSERT(!containsMaterial(pMat->id()) || (pMat->id() == oldId));
775 
776  if (pMat->id() != oldId)
777  {
778  // Iterate over Level of detail
779  PrimitiveGroupsHash::const_iterator iGroups= m_PrimitiveGroups.constBegin();
780  while (m_PrimitiveGroups.constEnd() != iGroups)
781  {
782  LodPrimitiveGroups* pPrimitiveGroups= iGroups.value();
783  // Iterate over material group
784  LodPrimitiveGroups::iterator iGroup= pPrimitiveGroups->begin();
785  while (pPrimitiveGroups->constEnd() != iGroup)
786  {
787  if (iGroup.key() == oldId)
788  {
789  GLC_PrimitiveGroup* pGroup= iGroup.value();
790  // Erase old group pointer
791  pPrimitiveGroups->erase(iGroup);
792  // Change the group ID
793  pGroup->setId(pMat->id());
794  // Add the group with new ID
795  pPrimitiveGroups->insert(pMat->id(), pGroup);
796  iGroup= pPrimitiveGroups->end();
797  }
798  else
799  {
800  ++iGroup;
801  }
802  }
803  ++iGroups;
804  }
805  }
806 
807  if (pMat != m_MaterialHash.value(oldId))
808  {
809  // Remove old material
810  removeMaterial(oldId);
811 
812  addMaterial(pMat);
813  }
814 
815 }
816 
818 {
821 }
822 
824 {
827 }
828 
829 void GLC_Mesh::setVboUsage(bool usage)
830 {
831  if (!isEmpty())
832  {
834  m_MeshData.setVboUsage(usage);
835  }
836 }
837 
838 // Load the mesh from binary data stream
839 void GLC_Mesh::loadFromDataStream(QDataStream& stream, const MaterialHash& materialHash, const QHash<GLC_uint, GLC_uint>& materialIdMap)
840 {
841  quint32 chunckId;
842  stream >> chunckId;
843  Q_ASSERT(chunckId == m_ChunkId);
844 
845  // The mesh name
846  QString meshName;
847  stream >> meshName;
848  setName(meshName);
849 
850  // The wire data
851  stream >> GLC_Geometry::m_WireData;
852 
853  // The mesh next primitive local id
854  GLC_uint localId;
855  stream >> localId;
856  setNextPrimitiveLocalId(localId);
857 
858  // Retrieve geom mesh data
859  stream >> m_MeshData;
860 
861  // Retrieve primitiveGroupLodList
862  QList<int> primitiveGroupLodList;
863  stream >> primitiveGroupLodList;
864 
865  // Retrieve primitiveGroup list
866  QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
867  stream >> primitiveListOfGroupList;
868 
869  // Construct mesh primitiveGroupHash
870  const int lodCount= primitiveGroupLodList.size();
871  for (int i= 0; i < lodCount; ++i)
872  {
873  GLC_Mesh::LodPrimitiveGroups* pCurrentPrimitiveGroup= new GLC_Mesh::LodPrimitiveGroups();
874  m_PrimitiveGroups.insert(primitiveGroupLodList.at(i), pCurrentPrimitiveGroup);
875  const int groupCount= primitiveListOfGroupList.at(i).size();
876  for (int iGroup= 0; iGroup < groupCount; ++iGroup)
877  {
878  Q_ASSERT(materialIdMap.contains(primitiveListOfGroupList.at(i).at(iGroup).id()));
879  const GLC_uint newId= materialIdMap.value(primitiveListOfGroupList.at(i).at(iGroup).id());
880  // Test if the mesh contains the material
881  if (!containsMaterial(newId))
882  {
883  addMaterial(materialHash.value(newId));
884  }
885  GLC_PrimitiveGroup* pGroup= new GLC_PrimitiveGroup(primitiveListOfGroupList.at(i).at(iGroup), newId);
886 
887  Q_ASSERT(! m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->contains(newId));
888  m_PrimitiveGroups.value(primitiveGroupLodList.at(i))->insert(newId, pGroup);
889  }
890  }
891  stream >> m_NumberOfVertice;
892  stream >> m_NumberOfNormals;
893 
895 }
896 
897 // Save the mesh to binary data stream
898 void GLC_Mesh::saveToDataStream(QDataStream& stream) const
899 {
900  quint32 chunckId= m_ChunkId;
901  stream << chunckId;
902 
903  // The mesh name
904  stream << name();
905 
906  // The wire data
907  stream << m_WireData;
908 
909  // The mesh next primitive local id
910  stream << nextPrimitiveLocalId();
911 
912  // Mesh data serialisation
913  stream << m_MeshData;
914 
915  // Primitive groups serialisation
916  QList<int> primitiveGroupLodList;
917  QList<QList<GLC_PrimitiveGroup> > primitiveListOfGroupList;
918 
919  GLC_Mesh::PrimitiveGroupsHash::const_iterator iGroupsHash= m_PrimitiveGroups.constBegin();
920  while (m_PrimitiveGroups.constEnd() != iGroupsHash)
921  {
922  primitiveGroupLodList.append(iGroupsHash.key());
923  QList<GLC_PrimitiveGroup> primitiveGroupList;
924  GLC_Mesh::LodPrimitiveGroups::const_iterator iGroups= iGroupsHash.value()->constBegin();
925  while (iGroupsHash.value()->constEnd() != iGroups)
926  {
927  primitiveGroupList.append(*(iGroups.value()));
928  ++iGroups;
929  }
930  primitiveListOfGroupList.append(primitiveGroupList);
931  ++iGroupsHash;
932  }
933  stream << primitiveGroupLodList;
934  stream << primitiveListOfGroupList;
935 
936  stream << m_NumberOfVertice;
937  stream << m_NumberOfNormals;
938 }
939 
941 // OpenGL Functions
943 
944 // Virtual interface for OpenGL Geometry set up.
945 void GLC_Mesh::glDraw(const GLC_RenderProperties& renderProperties)
946 {
947 
949 
951 
953  && !renderProperties.setOfSelectedPrimitiveIdIsEmpty())
954  {
955  m_CurrentLod= 0;
956  }
957 
958  if (vboIsUsed)
959  {
961 
962  // Create VBO and IBO
964  {
965  fillVbosAndIbos();
966  }
967 
968  // Activate mesh VBOs and IBO of the current LOD
970  }
971  else
972  {
973  if (!m_GeometryIsValid)
974  {
976  }
978  }
979 
980  if (renderProperties.renderingFlag() == glc::OutlineSilhouetteRenderFlag) {
982  outlineSilhouetteRenderLoop(renderProperties, vboIsUsed);
983  }
984  else if (GLC_State::isInSelectionMode())
985  {
986  if (renderProperties.renderingMode() == glc::PrimitiveSelection)
987  {
988  primitiveSelectionRenderLoop(vboIsUsed);
989  }
990  else if (renderProperties.renderingMode() == glc::BodySelection)
991  {
992  bodySelectionRenderLoop(vboIsUsed);
993  }
994  else
995  {
996  normalRenderLoop(renderProperties, vboIsUsed);
997  }
998  }
999  else if (m_IsSelected)
1000  {
1001  if (renderProperties.renderingMode() == glc::PrimitiveSelected)
1002  {
1003  if (!renderProperties.setOfSelectedPrimitiveIdIsEmpty())
1004  {
1005  primitiveSelectedRenderLoop(renderProperties, vboIsUsed);
1006  }
1007  else
1008  {
1009  m_IsSelected= false;
1010  if ((m_CurrentLod == 0) && (renderProperties.savedRenderingMode() == glc::OverwritePrimitiveMaterial) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
1011  primitiveRenderLoop(renderProperties, vboIsUsed);
1012  else
1013  normalRenderLoop(renderProperties, vboIsUsed);
1014  m_IsSelected= true;
1015  }
1016  }
1017  else
1018  {
1019  normalRenderLoop(renderProperties, vboIsUsed);
1020  }
1021  }
1022  else
1023  {
1024  // Choose the accurate render loop
1025  switch (renderProperties.renderingMode())
1026  {
1027  case glc::NormalRenderMode:
1028  normalRenderLoop(renderProperties, vboIsUsed);
1029  break;
1031  OverwriteMaterialRenderLoop(renderProperties, vboIsUsed);
1032  break;
1034  OverwriteTransparencyRenderLoop(renderProperties, vboIsUsed);
1035  break;
1037  OverwriteTransparencyAndMaterialRenderLoop(renderProperties, vboIsUsed);
1038  break;
1040  if ((m_CurrentLod == 0) && !renderProperties.hashOfOverwritePrimitiveMaterialsIsEmpty())
1041  primitiveRenderLoop(renderProperties, vboIsUsed);
1042  else
1043  normalRenderLoop(renderProperties, vboIsUsed);
1044  break;
1045  default:
1046  Q_ASSERT(false);
1047  break;
1048  }
1049  }
1050 
1051 
1052  // Restore client state
1053 
1055  {
1056  glDisableClientState(GL_COLOR_ARRAY);
1057  glDisable(GL_COLOR_MATERIAL);
1058  }
1059 
1060  glDisableClientState(GL_VERTEX_ARRAY);
1061  glDisableClientState(GL_NORMAL_ARRAY);
1062  glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1063 
1064  if (vboIsUsed)
1065  {
1066  QGLBuffer::release(QGLBuffer::IndexBuffer);
1067  QGLBuffer::release(QGLBuffer::VertexBuffer);
1068  }
1069 
1070  // Draw mesh's wire if necessary
1071  if ((renderProperties.renderingFlag() == glc::WireRenderFlag) && !m_WireData.isEmpty() && !GLC_Geometry::typeIsWire())
1072  {
1074  {
1076  // Set polyline colors
1077  GLfloat color[4]= {static_cast<float>(m_WireColor.redF()),
1078  static_cast<float>(m_WireColor.greenF()),
1079  static_cast<float>(m_WireColor.blueF()),
1080  static_cast<float>(m_WireColor.alphaF())};
1081 
1082  glColor4fv(color);
1083  m_WireData.glDraw(renderProperties, GL_LINE_STRIP);
1085  }
1086  else
1087  {
1088  m_WireData.glDraw(renderProperties, GL_LINE_STRIP);
1089  }
1090  }
1091 
1092  // Update statistics
1095 }
1096 
1098 // Private services Functions
1100 
1101 // Set the current material
1102 GLC_uint GLC_Mesh::setCurrentMaterial(GLC_Material* pMaterial, int lod, double accuracy)
1103 {
1104 
1105  // Test if a primitive group hash exists for the specified lod
1106  if (!m_PrimitiveGroups.contains(lod))
1107  {
1108  m_PrimitiveGroups.insert(lod, new LodPrimitiveGroups());
1109 
1110  m_MeshData.appendLod(accuracy);
1111  }
1112 
1113  GLC_uint returnId;
1114  if (NULL == pMaterial)
1115  {
1116  returnId= m_DefaultMaterialId; // Default material id
1117 
1118  // Test if the material has been already load
1119  if (m_DefaultMaterialId == 0)
1120  {
1121  pMaterial= new GLC_Material();
1122  // Add the material to the mesh
1123  addMaterial(pMaterial);
1124  m_DefaultMaterialId= pMaterial->id();
1125  returnId= m_DefaultMaterialId;
1126 
1127  }
1128  // Test if a primitive group for this material exist
1129  if (!m_PrimitiveGroups.value(lod)->contains(returnId))
1130  {
1131  m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
1132  }
1133  }
1134  else
1135  {
1136  returnId= pMaterial->id();
1137  // Test if the material has been already load
1138  if (!containsMaterial(returnId))
1139  {
1140  // Add the material to the mesh
1141  addMaterial(pMaterial);
1142  m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
1143 
1144  }
1145  else if (!m_PrimitiveGroups.value(lod)->contains(returnId))
1146  {
1147  // Add the material to the group
1148  m_PrimitiveGroups.value(lod)->insert(returnId, new GLC_PrimitiveGroup(returnId));
1149  }
1150  }
1151 
1152  return returnId;
1153 }
1154 
1155 // Fill VBOs and IBOs
1157 {
1158  // Fill VBO of vertices
1160 
1161  // Fill VBO of normals
1163 
1164  // Fill VBO of texel if needed
1166 
1167  // Fill VBO of color if needed
1169 
1170  // Fill a lod IBO
1172 
1173 }
1174 // set primitive group offset
1176 {
1177  PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
1178  while (iGroups != m_PrimitiveGroups.constEnd())
1179  {
1180  LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
1181  while (iGroup != iGroups.value()->constEnd())
1182  {
1183  iGroup.value()->computeVboOffset();
1184  ++iGroup;
1185  }
1186  ++iGroups;
1187  }
1188 }
1189 /*
1190 // Move Indexs from the primitive groups to the mesh Data LOD and Set IBOs offsets
1191 void GLC_Mesh::finishVbo()
1192 {
1193  PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
1194  while (iGroups != m_PrimitiveGroups.constEnd())
1195  {
1196  int currentLod= iGroups.key();
1197  LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
1198  while (iGroup != iGroups.value()->constEnd())
1199  {
1200  // Add group triangles index to mesh Data LOD triangles index vector
1201  if (iGroup.value()->containsTriangles())
1202  {
1203  iGroup.value()->setTrianglesOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
1204  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
1205  }
1206 
1207  // Add group strip index to mesh Data LOD strip index vector
1208  if (iGroup.value()->containsStrip())
1209  {
1210  iGroup.value()->setBaseTrianglesStripOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
1211  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
1212  }
1213 
1214  // Add group fan index to mesh Data LOD fan index vector
1215  if (iGroup.value()->containsFan())
1216  {
1217  iGroup.value()->setBaseTrianglesFanOffset(BUFFER_OFFSET(m_MeshData.indexVectorSize(currentLod) * sizeof(GLuint)));
1218  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
1219  }
1220 
1221  iGroup.value()->finish();
1222  ++iGroup;
1223  }
1224  ++iGroups;
1225 
1226  }
1227 }
1228 */
1229 
1230 // Move Indexs from the primitive groups to the mesh Data LOD and Set Index offsets
1232 {
1233  //qDebug() << "GLC_Mesh::moveIndexToMeshDataLod()";
1234  PrimitiveGroupsHash::iterator iGroups= m_PrimitiveGroups.begin();
1235  while (iGroups != m_PrimitiveGroups.constEnd())
1236  {
1237  int currentLod= iGroups.key();
1238  LodPrimitiveGroups::iterator iGroup= iGroups.value()->begin();
1239  while (iGroup != iGroups.value()->constEnd())
1240  {
1241  // Add group triangles index to mesh Data LOD triangles index vector
1242  if (iGroup.value()->containsTriangles())
1243  {
1244  iGroup.value()->setTrianglesOffseti(m_MeshData.indexVectorSize(currentLod));
1245  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->trianglesIndex().toVector();
1246  }
1247 
1248  // Add group strip index to mesh Data LOD strip index vector
1249  if (iGroup.value()->containsStrip())
1250  {
1251  iGroup.value()->setBaseTrianglesStripOffseti(m_MeshData.indexVectorSize(currentLod));
1252  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->stripsIndex().toVector();
1253  }
1254 
1255  // Add group fan index to mesh Data LOD fan index vector
1256  if (iGroup.value()->containsFan())
1257  {
1258  iGroup.value()->setBaseTrianglesFanOffseti(m_MeshData.indexVectorSize(currentLod));
1259  (*m_MeshData.indexVectorHandle(currentLod))+= iGroup.value()->fansIndex().toVector();
1260  }
1261 
1262  iGroup.value()->computeVboOffset();
1263  iGroup.value()->finish();
1264  ++iGroup;
1265  }
1266  ++iGroups;
1267  }
1268 }
1269 
1270 // The normal display loop
1271 void GLC_Mesh::normalRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1272 {
1273  const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1274  if ((!m_IsSelected || !isTransparent) || GLC_State::isInSelectionMode())
1275  {
1276  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1277  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1278  {
1279  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1280  GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
1281 
1282  // Test if the current material is renderable
1283  bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
1284 
1285  // Choose the material to render
1286  if ((materialIsrenderable || m_IsSelected) && !GLC_State::isInSelectionMode())
1287  {
1288  // Execute current material
1289  pCurrentMaterial->glExecute();
1290 
1292  }
1293 
1294  // Choose the primitives to render
1295  if (m_IsSelected || GLC_State::isInSelectionMode() || materialIsrenderable)
1296  {
1297 
1298  if (vboIsUsed)
1299  {
1300  vboDrawPrimitivesOf(pCurrentGroup);
1301  }
1302  else
1303  {
1304  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1305  }
1306  }
1307 
1308  ++iGroup;
1309  }
1310  }
1311 }
1312 
1313 // The overwrite material render loop
1314 void GLC_Mesh::OverwriteMaterialRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1315 {
1316  // Get the overwrite material
1317  GLC_Material* pOverwriteMaterial= renderProperties.overwriteMaterial();
1318  Q_ASSERT(NULL != pOverwriteMaterial);
1319  pOverwriteMaterial->glExecute();
1321 
1322  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1323  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1324  {
1325  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1326 
1327  // Test if the current material is renderable
1328  bool materialIsrenderable = (pOverwriteMaterial->isTransparent() == (renderProperties.renderingFlag() == glc::TransparentRenderFlag));
1329 
1330  // Choose the primitives to render
1331  if (m_IsSelected || materialIsrenderable)
1332  {
1333 
1334  if (vboIsUsed)
1335  vboDrawPrimitivesOf(pCurrentGroup);
1336  else
1337  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1338  }
1339 
1340  ++iGroup;
1341  }
1342 }
1343 // The overwrite transparency render loop
1344 void GLC_Mesh::OverwriteTransparencyRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1345 {
1346  // Get transparency value
1347  const float alpha= renderProperties.overwriteTransparency();
1348  Q_ASSERT(-1.0f != alpha);
1349 
1350  // Test if the current material is renderable
1351  bool materialIsrenderable = (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1352 
1353  if (materialIsrenderable || m_IsSelected)
1354  {
1355  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1356  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1357  {
1358  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1359  GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
1360 
1361  // Execute current material
1362  pCurrentMaterial->glExecute(alpha);
1363 
1365 
1366  // Choose the primitives to render
1367  if (m_IsSelected || materialIsrenderable)
1368  {
1369 
1370  if (vboIsUsed)
1371  vboDrawPrimitivesOf(pCurrentGroup);
1372  else
1373  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1374  }
1375  ++iGroup;
1376  }
1377  }
1378 }
1379 
1381 {
1382  // Get transparency value
1383  const float alpha= renderProperties.overwriteTransparency();
1384  Q_ASSERT(-1.0f != alpha);
1385 
1386  // Get the overwrite material
1387  GLC_Material* pOverwriteMaterial= renderProperties.overwriteMaterial();
1388  Q_ASSERT(NULL != pOverwriteMaterial);
1389  pOverwriteMaterial->glExecute(alpha);
1391 
1392  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1393  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1394  {
1395  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1396 
1397  // Test if the current material is renderable
1398  bool materialIsrenderable = (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1399 
1400  // Choose the primitives to render
1401  if (m_IsSelected || materialIsrenderable)
1402  {
1403 
1404  if (vboIsUsed)
1405  vboDrawPrimitivesOf(pCurrentGroup);
1406  else
1407  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1408  }
1409 
1410  ++iGroup;
1411  }
1412 }
1413 
1414 // The body selection render loop
1416 {
1417  Q_ASSERT(GLC_State::isInSelectionMode());
1418 
1419  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1420  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1421  {
1422  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1423 
1424  if (vboIsUsed)
1425  vboDrawPrimitivesOf(pCurrentGroup);
1426  else
1427  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1428 
1429  ++iGroup;
1430  }
1431 }
1432 
1433 // The primitive selection render loop
1435 {
1436  Q_ASSERT(GLC_State::isInSelectionMode());
1437 
1438  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1439 
1440  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1441  {
1442  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1443 
1444  if (vboIsUsed)
1445  vboDrawInSelectionModePrimitivesOf(pCurrentGroup);
1446  else
1448 
1449  ++iGroup;
1450  }
1451 }
1452 
1453 // The primitive rendeder loop
1454 void GLC_Mesh::primitiveRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1455 {
1456  const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1457  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1458  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1459  {
1460  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1461  GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
1462 
1463  // Test if the current material is renderable
1464  const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
1465 
1466  if (materialIsrenderable)
1467  {
1468  pCurrentMaterial->glExecute();
1469  }
1470  if (vboIsUsed)
1471  vboDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
1472  else
1473  vertexArrayDrawPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties.hashOfOverwritePrimitiveMaterials());
1474 
1475  ++iGroup;
1476  }
1477 }
1478 
1479 // The primitive Selected render loop
1480 void GLC_Mesh::primitiveSelectedRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1481 {
1482  const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1483  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1484  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1485  {
1486  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1487  GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
1488 
1489  // Test if the current material is renderable
1490  const bool materialIsrenderable = (pCurrentMaterial->isTransparent() == isTransparent);
1491 
1492  if (materialIsrenderable)
1493  {
1494  pCurrentMaterial->glExecute();
1495  }
1496 
1497  if (vboIsUsed)
1498  vboDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
1499  else
1500  vertexArrayDrawSelectedPrimitivesGroupOf(pCurrentGroup, pCurrentMaterial, materialIsrenderable, isTransparent, renderProperties);
1501 
1502  ++iGroup;
1503  }
1504 }
1505 
1506 // The outline silhouette render loop (draws in special colors for edge detection, passes extra data encoded in color)
1507 void GLC_Mesh::outlineSilhouetteRenderLoop(const GLC_RenderProperties& renderProperties, bool vboIsUsed)
1508 {
1509  const bool isTransparent= (renderProperties.renderingFlag() == glc::TransparentRenderFlag);
1510  //if ((!m_IsSelected || !isTransparent) || GLC_State::isInSelectionMode())
1511  if ((!isTransparent) || GLC_State::isInSelectionMode())
1512  {
1513  LodPrimitiveGroups::iterator iGroup= m_PrimitiveGroups.value(m_CurrentLod)->begin();
1514  while (iGroup != m_PrimitiveGroups.value(m_CurrentLod)->constEnd())
1515  {
1516  GLC_PrimitiveGroup* pCurrentGroup= iGroup.value();
1517  //GLC_Material* pCurrentMaterial= m_MaterialHash.value(pCurrentGroup->id());
1518 
1519  // Encode silhouette information in RGBA color
1520  GLubyte colorId[4];
1521  int uid = pCurrentGroup->id() + (id() << 16);
1522  int uid_flags = 0;
1523  if (renderProperties.isSelected()) {
1524  uid_flags = uid_flags | 0x800000; //Selection flag
1525  }
1526 
1527  glDisable(GL_TEXTURE_2D);
1528  glEnable(GL_CULL_FACE);
1529  glCullFace(GL_BACK);
1530 
1531  // Draw front faces
1532  glc::encodeRgbId(((uid) & 0x7FFFFF) | uid_flags,colorId);
1533  glColor4ubv(colorId);
1534  glFrontFace(GL_CCW);
1535  if (vboIsUsed)
1536  {
1537  vboDrawPrimitivesOf(pCurrentGroup);
1538  }
1539  else
1540  {
1541  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1542  }
1543 
1544  // Draw back faces
1545  glc::encodeRgbId(((~uid) & 0x7FFFFF) | uid_flags,colorId);
1546  glColor4ubv(colorId);
1547  glFrontFace(GL_CW);
1548  if (vboIsUsed)
1549  {
1550  vboDrawPrimitivesOf(pCurrentGroup);
1551  }
1552  else
1553  {
1554  vertexArrayDrawPrimitivesOf(pCurrentGroup);
1555  }
1556 
1557  glFrontFace(GL_CCW);
1558  glDisable(GL_CULL_FACE);
1559  ++iGroup;
1560  }
1561  }
1562 }
1563 
1564 void GLC_Mesh::copyIndex(int lodIndex, GLC_Mesh* pLodMesh, QHash<GLuint, GLuint>& sourceToTargetIndexMap, QHash<GLuint, GLuint>& tagetToSourceIndexMap, int& maxIndex, int targetLod)
1565 {
1567  QList<GLuint> materialId= m_PrimitiveGroups.value(lodIndex)->keys();
1568 
1569  const int materialCount= materialId.size();
1570  for (int i= 0; i < materialCount; ++i)
1571  {
1572  GLuint currentMaterialId= materialId.at(i);
1573  GLC_Material* pCurrentMaterial= GLC_Geometry::material(currentMaterialId);
1574 
1575  // Triangles
1576  if (containsTriangles(lodIndex, currentMaterialId))
1577  {
1578  QVector<GLuint> sourceTriangleIndex= getTrianglesIndex(lodIndex, currentMaterialId);
1579  QList<GLuint> targetTriangleIndex;
1580  const int triangleIndexCount= sourceTriangleIndex.size();
1581  for (int i= 0; i < triangleIndexCount; ++i)
1582  {
1583  const GLuint currentIndex= sourceTriangleIndex.at(i);
1584  if (!sourceToTargetIndexMap.contains(currentIndex))
1585  {
1586  sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
1587  tagetToSourceIndexMap.insert(maxIndex, currentIndex);
1588  targetTriangleIndex.append(maxIndex);
1589  }
1590  else
1591  {
1592  targetTriangleIndex.append(sourceToTargetIndexMap.value(currentIndex));
1593  }
1594  }
1595  pLodMesh->addTriangles(pCurrentMaterial, targetTriangleIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
1596  }
1597 
1598  //Triangles strips
1599  if (containsStrips(lodIndex, currentMaterialId))
1600  {
1601  QList<QVector<GLuint> > sourceStripIndex= getStripsIndex(lodIndex, currentMaterialId);
1602  const int stripCount= sourceStripIndex.size();
1603  for (int stripIndex= 0; stripIndex < stripCount; ++stripIndex)
1604  {
1605 
1606  QVector<GLuint> sourceTriangleStripIndex= sourceStripIndex.at(stripIndex);
1607  QList<GLuint> targetTriangleStripIndex;
1608  const int triangleStripIndexCount= sourceTriangleStripIndex.size();
1609  for (int i= 0; i < triangleStripIndexCount; ++i)
1610  {
1611  const GLuint currentIndex= sourceTriangleStripIndex.at(i);
1612  if (!sourceToTargetIndexMap.contains(currentIndex))
1613  {
1614  sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
1615  tagetToSourceIndexMap.insert(maxIndex, currentIndex);
1616  targetTriangleStripIndex.append(maxIndex);
1617  }
1618  else
1619  {
1620  targetTriangleStripIndex.append(sourceToTargetIndexMap.value(currentIndex));
1621  }
1622  }
1623  pLodMesh->addTrianglesStrip(pCurrentMaterial, targetTriangleStripIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
1624  }
1625  }
1626  //Triangles fans
1627  if (containsFans(lodIndex, currentMaterialId))
1628  {
1629  QList<QVector<GLuint> > sourceFanIndex= getFansIndex(lodIndex, currentMaterialId);
1630  const int fanCount= sourceFanIndex.size();
1631  for (int fanIndex= 0; fanIndex < fanCount; ++fanIndex)
1632  {
1633 
1634  QVector<GLuint> sourceTriangleFanIndex= sourceFanIndex.at(fanIndex);
1635  QList<GLuint> targetTriangleFanIndex;
1636  const int triangleFanIndexCount= sourceTriangleFanIndex.size();
1637  for (int i= 0; i < triangleFanIndexCount; ++i)
1638  {
1639  const GLuint currentIndex= sourceTriangleFanIndex.at(i);
1640  if (!sourceToTargetIndexMap.contains(currentIndex))
1641  {
1642  sourceToTargetIndexMap.insert(currentIndex, ++maxIndex);
1643  tagetToSourceIndexMap.insert(maxIndex, currentIndex);
1644  targetTriangleFanIndex.append(maxIndex);
1645  }
1646  else
1647  {
1648  targetTriangleFanIndex.append(sourceToTargetIndexMap.value(currentIndex));
1649  }
1650  }
1651  pLodMesh->addTrianglesFan(pCurrentMaterial, targetTriangleFanIndex, targetLod, m_MeshData.getLod(lodIndex)->accuracy());
1652  }
1653  }
1654  }
1655 }
1656 
1657 void GLC_Mesh::copyBulkData(GLC_Mesh* pLodMesh, const QHash<GLuint, GLuint>& tagetToSourceIndexMap, int maxIndex)
1658 {
1659  GLfloatVector tempFloatVector;
1660  int stride= 3;
1661  // Extract position bulk data
1662  Q_ASSERT(!m_MeshData.positionVectorHandle()->isEmpty());
1663  tempFloatVector.resize(stride * (maxIndex + 1));
1664  for (int i= 0; i < maxIndex + 1; ++i)
1665  {
1666  GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
1667  GLfloat* pSource= &(m_MeshData.positionVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
1668 
1669  memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
1670  }
1671  pLodMesh->addVertice(tempFloatVector);
1672  tempFloatVector.clear();
1673 
1674  // Extract normal bulk data
1675  Q_ASSERT(!m_MeshData.normalVectorHandle()->isEmpty());
1676  tempFloatVector.resize(stride * (maxIndex + 1));
1677  for (int i= 0; i < maxIndex + 1; ++i)
1678  {
1679  GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
1680  GLfloat* pSource= &(m_MeshData.normalVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
1681 
1682  memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
1683  }
1684  pLodMesh->addNormals(tempFloatVector);
1685  tempFloatVector.clear();
1686 
1687  if (!m_MeshData.texelVectorHandle()->isEmpty())
1688  {
1689  // Extract texel bulk data
1690  stride= 2;
1691  tempFloatVector.resize(stride * (maxIndex + 1));
1692 
1693  for (int i= 0; i < maxIndex + 1; ++i)
1694  {
1695  GLfloat* pTarget= &(tempFloatVector.data()[i * stride]);
1696  GLfloat* pSource= &(m_MeshData.texelVectorHandle()->data()[tagetToSourceIndexMap.value(i) * stride]);
1697 
1698  memcpy(pTarget, pSource, sizeof(GLfloat) * stride);
1699  }
1700  pLodMesh->addTexels(tempFloatVector);
1701  tempFloatVector.clear();
1702  }
1703 }
1704 
1706 {
1707  IndexList trianglesIndex;
1708  if (containsStrips(lodIndex, materialId))
1709  {
1710  const QList<QVector<GLuint> > stripsIndex= getStripsIndex(lodIndex, materialId);
1711  const int stripCount= stripsIndex.count();
1712  for (int i= 0; i < stripCount; ++i)
1713  {
1714  const QVector<GLuint> currentStripIndex= stripsIndex.at(i);
1715 
1716  trianglesIndex.append(currentStripIndex.at(0));
1717  trianglesIndex.append(currentStripIndex.at(1));
1718  trianglesIndex.append(currentStripIndex.at(2));
1719  const int stripSize= currentStripIndex.size();
1720  for (int j= 3; j < stripSize; ++j)
1721  {
1722  if ((j % 2) != 0)
1723  {
1724  trianglesIndex.append(currentStripIndex.at(j));
1725  trianglesIndex.append(currentStripIndex.at(j - 1));
1726  trianglesIndex.append(currentStripIndex.at(j - 2));
1727  }
1728  else
1729  {
1730  trianglesIndex.append(currentStripIndex.at(j));
1731  trianglesIndex.append(currentStripIndex.at(j - 2));
1732  trianglesIndex.append(currentStripIndex.at(j - 1));
1733  }
1734  }
1735  }
1736  }
1737  return trianglesIndex;
1738 }
1739 
1741 {
1742  IndexList trianglesIndex;
1743  if (containsFans(lodIndex, materialId))
1744  {
1745  const QList<QVector<GLuint> > fanIndex= getFansIndex(lodIndex, materialId);
1746  const int fanCount= fanIndex.count();
1747  for (int i= 0; i < fanCount; ++i)
1748  {
1749  const QVector<GLuint> currentFanIndex= fanIndex.at(i);
1750  const int size= currentFanIndex.size();
1751  for (int j= 1; j < size - 1; ++j)
1752  {
1753  trianglesIndex.append(currentFanIndex.first());
1754  trianglesIndex.append(currentFanIndex.at(j));
1755  trianglesIndex.append(currentFanIndex.at(j + 1));
1756  }
1757  }
1758  }
1759  return trianglesIndex;
1760 }
1761 

©2005-2013 Laurent Ribon