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-2011, 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 DrawElements_INCLUDE_ONCE 00033 #define DrawElements_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 // DrawElementsBase 00047 //------------------------------------------------------------------------------ 00053 class DrawElementsBase: public DrawCall 00054 { 00055 VL_INSTRUMENT_ABSTRACT_CLASS(vl::DrawElementsBase, DrawCall) 00056 00057 public: 00059 virtual bool primitiveRestartEnabled() const { return mPrimitiveRestartEnabled; } 00060 00062 void setPrimitiveRestartEnabled(bool enabled) { mPrimitiveRestartEnabled = enabled; } 00063 00065 void setInstances(int instances) { mInstances = instances; } 00066 00068 int instances() const { return mInstances; } 00069 00074 void setBaseVertex(int base_vertex) { mBaseVertex = base_vertex; } 00075 00078 int baseVertex() const { return mBaseVertex; } 00079 00080 protected: 00081 int mInstances; 00082 bool mPrimitiveRestartEnabled; 00083 GLuint mBaseVertex; 00084 }; 00085 //------------------------------------------------------------------------------ 00086 // DrawElements 00087 //------------------------------------------------------------------------------ 00117 template <class arr_type> 00118 class DrawElements: public DrawElementsBase 00119 { 00120 VL_INSTRUMENT_CLASS(vl::DrawElements<arr_type>, DrawElementsBase) 00121 00122 public: 00123 typedef typename arr_type::scalar_type index_type; 00125 static const index_type primitive_restart_index = index_type(~0); 00126 virtual unsigned int primitiveRestartIndex() { return (unsigned int)primitive_restart_index; } 00127 00128 private: 00129 template<typename T> 00130 class Triangle 00131 { 00132 public: 00133 T ABC[3]; 00134 bool operator<(const Triangle<index_type>& b) const 00135 { 00136 if (ABC[0] != b.ABC[0]) 00137 return ABC[0] < b.ABC[0]; 00138 else 00139 if (ABC[1] != b.ABC[1]) 00140 return ABC[1] < b.ABC[1]; 00141 else 00142 return ABC[2] < b.ABC[2]; 00143 } 00144 void rotate() 00145 { 00146 if (ABC[0] > ABC[1]) 00147 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; } 00148 if (ABC[0] > ABC[1]) 00149 { T tmp = ABC[0]; ABC[0] = ABC[1]; ABC[1] = ABC[2]; ABC[2] = tmp; } 00150 } 00151 }; 00152 00153 public: 00155 DrawElements(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1) 00156 { 00157 VL_DEBUG_SET_OBJECT_NAME() 00158 mType = primitive; 00159 mInstances = instances; 00160 mIndexBuffer = new arr_type; 00161 mPrimitiveRestartEnabled = false; 00162 mBaseVertex = 0; 00163 mCount = -1; // till the end of the indexBuffer() 00164 mOffset = 0; // from the beginning of the indexBuffer() 00165 } 00166 00168 DrawElements& operator=(const DrawElements& other) 00169 { 00170 super::operator=(other); 00171 *indexBuffer() = *other.indexBuffer(); 00172 mInstances = other.mInstances; 00173 mPrimitiveRestartEnabled = other.mPrimitiveRestartEnabled; 00174 mBaseVertex = other.mBaseVertex; 00175 mCount = other.mCount; 00176 mOffset = other.mOffset; 00177 return *this; 00178 } 00179 00181 virtual ref<DrawCall> clone() const 00182 { 00183 ref<DrawElements> de = new DrawElements; 00184 *de = *this; 00185 return de; 00186 } 00187 00189 void setCount(i32 count) { mCount = count; } 00190 00192 i32 count() const { return mCount; } 00193 00195 void setOffset(u32 offset) { mOffset = offset; } 00196 00198 u32 offset() const { return mOffset; } 00199 00201 void setIndexBuffer(arr_type* index_buffer) { mIndexBuffer = index_buffer; } 00202 00204 arr_type* indexBuffer() { return mIndexBuffer.get(); } 00205 00207 const arr_type* indexBuffer() const { return mIndexBuffer.get(); } 00208 00209 virtual void updateDirtyBufferObject(EBufferObjectUpdateMode mode) 00210 { 00211 if (indexBuffer()->isBufferObjectDirty() || (mode & BUF_ForceUpdate)) 00212 indexBuffer()->updateBufferObject(mode); 00213 } 00214 00215 virtual void deleteBufferObject() 00216 { 00217 indexBuffer()->bufferObject()->deleteBufferObject(); 00218 } 00219 00220 virtual void render(bool use_bo) const 00221 { 00222 VL_CHECK_OGL() 00223 VL_CHECK(!use_bo || (use_bo && Has_BufferObject)) 00224 00225 #if !defined(NDEBUG) && (defined(VL_OPENGL_ES1) || defined(GL_OPENGL_ES2)) 00226 bool error = true; 00227 // check primitive type 00228 switch(primitiveType()) 00229 { 00230 case PT_QUADS: Log::error("vl::DrawElements does not support PT_QUADS under OpenGL ES!\n"); break; 00231 case PT_QUAD_STRIP: Log::error("vl::DrawElements does not support PT_QUAD_STRIP under OpenGL ES!\n"); break; 00232 case PT_POLYGON: Log::error("vl::DrawElements does not support PT_POLYGON under OpenGL ES!\n"); break; 00233 case PT_LINES_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINES_ADJACENCY under OpenGL ES!\n"); break; 00234 case PT_LINE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_LINE_STRIP_ADJACENCY under OpenGL ES!\n"); break; 00235 case PT_TRIANGLES_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLES_ADJACENCY under OpenGL ES!\n"); break; 00236 case PT_TRIANGLE_STRIP_ADJACENCY: Log::error("vl::DrawElements does not support PT_TRIANGLE_STRIP_ADJACENCY under OpenGL ES!\n"); break; 00237 case PT_PATCHES: Log::error("vl::DrawElements does not support PT_PATCHES under OpenGL ES!\n"); break; 00238 default: 00239 error = false; 00240 break; 00241 } 00242 // check index type 00243 if (indexBuffer()->glType() != GL_UNSIGNED_BYTE && indexBuffer()->glType() != GL_UNSIGNED_SHORT) 00244 { 00245 Log::error("vl::DrawElements only supports GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT under OpenGL ES!\n"); 00246 error = true; 00247 } 00248 VL_CHECK(!error) 00249 #endif 00250 00251 use_bo &= Has_BufferObject; // && indexBuffer()->bufferObject()->handle() && indexBuffer()->sizeBufferObject(); 00252 if ( !use_bo && !indexBuffer()->size() ) 00253 return; 00254 00255 // apply patch parameters if any and if using PT_PATCHES 00256 applyPatchParameters(); 00257 00258 // primitive restart enable 00259 if(primitiveRestartEnabled()) 00260 { 00261 VL_CHECK(Has_Primitive_Restart); 00262 glEnable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL(); 00263 glPrimitiveRestartIndex(primitive_restart_index); VL_CHECK_OGL(); 00264 } 00265 00266 // compute base pointer 00267 00268 const GLvoid* ptr = indexBuffer()->bufferObject()->ptr(); 00269 if (use_bo && indexBuffer()->bufferObject()->handle()) 00270 { 00271 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer()->bufferObject()->handle()); VL_CHECK_OGL() 00272 ptr = 0; 00273 } 00274 else 00275 { 00276 VL_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); VL_CHECK_OGL() 00277 } 00278 00279 // compute final pointer and count 00280 00281 const char*ptr_end = NULL; 00282 if(mCount < 0) 00283 { 00284 // compute the end of the index buffer 00285 ptr_end = (char*)ptr + sizeof(index_type)*(use_bo ? indexBuffer()->sizeBufferObject() : indexBuffer()->size()); 00286 00287 // offset in the index buffer 00288 ptr = (char*)ptr + mOffset; 00289 } 00290 else 00291 { 00292 // offset in the index buffer 00293 ptr = (char*)ptr + mOffset; 00294 00295 // compute the end of the indices 00296 ptr_end = (char*)ptr + sizeof(index_type)*mCount; 00297 } 00298 00299 // compute the remaining indices 00300 const GLsizei count = (GLsizei)((index_type*)ptr_end - (index_type*)ptr); 00301 00302 if (mBaseVertex == 0) 00303 { 00304 if ( instances() == 1 ) 00305 { 00306 glDrawElements( primitiveType(), count, arr_type::gl_type, ptr ); VL_CHECK_OGL() 00307 } 00308 else 00309 { 00310 VL_CHECK(Has_Primitive_Instancing) 00311 VL_glDrawElementsInstanced( primitiveType(), count, arr_type::gl_type, ptr, instances() ); VL_CHECK_OGL() 00312 } 00313 } 00314 else 00315 { 00316 VL_CHECK(Has_Base_Vertex) 00317 if ( instances() == 1 ) 00318 { 00319 VL_glDrawElementsBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, mBaseVertex ); VL_CHECK_OGL() 00320 } 00321 else 00322 { 00323 VL_CHECK(Has_Primitive_Instancing) 00324 VL_glDrawElementsInstancedBaseVertex( primitiveType(), count, arr_type::gl_type, ptr, instances(), mBaseVertex ); VL_CHECK_OGL() 00325 } 00326 } 00327 00328 // primitive restart disable 00329 00330 if(primitiveRestartEnabled()) 00331 { 00332 glDisable(GL_PRIMITIVE_RESTART); VL_CHECK_OGL() 00333 } 00334 00335 #ifndef NDEBUG 00336 unsigned int glerr = glGetError(); 00337 if (glerr != GL_NO_ERROR) 00338 { 00339 String msg( getGLErrorString(glerr) ); 00340 Log::error( Say("glGetError() [%s:%n]: %s\n") << __FILE__ << __LINE__ << msg ); 00341 Log::warning( "- If you are using geometry instancing in conjunction with display lists you will have to disable one of them.\n" ); 00342 Log::warning( "- If you are using OpenGL ES you must not use GL_QUADS, GL_QUAD_STRIP and GL_POLYGON primitive types.\n" ); 00343 VL_TRAP() 00344 } 00345 #endif 00346 } 00347 00348 TriangleIterator triangleIterator() const 00349 { 00350 ref< TriangleIteratorIndexed<arr_type> > it = 00351 new TriangleIteratorIndexed<arr_type>( mIndexBuffer.get(), primitiveType(), 00352 baseVertex(), primitiveRestartEnabled(), primitive_restart_index ); 00353 it->initialize(); 00354 return TriangleIterator(it.get()); 00355 } 00356 00357 IndexIterator indexIterator() const 00358 { 00359 ref< IndexIteratorElements<arr_type> > iie = new IndexIteratorElements<arr_type>; 00360 iie->initialize( mIndexBuffer.get(), NULL, NULL, mBaseVertex, mPrimitiveRestartEnabled, primitive_restart_index ); 00361 IndexIterator iit; 00362 iit.initialize( iie.get() ); 00363 return iit; 00364 } 00365 00366 protected: 00367 ref< arr_type > mIndexBuffer; 00368 i32 mCount; 00369 u32 mOffset; 00370 }; 00371 //------------------------------------------------------------------------------ 00372 // typedefs 00373 //------------------------------------------------------------------------------ 00375 class DrawElementsUInt: public DrawElements<ArrayUInt1> 00376 { 00377 VL_INSTRUMENT_CLASS(vl::DrawElementsUInt, DrawElements<ArrayUInt1>) 00378 00379 public: 00380 DrawElementsUInt(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1) 00381 :DrawElements<ArrayUInt1>(primitive, instances) 00382 { 00383 VL_DEBUG_SET_OBJECT_NAME(); 00384 } 00385 }; 00386 //------------------------------------------------------------------------------ 00388 class DrawElementsUShort: public DrawElements<ArrayUShort1> 00389 { 00390 VL_INSTRUMENT_CLASS(vl::DrawElementsUShort, DrawElements<ArrayUShort1>) 00391 00392 public: 00393 DrawElementsUShort(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1) 00394 :DrawElements<ArrayUShort1>(primitive, instances) 00395 { 00396 VL_DEBUG_SET_OBJECT_NAME(); 00397 } 00398 }; 00399 //------------------------------------------------------------------------------ 00401 class DrawElementsUByte: public DrawElements<ArrayUByte1> 00402 { 00403 VL_INSTRUMENT_CLASS(vl::DrawElementsUByte, DrawElements<ArrayUByte1>) 00404 00405 public: 00406 DrawElementsUByte(EPrimitiveType primitive = PT_TRIANGLES, int instances = 1) 00407 :DrawElements<ArrayUByte1>(primitive, instances) 00408 { 00409 VL_DEBUG_SET_OBJECT_NAME(); 00410 } 00411 }; 00412 //------------------------------------------------------------------------------ 00413 } 00414 00415 #endif