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 <vlGraphics/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 VL_INSTRUMENT_ABSTRACT_CLASS(vl::MultiDrawElementsBase, DrawCall)
00055
00056 public:
00058 virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00059
00061 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00062
00065 void finalizeSetup()
00066 {
00067
00068 computePointerVector();
00069 computeBufferObjectPointerVector();
00070
00071 if (mBaseVertices.size() != mCountVector.size())
00072 mBaseVertices.resize(mCountVector.size());
00073 }
00074
00077 void setCountVector(const std::vector<GLsizei>& vcount)
00078 {
00079 mCountVector = vcount;
00080 finalizeSetup();
00081 }
00082
00085 void setCountVector(const GLsizei* vcount, size_t size)
00086 {
00087 mCountVector.resize(size);
00088 for(size_t i=0; i<size; ++i)
00089 mCountVector[i] = vcount[i];
00090 finalizeSetup();
00091 }
00092
00094 const std::vector<GLsizei>& countVector() const { return mCountVector; }
00095
00097 std::vector<GLsizei>& countVector() { return mCountVector; }
00098
00102 void setBaseVertices(const std::vector<GLint>& base_verts) { mBaseVertices = base_verts; }
00103
00105 const std::vector<GLint>& baseVertices() const { return mBaseVertices; }
00106
00108 std::vector<GLint>& baseVertices() { return mBaseVertices; }
00109
00112 virtual void computePointerVector() = 0;
00113
00116 virtual void computeBufferObjectPointerVector() = 0;
00117
00118 protected:
00119 bool mPrimitiveRestartEnabled;
00120 std::vector<GLsizei> mCountVector;
00121 std::vector<GLint> mBaseVertices;
00122 };
00123
00124
00125
00150 template <class arr_type>
00151 class MultiDrawElements: public MultiDrawElementsBase
00152 {
00153 VL_INSTRUMENT_CLASS(vl::MultiDrawElements<arr_type>, MultiDrawElementsBase)
00154
00155 public:
00156 typedef typename arr_type::scalar_type index_type;
00158 static const index_type primitive_restart_index = index_type(~0);
00159 virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; }
00160
00161 public:
00162 MultiDrawElements(EPrimitiveType primitive = PT_TRIANGLES)
00163 {
00164 VL_DEBUG_SET_OBJECT_NAME()
00165 mType = primitive;
00166 mIndexBuffer = new arr_type;
00167 mPrimitiveRestartEnabled = false;
00168 }
00169
00170 MultiDrawElements& operator=(const MultiDrawElements& other)
00171 {
00172 super::operator=(other);
00173 *indexBuffer() = *other.indexBuffer();
00174 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00175 setCountVector(other.mCountVector);
00176 return *this;
00177 }
00178
00179 virtual ref<DrawCall> clone() const
00180 {
00181 ref<MultiDrawElements> de = new MultiDrawElements;
00182 *de = *this;
00183 return de;
00184 }
00185
00186 void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; }
00187
00188 arr_type* indexBuffer() { return mIndexBuffer.get(); }
00189
00190 const arr_type* indexBuffer() const { return mIndexBuffer.get(); }
00191
00192 virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode)
00193 {
00194 if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate))
00195 indexBuffer()->updateBufferObject(mode);
00196 }
00197
00198 virtual void deleteBufferObject()
00199 {
00200 indexBuffer()->bufferObject()->deleteBufferObject();
00201 }
00202
00203 virtual void render(bool use_bo) const
00204 {
00205 VL_CHECK_OGL()
00206 VL_CHECK(Has_GL_EXT_multi_draw_arrays||Has_GL_Version_1_4||Has_GL_Version_3_0||Has_GL_Version_4_0);
00207 VL_CHECK(!use_bo || (use_bo && Has_BufferObject))
00208 use_bo &= Has_BufferObject;
00209 if ( !use_bo && !indexBuffer()->size() )
00210 return;
00211
00212
00213 applyPatchParameters();
00214
00215
00216 if(primitiveRestartEnabled())
00217 {
00218 VL_CHECK(Has_Primitive_Restart);
00219 glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL();
00220 glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL();
00221 }
00222
00223 const GLvoid **indices_ptr = NULL;
00224 if (use_bo && indexBuffer()->bufferObject()->handle())
00225 {
00226 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL()
00227 VL_CHECK(!mBufferObjectPointerVector.empty())
00228 indices_ptr = (const GLvoid**)&mBufferObjectPointerVector[0];
00229 }
00230 else
00231 {
00232 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00233 VL_CHECK(!mPointerVector.empty())
00234 indices_ptr = (const GLvoid**)&mPointerVector[0];
00235 }
00236
00237 if (baseVertices().size())
00238 {
00239 VL_CHECK( baseVertices().size() == pointerVector().size() )
00240 VL_CHECK( baseVertices().size() == countVector().size() )
00241 if (Has_GL_ARB_draw_elements_base_vertex||Has_GL_Version_3_1||Has_GL_Version_4_0)
00242 {
00243 glMultiDrawElementsBaseVertex( primitiveType(), (GLsizei*)&mCountVector[0], indexBuffer()->glType(), indices_ptr, (GLsizei)mCountVector.size(), (GLint*)&mBaseVertices[0] ); VL_CHECK_OGL()
00244 }
00245 else
00246 {
00247 vl::Log::error("MultiDrawElements::render(): glMultiDrawElementsBaseVertex() not supported!\n"
00248 "OpenGL 3.1 or GL_ARB_draw_elements_base_vertex extension required.\n"
00249 );
00250 }
00251 }
00252 else
00253 {
00254 glMultiDrawElements( primitiveType(), (GLsizei*)&mCountVector[0], indexBuffer()->glType(), (const GLvoid**)indices_ptr, (GLsizei)mCountVector.size() ); VL_CHECK_OGL()
00255 }
00256
00257
00258 if(primitiveRestartEnabled())
00259 {
00260 glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL()
00261 }
00262 }
00263
00264 TriangleIterator triangleIterator() const;
00265
00266 IndexIterator indexIterator() const
00267 {
00268 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00269 iie->initialize( mIndexBuffer.get(), &mBaseVertices, &mCountVector, 0, mPrimitiveRestartEnabled, primitive_restart_index );
00270 IndexIterator iit;
00271 iit.initialize( iie.get() );
00272 return iit;
00273 }
00274
00277 const std::vector<const index_type*>& pointerVector() const { return mPointerVector; }
00278
00280 std::vector<const index_type*>& pointerVector() { return mPointerVector; }
00281
00283 const std::vector<const index_type*>& bufferObjectPointerVector() const { return mBufferObjectPointerVector; }
00284
00286 std::vector<const index_type*>& bufferObjectPointerVector() { return mBufferObjectPointerVector; }
00287
00289 void computePointerVector()
00290 {
00291 VL_CHECK( indexBuffer() && indexBuffer()->size() )
00292 mPointerVector.resize( mCountVector.size() );
00293 const index_type* ptr = (const index_type*)indexBuffer()->bufferObject()->ptr();
00294 for(size_t i=0; i<mCountVector.size(); ++i)
00295 {
00296 mPointerVector[i] = ptr;
00297 ptr += mCountVector[i];
00298 }
00299 }
00300
00302 void computeBufferObjectPointerVector()
00303 {
00304 VL_CHECK( indexBuffer() && indexBuffer()->size() )
00305 mBufferObjectPointerVector.resize( mPointerVector.size() );
00306 const index_type* base_ptr = (const index_type*)indexBuffer()->ptr();
00307 VL_CHECK(base_ptr)
00308 for(size_t i=0; i<mPointerVector.size(); ++i)
00309 {
00310 size_t offset = mPointerVector[i] - base_ptr;
00311 mBufferObjectPointerVector[i] = (const index_type*)0 + offset;
00312 }
00313 }
00314
00315 protected:
00316 ref< arr_type > mIndexBuffer;
00317 std::vector<const index_type*> mPointerVector;
00318 std::vector<const index_type*> mBufferObjectPointerVector;
00319 };
00320
00321
00322
00324 class MultiDrawElementsUInt: public MultiDrawElements<ArrayUInt1>
00325 {
00326 VL_INSTRUMENT_CLASS(vl::MultiDrawElementsUInt, MultiDrawElements< ArrayUInt1>)
00327
00328 public:
00329 MultiDrawElementsUInt(EPrimitiveType primitive = PT_TRIANGLES)
00330 :MultiDrawElements<ArrayUInt1>(primitive)
00331 {
00332 VL_DEBUG_SET_OBJECT_NAME();
00333 }
00334 };
00335
00337 class MultiDrawElementsUShort: public MultiDrawElements<ArrayUShort1>
00338 {
00339 VL_INSTRUMENT_CLASS(vl::MultiDrawElementsUShort, MultiDrawElements< ArrayUShort1>)
00340
00341 public:
00342 MultiDrawElementsUShort(EPrimitiveType primitive = PT_TRIANGLES)
00343 :MultiDrawElements<ArrayUShort1>(primitive)
00344 {
00345 VL_DEBUG_SET_OBJECT_NAME();
00346 }
00347 };
00348
00350 class MultiDrawElementsUByte: public MultiDrawElements<ArrayUByte1>
00351 {
00352 VL_INSTRUMENT_CLASS(vl::MultiDrawElementsUByte, MultiDrawElements<ArrayUByte1>)
00353
00354 public:
00355 MultiDrawElementsUByte(EPrimitiveType primitive = PT_TRIANGLES)
00356 :MultiDrawElements<ArrayUByte1>(primitive)
00357 {
00358 VL_DEBUG_SET_OBJECT_NAME();
00359 }
00360 };
00361
00362 template <class arr_type>
00363 TriangleIterator MultiDrawElements<arr_type>::triangleIterator() const
00364 {
00365 ref< TriangleIteratorMulti<arr_type> > it =
00366 new TriangleIteratorMulti<arr_type>( &mBaseVertices, &mCountVector, mIndexBuffer.get(), primitiveType(),
00367 primitiveRestartEnabled(), primitive_restart_index );
00368 it->initialize();
00369 return TriangleIterator(it.get());
00370 }
00371
00372 }
00373
00374 #endif