Visualization Library 2.1.0

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

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
DrawElements.hpp
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 #ifndef DrawElements_INCLUDE_ONCE
33 #define DrawElements_INCLUDE_ONCE
34 
35 #include <vlGraphics/DrawCall.hpp>
37 #include <vlGraphics/Array.hpp>
38 #include <vlCore/Log.hpp>
39 #include <vlCore/Say.hpp>
40 #include <algorithm>
41 
42 namespace vl
43 {
44 
45  //------------------------------------------------------------------------------
46  // DrawElementsBase
47  //------------------------------------------------------------------------------
53  class DrawElementsBase: public DrawCall
54  {
56 
57  public:
59  virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
60 
62  void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
63 
66 
68  int instances() const { return mInstances; }
69 
74  void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; }
75 
78  int baseVertex() const { return mBaseVertex; }
79 
80  protected:
83  GLuint mBaseVertex;
84  };
85  //------------------------------------------------------------------------------
86  // DrawElements
87  //------------------------------------------------------------------------------
117  template <class arr_type>
119  {
121 
122  public:
123  typedef typename arr_type::scalar_type index_type;
125  static const index_type primitive_restart_index = index_type(~0);
126  virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; }
127 
128  private:
129  template<typename T>
130  class Triangle
131  {
132  public:
133  T ABC[3];
134  bool operator<(const Triangle<index_type>& b) const
135  {
136  if (ABC[0] != b.ABC[0])
137  return ABC[0] < b.ABC[0];
138  else
139  if (ABC[1] != b.ABC[1])
140  return ABC[1] < b.ABC[1];
141  else
142  return ABC[2] < b.ABC[2];
143  }
144  void rotate()
145  {
146  if (ABC[0] > ABC[1])
147  { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
148  if (ABC[0] > ABC[1])
149  { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
150  }
151  };
152 
153  public:
156  {
157  VL_DEBUG_SET_OBJECT_NAME()
158  mType = primitive;
160  mIndexBuffer = new arr_type;
161  mPrimitiveRestartEnabled = false;
162  mBaseVertex = 0;
163  mCount = -1; // till the end of the indexBuffer()
164  mOffset = 0; // from the beginning of the indexBuffer()
165  }
166 
169  {
170  super::operator=(other);
171  *indexBuffer() = *other.indexBuffer();
172  mInstances = other.mInstances;
174  mBaseVertex = other.mBaseVertex;
175  mCount = other.mCount;
176  mOffset = other.mOffset;
177  return *this;
178  }
179 
181  virtual ref<DrawCall> clone() const
182  {
184  *de = *this;
185  return de;
186  }
187 
189  void setCount(i32 count) { mCount = count; }
190 
192  i32 count() const { return mCount; }
193 
195  void setOffset(u32 offset) { mOffset = offset; }
196 
198  u32 offset() const { return mOffset; }
199 
201  void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; }
202 
204  arr_type* indexBuffer() { return mIndexBuffer.get(); }
205 
207  const arr_type* indexBuffer() const { return mIndexBuffer.get(); }
208 
210  {
211  if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate))
212  indexBuffer()->updateBufferObject(mode);
213  }
214 
215  virtual void deleteBufferObject()
216  {
217  indexBuffer()->bufferObject()->deleteBufferObject();
218  }
219 
220  virtual void render(bool use_bo) const
221  {
222  VL_CHECK_OGL()
223  VL_CHECK(!use_bo || (use_bo && Has_BufferObject))
224 
225 #if !defined(NDEBUG) && (defined(VL_OPENGL_ES1) || defined(GL_OPENGL_ES2))
226  bool error = true;
227  // check primitive type
228  switch(primitiveType())
229  {
230  case PT_QUADS: Log::error("vl::DrawElements does not support PT_QUADS under OpenGL ES!\n"); break;
231  case PT_QUAD_STRIP: Log::error("vl::DrawElements does not support PT_QUAD_STRIP under OpenGL ES!\n"); break;
232  case PT_POLYGON: Log::error("vl::DrawElements does not support PT_POLYGON under OpenGL ES!\n"); break;
233  case PT_LINES_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINES_ADJACENCY under OpenGL ES!\n"); break;
234  case PT_LINE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINE_STRIP_ADJACENCY under OpenGL ES!\n"); break;
235  case PT_TRIANGLES_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLES_ADJACENCY under OpenGL ES!\n"); break;
236  case PT_TRIANGLE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLE_STRIP_ADJACENCY under OpenGL ES!\n"); break;
237  case PT_PATCHES: Log::error("vl::DrawElements does not support PT_PATCHES under OpenGL ES!\n"); break;
238  default:
239  error = false;
240  break;
241  }
242  // check index type
243  if (indexBuffer()->glType() != GL_UNSIGNED_BYTE && indexBuffer()->glType() != GL_UNSIGNED_SHORT)
244  {
245  Log::error("vl::DrawElements only supports GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT under OpenGL ES!\n");
246  error = true;
247  }
248  VL_CHECK(!error)
249 #endif
250 
251  use_bo &= Has_BufferObject; // && indexBuffer()->bufferObject()->handle() && indexBuffer()->sizeBufferObject();
252  if ( !use_bo && !indexBuffer()->size() )
253  return;
254 
255  // apply patch parameters if any and if using PT_PATCHES
257 
258  // primitive restart enable
260  {
262  glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL();
263  glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL();
264  }
265 
266  // compute base pointer
267 
268  const GLvoid* ptr = indexBuffer()->bufferObject()->ptr();
269  if (use_bo && indexBuffer()->bufferObject()->handle())
270  {
271  VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL()
272  ptr = 0;
273  }
274  else
275  {
276  VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); VL_CHECK_OGL()
277  }
278 
279  // compute final pointer and count
280 
281  const char*ptr_end = NULL;
282  if(mCount < 0)
283  {
284  // compute the end of the index buffer
285  ptr_end = (char*)ptr + sizeof(index_type)*(use_bo ? indexBuffer()->sizeBufferObject() : indexBuffer()->size());
286 
287  // offset in the index buffer
288  ptr = (char*)ptr + mOffset;
289  }
290  else
291  {
292  // offset in the index buffer
293  ptr = (char*)ptr + mOffset;
294 
295  // compute the end of the indices
296  ptr_end = (char*)ptr + sizeof(index_type)*mCount;
297  }
298 
299  // compute the remaining indices
300  const GLsizei count = (GLsizei)((index_type*)ptr_end - (index_type*)ptr);
301 
302  if (mBaseVertex == 0)
303  {
304  if ( instances() == 1 )
305  {
306  glDrawElements( primitiveType(), count, arr_type::gl_type, ptr ); VL_CHECK_OGL()
307  }
308  else
309  {
311  VL_glDrawElementsInstanced( primitiveType(), count, arr_type::gl_type, ptr, instances() ); VL_CHECK_OGL()
312  }
313  }
314  else
315  {
317  if ( instances() == 1 )
318  {
319  VL_glDrawElementsBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, mBaseVertex ); VL_CHECK_OGL()
320  }
321  else
322  {
324  VL_glDrawElementsInstancedBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, instances(), mBaseVertex ); VL_CHECK_OGL()
325  }
326  }
327 
328  // primitive restart disable
329 
331  {
332  glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL()
333  }
334 
335  #ifndef NDEBUG
336  unsigned int glerr = glGetError();
337  if (glerr != GL_NO_ERROR)
338  {
339  String msg( getGLErrorString(glerr) );
340  Log::error( Say("glGetError() [%s:%n]: %s\n") << __FILE__ << __LINE__ << msg );
341  Log::warning( "- If you are using geometry instancing in conjunction with display lists you will have to disable one of them.\n" );
342  Log::warning( "- If you are using OpenGL ES you must not use GL_QUADS, GL_QUAD_STRIP and GL_POLYGON primitive types.\n" );
343  VL_TRAP()
344  }
345  #endif
346  }
347 
349  {
351  new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
352  baseVertex(), primitiveRestartEnabled(), primitive_restart_index );
353  it->initialize();
354  return TriangleIterator(it.get());
355  }
356 
358  {
360  iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, primitive_restart_index );
361  IndexIterator iit;
362  iit.initialize( iie.get() );
363  return iit;
364  }
365 
366  protected:
370  };
371  //------------------------------------------------------------------------------
372  // typedefs
373  //------------------------------------------------------------------------------
375  class DrawElementsUInt: public DrawElements<ArrayUInt1>
376  {
378 
379  public:
381  :DrawElements<ArrayUInt1>(primitive, instances)
382  {
383  VL_DEBUG_SET_OBJECT_NAME();
384  }
385  };
386  //------------------------------------------------------------------------------
388  class DrawElementsUShort: public DrawElements<ArrayUShort1>
389  {
391 
392  public:
394  :DrawElements<ArrayUShort1>(primitive, instances)
395  {
396  VL_DEBUG_SET_OBJECT_NAME();
397  }
398  };
399  //------------------------------------------------------------------------------
401  class DrawElementsUByte: public DrawElements<ArrayUByte1>
402  {
404 
405  public:
407  :DrawElements<ArrayUByte1>(primitive, instances)
408  {
409  VL_DEBUG_SET_OBJECT_NAME();
410  }
411  };
412  //------------------------------------------------------------------------------
413 }
414 
415 #endif
See DrawElements.
int baseVertex() const
Returns the currently used base vertex.
void setBaseVertex(int base_vertex)
If base_vertx is != 0 glDrawElementsBaseVertex/glDrawElementsInstancedBaseVertex will be used instead...
DrawElements & operator=(const DrawElements &other)
Assign operator.
An array of GLubyte.
Definition: Array.hpp:455
const T * get() const
Definition: Object.hpp:128
A simple String formatting class.
Definition: Say.hpp:124
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
TriangleIterator triangleIterator() const
Returns a TriangleIterator used to iterate through the triangles of a DrawCall.
Index iterator operating over DrawElements, DrawRangeElements and MultiDrawElements.
The String class implements an advanced UTF16 (Unicode BMP) string manipulation engine.
Definition: String.hpp:62
virtual void render(bool use_bo) const
Executes the draw call.
ref< arr_type > mIndexBuffer
See DrawElements.
An array of GLuint.
Definition: Array.hpp:437
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
void setInstances(int instances)
Sets the number of instances for this set of primitives.
bool Has_Primitive_Instancing
Definition: OpenGL.cpp:100
int i32
32 bits signed integer
Definition: std_types.hpp:49
Wrapper for the OpenGL function glDrawElements().
#define VL_INSTRUMENT_CLASS(ClassName, BaseClass)
Definition: TypeInfo.hpp:122
EPrimitiveType
Visualization Library main namespace.
void initialize(IndexIteratorAbstract *iterator)
Base interface for all DrawElements* sub classes.
void applyPatchParameters() const
Definition: DrawCall.hpp:178
IndexIterator indexIterator() const
Returns a IndexIterator used to iterate through the virtual indices of a DrawCall.
i32 count() const
The number of indices to render, default is -1 which means &#39;till the end of the indexBuffer() from of...
bool Has_BufferObject
Definition: OpenGL.cpp:82
arr_type::scalar_type index_type
#define VL_TRAP()
Definition: checks.hpp:70
For internal use only.
An array of GLushort.
Definition: Array.hpp:473
See DrawElements.
unsigned int u32
32 bits unsigned integer
Definition: std_types.hpp:51
const arr_type * indexBuffer() const
The BufferObject containing the indices used to render.
EPrimitiveType mType
Definition: DrawCall.hpp:196
DrawElementsUByte(EPrimitiveType primitive=PT_TRIANGLES, int instances=1)
Iterator used to extract the indices of every single triangle of a DrawCall regardless of the primiti...
virtual ref< DrawCall > clone() const
Returns a clone of this DrawCall.
EBufferObjectUpdateMode
#define NULL
Definition: OpenGLDefs.hpp:81
virtual void deleteBufferObject()
Deletes the index buffer&#39;s BufferObject.
arr_type * indexBuffer()
The BufferObject containing the indices used to render.
VLGRAPHICS_EXPORT const char * getGLErrorString(int err)
Returns a readable string corresponding to the given OpenGL error code as returned by glGetError() ...
Definition: OpenGL.cpp:591
#define VL_CHECK_OGL()
Definition: OpenGL.hpp:156
int instances() const
Returns the number of instances for this set of primitives.
#define VL_INSTRUMENT_ABSTRACT_CLASS(ClassName, BaseClass)
Definition: TypeInfo.hpp:145
The base class of DrawArrays, DrawElements, MultiDrawElements and DrawRangeElements.
Definition: DrawCall.hpp:90
virtual bool primitiveRestartEnabled() const
Returns whether the primitive-restart functionality is enabled or not (requires OpenGL 3...
DrawElementsUInt(EPrimitiveType primitive=PT_TRIANGLES, int instances=1)
bool Has_Base_Vertex
Definition: OpenGL.cpp:99
bool Has_Primitive_Restart
Definition: OpenGL.cpp:93
The ref<> class is used to reference-count an Object.
Definition: Object.hpp:55
u32 offset() const
The offset in bytes from which the index buffer will be read.
Wraps a IndexIteratorAbstract to iterate over the indices of a DrawCall.
EPrimitiveType primitiveType() const
Returns the draw call&#39;s primitive type.
Definition: DrawCall.hpp:110
DrawElementsUShort(EPrimitiveType primitive=PT_TRIANGLES, int instances=1)
void setCount(i32 count)
The number of indices to render, default is -1 which means &#39;till the end of the indexBuffer() from of...
virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode)
Updates the index buffer&#39;s BufferObject if marked as dirty.
void setIndexBuffer(arr_type *index_buffer)
The BufferObject containing the indices used to render.
#define VL_CHECK(expr)
Definition: checks.hpp:73
DrawElements(EPrimitiveType primitive=PT_TRIANGLES, int instances=1)
Constructor.
virtual unsigned int primitiveRestartIndex()
Returns the primitive restart index used by the draw call or 0 if primitive restart is not supported...
void setPrimitiveRestartEnabled(bool enabled)
Enables the primitive-restart functionality (requires OpenGL 3.1).
void setOffset(u32 offset)
The offset in bytes from which the index buffer will be read.