Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

include/cinder/gl/Vbo.h

Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00006  the following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00009     the following disclaimer.
00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
00012 
00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00020  POSSIBILITY OF SUCH DAMAGE.
00021 */
00022 
00023 #pragma once
00024 
00025 #include "cinder/gl/gl.h"
00026 #include "cinder/TriMesh.h"
00027 
00028 #include <vector>
00029 #include <utility>
00030 
00031 namespace cinder { namespace gl {
00032 
00033 class Vbo {
00034  public:
00035     Vbo() {}
00036     Vbo( GLenum aTarget );
00037     
00038     void        bind();
00039     void        unbind();
00040     
00041     void        bufferData( size_t size, const void *data, GLenum usage );
00042     void        bufferSubData( ptrdiff_t offset, size_t size, const void *data );
00043     
00044     uint8_t*    map( GLenum access );
00045     void        unmap();
00046 
00047     GLenum      getTarget() const { return mObj->mTarget; }
00048     GLuint      getId() const { return mObj->mId; }
00049     
00050  protected:
00051     struct Obj {
00052         Obj( GLenum aTarget );
00053         ~Obj();
00054 
00055         GLenum          mTarget;
00056         GLuint          mId;
00057     };
00058     
00059     shared_ptr<Obj> mObj;
00060 
00061   public:
00063 
00064     typedef shared_ptr<Obj> Vbo::*unspecified_bool_type;
00065     operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &Vbo::mObj; }
00066     void reset() { mObj.reset(); }
00068 };
00069 
00070 class VboMesh {
00071  public:
00072     enum { NONE, STATIC, DYNAMIC };
00073     enum { ATTR_INDICES, ATTR_POSITIONS, ATTR_NORMALS, ATTR_COLORS_RGB, ATTR_COLORS_RGBA, ATTR_TEXCOORDS2D_0, ATTR_TEXCOORDS2D_1, ATTR_TEXCOORDS2D_2, ATTR_TEXCOORDS2D_3, ATTR_TEXCOORDS3D_0, ATTR_TEXCOORDS3D_1, ATTR_TEXCOORDS3D_2, ATTR_TEXCOORDS3D_3, ATTR_TOTAL };
00074     enum { ATTR_MAX_TEXTURE_UNIT = 3 };
00075 
00076     struct Layout {
00077         Layout() { initAttributes(); }
00078 
00080         bool    isDefaults() const { for( int a = 0; a < ATTR_TOTAL; ++a ) if( mAttributes[a] != NONE ) return false; return true; }
00081     
00082         bool    hasNormals() const { return hasDynamicNormals() || hasStaticNormals(); }
00083         bool    hasStaticNormals() const { return mAttributes[ATTR_NORMALS] == STATIC; }
00084         bool    hasDynamicNormals() const { return mAttributes[ATTR_NORMALS] == DYNAMIC; }
00085         void    setStaticNormals() { mAttributes[ATTR_NORMALS] = STATIC; }
00086         void    setDynamicNormals() { mAttributes[ATTR_NORMALS] = DYNAMIC; }        
00087 
00088         bool    hasColorsRGB() const { return hasDynamicColorsRGB() || hasStaticColorsRGB(); }
00089         bool    hasStaticColorsRGB() const { return mAttributes[ATTR_COLORS_RGB] == STATIC; }
00090         bool    hasDynamicColorsRGB() const { return mAttributes[ATTR_COLORS_RGB] == DYNAMIC; }
00091         void    setStaticColorsRGB() { mAttributes[ATTR_COLORS_RGB] = STATIC; mAttributes[ATTR_COLORS_RGBA] = NONE; }
00092         void    setDynamicColorsRGB() { mAttributes[ATTR_COLORS_RGB] = DYNAMIC; mAttributes[ATTR_COLORS_RGBA] = NONE; }     
00093 
00094         bool    hasColorsRGBA() const { return hasDynamicColorsRGBA() || hasStaticColorsRGBA(); }
00095         bool    hasStaticColorsRGBA() const { return mAttributes[ATTR_COLORS_RGBA] == STATIC; }
00096         bool    hasDynamicColorsRGBA() const { return mAttributes[ATTR_COLORS_RGBA] == DYNAMIC; }
00097         void    setStaticColorsRGBA() { mAttributes[ATTR_COLORS_RGBA] = STATIC; mAttributes[ATTR_COLORS_RGB] = NONE; }
00098         void    setDynamicColorsRGBA() { mAttributes[ATTR_COLORS_RGBA] = DYNAMIC; mAttributes[ATTR_COLORS_RGB] = NONE; }        
00099         
00100         bool    hasTexCoords2d( size_t unit = 0 ) const { return hasDynamicTexCoords2d( unit ) || hasStaticTexCoords2d( unit ); }
00101         bool    hasStaticTexCoords2d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS2D_0 + unit] == STATIC; }      
00102         bool    hasDynamicTexCoords2d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS2D_0 + unit] == DYNAMIC; }
00103         void    setStaticTexCoords2d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS2D_0 + unit] = STATIC; mAttributes[ATTR_TEXCOORDS3D_0 + unit] = NONE; }
00104         void    setDynamicTexCoords2d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS2D_0 + unit] = DYNAMIC; mAttributes[ATTR_TEXCOORDS3D_0 + unit] = NONE; }
00106         bool    hasStaticTexCoords() const;
00108         bool    hasDynamicTexCoords() const;
00110         bool    hasTexCoords( size_t unit ) const { return ( mAttributes[ATTR_TEXCOORDS2D_0 + unit] != NONE ) || ( mAttributes[ATTR_TEXCOORDS3D_0 + unit] != NONE ); }
00111 
00112         bool    hasTexCoords3d( size_t unit = 0 ) const { return hasDynamicTexCoords3d( unit ) || hasStaticTexCoords3d( unit ); }
00113         bool    hasStaticTexCoords3d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS3D_0 + unit] == STATIC; }      
00114         bool    hasDynamicTexCoords3d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS3D_0 + unit] == DYNAMIC; }
00115         void    setStaticTexCoords3d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS3D_0 + unit] = STATIC; mAttributes[ATTR_TEXCOORDS2D_0 + unit] = NONE; }
00116         void    setDynamicTexCoords3d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS3D_0 + unit] = DYNAMIC; mAttributes[ATTR_TEXCOORDS2D_0 + unit] = NONE; }
00117 
00118         bool    hasIndices() const { return hasStaticIndices() || hasDynamicIndices(); }
00119         bool    hasStaticIndices() const { return mAttributes[ATTR_INDICES] == STATIC; }
00120         bool    hasDynamicIndices() const { return mAttributes[ATTR_INDICES] == DYNAMIC; }
00121         void    setStaticIndices() { mAttributes[ATTR_INDICES] = STATIC; }
00122         void    setDynamicIndices() { mAttributes[ATTR_INDICES] = DYNAMIC; }
00123 
00124         bool    hasPositions() const { return hasStaticPositions() || hasDynamicPositions(); }
00125         bool    hasStaticPositions() const { return mAttributes[ATTR_POSITIONS] == STATIC; }
00126         bool    hasDynamicPositions() const { return mAttributes[ATTR_POSITIONS] == DYNAMIC; }
00127         void    setStaticPositions() { mAttributes[ATTR_POSITIONS] = STATIC; }
00128         void    setDynamicPositions() { mAttributes[ATTR_POSITIONS] = DYNAMIC; }
00129         
00130         enum CustomAttr { CUSTOM_ATTR_FLOAT, CUSTOM_ATTR_FLOAT2, CUSTOM_ATTR_FLOAT3, CUSTOM_ATTR_FLOAT4, TOTAL_CUSTOM_ATTR_TYPES };
00131         static int sCustomAttrSizes[TOTAL_CUSTOM_ATTR_TYPES];
00132         static GLint sCustomAttrNumComponents[TOTAL_CUSTOM_ATTR_TYPES];
00133         static GLenum sCustomAttrTypes[TOTAL_CUSTOM_ATTR_TYPES];
00134         void    addDynamicCustomFloat() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT, 0 ) ); }
00135         void    addDynamicCustomVec2f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT2, 0 ) ); }
00136         void    addDynamicCustomVec3f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT3, 0 ) ); }
00137         void    addDynamicCustomVec4f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT4, 0 ) ); }
00138 
00139         int                                             mAttributes[ATTR_TOTAL];
00140         std::vector<std::pair<CustomAttr,size_t> >      mCustomDynamic, mCustomStatic; // pair of <types,offset>
00141         
00142      private:
00143         void initAttributes() { for( int a = 0; a < ATTR_TOTAL; ++a ) mAttributes[a] = NONE; }
00144     };
00145 
00146     enum            { INDEX_BUFFER = 0, STATIC_BUFFER, DYNAMIC_BUFFER, TOTAL_BUFFERS };
00147     
00148   protected:
00149     struct Obj {
00150         size_t          mNumIndices, mNumVertices;  
00151 
00152         Vbo             mBuffers[TOTAL_BUFFERS];
00153         size_t          mPositionOffset;
00154         size_t          mNormalOffset;
00155         size_t          mColorRGBOffset, mColorRGBAOffset;      
00156         size_t          mTexCoordOffset[ATTR_MAX_TEXTURE_UNIT+1];
00157         size_t          mStaticStride, mDynamicStride;  
00158         GLenum          mPrimitiveType;
00159         Layout          mLayout;
00160         std::vector<GLint>      mCustomStaticLocations;
00161         std::vector<GLint>      mCustomDynamicLocations;
00162     };
00163 
00164   public:
00165     class VertexIter;
00166  
00167     VboMesh() {}
00168     explicit VboMesh( const TriMesh &triMesh, Layout layout = Layout() );
00169     /*** Creates a VboMesh with \a numVertices vertices and \a numIndices indices. Dynamic data is stored interleaved and static data is planar. **/
00170     VboMesh( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType );
00171     /*** Creates a VboMesh with \a numVertices vertices and \a numIndices indices. Accepts pointers to preexisting buffers, which may be NULL to request allocation **/
00172     VboMesh( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType, Vbo *indexBuffer, Vbo *staticBuffer, Vbo *dynamicBuffer );
00173 
00174     size_t  getNumIndices() const { return mObj->mNumIndices; }
00175     size_t  getNumVertices() const { return mObj->mNumVertices; }
00176     GLenum  getPrimitiveType() const { return mObj->mPrimitiveType; }
00177     
00178     const Layout&   getLayout() const { return mObj->mLayout; }
00179 
00180     void            bindIndexBuffer() const;
00181     void            enableClientStates() const;
00182     void            disableClientStates() const;
00183     void            bindAllData() const;
00184     static void     unbindBuffers();
00185 
00186     void                        bufferIndices( const std::vector<uint32_t> &indices );
00187     void                        bufferPositions( const std::vector<Vec3f> &normals );
00188     void                        bufferNormals( const std::vector<Vec3f> &normals );
00189     void                        bufferTexCoords2d( size_t unit, const std::vector<Vec2f> &texCoords );
00190     class VertexIter            mapVertexBuffer();
00191 
00192     Vbo&                getIndexVbo() const { return mObj->mBuffers[INDEX_BUFFER]; }
00193     Vbo&                getStaticVbo() const { return mObj->mBuffers[STATIC_BUFFER]; }
00194     Vbo&                getDynamicVbo() const { return mObj->mBuffers[DYNAMIC_BUFFER]; }
00195 
00196     void                setCustomStaticLocation( size_t internalIndex, GLuint location ) { mObj->mCustomStaticLocations[internalIndex] = location; }
00197     void                setCustomDynamicLocation( size_t internalIndex, GLuint location ) { mObj->mCustomDynamicLocations[internalIndex] = location; }
00198 
00199     size_t                      getTexCoordOffset( size_t unit ) const { return mObj->mTexCoordOffset[unit]; }
00200     void                        setTexCoordOffset( size_t unit, size_t aTexCoordOffset ) { mObj->mTexCoordOffset[unit] = aTexCoordOffset; } 
00201 
00203 
00204     VboMesh( const VboMesh &other ) { mObj = other.mObj; }
00205     VboMesh& operator=( const VboMesh &other ) { mObj = other.mObj; return *this; }
00206     bool operator==( const VboMesh &other ) { return mObj == other.mObj; }
00207     typedef shared_ptr<Obj> VboMesh::*unspecified_bool_type;
00208     operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &VboMesh::mObj; }
00209     void reset() { mObj.reset(); }
00211 
00212     class VertexIter {
00213      public:
00214         VertexIter( const VboMesh &mesh );
00215 
00216         void    setPosition( const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = v; }
00217         void    setPosition( float x, float y, float z ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = Vec3f( x, y, z ); }
00218         void    setNormal( const Vec3f &n ) { *(reinterpret_cast<Vec3f*>( &mPtr[mNormalOffset] )) = n; }
00219         void    setColorRGB( const Color &n ) { *(reinterpret_cast<Color*>( &mPtr[mColorRGBOffset] )) = n; }
00220         void    setColorRGBA( const Color &n ) { *(reinterpret_cast<Color*>( &mPtr[mColorRGBAOffset] )) = n; }
00221         void    setTexCoord2d0( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00222         void    setTexCoord3d0( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00223         void    setTexCoord2d1( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00224         void    setTexCoord3d1( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00225         void    setTexCoord2d2( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00226         void    setTexCoord3d2( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00227         void    setCustomFloat( size_t index, float v ) { *(reinterpret_cast<float*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00228         void    setCustomVec2f( size_t index, const Vec2f &v ) { *(reinterpret_cast<Vec2f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00229         void    setCustomVec3f( size_t index, const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00230         void    setCustomVec4f( size_t index, const Vec4f &v ) { *(reinterpret_cast<Vec4f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00231 
00232         void operator++() { mPtr += mStride; }
00233         bool    isDone() const { return mPtr < mDataEnd; }
00234         
00236         size_t      getIndex() const { return ( mPtr - mData ) / mStride; }
00238         size_t      getStride() const { return mStride; }
00240         void*       getPointer() const { return reinterpret_cast<void*>( mPtr ); }
00242         Vec3f*      getPositionPointer() const { return reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] ); }       
00243 
00244 //      VertexIter( const VertexIter &other ) { set( other ); } 
00245 //      VertexIter& operator=( const VertexIter &other ) { set( other ); return *this; }
00246         
00247      protected:
00248         void set( const VertexIter &other );
00249 
00250         struct Obj {
00251          public:
00252             Obj( const VboMesh &mesh );
00253             ~Obj();
00254             
00255             uint8_t                 *mData, *mDataEnd;
00256             std::vector<size_t>     mCustomOffsets;         
00257             Vbo                     mVbo;
00258         };
00259          
00260         shared_ptr<Obj>     mObj;
00261         uint8_t             *mPtr;
00262         uint8_t             *mData, *mDataEnd; // we cache these from the Obj to reduce dereferencing
00263         size_t              mPositionOffset, mNormalOffset;
00264         size_t              mColorRGBOffset, mColorRGBAOffset;
00265         size_t              mTexCoordOffset[ATTR_MAX_TEXTURE_UNIT+1];
00266         uint8_t             mStride;
00267     };
00268 
00269  protected:
00270     void    initializeBuffers( bool staticDataPlanar );
00271 
00272     shared_ptr<Obj>     mObj;
00273 };
00274 
00275 class VboExc : public std::exception {
00276  public:
00277     virtual const char* what() const throw() { return "OpenGL Vbo exception"; }
00278 };
00279 
00280 class VboInvalidTargetExc : public VboExc {
00281  public:
00282     virtual const char* what() const throw() { return "OpenGL Vbo exception: Invalid Target"; }
00283 };
00284 
00285 class VboFailedMapExc : public VboExc {
00286  public:
00287     virtual const char* what() const throw() { return "OpenGL Vbo exception: Map failure"; } 
00288 };
00289 
00290 class VboFailedUnmapExc : public VboExc {
00291  public:
00292     virtual const char* what() const throw() { return "OpenGL Vbo exception: Unmap failure"; } 
00293 };
00294 
00295 } } // namespace cinder::gl