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 MultiDrawElements_INCLUDE_ONCE
00033 #define MultiDrawElements_INCLUDE_ONCE
00034
00035 #include <vlGraphics/DrawCall.hpp>
00036 #include <vlCore/Array.hpp>
00037 #include <vlGraphics/TriangleIterator.hpp>
00038 #include <vlCore/Log.hpp>
00039 #include <vlCore/Say.hpp>
00040 #include <algorithm>
00041
00042 namespace vl
00043 {
00044
00045
00046
00052 class MultiDrawElementsBase: public DrawCall
00053 {
00054 public:
00057 GLuint primitiveRestartIndex() const { return mPrimitiveRestartIndex; }
00058
00061 void setPrimitiveRestartIndex(GLuint index) { mPrimitiveRestartIndex = index; }
00062
00064 bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00065
00067 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00068
00071 void setCountVector(const std::vector<GLsizei>& vcount)
00072 {
00073 mCountVector = vcount;
00074 compute_pointer_vector();
00075 }
00076
00078 const std::vector<GLsizei>& countVector() const { return mCountVector; }
00079
00083 void setBaseVertices(const std::vector<GLint>& base_verts) { mBaseVertices = base_verts; }
00084
00086 const std::vector<GLint>& baseVertices() const { return mBaseVertices; }
00087
00089 std::vector<GLint>& baseVertices() { return mBaseVertices; }
00090
00091 protected:
00092 virtual void compute_pointer_vector() = 0;
00093
00094 protected:
00095 GLuint mPrimitiveRestartIndex;
00096 bool mPrimitiveRestartEnabled;
00097 std::vector<GLsizei> mCountVector;
00098 std::vector<GLint> mBaseVertices;
00099 };
00100
00101
00102
00122 template <GLenum Tgltype, class arr_type>
00123 class MultiDrawElements: public MultiDrawElementsBase
00124 {
00125 public:
00126 virtual const char* className() { return "vl::MultiDrawElements"; }
00127
00128 MultiDrawElements(EPrimitiveType primitive = PT_TRIANGLES)
00129 {
00130 VL_DEBUG_SET_OBJECT_NAME()
00131 mType = primitive;
00132 mIndexBuffer = new arr_type;
00133 mPrimitiveRestartIndex = typename arr_type::scalar_type(~0);
00134 mPrimitiveRestartEnabled = false;
00135 }
00136
00137 MultiDrawElements& operator=(const MultiDrawElements& other)
00138 {
00139 DrawCall::operator=(other);
00140 *indices() = *other.indices();
00141 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00142 mPrimitiveRestartIndex = other.mPrimitiveRestartIndex;
00143 setCountVector(other.mCountVector);
00144 return *this;
00145 }
00146
00147 virtual ref<DrawCall> clone() const
00148 {
00149 ref<MultiDrawElements> de = new MultiDrawElements;
00150 *de = *this;
00151 return de;
00152 }
00153
00154 virtual unsigned int handle() const { return indices()->gpuBuffer()->handle(); }
00155
00156 arr_type* indices() { return mIndexBuffer.get(); }
00157
00158 const arr_type* indices() const { return mIndexBuffer.get(); }
00159
00160 virtual void updateVBOs(bool discard_local_data=false, bool force_update=false)
00161 {
00162 if (indices()->isVBODirty() || force_update)
00163 indices()->updateVBO(discard_local_data);
00164 }
00165
00166 virtual void deleteVBOs()
00167 {
00168 indices()->gpuBuffer()->deleteGLBufferObject();
00169 }
00170
00171 virtual void clearLocalBuffer()
00172 {
00173 indices()->gpuBuffer()->resize(0);
00174 }
00175
00176 virtual void render(bool use_vbo) const
00177 {
00178 VL_CHECK(GLEW_VERSION_1_4);
00179 VL_CHECK(!use_vbo || (use_vbo && (GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0)))
00180 use_vbo &= GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0;
00181 if ( !use_vbo && !indices()->size() )
00182 return;
00183
00184
00185 applyPatchParameters();
00186
00187
00188 if(primitiveRestartEnabled())
00189 {
00190 if(GLEW_VERSION_3_1)
00191 {
00192 glEnable(GL_PRIMITIVE_RESTART);
00193 glPrimitiveRestartIndex(primitiveRestartIndex());
00194 }
00195 else
00196 if(GLEW_NV_primitive_restart)
00197 {
00198 glEnable(GL_PRIMITIVE_RESTART_NV);
00199 glPrimitiveRestartIndexNV(primitiveRestartIndex());
00200 }
00201 else
00202 {
00203 vl::Log::error("MultiDrawElements error: primitive restart not supported by this OpenGL implementation!\n");
00204 VL_TRAP();
00205 return;
00206 }
00207 }
00208
00209 GLvoid **indices_ptr = (GLvoid**)&mPointerVector[0];
00210 if (use_vbo && indices()->gpuBuffer()->handle())
00211 {
00212 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices()->gpuBuffer()->handle());
00213 indices_ptr = (GLvoid**)&mNULLPointerVector[0];
00214 }
00215 else
00216 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00217
00218 if (baseVertices().size())
00219 {
00220 VL_CHECK( baseVertices().size() == pointerVector().size() )
00221 VL_CHECK( baseVertices().size() == countVector().size() )
00222 if (GLEW_ARB_draw_elements_base_vertex || GLEW_VERSION_3_1)
00223 glMultiDrawElementsBaseVertex(
00224 primitiveType(), (GLsizei*)&mCountVector[0], indices()->glType(), indices_ptr, (GLsizei)mCountVector.size(), (GLint*)&mBaseVertices[0]
00225 );
00226 else
00227 {
00228 vl::Log::error("MultiDrawElements::render(): glMultiDrawElementsBaseVertex() not supported!\n"
00229 "OpenGL 3.1 or GL_ARB_draw_elements_base_vertex extension required.\n"
00230 );
00231 }
00232 }
00233 else
00234 glMultiDrawElements( primitiveType(), (GLsizei*)&mCountVector[0], indices()->glType(), (const GLvoid**)indices_ptr, (GLsizei)mCountVector.size() );
00235
00236
00237 if(primitiveRestartEnabled())
00238 {
00239 if(GLEW_VERSION_3_1)
00240 glDisable(GL_PRIMITIVE_RESTART);
00241 else
00242 if(GLEW_NV_primitive_restart)
00243 glDisable(GL_PRIMITIVE_RESTART_NV);
00244 }
00245 }
00246
00247 TriangleIterator triangleIterator() const;
00248
00249 IndexIterator indexIterator() const
00250 {
00251 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00252 iie->initialize( mIndexBuffer.get(), &mBaseVertices, &mCountVector, 0, mPrimitiveRestartEnabled, mPrimitiveRestartIndex );
00253 IndexIterator iit;
00254 iit.initialize( iie.get() );
00255 return iit;
00256 }
00257
00259 const std::vector<const typename arr_type::scalar_type*>& pointerVector() const { return mPointerVector; }
00260
00261 protected:
00262 void compute_pointer_vector()
00263 {
00264
00265 mNULLPointerVector.resize( mCountVector.size() );
00266
00267
00268 mPointerVector.clear();
00269 const typename arr_type::scalar_type* ptr = (const typename arr_type::scalar_type*)indices()->gpuBuffer()->ptr();
00270 for(size_t i=0; i<mCountVector.size(); ++i)
00271 {
00272 mPointerVector.push_back(ptr);
00273 ptr += mCountVector[i];
00274 }
00275 VL_CHECK( ptr - (const typename arr_type::scalar_type*)indices()->gpuBuffer()->ptr() <= (int)indices()->size() );
00276 }
00277
00278
00279 protected:
00280 ref< arr_type > mIndexBuffer;
00281 std::vector<const typename arr_type::scalar_type*> mPointerVector;
00282 std::vector<const typename arr_type::scalar_type*> mNULLPointerVector;
00283 };
00284
00285
00286
00288 class MultiDrawElementsUInt: public MultiDrawElements<GL_UNSIGNED_INT, ArrayUInt1>
00289 {
00290 public:
00291 MultiDrawElementsUInt(EPrimitiveType primitive = PT_TRIANGLES)
00292 :MultiDrawElements<GL_UNSIGNED_INT, ArrayUInt1>(primitive) {}
00293 };
00294
00296 class MultiDrawElementsUShort: public MultiDrawElements<GL_UNSIGNED_SHORT, ArrayUShort1>
00297 {
00298 public:
00299 MultiDrawElementsUShort(EPrimitiveType primitive = PT_TRIANGLES)
00300 :MultiDrawElements<GL_UNSIGNED_SHORT, ArrayUShort1>(primitive) {}
00301 };
00302
00304 class MultiDrawElementsUByte: public MultiDrawElements<GL_UNSIGNED_BYTE, ArrayUByte1>
00305 {
00306 public:
00307 MultiDrawElementsUByte(EPrimitiveType primitive = PT_TRIANGLES)
00308 :MultiDrawElements<GL_UNSIGNED_BYTE, ArrayUByte1>(primitive) {}
00309 };
00310
00311 template <GLenum Tgltype, class arr_type>
00312 TriangleIterator MultiDrawElements<Tgltype, arr_type>::triangleIterator() const
00313 {
00314 ref< TriangleIteratorMulti<arr_type> > it =
00315 new TriangleIteratorMulti<arr_type>( &mBaseVertices, &mCountVector, mIndexBuffer.get(), primitiveType(),
00316 primitiveRestartEnabled(), primitiveRestartIndex() );
00317 it->initialize();
00318 return TriangleIterator(it.get());
00319 }
00320
00321 }
00322
00323 #endif