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 <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 DrawRangeElementsBase: public DrawCall
00054 {
00055 public:
00057 void setRangeStart(int rstart) { mRangeStart = rstart; }
00058
00060 int rangeStart() const { return mRangeStart; }
00061
00063 void setRangeEnd(int rend) { mRangeEnd = rend; }
00064
00066 int rangeEnd() const { return mRangeEnd; }
00067
00070 GLuint primitiveRestartIndex() const { return mPrimitiveRestartIndex; }
00071
00074 void setPrimitiveRestartIndex(GLuint index) { mPrimitiveRestartIndex = index; }
00075
00077 bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; }
00078
00080 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; }
00081
00086 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; }
00087
00090 int baseVertex() const { return mBaseVertex; }
00091
00092 protected:
00093 int mRangeStart;
00094 int mRangeEnd;
00095 int mBaseVertex;
00096 GLuint mPrimitiveRestartIndex;
00097 bool mPrimitiveRestartEnabled;
00098 };
00099
00100
00101
00121 template <typename index_type, GLenum Tgltype, class arr_type>
00122 class DrawRangeElements: public DrawRangeElementsBase
00123 {
00124 private:
00125 template<typename T>
00126 class Triangle
00127 {
00128 public:
00129 T ABC[3];
00130 bool operator<(const Triangle<index_type>& b) const
00131 {
00132 if (ABC[0] != b.ABC[0])
00133 return ABC[0] < b.ABC[0];
00134 else
00135 if (ABC[1] != b.ABC[1])
00136 return ABC[1] < b.ABC[1];
00137 else
00138 return ABC[2] < b.ABC[2];
00139 }
00140 void rotate()
00141 {
00142 if (ABC[0] > ABC[1])
00143 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00144 if (ABC[0] > ABC[1])
00145 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; }
00146 }
00147 };
00148
00149 public:
00150 virtual const char* className() { return "vl::DrawRangeElements"; }
00151
00152 DrawRangeElements(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=index_type(~0))
00153 {
00154 VL_DEBUG_SET_OBJECT_NAME()
00155 mType = primitive;
00156 mRangeStart = r_start;
00157 mRangeEnd = r_end;
00158 mIndexBuffer = new arr_type;
00159 mPrimitiveRestartIndex = index_type(~0);
00160 mPrimitiveRestartEnabled = false;
00161 mBaseVertex = 0;
00162 }
00163
00164 DrawRangeElements& operator=(const DrawRangeElements& other)
00165 {
00166 DrawRangeElementsBase::operator=(other);
00167 *indices() = *other.indices();
00168 mRangeStart = other.mRangeStart;
00169 mRangeEnd = other.mRangeEnd;
00170 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled;
00171 mPrimitiveRestartIndex = other.mPrimitiveRestartIndex;
00172 mBaseVertex = other.mBaseVertex;
00173 return *this;
00174 }
00175
00176 virtual ref<DrawCall> clone() const
00177 {
00178 ref<DrawRangeElements> de = new DrawRangeElements;
00179 *de = *this;
00180 return de;
00181 }
00182
00183 virtual unsigned int handle() const { return indices()->gpuBuffer()->handle(); }
00184
00185 arr_type* indices() { return mIndexBuffer.get(); }
00186
00187 const arr_type* indices() const { return mIndexBuffer.get(); }
00188
00189 virtual void updateVBOs(bool discard_local_data=false, bool force_update=false)
00190 {
00191 if (indices()->isVBODirty() || force_update)
00192 indices()->updateVBO(discard_local_data);
00193 }
00194
00195 virtual void deleteVBOs()
00196 {
00197 indices()->gpuBuffer()->deleteGLBufferObject();
00198 }
00199
00200 virtual void clearLocalBuffer()
00201 {
00202 indices()->gpuBuffer()->resize(0);
00203 }
00204
00205 virtual void render(bool use_vbo) const
00206 {
00207 VL_CHECK(mBaseVertex>=0)
00208 VL_CHECK(!use_vbo || (use_vbo && (GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0)))
00209 use_vbo &= GLEW_ARB_vertex_buffer_object||GLEW_VERSION_1_5||GLEW_VERSION_3_0;
00210 if ( !use_vbo && !indices()->size() )
00211 return;
00212
00213
00214 applyPatchParameters();
00215
00216
00217 if(primitiveRestartEnabled())
00218 {
00219 if(GLEW_VERSION_3_1)
00220 {
00221 glEnable(GL_PRIMITIVE_RESTART);
00222 glPrimitiveRestartIndex(primitiveRestartIndex());
00223 }
00224 else
00225 if(GLEW_NV_primitive_restart)
00226 {
00227 glEnable(GL_PRIMITIVE_RESTART_NV);
00228 glPrimitiveRestartIndexNV(primitiveRestartIndex());
00229 }
00230 else
00231 {
00232 vl::Log::error("DrawRangeElements error: primitive restart not supported by this OpenGL implementation!\n");
00233 VL_TRAP();
00234 return;
00235 }
00236 }
00237
00238 const GLvoid* ptr = indices()->gpuBuffer()->ptr();
00239
00240 if (use_vbo && indices()->gpuBuffer()->handle())
00241 {
00242 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices()->gpuBuffer()->handle());
00243 ptr = 0;
00244 }
00245 else
00246 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
00247
00248 if (mBaseVertex == 0)
00249 glDrawRangeElements( primitiveType(), mRangeStart, mRangeEnd, use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr );
00250 else
00251 VL_glDrawRangeElementsBaseVertex( primitiveType(), mRangeStart, mRangeEnd, use_vbo ? (GLsizei)indices()->sizeGPU() : (GLsizei)indices()->size(), indices()->glType(), ptr, mBaseVertex );
00252
00253
00254
00255 if(primitiveRestartEnabled())
00256 {
00257 if(GLEW_VERSION_3_1)
00258 glDisable(GL_PRIMITIVE_RESTART);
00259 else
00260 if(GLEW_NV_primitive_restart)
00261 glDisable(GL_PRIMITIVE_RESTART_NV);
00262 }
00263 }
00264
00265 TriangleIterator triangleIterator() const
00266 {
00267 ref< TriangleIteratorIndexed<arr_type> > it =
00268 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(),
00269 baseVertex(), primitiveRestartEnabled(), primitiveRestartIndex() );
00270 it->initialize();
00271 return TriangleIterator(it.get());
00272 }
00273
00274 IndexIterator indexIterator() const
00275 {
00276 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>;
00277 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, mPrimitiveRestartIndex );
00278 IndexIterator iit;
00279 iit.initialize( iie.get() );
00280 return iit;
00281 }
00282
00283 void computeRange()
00284 {
00285 mRangeStart = index_type(~0);
00286 mRangeEnd = 0;
00287
00288 for(IndexIterator it=indexIterator(); !it.isEnd(); it.next())
00289 {
00290 if (it.index() < mRangeStart)
00291 mRangeStart = it.index();
00292 if (it.index() > mRangeEnd)
00293 mRangeEnd = it.index();
00294 }
00295
00296 if (mRangeEnd < mRangeStart)
00297 {
00298 mRangeStart = 0;
00299 mRangeEnd = index_type(~0);
00300 }
00301 }
00302
00303 protected:
00304 ref< arr_type > mIndexBuffer;
00305 };
00306
00307
00308
00310 class DrawRangeElementsUInt: public DrawRangeElements<GLuint, GL_UNSIGNED_INT, ArrayUInt1>
00311 {
00312 public:
00313 DrawRangeElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLuint(~0))
00314 :DrawRangeElements<GLuint, GL_UNSIGNED_INT, ArrayUInt1>(primitive, r_start, r_end) {}
00315 };
00316
00318 class DrawRangeElementsUShort: public DrawRangeElements<GLushort, GL_UNSIGNED_SHORT, ArrayUShort1>
00319 {
00320 public:
00321 DrawRangeElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLushort(~0))
00322 :DrawRangeElements<GLushort, GL_UNSIGNED_SHORT, ArrayUShort1>(primitive, r_start, r_end) {}
00323 };
00324
00326 class DrawRangeElementsUByte: public DrawRangeElements<GLubyte, GL_UNSIGNED_BYTE, ArrayUByte1>
00327 {
00328 public:
00329 DrawRangeElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLubyte(~0))
00330 :DrawRangeElements<GLubyte, GL_UNSIGNED_BYTE, ArrayUByte1>(primitive, r_start, r_end) {}
00331 };
00332
00333 }
00334
00335 #endif