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() const { 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> &positions );
00188     void                        bufferPositions( const Vec3f *positions, size_t count );
00189     void                        bufferNormals( const std::vector<Vec3f> &normals );
00190     void                        bufferTexCoords2d( size_t unit, const std::vector<Vec2f> &texCoords );
00191     class VertexIter            mapVertexBuffer();
00192 
00193     Vbo&                getIndexVbo() const { return mObj->mBuffers[INDEX_BUFFER]; }
00194     Vbo&                getStaticVbo() const { return mObj->mBuffers[STATIC_BUFFER]; }
00195     Vbo&                getDynamicVbo() const { return mObj->mBuffers[DYNAMIC_BUFFER]; }
00196 
00197     void                setCustomStaticLocation( size_t internalIndex, GLuint location ) { mObj->mCustomStaticLocations[internalIndex] = location; }
00198     void                setCustomDynamicLocation( size_t internalIndex, GLuint location ) { mObj->mCustomDynamicLocations[internalIndex] = location; }
00199 
00200     size_t                      getTexCoordOffset( size_t unit ) const { return mObj->mTexCoordOffset[unit]; }
00201     void                        setTexCoordOffset( size_t unit, size_t aTexCoordOffset ) { mObj->mTexCoordOffset[unit] = aTexCoordOffset; } 
00202 
00204 
00205     typedef shared_ptr<Obj> VboMesh::*unspecified_bool_type;
00206     operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &VboMesh::mObj; }
00207     void reset() { mObj.reset(); }
00209 
00210     class VertexIter {
00211      public:
00212         VertexIter( const VboMesh &mesh );
00213 
00214         void    setPosition( const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = v; }
00215         void    setPosition( float x, float y, float z ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = Vec3f( x, y, z ); }
00216         void    setNormal( const Vec3f &n ) { *(reinterpret_cast<Vec3f*>( &mPtr[mNormalOffset] )) = n; }
00217         void    setColorRGB( const Color &n ) { *(reinterpret_cast<Color*>( &mPtr[mColorRGBOffset] )) = n; }
00218         void    setColorRGBA( const ColorA &n ) { *(reinterpret_cast<ColorA*>( &mPtr[mColorRGBAOffset] )) = n; }
00219         void    setTexCoord2d0( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00220         void    setTexCoord3d0( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00221         void    setTexCoord2d1( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00222         void    setTexCoord3d1( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00223         void    setTexCoord2d2( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00224         void    setTexCoord3d2( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00225         void    setCustomFloat( size_t index, float v ) { *(reinterpret_cast<float*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00226         void    setCustomVec2f( size_t index, const Vec2f &v ) { *(reinterpret_cast<Vec2f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00227         void    setCustomVec3f( size_t index, const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00228         void    setCustomVec4f( size_t index, const Vec4f &v ) { *(reinterpret_cast<Vec4f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00229 
00230         void operator++() { mPtr += mStride; }
00231         bool    isDone() const { return mPtr < mDataEnd; }
00232         
00234         size_t      getIndex() const { return ( mPtr - mData ) / mStride; }
00236         size_t      getStride() const { return mStride; }
00238         void*       getPointer() const { return reinterpret_cast<void*>( mPtr ); }
00240         Vec3f*      getPositionPointer() const { return reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] ); }       
00241 
00242 //      VertexIter( const VertexIter &other ) { set( other ); } 
00243 //      VertexIter& operator=( const VertexIter &other ) { set( other ); return *this; }
00244         
00245      protected:
00246         void set( const VertexIter &other );
00247 
00248         struct Obj {
00249          public:
00250             Obj( const VboMesh &mesh );
00251             ~Obj();
00252             
00253             uint8_t                 *mData, *mDataEnd;
00254             std::vector<size_t>     mCustomOffsets;         
00255             Vbo                     mVbo;
00256         };
00257          
00258         shared_ptr<Obj>     mObj;
00259         uint8_t             *mPtr;
00260         uint8_t             *mData, *mDataEnd; // we cache these from the Obj to reduce dereferencing
00261         size_t              mPositionOffset, mNormalOffset;
00262         size_t              mColorRGBOffset, mColorRGBAOffset;
00263         size_t              mTexCoordOffset[ATTR_MAX_TEXTURE_UNIT+1];
00264         uint8_t             mStride;
00265     };
00266 
00267  protected:
00268     void    initializeBuffers( bool staticDataPlanar );
00269 
00270     shared_ptr<Obj>     mObj;
00271 };
00272 
00273 class VboExc : public std::exception {
00274  public:
00275     virtual const char* what() const throw() { return "OpenGL Vbo exception"; }
00276 };
00277 
00278 class VboInvalidTargetExc : public VboExc {
00279  public:
00280     virtual const char* what() const throw() { return "OpenGL Vbo exception: Invalid Target"; }
00281 };
00282 
00283 class VboFailedMapExc : public VboExc {
00284  public:
00285     virtual const char* what() const throw() { return "OpenGL Vbo exception: Map failure"; } 
00286 };
00287 
00288 class VboFailedUnmapExc : public VboExc {
00289  public:
00290     virtual const char* what() const throw() { return "OpenGL Vbo exception: Unmap failure"; } 
00291 };
00292 
00293 } } // namespace cinder::gl