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 <vlCore/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 public:
00058 GLuint primitiveRestartIndex() const { return mPrimitiveRestartIndex; }
00059
00062 void setPrimitiveRestartIndex(GLuint index) { mPrimitiveRestartIndex = index; }
00063
00065 bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00066
00068 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00069
00071 void setInstances(int instances) { mInstances = instances; }
00072
00074 int instances() const { return mInstances; }
00075
00080 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; }
00081
00084 int baseVertex() const { return mBaseVertex; }
00085
00086 protected:
00087 int mInstances;
00088 GLuint mPrimitiveRestartIndex;
00089 bool mPrimitiveRestartEnabled;
00090 int mBaseVertex;
00091 };
00092
00093
00094
00117 template <GLenum Tgltype, class arr_type>
00118 class DrawElements: public DrawElementsBase
00119 {
00120 private:
00121 template<typename T>
00122 class Triangle
00123 {
00124 public:
00125 T ABC[3];
00126 bool operator<(const Triangle< typename arr_type::scalar_type>& b) const
00127 {
00128 if (ABC[0] != b.ABC[0])
00129 return ABC[0] < b.ABC[0];
00130 else
00131 if (ABC[1] != b.ABC[1])
00132 return ABC[1] < b.ABC[1];
00133 else
00134 return ABC[2] < b.ABC[2];
00135 }
00136 void rotate()
00137 {
00138 if (ABC[0] > ABC[1])
00139 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00140 if (ABC[0] > ABC[1])
00141 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00142 }
00143 };
00144
00145 public:
00146 virtual const char* className() { return "vl::DrawElements"; }
00147
00148 DrawElements(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00149 {
00150 VL_DEBUG_SET_OBJECT_NAME()
00151 mType = primitive;
00152 mInstances = instances;
00153 mIndexBuffer = new arr_type;
00154 mPrimitiveRestartIndex = typename arr_type::scalar_type(~0);
00155 mPrimitiveRestartEnabled = false;
00156 mBaseVertex = 0;
00157 }
00158
00159 DrawElements& operator=(const DrawElements& other)
00160 {
00161 DrawElementsBase::operator=(other);
00162 *indices() = *other.indices();
00163 mInstances = other.mInstances;
00164 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00165 mPrimitiveRestartIndex = other.mPrimitiveRestartIndex;
00166 mBaseVertex = other.mBaseVertex;
00167 return *this;
00168 }
00169
00170 virtual ref<DrawCall> clone() const
00171 {
00172 ref<DrawElements> de = new DrawElements;
00173 *de = *this;
00174 return de;
00175 }
00176
00177 virtual unsigned int handle() const { return indices()->gpuBuffer()->handle(); }
00178
00179 arr_type* indices() { return mIndexBuffer.get(); }
00180
00181 const arr_type* indices() const { return mIndexBuffer.get(); }
00182
00183 virtual void updateVBOs(bool discard_local_data=false, bool force_update=false)
00184 {
00185 if (indices()->isVBODirty() || force_update)
00186 indices()->updateVBO(discard_local_data);
00187 }
00188
00189 virtual void deleteVBOs()
00190 {
00191 indices()->gpuBuffer()->deleteGLBufferObject();
00192 }
00193
00194 virtual void clearLocalBuffer()
00195 {
00196 indices()->gpuBuffer()->resize(0);
00197 }
00198
00199 virtual void render(bool use_vbo) const
00200 {
00201 VL_CHECK(mBaseVertex>=0)
00202 VL_CHECK(!use_vbo || (use_vbo && (GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0)))
00203 use_vbo &= GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0;
00204 if ( !use_vbo && !indices()->size() )
00205 return;
00206
00207
00208 applyPatchParameters();
00209
00210
00211 if(primitiveRestartEnabled())
00212 {
00213 if(GLEW_VERSION_3_1)
00214 {
00215 glEnable(GL_PRIMITIVE_RESTART);
00216 glPrimitiveRestartIndex(primitiveRestartIndex());
00217 }
00218 else
00219 if(GLEW_NV_primitive_restart)
00220 {
00221 glEnable(GL_PRIMITIVE_RESTART_NV);
00222 glPrimitiveRestartIndexNV(primitiveRestartIndex());
00223 }
00224 else
00225 {
00226 vl::Log::error("DrawElements error: primitive restart not supported by this OpenGL implementation!\n");
00227 VL_TRAP();
00228 return;
00229 }
00230 }
00231
00232 const GLvoid* ptr = indices()->gpuBuffer()->ptr();
00233
00234 if (use_vbo && indices()->gpuBuffer()->handle())
00235 {
00236 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices()->gpuBuffer()->handle());
00237 ptr = 0;
00238 }
00239 else
00240 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00241
00242
00243 if (mBaseVertex == 0)
00244 {
00245 if ( instances() > 1 && (GLEW_ARB_draw_instanced||GLEW_EXT_draw_instanced) )
00246 VL_glDrawElementsInstanced( primitiveType(), use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr, (GLsizei)instances() );
00247 else
00248 glDrawElements( primitiveType(), use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr );
00249 }
00250 else
00251 {
00252 if ( instances() > 1 && (GLEW_ARB_draw_instanced||GLEW_EXT_draw_instanced) )
00253 VL_glDrawElementsInstancedBaseVertex( primitiveType(), use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr, (GLsizei)instances(), mBaseVertex );
00254 else
00255 VL_glDrawElementsBaseVertex( primitiveType(), use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr, mBaseVertex );
00256 }
00257
00258
00259
00260 if(primitiveRestartEnabled())
00261 {
00262 if(GLEW_VERSION_3_1)
00263 glDisable(GL_PRIMITIVE_RESTART);
00264 else
00265 if(GLEW_NV_primitive_restart)
00266 glDisable(GL_PRIMITIVE_RESTART_NV);
00267 }
00268
00269 #ifndef NDEBUG
00270 unsigned int glerr = glGetError();
00271 if (glerr != GL_NO_ERROR)
00272 {
00273 String msg( (char*)gluErrorString(glerr) );
00274 Log::error( Say("glGetError() [%s:%n]: %s\n") << __FILE__ << __LINE__ << msg );
00275 Log::print(
00276 "OpenGL Geometry Instancing (GL_ARB_draw_instanced) does not support display lists."
00277 "If you are using geometry instancing in conjunction with display lists you will have to disable one of them.\n"
00278 );
00279 VL_TRAP()
00280 }
00281 #endif
00282 }
00283
00284 TriangleIterator triangleIterator() const
00285 {
00286 ref< TriangleIteratorIndexed<arr_type> > it =
00287 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
00288 baseVertex(), primitiveRestartEnabled(), primitiveRestartIndex() );
00289 it->initialize();
00290 return TriangleIterator(it.get());
00291 }
00292
00293 IndexIterator indexIterator() const
00294 {
00295 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00296 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, mPrimitiveRestartIndex );
00297 IndexIterator iit;
00298 iit.initialize( iie.get() );
00299 return iit;
00300 }
00301
00302 protected:
00303 ref< arr_type > mIndexBuffer;
00304 };
00305
00306
00307
00309 class DrawElementsUInt: public DrawElements<GL_UNSIGNED_INT, ArrayUInt1>
00310 {
00311 public:
00312 DrawElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00313 :DrawElements<GL_UNSIGNED_INT, ArrayUInt1>(primitive, instances) {}
00314 };
00315
00317 class DrawElementsUShort: public DrawElements<GL_UNSIGNED_SHORT, ArrayUShort1>
00318 {
00319 public:
00320 DrawElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00321 :DrawElements<GL_UNSIGNED_SHORT, ArrayUShort1>(primitive, instances) {}
00322 };
00323
00325 class DrawElementsUByte: public DrawElements<GL_UNSIGNED_BYTE, ArrayUByte1>
00326 {
00327 public:
00328 DrawElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1)
00329 :DrawElements<GL_UNSIGNED_BYTE, ArrayUByte1>(primitive, instances) {}
00330 };
00331
00332 }
00333
00334 #endif