Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef DrawElements_INCLUDE_ONCE
00033 #define DrawElements_INCLUDE_ONCE
00034
00035 #include <vlGraphics/DrawCall.hpp>
00036 #include <vlGraphics/TriangleIterator.hpp>
00037 #include <vlGraphics/Array.hpp>
00038 #include <vlCore/Log.hpp>
00039 #include <vlCore/Say.hpp>
00040 #include <algorithm>
00041
00042 namespace vl
00043 {
00044
00045
00046
00047
00053 class DrawElementsBase: public DrawCall
00054 {
00055 VL_INSTRUMENT_ABSTRACT_CLASS(vl::DrawElementsBase, DrawCall)
00056
00057 public:
00059 virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00060
00062 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00063
00065 void setInstances(int instances) { mInstances = instances; }
00066
00068 int instances() const { return mInstances; }
00069
00074 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; }
00075
00078 int baseVertex() const { return mBaseVertex; }
00079
00080 protected:
00081 int mInstances;
00082 bool mPrimitiveRestartEnabled;
00083 GLuint mBaseVertex;
00084 };
00085
00086
00087
00117 template <class arr_type>
00118 class DrawElements: public DrawElementsBase
00119 {
00120 VL_INSTRUMENT_CLASS(vl::DrawElements<arr_type>, DrawElementsBase)
00121
00122 public:
00123 typedef typename arr_type::scalar_type index_type;
00125 static const index_type primitive_restart_index = index_type(~0);
00126 virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; }
00127
00128 private:
00129 template<typename T>
00130 class Triangle
00131 {
00132 public:
00133 T ABC[3];
00134 bool operator<(const Triangle<index_type>& b) const
00135 {
00136 if (ABC[0] != b.ABC[0])
00137 return ABC[0] < b.ABC[0];
00138 else
00139 if (ABC[1] != b.ABC[1])
00140 return ABC[1] < b.ABC[1];
00141 else
00142 return ABC[2] < b.ABC[2];
00143 }
00144 void rotate()
00145 {
00146 if (ABC[0] > ABC[1])
00147 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00148 if (ABC[0] > ABC[1])
00149 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00150 }
00151 };
00152
00153 public:
00155 DrawElements(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00156 {
00157 VL_DEBUG_SET_OBJECT_NAME()
00158 mType = primitive;
00159 mInstances = instances;
00160 mIndexBuffer = new arr_type;
00161 mPrimitiveRestartEnabled = false;
00162 mBaseVertex = 0;
00163 mCount = -1;
00164 mOffset = 0;
00165 }
00166
00168 DrawElements& operator=(const DrawElements& other)
00169 {
00170 super::operator=(other);
00171 *indexBuffer() = *other.indexBuffer();
00172 mInstances = other.mInstances;
00173 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00174 mBaseVertex = other.mBaseVertex;
00175 mCount = other.mCount;
00176 mOffset = other.mOffset;
00177 return *this;
00178 }
00179
00181 virtual ref<DrawCall> clone() const
00182 {
00183 ref<DrawElements> de = new DrawElements;
00184 *de = *this;
00185 return de;
00186 }
00187
00189 void setCount(i32 count) { mCount = count; }
00190
00192 i32 count() const { return mCount; }
00193
00195 void setOffset(u32 offset) { mOffset = offset; }
00196
00198 u32 offset() const { return mOffset; }
00199
00201 void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; }
00202
00204 arr_type* indexBuffer() { return mIndexBuffer.get(); }
00205
00207 const arr_type* indexBuffer() const { return mIndexBuffer.get(); }
00208
00209 virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode)
00210 {
00211 if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate))
00212 indexBuffer()->updateBufferObject(mode);
00213 }
00214
00215 virtual void deleteBufferObject()
00216 {
00217 indexBuffer()->bufferObject()->deleteBufferObject();
00218 }
00219
00220 virtual void render(bool use_bo) const
00221 {
00222 VL_CHECK_OGL()
00223 VL_CHECK(!use_bo || (use_bo && Has_BufferObject))
00224
00225 #if !defined(NDEBUG) && (defined(VL_OPENGL_ES1) || defined(GL_OPENGL_ES2))
00226 bool error = true;
00227
00228 switch(primitiveType())
00229 {
00230 case PT_QUADS: Log::error("vl::DrawElements does not support PT_QUADS under OpenGL ES!\n"); break;
00231 case PT_QUAD_STRIP: Log::error("vl::DrawElements does not support PT_QUAD_STRIP under OpenGL ES!\n"); break;
00232 case PT_POLYGON: Log::error("vl::DrawElements does not support PT_POLYGON under OpenGL ES!\n"); break;
00233 case PT_LINES_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINES_ADJACENCY under OpenGL ES!\n"); break;
00234 case PT_LINE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINE_STRIP_ADJACENCY under OpenGL ES!\n"); break;
00235 case PT_TRIANGLES_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLES_ADJACENCY under OpenGL ES!\n"); break;
00236 case PT_TRIANGLE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLE_STRIP_ADJACENCY under OpenGL ES!\n"); break;
00237 case PT_PATCHES: Log::error("vl::DrawElements does not support PT_PATCHES under OpenGL ES!\n"); break;
00238 default:
00239 error = false;
00240 break;
00241 }
00242
00243 if (indexBuffer()->glType() != GL_UNSIGNED_BYTE && indexBuffer()->glType() != GL_UNSIGNED_SHORT)
00244 {
00245 Log::error("vl::DrawElements only supports GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT under OpenGL ES!\n");
00246 error = true;
00247 }
00248 VL_CHECK(!error)
00249 #endif
00250
00251 use_bo &= Has_BufferObject;
00252 if ( !use_bo && !indexBuffer()->size() )
00253 return;
00254
00255
00256 applyPatchParameters();
00257
00258
00259 if(primitiveRestartEnabled())
00260 {
00261 VL_CHECK(Has_Primitive_Restart);
00262 glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL();
00263 glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL();
00264 }
00265
00266
00267
00268 const GLvoid* ptr = indexBuffer()->bufferObject()->ptr();
00269 if (use_bo && indexBuffer()->bufferObject()->handle())
00270 {
00271 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL()
00272 ptr = 0;
00273 }
00274 else
00275 {
00276 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); VL_CHECK_OGL()
00277 }
00278
00279
00280
00281 const char*ptr_end = NULL;
00282 if(mCount < 0)
00283 {
00284
00285 ptr_end = (char*)ptr + sizeof(index_type)*(use_bo ? indexBuffer()->sizeBufferObject() : indexBuffer()->size());
00286
00287
00288 ptr = (char*)ptr + mOffset;
00289 }
00290 else
00291 {
00292
00293 ptr = (char*)ptr + mOffset;
00294
00295
00296 ptr_end = (char*)ptr + sizeof(index_type)*mCount;
00297 }
00298
00299
00300 const GLsizei count = (GLsizei)((index_type*)ptr_end - (index_type*)ptr);
00301
00302 if (mBaseVertex == 0)
00303 {
00304 if ( instances() == 1 )
00305 {
00306 glDrawElements( primitiveType(), count, arr_type::gl_type, ptr ); VL_CHECK_OGL()
00307 }
00308 else
00309 {
00310 VL_CHECK(Has_Primitive_Instancing)
00311 VL_glDrawElementsInstanced( primitiveType(), count, arr_type::gl_type, ptr, instances() ); VL_CHECK_OGL()
00312 }
00313 }
00314 else
00315 {
00316 VL_CHECK(Has_Base_Vertex)
00317 if ( instances() == 1 )
00318 {
00319 VL_glDrawElementsBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, mBaseVertex ); VL_CHECK_OGL()
00320 }
00321 else
00322 {
00323 VL_CHECK(Has_Primitive_Instancing)
00324 VL_glDrawElementsInstancedBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, instances(), mBaseVertex ); VL_CHECK_OGL()
00325 }
00326 }
00327
00328
00329
00330 if(primitiveRestartEnabled())
00331 {
00332 glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL()
00333 }
00334
00335 #ifndef NDEBUG
00336 unsigned int glerr = glGetError();
00337 if (glerr != GL_NO_ERROR)
00338 {
00339 String msg( getGLErrorString(glerr) );
00340 Log::error( Say("glGetError() [%s:%n]: %s\n") << __FILE__ << __LINE__ << msg );
00341 Log::warning( "- If you are using geometry instancing in conjunction with display lists you will have to disable one of them.\n" );
00342 Log::warning( "- If you are using OpenGL ES you must not use GL_QUADS, GL_QUAD_STRIP and GL_POLYGON primitive types.\n" );
00343 VL_TRAP()
00344 }
00345 #endif
00346 }
00347
00348 TriangleIterator triangleIterator() const
00349 {
00350 ref< TriangleIteratorIndexed<arr_type> > it =
00351 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
00352 baseVertex(), primitiveRestartEnabled(), primitive_restart_index );
00353 it->initialize();
00354 return TriangleIterator(it.get());
00355 }
00356
00357 IndexIterator indexIterator() const
00358 {
00359 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00360 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, primitive_restart_index );
00361 IndexIterator iit;
00362 iit.initialize( iie.get() );
00363 return iit;
00364 }
00365
00366 protected:
00367 ref< arr_type > mIndexBuffer;
00368 i32 mCount;
00369 u32 mOffset;
00370 };
00371
00372
00373
00375 class DrawElementsUInt: public DrawElements<ArrayUInt1>
00376 {
00377 VL_INSTRUMENT_CLASS(vl::DrawElementsUInt, DrawElements<ArrayUInt1>)
00378
00379 public:
00380 DrawElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00381 :DrawElements<ArrayUInt1>(primitive, instances)
00382 {
00383 VL_DEBUG_SET_OBJECT_NAME();
00384 }
00385 };
00386
00388 class DrawElementsUShort: public DrawElements<ArrayUShort1>
00389 {
00390 VL_INSTRUMENT_CLASS(vl::DrawElementsUShort, DrawElements<ArrayUShort1>)
00391
00392 public:
00393 DrawElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00394 :DrawElements<ArrayUShort1>(primitive, instances)
00395 {
00396 VL_DEBUG_SET_OBJECT_NAME();
00397 }
00398 };
00399
00401 class DrawElementsUByte: public DrawElements<ArrayUByte1>
00402 {
00403 VL_INSTRUMENT_CLASS(vl::DrawElementsUByte, DrawElements<ArrayUByte1>)
00404
00405 public:
00406 DrawElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00407 :DrawElements<ArrayUByte1>(primitive, instances)
00408 {
00409 VL_DEBUG_SET_OBJECT_NAME();
00410 }
00411 };
00412
00413 }
00414
00415 #endif