00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 std::shared_ptr<Obj> mObj;
00060
00061 public:
00063
00064 typedef std::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 typedef std::shared_ptr<VboMesh> VboMeshRef;
00072
00073 class VboMesh {
00074 public:
00075 enum { NONE, STATIC, DYNAMIC };
00076 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 };
00077 enum { ATTR_MAX_TEXTURE_UNIT = 3 };
00078
00079 struct Layout {
00080 Layout() { initAttributes(); }
00081
00083 bool isDefaults() const { for( int a = 0; a < ATTR_TOTAL; ++a ) if( mAttributes[a] != NONE ) return false; return true; }
00084
00085 bool hasNormals() const { return hasDynamicNormals() || hasStaticNormals(); }
00086 bool hasStaticNormals() const { return mAttributes[ATTR_NORMALS] == STATIC; }
00087 bool hasDynamicNormals() const { return mAttributes[ATTR_NORMALS] == DYNAMIC; }
00088 void setStaticNormals() { mAttributes[ATTR_NORMALS] = STATIC; }
00089 void setDynamicNormals() { mAttributes[ATTR_NORMALS] = DYNAMIC; }
00090
00091 bool hasColorsRGB() const { return hasDynamicColorsRGB() || hasStaticColorsRGB(); }
00092 bool hasStaticColorsRGB() const { return mAttributes[ATTR_COLORS_RGB] == STATIC; }
00093 bool hasDynamicColorsRGB() const { return mAttributes[ATTR_COLORS_RGB] == DYNAMIC; }
00094 void setStaticColorsRGB() { mAttributes[ATTR_COLORS_RGB] = STATIC; mAttributes[ATTR_COLORS_RGBA] = NONE; }
00095 void setDynamicColorsRGB() { mAttributes[ATTR_COLORS_RGB] = DYNAMIC; mAttributes[ATTR_COLORS_RGBA] = NONE; }
00096
00097 bool hasColorsRGBA() const { return hasDynamicColorsRGBA() || hasStaticColorsRGBA(); }
00098 bool hasStaticColorsRGBA() const { return mAttributes[ATTR_COLORS_RGBA] == STATIC; }
00099 bool hasDynamicColorsRGBA() const { return mAttributes[ATTR_COLORS_RGBA] == DYNAMIC; }
00100 void setStaticColorsRGBA() { mAttributes[ATTR_COLORS_RGBA] = STATIC; mAttributes[ATTR_COLORS_RGB] = NONE; }
00101 void setDynamicColorsRGBA() { mAttributes[ATTR_COLORS_RGBA] = DYNAMIC; mAttributes[ATTR_COLORS_RGB] = NONE; }
00102
00103 bool hasTexCoords2d( size_t unit = 0 ) const { return hasDynamicTexCoords2d( unit ) || hasStaticTexCoords2d( unit ); }
00104 bool hasStaticTexCoords2d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS2D_0 + unit] == STATIC; }
00105 bool hasDynamicTexCoords2d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS2D_0 + unit] == DYNAMIC; }
00106 void setStaticTexCoords2d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS2D_0 + unit] = STATIC; mAttributes[ATTR_TEXCOORDS3D_0 + unit] = NONE; }
00107 void setDynamicTexCoords2d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS2D_0 + unit] = DYNAMIC; mAttributes[ATTR_TEXCOORDS3D_0 + unit] = NONE; }
00109 bool hasStaticTexCoords() const;
00111 bool hasDynamicTexCoords() const;
00113 bool hasTexCoords( size_t unit ) const { return ( mAttributes[ATTR_TEXCOORDS2D_0 + unit] != NONE ) || ( mAttributes[ATTR_TEXCOORDS3D_0 + unit] != NONE ); }
00114
00115 bool hasTexCoords3d( size_t unit = 0 ) const { return hasDynamicTexCoords3d( unit ) || hasStaticTexCoords3d( unit ); }
00116 bool hasStaticTexCoords3d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS3D_0 + unit] == STATIC; }
00117 bool hasDynamicTexCoords3d( size_t unit = 0 ) const { return mAttributes[ATTR_TEXCOORDS3D_0 + unit] == DYNAMIC; }
00118 void setStaticTexCoords3d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS3D_0 + unit] = STATIC; mAttributes[ATTR_TEXCOORDS2D_0 + unit] = NONE; }
00119 void setDynamicTexCoords3d( size_t unit = 0 ) { mAttributes[ATTR_TEXCOORDS3D_0 + unit] = DYNAMIC; mAttributes[ATTR_TEXCOORDS2D_0 + unit] = NONE; }
00120
00121 bool hasIndices() const { return hasStaticIndices() || hasDynamicIndices(); }
00122 bool hasStaticIndices() const { return mAttributes[ATTR_INDICES] == STATIC; }
00123 bool hasDynamicIndices() const { return mAttributes[ATTR_INDICES] == DYNAMIC; }
00124 void setStaticIndices() { mAttributes[ATTR_INDICES] = STATIC; }
00125 void setDynamicIndices() { mAttributes[ATTR_INDICES] = DYNAMIC; }
00126
00127 bool hasPositions() const { return hasStaticPositions() || hasDynamicPositions(); }
00128 bool hasStaticPositions() const { return mAttributes[ATTR_POSITIONS] == STATIC; }
00129 bool hasDynamicPositions() const { return mAttributes[ATTR_POSITIONS] == DYNAMIC; }
00130 void setStaticPositions() { mAttributes[ATTR_POSITIONS] = STATIC; }
00131 void setDynamicPositions() { mAttributes[ATTR_POSITIONS] = DYNAMIC; }
00132
00133 enum CustomAttr { CUSTOM_ATTR_FLOAT, CUSTOM_ATTR_FLOAT2, CUSTOM_ATTR_FLOAT3, CUSTOM_ATTR_FLOAT4, TOTAL_CUSTOM_ATTR_TYPES };
00134 static int sCustomAttrSizes[TOTAL_CUSTOM_ATTR_TYPES];
00135 static GLint sCustomAttrNumComponents[TOTAL_CUSTOM_ATTR_TYPES];
00136 static GLenum sCustomAttrTypes[TOTAL_CUSTOM_ATTR_TYPES];
00137 void addDynamicCustomFloat() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT, 0 ) ); }
00138 void addDynamicCustomVec2f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT2, 0 ) ); }
00139 void addDynamicCustomVec3f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT3, 0 ) ); }
00140 void addDynamicCustomVec4f() { mCustomDynamic.push_back( std::make_pair( CUSTOM_ATTR_FLOAT4, 0 ) ); }
00141
00142 int mAttributes[ATTR_TOTAL];
00143 std::vector<std::pair<CustomAttr,size_t> > mCustomDynamic, mCustomStatic;
00144
00145 private:
00146 void initAttributes() { for( int a = 0; a < ATTR_TOTAL; ++a ) mAttributes[a] = NONE; }
00147 };
00148
00149 enum { INDEX_BUFFER = 0, STATIC_BUFFER, DYNAMIC_BUFFER, TOTAL_BUFFERS };
00150
00151 protected:
00152 struct Obj {
00153 size_t mNumIndices, mNumVertices;
00154
00155 Vbo mBuffers[TOTAL_BUFFERS];
00156 size_t mPositionOffset;
00157 size_t mNormalOffset;
00158 size_t mColorRGBOffset, mColorRGBAOffset;
00159 size_t mTexCoordOffset[ATTR_MAX_TEXTURE_UNIT+1];
00160 size_t mStaticStride, mDynamicStride;
00161 GLenum mPrimitiveType;
00162 Layout mLayout;
00163 std::vector<GLint> mCustomStaticLocations;
00164 std::vector<GLint> mCustomDynamicLocations;
00165 };
00166
00167 public:
00168 class VertexIter;
00169
00170 VboMesh() {}
00171 explicit VboMesh( const TriMesh &triMesh, Layout layout = Layout() );
00172 explicit VboMesh( const TriMesh2d &triMesh, Layout layout = Layout() );
00173
00174 VboMesh( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType );
00175
00176 VboMesh( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType, Vbo *indexBuffer, Vbo *staticBuffer, Vbo *dynamicBuffer );
00177
00178 static VboMeshRef create( const TriMesh &triMesh, Layout layout = Layout() ) { return std::shared_ptr<VboMesh>( new VboMesh( triMesh, layout ) ); }
00179 static VboMeshRef create( const TriMesh2d &triMesh, Layout layout = Layout() ) { return std::shared_ptr<VboMesh>( new VboMesh( triMesh, layout ) ); }
00180 static VboMeshRef create( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType ) { return std::shared_ptr<VboMesh>( new VboMesh( numVertices, numIndices, layout, primitiveType ) ); }
00181 static VboMeshRef create( size_t numVertices, size_t numIndices, Layout layout, GLenum primitiveType, Vbo *indexBuffer, Vbo *staticBuffer, Vbo *dynamicBuffer )
00182 { return std::shared_ptr<VboMesh>( new VboMesh( numVertices, numIndices, layout, primitiveType, indexBuffer, staticBuffer, dynamicBuffer ) ); }
00183
00184
00185 size_t getNumIndices() const { return mObj->mNumIndices; }
00186 size_t getNumVertices() const { return mObj->mNumVertices; }
00187 GLenum getPrimitiveType() const { return mObj->mPrimitiveType; }
00188
00189 const Layout& getLayout() const { return mObj->mLayout; }
00190
00191 void bindIndexBuffer() const;
00192 void enableClientStates() const;
00193 void disableClientStates() const;
00194 void bindAllData() const;
00195 static void unbindBuffers();
00196
00197 void bufferIndices( const std::vector<uint32_t> &indices );
00198 void bufferPositions( const std::vector<Vec3f> &positions );
00199 void bufferPositions( const Vec3f *positions, size_t count );
00200 void bufferNormals( const std::vector<Vec3f> &normals );
00201 void bufferTexCoords2d( size_t unit, const std::vector<Vec2f> &texCoords );
00202 void bufferTexCoords3d( size_t unit, const std::vector<Vec3f> &texCoords );
00203 void bufferColorsRGB( const std::vector<Color> &colors );
00204 void bufferColorsRGBA( const std::vector<ColorA> &colors );
00205 class VertexIter mapVertexBuffer();
00206
00207 Vbo& getIndexVbo() const { return mObj->mBuffers[INDEX_BUFFER]; }
00208 Vbo& getStaticVbo() const { return mObj->mBuffers[STATIC_BUFFER]; }
00209 Vbo& getDynamicVbo() const { return mObj->mBuffers[DYNAMIC_BUFFER]; }
00210
00211 void setCustomStaticLocation( size_t internalIndex, GLuint location ) { mObj->mCustomStaticLocations[internalIndex] = location; }
00212 void setCustomDynamicLocation( size_t internalIndex, GLuint location ) { mObj->mCustomDynamicLocations[internalIndex] = location; }
00213
00214 size_t getTexCoordOffset( size_t unit ) const { return mObj->mTexCoordOffset[unit]; }
00215 void setTexCoordOffset( size_t unit, size_t aTexCoordOffset ) { mObj->mTexCoordOffset[unit] = aTexCoordOffset; }
00216
00218
00219 typedef std::shared_ptr<Obj> VboMesh::*unspecified_bool_type;
00220 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &VboMesh::mObj; }
00221 void reset() { mObj.reset(); }
00223
00224 class VertexIter {
00225 public:
00226 VertexIter( const VboMesh &mesh );
00227
00228 void setPosition( const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = v; }
00229 void setPosition( float x, float y, float z ) { *(reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] )) = Vec3f( x, y, z ); }
00230 void setNormal( const Vec3f &n ) { *(reinterpret_cast<Vec3f*>( &mPtr[mNormalOffset] )) = n; }
00231 void setColorRGB( const Color &n ) { *(reinterpret_cast<Color*>( &mPtr[mColorRGBOffset] )) = n; }
00232 void setColorRGBA( const ColorA &n ) { *(reinterpret_cast<ColorA*>( &mPtr[mColorRGBAOffset] )) = n; }
00233 void setTexCoord2d0( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00234 void setTexCoord3d0( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[0]] )) = t; }
00235 void setTexCoord2d1( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00236 void setTexCoord3d1( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[1]] )) = t; }
00237 void setTexCoord2d2( const Vec2f &t ) { *(reinterpret_cast<Vec2f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00238 void setTexCoord3d2( const Vec3f &t ) { *(reinterpret_cast<Vec3f*>( &mPtr[mTexCoordOffset[2]] )) = t; }
00239 void setCustomFloat( size_t index, float v ) { *(reinterpret_cast<float*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00240 void setCustomVec2f( size_t index, const Vec2f &v ) { *(reinterpret_cast<Vec2f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00241 void setCustomVec3f( size_t index, const Vec3f &v ) { *(reinterpret_cast<Vec3f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00242 void setCustomVec4f( size_t index, const Vec4f &v ) { *(reinterpret_cast<Vec4f*>( &mPtr[mObj->mCustomOffsets[index]] )) = v; }
00243
00244 void operator++() { mPtr += mStride; }
00245 bool isDone() const { return mPtr < mDataEnd; }
00246
00248 size_t getIndex() const { return ( mPtr - mData ) / mStride; }
00250 size_t getStride() const { return mStride; }
00252 void* getPointer() const { return reinterpret_cast<void*>( mPtr ); }
00254 Vec3f* getPositionPointer() const { return reinterpret_cast<Vec3f*>( &mPtr[mPositionOffset] ); }
00255
00256
00257
00258
00259 protected:
00260 void set( const VertexIter &other );
00261
00262 struct Obj {
00263 public:
00264 Obj( const VboMesh &mesh );
00265 ~Obj();
00266
00267 uint8_t *mData, *mDataEnd;
00268 std::vector<size_t> mCustomOffsets;
00269 Vbo mVbo;
00270 };
00271
00272 std::shared_ptr<Obj> mObj;
00273 uint8_t *mPtr;
00274 uint8_t *mData, *mDataEnd;
00275 size_t mPositionOffset, mNormalOffset;
00276 size_t mColorRGBOffset, mColorRGBAOffset;
00277 size_t mTexCoordOffset[ATTR_MAX_TEXTURE_UNIT+1];
00278 uint8_t mStride;
00279 };
00280
00281 protected:
00282 void initializeBuffers( bool staticDataPlanar );
00283
00284 std::shared_ptr<Obj> mObj;
00285 };
00286
00287 class VboExc : public std::exception {
00288 public:
00289 virtual const char* what() const throw() { return "OpenGL Vbo exception"; }
00290 };
00291
00292 class VboInvalidTargetExc : public VboExc {
00293 public:
00294 virtual const char* what() const throw() { return "OpenGL Vbo exception: Invalid Target"; }
00295 };
00296
00297 class VboFailedMapExc : public VboExc {
00298 public:
00299 virtual const char* what() const throw() { return "OpenGL Vbo exception: Map failure"; }
00300 };
00301
00302 class VboFailedUnmapExc : public VboExc {
00303 public:
00304 virtual const char* what() const throw() { return "OpenGL Vbo exception: Unmap failure"; }
00305 };
00306
00307 } }