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 DrawRangeElements_INCLUDE_ONCE
00033 #define DrawRangeElements_INCLUDE_ONCE
00034
00035 #include <vlGraphics/DrawCall.hpp>
00036 #include <vlGraphics/TriangleIterator.hpp>
00037 #include <vlGraphics/LineIterator.hpp>
00038 #include <vlGraphics/Array.hpp>
00039 #include <vlCore/Log.hpp>
00040 #include <vlCore/Say.hpp>
00041 #include <algorithm>
00042
00043 namespace vl
00044 {
00045
00046
00047
00048
00054 class DrawRangeElementsBase: public DrawCall
00055 {
00056 VL_INSTRUMENT_ABSTRACT_CLASS(vl::DrawRangeElementsBase, DrawCall)
00057
00058 public:
00060 void setRangeStart(int rstart) { mRangeStart = rstart; }
00061
00063 int rangeStart() const { return mRangeStart; }
00064
00066 void setRangeEnd(int rend) { mRangeEnd = rend; }
00067
00069 int rangeEnd() const { return mRangeEnd; }
00070
00072 virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00073
00075 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00076
00081 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; }
00082
00085 int baseVertex() const { return mBaseVertex; }
00086
00087 protected:
00088 int mRangeStart;
00089 int mRangeEnd;
00090 GLuint mBaseVertex;
00091 bool mPrimitiveRestartEnabled;
00092 };
00093
00094
00095
00120 template <class arr_type>
00121 class DrawRangeElements: public DrawRangeElementsBase
00122 {
00123 VL_INSTRUMENT_CLASS(vl::DrawRangeElements<arr_type>, DrawRangeElementsBase)
00124
00125 public:
00126 typedef typename arr_type::scalar_type index_type;
00128 static const index_type primitive_restart_index = index_type(~0);
00129 virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; }
00130
00131 private:
00132 template<typename T>
00133 class Triangle
00134 {
00135 public:
00136 T ABC[3];
00137 bool operator<(const Triangle<index_type>& b) const
00138 {
00139 if (ABC[0] != b.ABC[0])
00140 return ABC[0] < b.ABC[0];
00141 else
00142 if (ABC[1] != b.ABC[1])
00143 return ABC[1] < b.ABC[1];
00144 else
00145 return ABC[2] < b.ABC[2];
00146 }
00147 void rotate()
00148 {
00149 if (ABC[0] > ABC[1])
00150 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00151 if (ABC[0] > ABC[1])
00152 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00153 }
00154 };
00155
00156 public:
00157 DrawRangeElements(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=primitive_restart_index)
00158 {
00159 VL_DEBUG_SET_OBJECT_NAME()
00160 mType = primitive;
00161 mRangeStart = r_start;
00162 mRangeEnd = r_end;
00163 mIndexBuffer = new arr_type;
00164 mPrimitiveRestartEnabled = false;
00165 mBaseVertex = 0;
00166 mCount = -1;
00167 mOffset = 0;
00168 }
00169
00170 DrawRangeElements& operator=(const DrawRangeElements& other)
00171 {
00172 super::operator=(other);
00173 *indexBuffer() = *other.indexBuffer();
00174 mRangeStart = other.mRangeStart;
00175 mRangeEnd = other.mRangeEnd;
00176 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00177 mBaseVertex = other.mBaseVertex;
00178 mCount = other.mCount;
00179 mOffset = other.mOffset;
00180 return *this;
00181 }
00182
00183 virtual ref<DrawCall> clone() const
00184 {
00185 ref<DrawRangeElements> de = new DrawRangeElements;
00186 *de = *this;
00187 return de;
00188 }
00189
00191 void setCount(i32 count) { mCount = count; }
00192
00194 i32 count() const { return mCount; }
00195
00197 void setOffset(u32 offset) { mOffset = offset; }
00198
00200 u32 offset() const { return mOffset; }
00201
00203 void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; }
00204
00206 arr_type* indexBuffer() { return mIndexBuffer.get(); }
00207
00209 const arr_type* indexBuffer() const { return mIndexBuffer.get(); }
00210
00211 virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode)
00212 {
00213 if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate))
00214 indexBuffer()->updateBufferObject(mode);
00215 }
00216
00217 virtual void deleteBufferObject()
00218 {
00219 indexBuffer()->bufferObject()->deleteBufferObject();
00220 }
00221
00222 virtual void render(bool use_bo) const
00223 {
00224 VL_CHECK_OGL()
00225 VL_CHECK(!use_bo || (use_bo && Has_BufferObject))
00226 use_bo &= Has_BufferObject;
00227 if ( !use_bo && !indexBuffer()->size() )
00228 return;
00229
00230
00231 applyPatchParameters();
00232
00233
00234 if(primitiveRestartEnabled())
00235 {
00236 VL_CHECK(Has_Primitive_Restart);
00237 glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL();
00238 glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL();
00239 }
00240
00241
00242
00243 const GLvoid* ptr = indexBuffer()->bufferObject()->ptr();
00244 if (use_bo && indexBuffer()->bufferObject()->handle())
00245 {
00246 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL()
00247 ptr = 0;
00248 }
00249 else
00250 {
00251 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); VL_CHECK_OGL()
00252 }
00253
00254
00255
00256 const char*ptr_end = NULL;
00257 if(mCount < 0)
00258 {
00259
00260 ptr_end = (char*)ptr + sizeof(index_type)*(use_bo ? indexBuffer()->sizeBufferObject() : indexBuffer()->size());
00261
00262
00263 ptr = (char*)ptr + mOffset;
00264 }
00265 else
00266 {
00267
00268 ptr = (char*)ptr + mOffset;
00269
00270
00271 ptr_end = (char*)ptr + sizeof(index_type)*mCount;
00272 }
00273
00274
00275 const GLsizei count = (GLsizei)((index_type*)ptr_end - (index_type*)ptr);
00276
00277 if (mBaseVertex == 0)
00278 {
00279 glDrawRangeElements( primitiveType(), mRangeStart, mRangeEnd, count, arr_type::gl_type, ptr ); VL_CHECK_OGL()
00280 }
00281 else
00282 {
00283 VL_CHECK(Has_Base_Vertex)
00284 VL_glDrawRangeElementsBaseVertex( primitiveType(), mRangeStart, mRangeEnd, count, arr_type::gl_type, ptr, mBaseVertex ); VL_CHECK_OGL()
00285 }
00286
00287
00288
00289 if(primitiveRestartEnabled())
00290 {
00291 glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL()
00292 }
00293 }
00294
00295 TriangleIterator triangleIterator() const
00296 {
00297 ref< TriangleIteratorIndexed<arr_type> > it =
00298 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
00299 baseVertex(), primitiveRestartEnabled(), primitive_restart_index );
00300 it->initialize();
00301 return TriangleIterator(it.get());
00302 }
00303
00304 LineIterator lineIterator() const
00305 {
00306 ref< LineIteratorIndexed<arr_type> > it =
00307 new LineIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
00308 baseVertex(), primitiveRestartEnabled(), primitive_restart_index );
00309 it->initialize();
00310 return LineIterator(it.get());
00311 }
00312
00313 IndexIterator indexIterator() const
00314 {
00315 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00316 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, primitive_restart_index );
00317 IndexIterator iit;
00318 iit.initialize( iie.get() );
00319 return iit;
00320 }
00321
00322 void computeRange()
00323 {
00324 mRangeStart = primitive_restart_index;
00325 mRangeEnd = 0;
00326
00327 for(IndexIterator it=indexIterator(); it.hasNext(); it.next())
00328 {
00329 if (it.index() < mRangeStart)
00330 mRangeStart = it.index();
00331 if (it.index() > mRangeEnd)
00332 mRangeEnd = it.index();
00333 }
00334
00335 if (mRangeEnd < mRangeStart)
00336 {
00337 mRangeStart = 0;
00338 mRangeEnd = primitive_restart_index;
00339 }
00340 }
00341
00342 protected:
00343 ref< arr_type > mIndexBuffer;
00344 i32 mCount;
00345 u32 mOffset;
00346 };
00347
00348
00349
00351 class DrawRangeElementsUInt: public DrawRangeElements<ArrayUInt1>
00352 {
00353 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUInt, DrawRangeElements<ArrayUInt1>)
00354
00355 public:
00356 DrawRangeElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLuint(~0))
00357 :DrawRangeElements<ArrayUInt1>(primitive, r_start, r_end)
00358 {
00359 VL_DEBUG_SET_OBJECT_NAME();
00360 }
00361 };
00362
00364 class DrawRangeElementsUShort: public DrawRangeElements<ArrayUShort1>
00365 {
00366 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUShort, DrawRangeElements<ArrayUShort1>)
00367
00368 public:
00369 DrawRangeElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLushort(~0))
00370 :DrawRangeElements<ArrayUShort1>(primitive, r_start, r_end)
00371 {
00372 VL_DEBUG_SET_OBJECT_NAME();
00373 }
00374 };
00375
00377 class DrawRangeElementsUByte: public DrawRangeElements<ArrayUByte1>
00378 {
00379 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUByte, DrawRangeElements<ArrayUByte1>)
00380
00381 public:
00382 DrawRangeElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLubyte(~0))
00383 :DrawRangeElements<ArrayUByte1>(primitive, r_start, r_end)
00384 {
00385 VL_DEBUG_SET_OBJECT_NAME();
00386 }
00387 };
00388
00389 }
00390
00391 #endif