Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics
[Home] [Tutorials] [All Classes] [Grouped Classes]

X:/dropbox/visualizationlibrary/src/vlGraphics/DrawElements.hpp

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

Visualization Library 2011.09.1160 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu May 2 2013 13:40:36.
Permission is granted to use this page to write and publish articles regarding Visualization Library.