# 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