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