Visualization Library 2.0.0

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
Geometry.cpp
Go to the documentation of this file.
1 /**************************************************************************************/
2 /* */
3 /* Visualization Library */
4 /* http://visualizationlibrary.org */
5 /* */
6 /* Copyright (c) 2005-2020, Michele Bosi */
7 /* All rights reserved. */
8 /* */
9 /* Redistribution and use in source and binary forms, with or without modification, */
10 /* are permitted provided that the following conditions are met: */
11 /* */
12 /* - Redistributions of source code must retain the above copyright notice, this */
13 /* list of conditions and the following disclaimer. */
14 /* */
15 /* - Redistributions in binary form must reproduce the above copyright notice, this */
16 /* list of conditions and the following disclaimer in the documentation and/or */
17 /* other materials provided with the distribution. */
18 /* */
19 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */
20 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
21 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */
22 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */
23 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */
24 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */
25 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */
26 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
27 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
28 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
29 /* */
30 /**************************************************************************************/
31 
32 #include <vlGraphics/Geometry.hpp>
37 #include <cmath>
38 #include <algorithm>
39 
40 using namespace vl;
41 
42 //-----------------------------------------------------------------------------
43 // Geometry
44 //-----------------------------------------------------------------------------
46 {
47  VL_DEBUG_SET_OBJECT_NAME()
48  mDrawCalls.setAutomaticDelete(false);
49 }
50 //-----------------------------------------------------------------------------
52 {
53 }
54 //-----------------------------------------------------------------------------
56 {
57  const ArrayAbstract* coords = vertexArray();
58 
59  if (coords == NULL)
60  {
61  Log::debug("Geometry::computeBounds_Implementation() failed! No vertex buffer present!\n");
62  return;
63  }
64 
65  if (coords->size() == 0)
66  {
67  Log::debug("Geometry::computeBounds_Implementation() failed! No vertices present in the local buffer! Did you forget to call setBoundingBox() and setBoundingSphere()?\n");
68  return;
69  }
70 
71  AABB aabb;
72  for(int i=0; i<drawCalls().size(); ++i)
73  {
74  for(IndexIterator iit = drawCalls().at(i)->indexIterator(); iit.hasNext(); iit.next())
75  {
76  aabb += coords->getAsVec3( iit.index() );
77  }
78  }
79 
80  real radius = 0, r = 0;
81  vec3 center = aabb.center();
82  for(int i=0; i<drawCalls().size(); ++i)
83  {
84  for(IndexIterator iit = drawCalls().at(i)->indexIterator(); iit.hasNext(); iit.next())
85  {
86  r = (coords->getAsVec3(iit.index()) - center).lengthSquared();
87  if (r > radius)
88  radius = r;
89  }
90  }
91 
92  setBoundingBox( aabb );
93  setBoundingSphere( Sphere(center, radius) );
94 }
95 //-----------------------------------------------------------------------------
97 {
98  ref<Geometry> geom = new Geometry;
99  geom->deepCopyFrom(*this);
100  return geom;
101 }
102 //-----------------------------------------------------------------------------
104 {
105  // copy the base class Renderable
106  super::operator=(other);
107 
108  // clone generic vertex attribs
109  for(int i=0; i<VA_MaxAttribCount; ++i)
110  {
111  if ( other.mVertexAttribArrays[i].get() ) {
112  mVertexAttribArrays[i] = other.mVertexAttribArrays[i]->clone().get();
113  } else {
115  }
116  }
117 
118  // primitives
119  mDrawCalls.clear();
120  for(int i=0; i<other.mDrawCalls.size(); ++i) {
121  mDrawCalls.push_back( other.mDrawCalls[i]->clone().get() );
122  }
123 
124  return *this;
125 }
126 //-----------------------------------------------------------------------------
128 {
129  ref<Geometry> geom = new Geometry;
130  geom->shallowCopyFrom(*this);
131  return geom;
132 }
133 //-----------------------------------------------------------------------------
135 {
136  // copy the base class Renderable
137  super::operator=(other);
138 
139  // draw calls
140  mDrawCalls = other.mDrawCalls;
141 
142  // copy generic vertex attribs
143  for(int i=0; i<VA_MaxAttribCount; ++i)
144  {
145  if ( other.mVertexAttribArrays[i].get() ) {
146  mVertexAttribArrays[i] = const_cast<ArrayAbstract*>( other.mVertexAttribArrays[i].get() );
147  } else {
149  }
150  }
151 
152  return *this;
153 }
154 //-----------------------------------------------------------------------------
156 {
157  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
158  // to see what "size" and "type" are allowed for glVertexPointer
159  VL_CHECK( !data || (data->glSize() >=2 && data->glSize()<=4) )
160 
162 }
163 //-----------------------------------------------------------------------------
165 {
166  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
167  // to see what "size" and "type" are allowed for glNormalPointer
168  VL_CHECK( !data || data->glSize() == 3 )
169  VL_CHECK( !data || (data->glType() == GL_BYTE||
170  data->glType() == GL_SHORT ||
171  data->glType() == GL_INT ||
172  data->glType() == GL_FLOAT ||
173  data->glType() == GL_DOUBLE) );
174 
176 }
177 //-----------------------------------------------------------------------------
179 {
180  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
181  // to see what "size" and "type" are allowed for glColorPointer
182  VL_CHECK( !data || (data->glSize() >=3 && data->glSize()<=4) )
183  VL_CHECK( !data || (data->glType() == GL_BYTE ||
184  data->glType() == GL_SHORT ||
185  data->glType() == GL_INT ||
186  data->glType() == GL_UNSIGNED_BYTE ||
187  data->glType() == GL_UNSIGNED_SHORT ||
188  data->glType() == GL_UNSIGNED_INT ||
189  data->glType() == GL_FLOAT ||
190  data->glType() == GL_DOUBLE) );
191 
193 }
194 //-----------------------------------------------------------------------------
196 {
197  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
198  // to see what "size" and "type" are allowed for glSecondaryColorPointer
199  VL_CHECK( !data || (data->glSize() >=3 && data->glSize()<=4) )
200  VL_CHECK( !data || (data->glType() == GL_BYTE ||
201  data->glType() == GL_SHORT ||
202  data->glType() == GL_INT ||
203  data->glType() == GL_UNSIGNED_BYTE ||
204  data->glType() == GL_UNSIGNED_SHORT ||
205  data->glType() == GL_UNSIGNED_INT ||
206  data->glType() == GL_FLOAT ||
207  data->glType() == GL_DOUBLE) );
208 
210 }
211 //-----------------------------------------------------------------------------
213 {
214  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
215  // to see what "size" and "type" are allowed for glFogCoordPointer
216  VL_CHECK( !data || (data->glSize() == 1) )
217  VL_CHECK( !data || (data->glType() == GL_FLOAT || data->glType() == GL_DOUBLE) );
218 
220 }
221 //-----------------------------------------------------------------------------
222 void Geometry::setTexCoordArray(int tex_unit, ArrayAbstract* data)
223 {
224  // if one of this checks fail read the OpenGL Programmers Guide or the Reference Manual
225  // to see what "size" and "type" are allowed for glTexCoordPointer
226  VL_CHECK( !data || (data->glSize() == 1 || data->glSize() == 2 || data->glSize() == 3 || data->glSize() == 4) )
227  VL_CHECK( !data || (data->glType() == GL_FLOAT ||
228  data->glType() == GL_DOUBLE ||
229  data->glType() == GL_SHORT ||
230  data->glType() == GL_INT) );
231 
232  VL_CHECK( tex_unit < VA_MaxTexCoordCount );
233 
234  mVertexAttribArrays[VA_TexCoord0 + tex_unit] = data;
235 }
236 //-----------------------------------------------------------------------------
237 void Geometry::clearArrays(bool clear_draw_calls)
238 {
239  setBufferObjectDirty(true);
240 
241  if (clear_draw_calls) {
242  mDrawCalls.clear();
243  }
244 
245  for(int i=0; i<VA_MaxAttribCount; ++i) {
247  }
248 }
249 //-----------------------------------------------------------------------------
251 {
252  ArrayAbstract* normarr = normalArray();
253 
254  if (normarr)
255  {
256  ArrayFloat3* norm3f = normarr->as<ArrayFloat3>();
257  if (norm3f)
258  {
259  for(u32 i=0; i<norm3f->size(); ++i)
260  {
261  norm3f->at(i) = -norm3f->at(i);
262  }
263  return true;
264  }
265  }
266  return false;
267 }
268 //-----------------------------------------------------------------------------
269 void Geometry::computeNormals(bool verbose)
270 {
271  // Retrieve vertex position array
272  ArrayAbstract* posarr = vertexArray();
273  if (!posarr || posarr->size() == 0)
274  {
275  Log::warning("Geometry::computeNormals() failed: no vertices found!\n");
276  return;
277  }
278 
279  ref<ArrayFloat3> norm3f = new ArrayFloat3;
280  norm3f->resize( posarr->size() );
281 
282  // Install the normal array
283  setNormalArray( norm3f.get() );
284 
285  // zero the normals
286  for(u32 i=0; i<norm3f->size(); ++i)
287  (*norm3f)[i] = 0;
288 
289  // iterate all draw calls
290  for(int prim=0; prim<(int)drawCalls().size(); prim++)
291  {
292  // iterate all triangles, if present
293  for(TriangleIterator trit = mDrawCalls[prim]->triangleIterator(); trit.hasNext(); trit.next())
294  {
295  u32 a = trit.a();
296  u32 b = trit.b();
297  u32 c = trit.c();
298 
299  if (verbose)
300  if (a == b || b == c || c == a)
301  {
302  Log::warning( Say("Geometry::computeNormals(): skipping degenerate triangle %n %n %n\n") << a << b << c );
303  continue;
304  }
305 
306  VL_CHECK( a < posarr->size() )
307  VL_CHECK( b < posarr->size() )
308  VL_CHECK( c < posarr->size() )
309 
310  vec3 n, v0, v1, v2;
311 
312  v0 = posarr->getAsVec3(a);
313  v1 = posarr->getAsVec3(b);
314  v2 = posarr->getAsVec3(c);
315 
316  if (verbose)
317  if (v0 == v1 || v1 == v2 || v2 == v0)
318  {
319  Log::warning("Geometry::computeNormals(): skipping degenerate triangle (same vertex coodinate).\n");
320  continue;
321  }
322 
323  v1 -= v0;
324  v2 -= v0;
325 
326  n = cross(v1, v2);
327  n.normalize();
328  if (verbose)
329  if ( fabs(1.0f - n.length()) > 0.1f )
330  {
331  Log::warning("Geometry::computeNormals(): skipping degenerate triangle (normalization failed).\n");
332  continue;
333  }
334 
335  (*norm3f)[a] += (fvec3)n;
336  (*norm3f)[b] += (fvec3)n;
337  (*norm3f)[c] += (fvec3)n;
338  }
339  }
340 
341  // normalize the normals
342  for(int i=0; i<(int)norm3f->size(); ++i)
343  (*norm3f)[i].normalize();
344 }
345 //-----------------------------------------------------------------------------
347 {
348  if (!Has_BufferObject)
349  return;
350 
351  for(int i=0; i<(int)drawCalls().size(); ++i) {
352  drawCalls().at(i)->deleteBufferObject();
353  }
354 
355  for(int i=0; i<VA_MaxAttribCount; ++i) {
356  if ( mVertexAttribArrays[i]->bufferObject() ) {
357  mVertexAttribArrays[i]->bufferObject()->deleteBufferObject();
358  }
359  }
360 }
361 //-----------------------------------------------------------------------------
363 {
364  if (!Has_BufferObject)
365  return;
366 
367  bool force_update = (mode & BUF_ForceUpdate) != 0;
368 
369  for(int i=0; i<VA_MaxAttribCount; ++i) {
370  if ( mVertexAttribArrays[i].get() && mVertexAttribArrays[i]->bufferObject() && (mVertexAttribArrays[i]->isBufferObjectDirty() || force_update) ) {
371  mVertexAttribArrays[i]->updateBufferObject(mode);
372  }
373  }
374 
375  for(int i=0; i<drawCalls().size(); ++i)
376  drawCalls().at(i)->updateDirtyBufferObject(mode);
377 }
378 //-----------------------------------------------------------------------------
379 void Geometry::render_Implementation(const Actor*, const Shader*, const Camera*, OpenGLContext* gl_ctx) const
380 {
381  VL_CHECK_OGL()
382 
383  // bind Vertex Attrib Set
384 
386  gl_ctx->bindVAS(this, vbo_on, false);
387 
388  // actual draw
389 
390  for( int i = 0; i < (int)drawCalls().size(); i++ ) {
391  if ( drawCalls().at(i)->isEnabled() ) {
392  drawCalls().at(i)->render( vbo_on );
393  }
394  }
395 
396  VL_CHECK_OGL()
397 }
398 //-----------------------------------------------------------------------------
399 void Geometry::transform(const mat4& m, bool normalize)
400 {
401  ArrayAbstract* posarr = vertexArray();
402  if (posarr)
403  posarr->transform(m);
404 
405  ArrayAbstract* normarr = normalArray();
406  if (normarr)
407  {
408  mat4 nmat = m.as3x3().invert().transpose();
409  normarr->transform(nmat);
410  if (normalize)
411  normarr->normalize();
412  }
413 }
414 //-----------------------------------------------------------------------------
415 void Geometry::setVertexAttribArray(int attrib_location, const ArrayAbstract* info)
416 {
417  mVertexAttribArrays[attrib_location] = info;
418 }
419 //-----------------------------------------------------------------------------
420 const ArrayAbstract* Geometry::vertexAttribArray(int attrib_location) const
421 {
422  return mVertexAttribArrays[attrib_location].get();
423 }
424 //-----------------------------------------------------------------------------
426 {
427  return mVertexAttribArrays[attrib_location].get();
428 }
429 //-----------------------------------------------------------------------------
431 {
432  ArrayAbstract* posarr = vertexArray();
433 
434  if (!posarr)
435  return NULL;
436 
437  std::vector< ref<DrawElementsBase> > de_vector;
438  std::vector<u32> indices;
439 
440  // collect DrawElementsUInt
441  for(int i=drawCalls().size(); i--; )
442  {
443  ref<DrawElementsBase> deb = cast<DrawElementsBase>( drawCalls().at(i) );
444  if (deb && deb->primitiveType() == PT_TRIANGLE_STRIP)
445  {
446  // preserve order
447  de_vector.push_back( deb );
448  drawCalls().eraseAt(i);
449  }
450  }
451  // preseve rendering order
452  std::reverse(de_vector.begin(), de_vector.end());
453 
454  // generate new strip
455  indices.reserve( posarr->size()*2 );
456  for(u32 i=0; i<de_vector.size(); ++i)
457  {
458  u32 index_count = 0;
459  for(IndexIterator it=de_vector[i]->indexIterator(); it.hasNext(); it.next(), ++index_count)
460  indices.push_back(it.index());
461 
462  if (index_count == 0)
463  continue;
464 
465  // odd -> even
466  if ( index_count % 2 )
467  indices.push_back( indices.back() );
468 
469  // concatenate next strip inserting degenerate triangles
470  if ( i != de_vector.size()-1 )
471  {
472  // grab the first two indices of the next draw call
473  IndexIterator it = de_vector[i+1]->indexIterator();
474  int A = it.index();
475  it.next();
476  int B = it.index();
477 
478  if (A == -1 || B == -1)
479  continue;
480 
481  indices.push_back( indices.back() );
482  indices.push_back(A);
483  indices.push_back(A);
484  indices.push_back(B);
485  }
486  }
487 
488  if (indices.size())
489  {
491  draw_elems->indexBuffer()->resize(indices.size());
492  memcpy(draw_elems->indexBuffer()->ptr(), &indices[0], sizeof(indices[0])*indices.size());
493  drawCalls().push_back(draw_elems.get());
494  return draw_elems.get();
495  }
496  else
497  return NULL;
498 }
499 //-----------------------------------------------------------------------------
501 {
502  u32 total_index_count = 0;
503  std::vector< ref<DrawCall> > mergendo_calls;
504  for( u32 i=drawCalls().size(); i--; )
505  {
506  if (drawCalls().at(i)->primitiveType() == primitive_type)
507  {
508  int index_count = drawCalls().at(i)->countIndices();
509  VL_CHECK(index_count >= 0);
510  total_index_count += index_count;
511  // insert at the head to preserve the primitive rendering order
512  mergendo_calls.push_back( drawCalls().at(i) );
513  drawCalls().eraseAt(i);
514  }
515  }
516  // preseve rendering order
517  std::reverse(mergendo_calls.begin(), mergendo_calls.end());
518 
519  Log::debug( Say("%n draw calls will be merged using primitive restart.\n") << mergendo_calls.size() );
520 
521  if (mergendo_calls.empty())
522  return;
523 
524 //#ifndef NDEBUG
525 // ArrayAbstract* posarr = vertexArray();
526 //#endif
527 
528  ref<DrawElementsUInt> de_prim_restart = new DrawElementsUInt(primitive_type);
529  // make space for all the indices plus the primitive restart markers.
530  de_prim_restart->indexBuffer()->resize(total_index_count + mergendo_calls.size()-1);
531  GLuint* index = de_prim_restart->indexBuffer()->begin();
532  // merge draw calls using primitive restart!
533  for( u32 i=0; i<mergendo_calls.size(); ++i )
534  {
535  for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
536  {
537  *index = it.index();
538  // VL_CHECK(*index < posarr->size());
539  }
540  if ( i != mergendo_calls.size() -1 )
541  {
543  ++index;
544  }
545  }
546  VL_CHECK( index == de_prim_restart->indexBuffer()->end() )
547 
548  // enable primitive restart!
549  de_prim_restart->setPrimitiveRestartEnabled(true);
550 
551  drawCalls().push_back( de_prim_restart.get() );
552 }
553 //-----------------------------------------------------------------------------
555 {
556  u32 total_index_count = 0;
557  std::vector< ref<DrawCall> > mergendo_calls;
558  std::vector<GLsizei> count_vector;
559  for( u32 i=drawCalls().size(); i--; )
560  {
561  if (drawCalls().at(i)->primitiveType() == primitive_type)
562  {
563  int index_count = drawCalls().at(i)->countIndices();
564  VL_CHECK(index_count >= 0);
565  total_index_count += index_count;
566  count_vector.push_back( index_count );
567  mergendo_calls.push_back( drawCalls().at(i) );
568  drawCalls().eraseAt(i);
569  }
570  }
571  // preseve rendering order
572  std::reverse(mergendo_calls.begin(), mergendo_calls.end());
573  std::reverse(count_vector.begin(), count_vector.end());
574 
575  Log::debug( Say("%n draw calls will be merged using MultiDrawElements.\n") << mergendo_calls.size() );
576 
577  if (mergendo_calls.empty())
578  return;
579 
580 //#ifndef NDEBUG
581 // ArrayAbstract* posarr = vertexArray();
582 //#endif
583 
584  ref<MultiDrawElementsUInt> de_multi = new MultiDrawElementsUInt(primitive_type);
585  // make space for all the indices plus the primitive restart markers.
586  de_multi->indexBuffer()->resize(total_index_count);
587  GLuint* index = de_multi->indexBuffer()->begin();
588  // merge draw calls using primitive restart!
589  for( u32 i=0; i<mergendo_calls.size(); ++i )
590  {
591  for( IndexIterator it = mergendo_calls[i]->indexIterator(); it.hasNext(); it.next(), ++index )
592  {
593  *index = it.index();
594  // VL_CHECK(*index < posarr->size());
595  }
596  }
597  VL_CHECK( index == de_multi->indexBuffer()->end() )
598 
599  // Specify primitive boundaries. This must be done last!
600  de_multi->setCountVector( count_vector );
601 
602  drawCalls().push_back( de_multi.get() );
603 }
604 //-----------------------------------------------------------------------------
606 {
607  u32 triangle_count = 0;
608  std::vector< ref<DrawCall> > mergendo_calls;
609  for( u32 i=drawCalls().size(); i--; )
610  {
611  const DrawCall& dc = *drawCalls().at(i);
612 
613  // ignore primitives that cannot be triangulated
614  switch(dc.primitiveType())
615  {
616  case PT_TRIANGLES:
617  case PT_TRIANGLE_STRIP:
618  case PT_TRIANGLE_FAN:
619  case PT_QUADS:
620  case PT_QUAD_STRIP:
621  case PT_POLYGON:
622  break;
623  default:
624  continue;
625  }
626 
627  if (primitive_type == PT_UNKNOWN || dc.primitiveType() == primitive_type || dc.primitiveType() == PT_TRIANGLES)
628  {
629  triangle_count += dc.countTriangles();
630  // insert at the head to preserve the primitive rendering order
631  mergendo_calls.insert( mergendo_calls.begin(), drawCalls().at(i) );
632  drawCalls().eraseAt(i);
633  }
634  }
635  // preseve rendering order
636  std::reverse(mergendo_calls.begin(), mergendo_calls.end());
637 
638  if (mergendo_calls.empty())
639  return;
640 
641  // if there was one single PT_TRIANGLES draw calls then we are done.
642  if ( mergendo_calls.size() == 1 && mergendo_calls[0]->primitiveType() == PT_TRIANGLES )
643  {
644  drawCalls().push_back( mergendo_calls[0].get() );
645  return;
646  }
647 
648 //#ifndef NDEBUG
649 // ArrayAbstract* posarr = vertexArray();
650 //#endif
651 
653  ArrayUInt1& index_buffer = *de->indexBuffer();
654  index_buffer.resize( triangle_count * 3 );
655  u32 idx = 0;
656  for(u32 i=0; i<mergendo_calls.size(); ++i)
657  {
658  for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
659  {
660  VL_CHECK( idx+2 < index_buffer.size() );
661 
662  index_buffer[idx+0] = it.a();
663  index_buffer[idx+1] = it.b();
664  index_buffer[idx+2] = it.c();
665 
666  // some sanity checks since we are here...
667  // VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
668  VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
669  }
670  }
671  VL_CHECK( idx == index_buffer.size() );
672  drawCalls().push_back(de.get());
673 }
674 //-----------------------------------------------------------------------------
676 {
677  ArrayAbstract* posarr = vertexArray();
678 
679  ArrayAbstract* normarr = normalArray();
680 
681  // fixing the triangle winding requires normals
682  if ( normarr == NULL || posarr == NULL )
683  return;
684 
685  u32 triangle_count = 0;
686  std::vector< ref<DrawCall> > mergendo_calls;
687  for( u32 i=drawCalls().size(); i--; )
688  {
689  const DrawCall& dc = *drawCalls().at(i);
690 
691  // ignore primitives that cannot be triangulated
692  switch(dc.primitiveType())
693  {
694  case PT_TRIANGLES:
695  case PT_TRIANGLE_STRIP:
696  case PT_TRIANGLE_FAN:
697  case PT_QUADS:
698  case PT_QUAD_STRIP:
699  case PT_POLYGON:
700  break;
701  default:
702  continue;
703  }
704 
705  triangle_count += dc.countTriangles();
706  // insert at the head to preserve the primitive rendering order
707  mergendo_calls.insert( mergendo_calls.begin(), drawCalls().at(i) );
708  drawCalls().eraseAt(i);
709  }
710  // preseve rendering order
711  std::reverse(mergendo_calls.begin(), mergendo_calls.end());
712 
714  ArrayUInt1& index_buffer = *de->indexBuffer();
715  index_buffer.resize( triangle_count * 3 );
716  u32 idx = 0;
717  for(u32 i=0; i<mergendo_calls.size(); ++i)
718  {
719  for(TriangleIterator it = mergendo_calls[i]->triangleIterator(); it.hasNext(); it.next(), idx+=3)
720  {
721  VL_CHECK( idx+2 < index_buffer.size() );
722 
723  vec3 p0 = posarr->getAsVec3(it.a());
724  vec3 p1 = posarr->getAsVec3(it.b());
725  vec3 p2 = posarr->getAsVec3(it.c());
726  p1 = (p1 - p0).normalize();
727  p2 = (p2 - p0).normalize();
728  vec3 n1 = vl::cross(p1, p2);
729 
730  vec3 v0 = normarr->getAsVec3(it.a());
731  vec3 v1 = normarr->getAsVec3(it.b());
732  vec3 v2 = normarr->getAsVec3(it.c());
733  vec3 n2 = (v0+v1+v2).normalize();
734 
735  if (dot(n1, n2) > 0)
736  {
737  index_buffer[idx+0] = it.a();
738  index_buffer[idx+1] = it.b();
739  index_buffer[idx+2] = it.c();
740  }
741  else
742  {
743  index_buffer[idx+0] = it.a();
744  index_buffer[idx+1] = it.c();
745  index_buffer[idx+2] = it.b();
746  }
747 
748  // some sanity checks since we are here...
749  VL_CHECK( it.a() < (int)posarr->size() && it.b() < (int)posarr->size() && it.c() < (int)posarr->size() );
750  VL_CHECK( it.a() >= 0 && it.b() >= 0 && it.c() >= 0 );
751  }
752  }
753  VL_CHECK( idx == index_buffer.size() );
754  drawCalls().push_back(de.get());
755 }
756 //-----------------------------------------------------------------------------
757 void Geometry::regenerateVertices(const std::vector<u32>& map_new_to_old)
758 {
759  VertexMapper mapper;
760 
761  for(int i=0; i<VA_MaxAttribCount; ++i) {
762  setVertexAttribArray(i, mapper.regenerate( vertexAttribArray(i), map_new_to_old ).get() );
763  }
764 }
765 //-----------------------------------------------------------------------------
767 {
768  ArrayAbstract* posarr = vertexArray();
769 
770  // generate mapping
771  std::vector<u32> map_new_to_old;
772  map_new_to_old.reserve( posarr ? (posarr->size() * 3) : (1024 * 64) );
773 
774  for(int i=drawCalls().size(); i--; )
775  {
776  int start = (int)map_new_to_old.size();
777  for(IndexIterator it=drawCalls().at(i)->indexIterator(); it.hasNext(); it.next())
778  map_new_to_old.push_back(it.index());
779  int count = (int)map_new_to_old.size() - start;
780 
781  // substitute with DrawArrays
782  ref<DrawArrays> da = new vl::DrawArrays( drawCalls().at(i)->primitiveType(), start, count, drawCalls().at(i)->instances() );
783  drawCalls().erase(i,1);
784  drawCalls().push_back(da.get());
785  }
786 
787  regenerateVertices(map_new_to_old);
788 }
789 //-----------------------------------------------------------------------------
791 {
792  // converts PT_QUADS, PT_QUADS_STRIP and PT_POLYGON into PT_TRIANGLES
793  for( int idraw=this->drawCalls().size(); idraw--; )
794  {
795  DrawCall* dc = this->drawCalls().at(idraw);
796  switch(dc->primitiveType())
797  {
798  case PT_QUADS:
799  case PT_QUAD_STRIP:
800  case PT_POLYGON:
801  break;
802  default:
803  continue;
804  }
805 
806  u32 tri_count = dc->countTriangles();
807 
809  triangles->indexBuffer()->resize( tri_count*3 );
810  unsigned int* ptr = triangles->indexBuffer()->begin();
811  for( TriangleIterator it = dc->triangleIterator(); it.hasNext(); ++it, ptr+=3 )
812  {
813  ptr[0] = it.a();
814  ptr[1] = it.b();
815  ptr[2] = it.c();
816  }
817  VL_CHECK( ptr == triangles->indexBuffer()->end() )
818  // substitute the draw call
819  drawCalls()[idraw] = triangles;
820  }
821 }
822 //-----------------------------------------------------------------------------
824 {
825 //#ifndef NDEBUG
826 // ArrayAbstract* posarr = vertexArray();
827 // VL_CHECK(posarr);
828 //#endif
829 
830  for( int idraw=this->drawCalls().size(); idraw--; )
831  {
832  ref<DrawCall> dc = this->drawCalls().at(idraw);
833 
834  unsigned int restart_idx = dc->primitiveRestartIndex();
835  bool restart_on = dc->primitiveRestartEnabled();
836 
837  // find max index
838  int max_idx = -1;
839  int idx_count = 0;
840  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); it.next(), ++idx_count )
841  {
842  // skip primitive restart indices
843  if (restart_on && it.index() == (int)restart_idx)
844  continue;
845  else
846  max_idx = it.index() > max_idx ? it.index() : max_idx;
847  }
848 
849  // can use UByte
850  if ( max_idx < 0xFF || (max_idx == 0xFF && !restart_on) )
851  {
852  if (dc->isOfType(DrawElementsBase::Type()))
853  {
855  // prim restart
857  // base vertex
858  de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
859  // regenerate indices
860  de->indexBuffer()->resize( idx_count );
861  u32 i=0;
862  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
863  {
864  // skip primitive restart indices
865  if (restart_on && it.index() == (int)restart_idx)
867  else
868  {
869  // VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
870  de->indexBuffer()->at(i) = (DrawElementsUByte::index_type)it.index();
871  }
872  }
873  VL_CHECK( i == de->indexBuffer()->size() );
874  // substitute new draw call
875  drawCalls()[idraw] = de;
876  }
877  else
878  if (dc->isOfType(DrawRangeElementsBase::Type()))
879  {
881  // prim restart
883  // base vertex
885  // range
887  de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
888  // regenerate indices
889  de->indexBuffer()->resize( idx_count );
890  u32 i=0;
891  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
892  {
893  // skip primitive restart indices
894  if (restart_on && it.index() == (int)restart_idx)
896  else
897  de->indexBuffer()->at(i) = (DrawRangeElementsUByte::index_type)it.index();
898  }
899  VL_CHECK( i == de->indexBuffer()->size() );
900  // substitute new draw call
901  drawCalls()[idraw] = de;
902  }
903  else
904  if (dc->isOfType(MultiDrawElementsBase::Type()))
905  {
907  // regenerate indices
908  de->indexBuffer()->resize( idx_count );
909  u32 i=0;
910  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
911  {
912  // skip primitive restart indices
913  if (restart_on && it.index() == (int)restart_idx)
915  else
916  de->indexBuffer()->at(i) = (MultiDrawElementsUByte::index_type)it.index();
917  }
918  VL_CHECK( i == de->indexBuffer()->size() );
919  // prim restart
921  // base vertex
923  // count vector
925  // substitute new draw call
926  drawCalls()[idraw] = de;
927  }
928  } // can use UByte
929  else
930  // can use UShort
931  if ( max_idx < 0xFFFF || (max_idx == 0xFFFF && !restart_on) )
932  {
933  if (dc->isOfType(DrawElementsBase::Type()))
934  {
936  // prim restart
938  // base vertex
939  de->setBaseVertex( dc->as<DrawElementsBase>()->baseVertex() );
940  // regenerate indices
941  de->indexBuffer()->resize( idx_count );
942  u32 i=0;
943  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
944  {
945  // skip primitive restart indices
946  if (restart_on && it.index() == (int)restart_idx)
948  else
949  {
950  // VL_CHECK( it.index() >= 0 && it.index() < (int)posarr->size() );
951  de->indexBuffer()->at(i) = (DrawElementsUShort::index_type)it.index();
952  }
953  }
954  VL_CHECK( i == de->indexBuffer()->size() );
955  // substitute new draw call
956  drawCalls()[idraw] = de;
957  }
958  else
959  if (dc->isOfType(DrawRangeElementsBase::Type()))
960  {
962  // prim restart
964  // base vertex
966  // range
968  de->setRangeEnd( dc->as<DrawRangeElementsBase>()->rangeEnd() );
969  // regenerate indices
970  de->indexBuffer()->resize( idx_count );
971  u32 i=0;
972  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
973  {
974  // skip primitive restart indices
975  if (restart_on && it.index() == (int)restart_idx)
977  else
978  de->indexBuffer()->at(i) = (DrawRangeElementsUShort::index_type)it.index();
979  }
980  VL_CHECK( i == de->indexBuffer()->size() );
981  // substitute new draw call
982  drawCalls()[idraw] = de;
983  }
984  else
985  if (dc->isOfType(MultiDrawElementsBase::Type()))
986  {
988  // regenerate indices
989  de->indexBuffer()->resize( idx_count );
990  u32 i=0;
991  for( vl::IndexIterator it = dc->indexIterator(); it.hasNext(); ++it, ++i )
992  {
993  // skip primitive restart indices
994  if (restart_on && it.index() == (int)restart_idx)
996  else
997  de->indexBuffer()->at(i) = (MultiDrawElementsUShort::index_type)it.index();
998  }
999  VL_CHECK( i == de->indexBuffer()->size() );
1000  // prim restart
1002  // base vertex
1004  // count vector
1006  // substitute new draw call
1007  drawCalls()[idraw] = de;
1008  }
1009  } // can use UShort
1010 
1011  } // for()
1012 }
1013 //-----------------------------------------------------------------------------
1015 {
1016  // converts quads and polygons into triangles
1018 
1019  // use short or byte instead of int
1020  shrinkDrawCalls();
1021 
1022  // check primitive type is supported by OpenGL ES
1023  for(int i=0; i<drawCalls().size(); ++i)
1024  {
1025  DrawCall* dc = drawCalls().at(i);
1026  // check supported primitive types
1027  switch(dc->primitiveType())
1028  {
1029  case GL_POINTS:
1030  case GL_LINE_STRIP:
1031  case GL_LINE_LOOP:
1032  case GL_LINES:
1033  case GL_TRIANGLE_STRIP:
1034  case GL_TRIANGLE_FAN:
1035  case GL_TRIANGLES:
1036  break;
1037 
1038  case PT_QUADS:
1039  case PT_QUAD_STRIP:
1040  case PT_POLYGON:
1041  case PT_LINES_ADJACENCY:
1045  case PT_PATCHES:
1046  dc->setEnabled(false);
1047  Log::error("Geometry::makeGLESFriendly(): primitive type illegal under GLES, draw call disabled.\n");
1048  break;
1049 
1050  default:
1051  VL_TRAP();
1052  break;
1053  }
1054  }
1055 }
1056 //-----------------------------------------------------------------------------
1058 {
1059  ArrayAbstract* posarr = vertexArray();
1060 
1061  if (!posarr)
1062  {
1063  Log::warning("Geometry::sortVertices() failed. No vertices found.\n");
1064  return false;
1065  }
1066 
1067  // supports only DrawElements* and generates DrawElementsUInt
1068 
1069  std::vector< ref<DrawElementsUInt> > de_u32_set;
1070 
1071  // collect DrawElements
1072  for(int i=0; i<drawCalls().size(); ++i)
1073  {
1074  DrawCall* dc = drawCalls().at(i);
1075  if (dc->primitiveRestartEnabled())
1076  {
1077  Log::error("Geometry::sortVertices() does not support DrawCalls with primitive restart enabled.\n");
1078  return false;
1079  }
1080 
1081  DrawElementsUInt* de_u32 = dc->as<DrawElementsUInt>();
1082  DrawElementsUShort* de_u16 = dc->as<DrawElementsUShort>();
1083  DrawElementsUByte* de_u8 = dc->as<DrawElementsUByte>();
1084  if (de_u32)
1085  {
1086  ref<DrawElementsUInt> de = new DrawElementsUInt(de_u32->primitiveType(), de_u32->instances());
1087  de_u32_set.push_back(de);
1088  de->indexBuffer()->resize( de_u32->indexBuffer()->size() );
1089  for(unsigned int j=0; j<de_u32->indexBuffer()->size(); ++j)
1090  de->indexBuffer()->at(j) = de_u32->indexBuffer()->at(j) + de_u32->baseVertex(); // bake base vertex
1091  }
1092  else
1093  if(de_u16)
1094  {
1095  ref<DrawElementsUInt> de = new DrawElementsUInt(de_u16->primitiveType(), de_u16->instances());
1096  de_u32_set.push_back(de);
1097  de->indexBuffer()->resize( de_u16->indexBuffer()->size() );
1098  for(unsigned int j=0; j<de_u16->indexBuffer()->size(); ++j)
1099  de->indexBuffer()->at(j) = de_u16->indexBuffer()->at(j) + de_u16->baseVertex(); // bake base vertex
1100  }
1101  else
1102  if(de_u8)
1103  {
1104  ref<DrawElementsUInt> de = new DrawElementsUInt(de_u8->primitiveType(), de_u8->instances());
1105  de_u32_set.push_back(de);
1106  de->indexBuffer()->resize( de_u8->indexBuffer()->size() );
1107  for(unsigned int j=0; j<de_u8->indexBuffer()->size(); ++j)
1108  de->indexBuffer()->at(j) = de_u8->indexBuffer()->at(j) + de_u8->baseVertex(); // bake base vertex
1109  }
1110  else
1111  {
1112  Log::error("Geometry::sortVertices() supports only DrawElements* draw calls.\n");
1113  return false;
1114  }
1115  }
1116 
1117  // erase all draw calls
1118  drawCalls().clear();
1119 
1120  // reset tables
1121  std::vector<u32> map_new_to_old;
1122  map_new_to_old.resize( posarr->size() );
1123  memset(&map_new_to_old[0], 0xFF, map_new_to_old.size()*sizeof(map_new_to_old[0])); // fill with 0xFF for debugging
1124 
1125  std::vector<u32> map_old_to_new;
1126  map_old_to_new.resize( posarr->size() );
1127  memset(&map_old_to_new[0], 0xFF, map_old_to_new.size()*sizeof(map_old_to_new[0])); // fill with 0xFF for debugging
1128 
1129  std::vector<u32> used;
1130  used.resize( posarr->size() );
1131  memset(&used[0], 0, used.size()*sizeof(used[0]));
1132 
1133  // assign new vertex indices in order of appearence
1134  u32 new_idx = 0;
1135  for(u32 i=0; i<de_u32_set.size(); ++i)
1136  {
1137  ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
1138  for(u32 idx=0; idx<index_buffer->size(); ++idx)
1139  {
1140  if (!used[index_buffer->at(idx)])
1141  {
1142  const DrawElementsUInt::index_type& old_idx = index_buffer->at(idx);
1143  map_new_to_old[new_idx] = old_idx;
1144  map_old_to_new[old_idx] = new_idx;
1145  used[old_idx] = 1;
1146  ++new_idx;
1147  }
1148  }
1149  }
1150 
1151  // regenerate vertices
1152  regenerateVertices(map_new_to_old);
1153 
1154  // regenerate draw calls
1155  for(u32 i=0; i<de_u32_set.size(); ++i)
1156  {
1157  drawCalls().push_back(de_u32_set[i].get());
1158  ArrayUInt1* index_buffer = de_u32_set[i]->indexBuffer();
1159  for(u32 j=0; j<index_buffer->size(); ++j)
1160  {
1161  index_buffer->at(j) = map_old_to_new[index_buffer->at(j)];
1162  }
1163  }
1164 
1165  return true;
1166 }
1167 //-----------------------------------------------------------------------------
1169 {
1170  ArrayAbstract* posarr = vertexArray();
1171 
1172  if (!posarr)
1173  return;
1174 
1176  col->resize( posarr->size() );
1177 
1178  setColorArray( col.get() );
1179 
1180  for(int i=0; i<drawCalls().size(); ++i)
1181  {
1182  fvec4 c;
1183  c.r() = rand()%100 / 99.0f;
1184  c.g() = rand()%100 / 99.0f;
1185  c.b() = rand()%100 / 99.0f;
1186  c.a() = 1.0f;
1187 
1188  for(IndexIterator it=drawCalls().at(i)->indexIterator(); it.hasNext(); it.next())
1189  col->at( it.index() ) = c;
1190  }
1191 }
1192 //-----------------------------------------------------------------------------
1194  u32 vert_count,
1195  const fvec3 *vertex,
1196  const fvec3* normal,
1197  const fvec2 *texcoord,
1198  const DrawCall* prim,
1199  fvec3 *tangent,
1200  fvec3 *bitangent )
1201 {
1202  std::vector<fvec3> tan1;
1203  std::vector<fvec3> tan2;
1204  tan1.resize(vert_count);
1205  tan2.resize(vert_count);
1206 
1207  for ( TriangleIterator trit = prim->triangleIterator(); trit.hasNext(); trit.next() )
1208  {
1209  int tri[] = { trit.a(), trit.b(), trit.c() };
1210 
1211  VL_CHECK(tri[0] < (int)vert_count );
1212  VL_CHECK(tri[1] < (int)vert_count );
1213  VL_CHECK(tri[2] < (int)vert_count );
1214 
1215  const fvec3& v1 = vertex[tri[0]];
1216  const fvec3& v2 = vertex[tri[1]];
1217  const fvec3& v3 = vertex[tri[2]];
1218 
1219  const fvec2& w1 = texcoord[tri[0]];
1220  const fvec2& w2 = texcoord[tri[1]];
1221  const fvec2& w3 = texcoord[tri[2]];
1222 
1223  float x1 = v2.x() - v1.x();
1224  float x2 = v3.x() - v1.x();
1225  float y1 = v2.y() - v1.y();
1226  float y2 = v3.y() - v1.y();
1227  float z1 = v2.z() - v1.z();
1228  float z2 = v3.z() - v1.z();
1229 
1230  float s1 = w2.x() - w1.x();
1231  float s2 = w3.x() - w1.x();
1232  float t1 = w2.y() - w1.y();
1233  float t2 = w3.y() - w1.y();
1234 
1235  float r = 1.0F / (s1 * t2 - s2 * t1);
1236  fvec3 sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r);
1237  fvec3 tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r);
1238 
1239  tan1[tri[0]] += sdir;
1240  tan1[tri[1]] += sdir;
1241  tan1[tri[2]] += sdir;
1242 
1243  tan2[tri[0]] += tdir;
1244  tan2[tri[1]] += tdir;
1245  tan2[tri[2]] += tdir;
1246  }
1247 
1248  for ( u32 a = 0; a < vert_count; a++)
1249  {
1250  const fvec3& n = normal[a];
1251  const fvec3& t = tan1[a];
1252 
1253  // Gram-Schmidt orthogonalize
1254  tangent[a] = (t - n * dot(n, t)).normalize();
1255 
1256  if ( bitangent )
1257  {
1258  // Calculate handedness
1259  float w = (dot(cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F;
1260  bitangent[a] = cross( n, tangent[a] ) * w;
1261  }
1262  }
1263 }
1264 //-----------------------------------------------------------------------------
static void debug(const String &message)
Use this function to provide extra information useful to investigate and solve problems.
Definition: Log.cpp:145
The ArrayAbstract class defines an abstract interface to conveniently manipulate data stored in a Buf...
Definition: Array.hpp:58
Generates a set of new vertices from the old one.
Associates a Renderable object to an Effect and Transform.
Definition: Actor.hpp:130
See DrawElements.
int baseVertex() const
Returns the currently used base vertex.
bool hasNext()
Returns false if the iterator has reached the end of the triangle list.
void setBaseVertex(int base_vertex)
If base_vertx is != 0 glDrawElementsBaseVertex/glDrawElementsInstancedBaseVertex will be used instead...
ref< Geometry > shallowCopy() const
Performs a shallow copy of a Geometry.
Definition: Geometry.cpp:127
virtual bool primitiveRestartEnabled() const
Returns whether the primitive-restart functionality is enabled or not.
Definition: DrawCall.hpp:163
void setBaseVertex(int base_vertex)
If base_vertx is != 0 glDrawRangeElementsBaseVertex/glDrawRangeElementsInstancedBaseVertex will be us...
const Vector3 & normalize(T_Scalar *len=NULL)
Definition: Vector3.hpp:227
An array of vl::fvec4.
Definition: Array.hpp:416
void mergeDrawCallsWithMultiDrawElements(EPrimitiveType primitive_type)
Merges all the draw calls that use the given primitive type into one single MultiDrawElements draw ca...
Definition: Geometry.cpp:554
See MultiDrawElements.
Vector3< float > fvec3
A 3 components vector with float precision.
Definition: Vector3.hpp:252
ref< ArrayAbstract > mVertexAttribArrays[VA_MaxAttribCount]
Definition: Geometry.hpp:297
const T_VectorType * end() const
Definition: Array.hpp:249
Geometry()
Constructor.
Definition: Geometry.cpp:45
Geometry & shallowCopyFrom(const Geometry &)
Performs a shallow copy of the specified Geometry.
Definition: Geometry.cpp:134
const T * get() const
Definition: Object.hpp:128
virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode)
Updates all the vertex buffer objects of both vertex arrays and draw calls that are marked as dirty...
Definition: Geometry.cpp:362
A simple String formatting class.
Definition: Say.hpp:124
void setBufferObjectDirty(bool dirty=true)
Whether BufferObjects associated to a Renderable should be recomputed on the next rendering...
Definition: Renderable.hpp:210
const std::vector< GLint > & baseVertices() const
Returns the list of base vertices, one for each primitive.
static void warning(const String &message)
Use this function to provide information about situations that might lead to errors or loss of data...
Definition: Log.cpp:155
Matrix4 & transpose()
Definition: Matrix4.hpp:350
virtual void deleteBufferObject()
Deletes all the vertex buffer objects of both vertex arrays and draw calls.
Definition: Geometry.cpp:346
u32 countTriangles() const
Counts the number of virtual triangles of a DrawCall., i.e.
Definition: DrawCall.hpp:151
const T_Scalar & z() const
Definition: Vector3.hpp:91
const std::vector< GLsizei > & countVector() const
The count vector used as &#39;count&#39; parameter of glMultiDrawElements.
const T_Scalar & r() const
Definition: Vector4.hpp:111
const ArrayAbstract * vertexArray() const
Conventional vertex array.
Definition: Geometry.hpp:248
See DrawRangeElements.
Represents an OpenGL context, possibly a widget or a pbuffer, which can also respond to keyboard...
Base interface for all MultiDrawElements* sub classes.
See DrawElements.
static const index_type primitive_restart_index
The special index which identifies a primitive restart. By default it is set to ~0 that is 0xFF...
See DrawRangeElements.
static void error(const String &message)
Use this function to provide information about run-time errors: file not found, out of memory...
Definition: Log.cpp:165
An array of GLuint.
Definition: Array.hpp:437
void setVertexArray(ArrayAbstract *data)
Conventional vertex array.
Definition: Geometry.cpp:155
bool sortVertices()
Sorts the vertices of the geometry (position, normals, textures, colors etc.) to maximize vertex-cach...
Definition: Geometry.cpp:1057
vec3 center() const
Returns the center of the AABB.
Definition: AABB.cpp:184
virtual size_t glSize() const =0
Returns the number of scalar components for the array, ie 3 for ArrayFloat3, 1 for ArrayUInt1 etc...
bool isBufferObjectEnabled() const
Returns true if BufferObject (vertex buffer object) are enabled for a Renderable (enabled by default)...
Definition: Renderable.hpp:201
void resize(size_t dim)
Definition: Array.hpp:233
void setBoundingSphere(const Sphere &sphere)
Sets the bounding sphere of a Renderable.
Definition: Renderable.hpp:140
void setNormalArray(ArrayAbstract *data)
Conventional normal array.
Definition: Geometry.cpp:164
See MultiDrawElements.
void setSecondaryColorArray(ArrayAbstract *data)
Conventional secondary color array.
Definition: Geometry.cpp:195
Matrix4 & invert(T_Scalar *determinant=NULL)
Definition: Matrix4.hpp:441
void setColorArray(const fvec4 &color)
Fills the color array with the given color.
Definition: Geometry.hpp:108
fvec3 cross(const fvec3 &v1, const fvec3 &v2)
Definition: Vector3.hpp:277
ref< ArrayAbstract > regenerate(ArrayAbstract *data, const std::vector< u32 > &map_new_to_old) const
Regenerates a new Array based on the given mapping.
static const index_type primitive_restart_index
The special index which identifies a primitive restart. By default it is set to ~0 that is 0xFF...
Geometry & deepCopyFrom(const Geometry &)
Performs a deep copy of the specified Geometry.
Definition: Geometry.cpp:103
static void computeTangentSpace(u32 vert_count, const vl::fvec3 *vertex, const vl::fvec3 *normal, const vl::fvec2 *texcoord, const vl::DrawCall *primitives, vl::fvec3 *tangent, vl::fvec3 *bitangent)
Computes the tangent (and optionally bitangent) vectors used to form a TBN matrix to be used for bump...
Definition: Geometry.cpp:1193
virtual vec3 getAsVec3(size_t vector_index) const =0
Returns a vector from the buffer as a vec3 value.
const T_VectorType * begin() const
Definition: Array.hpp:245
void setRangeStart(int rstart)
Sets the range start.
void setBoundingBox(const AABB &aabb)
Sets the bounding box of a Renderable.
Definition: Renderable.hpp:129
bool isDisplayListEnabled() const
Returns true if display lists are enabled for a Renderable (disabled by default). ...
Definition: Renderable.hpp:189
int rangeEnd() const
Returns the range end.
size_t size() const
Returns the number of elements of an array.
Definition: Array.hpp:235
The Geometry class is a Renderable that implements a polygonal mesh made of polygons, lines and points.
Definition: Geometry.hpp:66
EPrimitiveType
Visualization Library main namespace.
DrawRangeElements *MultiDrawElements *to the best fitting of *UInt UShort UByte *taking into instancing and base vertex *note Primitive type can be any *void shrinkDrawCalls()
Definition: Geometry.cpp:823
void fixTriangleWinding()
Converts all draw calls to triangles and fixes their winding according to the Geometry&#39;s normals...
Definition: Geometry.cpp:675
float dot(float a, float b)
Definition: glsl_math.hpp:1111
bool flipNormals()
Inverts the orientation of the normals.
Definition: Geometry.cpp:250
Base interface for all DrawElements* sub classes.
virtual void normalize()=0
Normalizes the vectors contained in the buffer.
const unsigned char * ptr() const
Returns the pointer to the first element of the local buffer. Equivalent to bufferObject()->ptr() ...
Definition: Array.hpp:103
bool Has_BufferObject
Definition: OpenGL.cpp:82
const T_Scalar & g() const
Definition: Vector4.hpp:112
T_Scalar lengthSquared() const
Definition: Vector3.hpp:225
ArrayUByte1 ::scalar_type index_type
#define VL_TRAP()
Definition: checks.hpp:70
The AABB class implements an axis-aligned bounding box using vl::real precision.
Definition: AABB.hpp:44
See DrawElements.
virtual TriangleIterator triangleIterator() const =0
Returns a TriangleIterator used to iterate through the triangles of a DrawCall.
unsigned int u32
32 bits unsigned integer
Definition: std_types.hpp:51
void colorizePrimitives()
Assigns a random color to each vertex of each DrawCall object. If a vertex is shared among more than ...
Definition: Geometry.cpp:1168
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
T_Scalar length() const
Definition: Vector3.hpp:224
const T_Scalar & y() const
Definition: Vector3.hpp:90
void convertDrawCallToDrawArrays()
Converts all the DrawCall objects bound to a Geometry into DrawArrays.
Definition: Geometry.cpp:766
void setCountVector(const std::vector< GLsizei > &vcount)
Sets the vector defining the length of each primitive and automatically computes the pointer vectors ...
Iterator used to extract the indices of every single triangle of a DrawCall regardless of the primiti...
void computeNormals(bool verbose=false)
Computes the normals in a "smooth" way, i.e.
Definition: Geometry.cpp:269
void setTexCoordArray(int tex_unit, ArrayAbstract *data)
Conventional texture coords arrays.
Definition: Geometry.cpp:222
void transform(const mat4 &matr, bool normalize=true)
Transforms vertices and normals belonging to this geometry.
Definition: Geometry.cpp:399
T * as()
Casts an Object to the specified class.
Definition: Object.hpp:282
virtual int instances() const
Returns the number of instances for this set of primitives.
Definition: DrawCall.hpp:160
virtual ~Geometry()
Destructor.
Definition: Geometry.cpp:51
EBufferObjectUpdateMode
const T_Scalar & b() const
Definition: Vector4.hpp:113
const ArrayAbstract * vertexAttribArray(int attrib_location) const
Returns a generic vertex attribute&#39;s info.
Definition: Geometry.cpp:420
DrawCall * mergeTriangleStrips()
Merges all the PT_TRIANGLE_STRIP DrawElementsUInt objects into one single PT_TRIANGLE_STRIP DrawEleme...
Definition: Geometry.cpp:430
#define NULL
Definition: OpenGLDefs.hpp:81
Manages most of the OpenGL rendering states responsible of the final aspect of the rendered objects...
Definition: Shader.hpp:1830
The Sphere class defines a sphere using a center and a radius using vl::real precision.
Definition: Sphere.hpp:43
virtual void clearArrays(bool clear_draw_calls=true)
Removes all the previously installed arrays.
Definition: Geometry.cpp:237
void setPrimitiveRestartEnabled(bool enabled)
Enables the primitive-restart functionality.
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
Base interface for all DrawRangeElements* sub classes.
See MultiDrawElements.
void setRangeEnd(int rend)
Sets the range end.
ref< Geometry > deepCopy() const
Performs a deep copy of a Geometry.
Definition: Geometry.cpp:96
T_VectorType & at(size_t i)
Definition: Array.hpp:255
void bindVAS(const IVertexAttribSet *vas, bool use_vbo, bool force)
Activates the specified vertex attribute set - For internal use only.
int rangeStart() const
Returns the range start.
virtual GLenum glType() const =0
Returns the OpenGL type for the array, ie GL_FLOAT for ArrayFloat3, GL_UNSIGNED_INT for ArrayUInt1 et...
#define VL_CHECK_OGL()
Definition: OpenGL.hpp:156
int instances() const
Returns the number of instances for this set of primitives.
void mergeDrawCallsWithTriangles(EPrimitiveType primitive_type)
Merges all the draw calls that use the given primitive type or PT_TRIANGLES into one single PT_TRIANG...
Definition: Geometry.cpp:605
The base class of DrawArrays, DrawElements, MultiDrawElements and DrawRangeElements.
Definition: DrawCall.hpp:90
virtual size_t size() const =0
Returns the number of elements of an array.
virtual IndexIterator indexIterator() const =0
Returns a IndexIterator used to iterate through the virtual indices of a DrawCall.
void regenerateVertices(const std::vector< u32 > &map_new_to_old)
Regenerates the vertex position and attributes using the given new-to-old map.
Definition: Geometry.cpp:757
const T_Scalar & x() const
Definition: Vector3.hpp:89
void triangulateDrawCalls()
Converts PT_QUADS, PT_QUADS_STRIP and PT_POLYGON into PT_TRIANGLE primitives.
Definition: Geometry.cpp:790
void setEnabled(bool enable)
Enables/disables the draw call.
Definition: DrawCall.hpp:125
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
virtual unsigned int primitiveRestartIndex()
Returns the primitive restart index used by the draw call or 0 if primitive restart is not supported...
Definition: DrawCall.hpp:166
const T_Scalar & x() const
Definition: Vector2.hpp:132
An array of vl::fvec3.
Definition: Array.hpp:414
void setFogCoordArray(ArrayAbstract *data)
Conventional fog array.
Definition: Geometry.cpp:212
virtual void transform(const mat4 &m)=0
Transforms the vectors contained in the buffer.
Represents a virtual camera defining, among other things, the point of view from which scenes can be ...
Definition: Camera.hpp:50
Wraps a IndexIteratorAbstract to iterate over the indices of a DrawCall.
void setPrimitiveRestartEnabled(bool enabled)
Enables the primitive-restart functionality.
virtual void computeBounds_Implementation()
Definition: Geometry.cpp:55
void setBaseVertices(const std::vector< GLint > &base_verts)
Returns the list of base vertices, one for each primitive.
virtual void render_Implementation(const Actor *actor, const Shader *shader, const Camera *camera, OpenGLContext *gl_context) const
Definition: Geometry.cpp:379
EPrimitiveType primitiveType() const
Returns the draw call&#39;s primitive type.
Definition: DrawCall.hpp:110
Matrix4 as3x3() const
Definition: Matrix4.hpp:310
void makeGLESFriendly()
Calls triangulateDrawCalls() and shrinkDrawCalls().
Definition: Geometry.cpp:1014
Wraps the OpenGL function glDrawArrays().
Definition: DrawArrays.hpp:57
const T_Scalar & y() const
Definition: Vector2.hpp:133
int baseVertex() const
Returns the currently used base vertex.
#define VL_CHECK(expr)
Definition: checks.hpp:73
Collection< DrawCall > mDrawCalls
Definition: Geometry.hpp:294
void mergeDrawCallsWithPrimitiveRestart(EPrimitiveType primitive_type)
Merges all the draw calls that use the given primitive type into one single draw call using primitive...
Definition: Geometry.cpp:500
const ArrayAbstract * normalArray() const
Conventional normal array.
Definition: Geometry.hpp:254
T normalize(T)
Definition: glsl_math.hpp:1128
Collection< DrawCall > & drawCalls()
Returns the list of DrawCall objects bound to a Geometry.
Definition: Geometry.hpp:102
void setVertexAttribArray(int attrib_location, const ArrayAbstract *info)
Binds a generic vertex attribute.
Definition: Geometry.cpp:415
const T_Scalar & a() const
Definition: Vector4.hpp:114
void setPrimitiveRestartEnabled(bool enabled)
Enables the primitive-restart functionality (requires OpenGL 3.1).