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 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 // MultiDrawElementsBase 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 // update pointers 00068 computePointerVector(); 00069 computeBufferObjectPointerVector(); 00070 // set default base vertices to 0 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 // MultiDrawElements 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; // && indexBuffer()->bufferObject()->handle() && indexBuffer()->sizeBufferObject(); 00209 if ( !use_bo && !indexBuffer()->size() ) 00210 return; 00211 00212 // apply patch parameters if any and if using PT_PATCHES 00213 applyPatchParameters(); 00214 00215 // primitive restart enable 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 // primitive restart disable 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 // typedefs 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