Visualization Library v1.0.3A lightweight C++ OpenGL middleware for 2D/3D graphics |
[Download] [Tutorials] [All Classes] [Grouped Classes] |
00001 /**************************************************************************************/ 00002 /* */ 00003 /* Visualization Library */ 00004 /* http://visualizationlibrary.org */ 00005 /* */ 00006 /* Copyright (c) 2005-2010, Michele Bosi */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without modification, */ 00010 /* are permitted provided that the following conditions are met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, this */ 00013 /* list of conditions and the following disclaimer. */ 00014 /* */ 00015 /* - Redistributions in binary form must reproduce the above copyright notice, this */ 00016 /* list of conditions and the following disclaimer in the documentation and/or */ 00017 /* other materials provided with the distribution. */ 00018 /* */ 00019 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND */ 00020 /* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */ 00021 /* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE */ 00022 /* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR */ 00023 /* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES */ 00024 /* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; */ 00025 /* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON */ 00026 /* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */ 00027 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */ 00028 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 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/Array.hpp> 00038 #include <vlCore/Log.hpp> 00039 #include <vlCore/Say.hpp> 00040 #include <algorithm> 00041 00042 namespace vl 00043 { 00044 00045 //------------------------------------------------------------------------------ 00046 // DrawRangeElementsBase 00047 //------------------------------------------------------------------------------ 00053 class DrawRangeElementsBase: public DrawCall 00054 { 00055 VL_INSTRUMENT_ABSTRACT_CLASS(vl::DrawRangeElementsBase, DrawCall) 00056 00057 public: 00059 void setRangeStart(int rstart) { mRangeStart = rstart; } 00060 00062 int rangeStart() const { return mRangeStart; } 00063 00065 void setRangeEnd(int rend) { mRangeEnd = rend; } 00066 00068 int rangeEnd() const { return mRangeEnd; } 00069 00071 virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; } 00072 00074 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; } 00075 00080 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; } 00081 00084 int baseVertex() const { return mBaseVertex; } 00085 00086 protected: 00087 int mRangeStart; 00088 int mRangeEnd; 00089 GLuint mBaseVertex; 00090 bool mPrimitiveRestartEnabled; 00091 }; 00092 //------------------------------------------------------------------------------ 00093 // DrawRangeElements 00094 //------------------------------------------------------------------------------ 00119 template <class arr_type> 00120 class DrawRangeElements: public DrawRangeElementsBase 00121 { 00122 VL_INSTRUMENT_CLASS(vl::DrawRangeElements<arr_type>, DrawRangeElementsBase) 00123 00124 public: 00125 typedef typename arr_type::scalar_type index_type; 00127 static const index_type primitive_restart_index = index_type(~0); 00128 virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; } 00129 00130 private: 00131 template<typename T> 00132 class Triangle 00133 { 00134 public: 00135 T ABC[3]; 00136 bool operator<(const Triangle<index_type>& b) const 00137 { 00138 if (ABC[0] != b.ABC[0]) 00139 return ABC[0] < b.ABC[0]; 00140 else 00141 if (ABC[1] != b.ABC[1]) 00142 return ABC[1] < b.ABC[1]; 00143 else 00144 return ABC[2] < b.ABC[2]; 00145 } 00146 void rotate() 00147 { 00148 if (ABC[0] > ABC[1]) 00149 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; } 00150 if (ABC[0] > ABC[1]) 00151 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; } 00152 } 00153 }; 00154 00155 public: 00156 DrawRangeElements(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=primitive_restart_index) 00157 { 00158 VL_DEBUG_SET_OBJECT_NAME() 00159 mType = primitive; 00160 mRangeStart = r_start; 00161 mRangeEnd = r_end; 00162 mIndexBuffer = new arr_type; 00163 mPrimitiveRestartEnabled = false; 00164 mBaseVertex = 0; 00165 mCount = -1; // till the end of the indexBuffer() 00166 mOffset = 0; // from the beginning of the indexBuffer() 00167 } 00168 00169 DrawRangeElements& operator=(const DrawRangeElements& other) 00170 { 00171 super::operator=(other); 00172 *indexBuffer() = *other.indexBuffer(); 00173 mRangeStart = other.mRangeStart; 00174 mRangeEnd = other.mRangeEnd; 00175 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled; 00176 mBaseVertex = other.mBaseVertex; 00177 mCount = other.mCount; 00178 mOffset = other.mOffset; 00179 return *this; 00180 } 00181 00182 virtual ref<DrawCall> clone() const 00183 { 00184 ref<DrawRangeElements> de = new DrawRangeElements; 00185 *de = *this; 00186 return de; 00187 } 00188 00190 void setCount(i32 count) { mCount = count; } 00191 00193 i32 count() const { return mCount; } 00194 00196 void setOffset(u32 offset) { mOffset = offset; } 00197 00199 u32 offset() const { return mOffset; } 00200 00202 void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; } 00203 00205 arr_type* indexBuffer() { return mIndexBuffer.get(); } 00206 00208 const arr_type* indexBuffer() const { return mIndexBuffer.get(); } 00209 00210 virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode) 00211 { 00212 if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate)) 00213 indexBuffer()->updateBufferObject(mode); 00214 } 00215 00216 virtual void deleteBufferObject() 00217 { 00218 indexBuffer()->bufferObject()->deleteBufferObject(); 00219 } 00220 00221 virtual void render(bool use_bo) const 00222 { 00223 VL_CHECK_OGL() 00224 VL_CHECK(!use_bo || (use_bo && Has_BufferObject)) 00225 use_bo &= Has_BufferObject; // && indexBuffer()->bufferObject()->handle() && indexBuffer()->sizeBufferObject(); 00226 if ( !use_bo && !indexBuffer()->size() ) 00227 return; 00228 00229 // apply patch parameters if any and if using PT_PATCHES 00230 applyPatchParameters(); 00231 00232 // primitive restart enable 00233 if(primitiveRestartEnabled()) 00234 { 00235 VL_CHECK(Has_Primitive_Restart); 00236 glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL(); 00237 glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL(); 00238 } 00239 00240 // compute base pointer 00241 00242 const GLvoid* ptr = indexBuffer()->bufferObject()->ptr(); 00243 if (use_bo && indexBuffer()->bufferObject()->handle()) 00244 { 00245 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL() 00246 ptr = 0; 00247 } 00248 else 00249 { 00250 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); VL_CHECK_OGL() 00251 } 00252 00253 // compute final pointer and count 00254 00255 const char*ptr_end = NULL; 00256 if(mCount < 0) 00257 { 00258 // compute the end of the index buffer 00259 ptr_end = (char*)ptr + sizeof(index_type)*(use_bo ? indexBuffer()->sizeBufferObject() : indexBuffer()->size()); 00260 00261 // offset in the index buffer 00262 ptr = (char*)ptr + mOffset; 00263 } 00264 else 00265 { 00266 // offset in the index buffer 00267 ptr = (char*)ptr + mOffset; 00268 00269 // compute the end of the indices 00270 ptr_end = (char*)ptr + sizeof(index_type)*mCount; 00271 } 00272 00273 // compute the remaining indices 00274 const GLsizei count = (GLsizei)((index_type*)ptr_end - (index_type*)ptr); 00275 00276 if (mBaseVertex == 0) 00277 { 00278 glDrawRangeElements( primitiveType(), mRangeStart, mRangeEnd, count, arr_type::gl_type, ptr ); VL_CHECK_OGL() 00279 } 00280 else 00281 { 00282 VL_CHECK(Has_Base_Vertex) 00283 VL_glDrawRangeElementsBaseVertex( primitiveType(), mRangeStart, mRangeEnd, count, arr_type::gl_type, ptr, mBaseVertex ); VL_CHECK_OGL() 00284 } 00285 00286 // primitive restart disable 00287 00288 if(primitiveRestartEnabled()) 00289 { 00290 glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL() 00291 } 00292 } 00293 00294 TriangleIterator triangleIterator() const 00295 { 00296 ref< TriangleIteratorIndexed<arr_type> > it = 00297 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(), 00298 baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); 00299 it->initialize(); 00300 return TriangleIterator(it.get()); 00301 } 00302 00303 IndexIterator indexIterator() const 00304 { 00305 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>; 00306 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, primitive_restart_index ); 00307 IndexIterator iit; 00308 iit.initialize( iie.get() ); 00309 return iit; 00310 } 00311 00312 void computeRange() 00313 { 00314 mRangeStart = primitive_restart_index; 00315 mRangeEnd = 0; 00316 00317 for(IndexIterator it=indexIterator(); it.hasNext(); it.next()) 00318 { 00319 if (it.index() < mRangeStart) 00320 mRangeStart = it.index(); 00321 if (it.index() > mRangeEnd) 00322 mRangeEnd = it.index(); 00323 } 00324 00325 if (mRangeEnd < mRangeStart) 00326 { 00327 mRangeStart = 0; 00328 mRangeEnd = primitive_restart_index; 00329 } 00330 } 00331 00332 protected: 00333 ref< arr_type > mIndexBuffer; 00334 i32 mCount; 00335 u32 mOffset; 00336 }; 00337 //------------------------------------------------------------------------------ 00338 // typedefs 00339 //------------------------------------------------------------------------------ 00341 class DrawRangeElementsUInt: public DrawRangeElements<ArrayUInt1> 00342 { 00343 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUInt, DrawRangeElements<ArrayUInt1>) 00344 00345 public: 00346 DrawRangeElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLuint(~0)) 00347 :DrawRangeElements<ArrayUInt1>(primitive, r_start, r_end) 00348 { 00349 VL_DEBUG_SET_OBJECT_NAME(); 00350 } 00351 }; 00352 //------------------------------------------------------------------------------ 00354 class DrawRangeElementsUShort: public DrawRangeElements<ArrayUShort1> 00355 { 00356 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUShort, DrawRangeElements<ArrayUShort1>) 00357 00358 public: 00359 DrawRangeElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLushort(~0)) 00360 :DrawRangeElements<ArrayUShort1>(primitive, r_start, r_end) 00361 { 00362 VL_DEBUG_SET_OBJECT_NAME(); 00363 } 00364 }; 00365 //------------------------------------------------------------------------------ 00367 class DrawRangeElementsUByte: public DrawRangeElements<ArrayUByte1> 00368 { 00369 VL_INSTRUMENT_CLASS(vl::DrawRangeElementsUByte, DrawRangeElements<ArrayUByte1>) 00370 00371 public: 00372 DrawRangeElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int r_start=0, int r_end=GLubyte(~0)) 00373 :DrawRangeElements<ArrayUByte1>(primitive, r_start, r_end) 00374 { 00375 VL_DEBUG_SET_OBJECT_NAME(); 00376 } 00377 }; 00378 //------------------------------------------------------------------------------ 00379 } 00380 00381 #endif