# Visualization Library

A lightweight C++ OpenGL middleware for 2D/3D graphics

[Home] [Tutorials] [All Classes] [Grouped Classes]

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# D:/VL/BuildSystem/VL_DISTRO/Visualization_Library_SDK/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/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

Visualization Library v2011.09.1162 Reference Documentation
Copyright 2005-2011 Michele Bosi. All rights reserved.
Updated on Thu Jan 26 2012 00:43:37.
Permission is granted to use this page to write and publish articles regarding Visualization Library.