00001 #include "Vertexbuffer.h"
00002 #include "Program.h"
00003 #include "Property.h"
00004 #include "Util.h"
00005
00006 namespace RenderTools {
00007
00009 Vertexbuffer::Vertexbuffer( void ):
00010 AbstractPropertyContainer(),
00011 m_useProgram( false ),
00012 m_directRendering( false ),
00013 m_usage( GL_STATIC_DRAW ),
00014 m_mode( GL_POINTS ),
00015 m_numVertices( 0 ),
00016 m_numAttributes( 0 ),
00017 m_vertexSize( 0 ),
00018 m_data( 0 ),
00019 m_id( 0 ){
00020
00021 }
00022
00023 PropertyPtr Vertexbuffer::create( const XMLNodePtr & xml ){
00024 VertexbufferPtr p( new Vertexbuffer() );
00025 p->setName( xml );
00026 p->createProperties();
00027 p->setProperties( xml, false );
00028 return( dynamic_pointer_cast< AbstractProperty, Vertexbuffer >( p ) );
00029 }
00030
00031 void Vertexbuffer::createProperties( void ){
00033 EnumList usage;
00034 #ifdef GL_STREAM_DRAW
00035 usage << GL_STREAM_DRAW;
00036 #endif
00037 #ifdef GL_STREAM_READ
00038 usage << GL_STREAM_READ;
00039 #endif
00040 #ifdef GL_STREAM_COPY
00041 usage << GL_STREAM_COPY;
00042 #endif
00043 #ifdef GL_STATIC_DRAW
00044 usage << GL_STATIC_DRAW;
00045 #endif
00046 #ifdef GL_STATIC_READ
00047 usage << GL_STATIC_READ;
00048 #endif
00049 #ifdef GL_STATIC_COPY
00050 usage << GL_STATIC_COPY;
00051 #endif
00052 #ifdef GL_DYNAMIC_DRAW
00053 usage << GL_DYNAMIC_DRAW;
00054 #endif
00055 #ifdef GL_DYNAMIC_READ
00056 usage << GL_DYNAMIC_READ;
00057 #endif
00058 #ifdef GL_DYNAMIC_COPY
00059 usage << GL_DYNAMIC_COPY;
00060 #endif
00061 createProperty( this, "usage", GLenumStruct( & m_usage ), usage );
00062
00063 EnumList modes;
00064 #ifdef GL_POINTS
00065 modes << GL_POINTS;
00066 #endif
00067 #ifdef GL_LINE_STRIP
00068 modes << GL_LINE_STRIP;
00069 #endif
00070 #ifdef GL_LINE_LOOP
00071 modes << GL_LINE_LOOP;
00072 #endif
00073 #ifdef GL_LINES
00074 modes << GL_LINES;
00075 #endif
00076 #ifdef GL_TRIANGLE_STRIP
00077 modes << GL_TRIANGLE_STRIP;
00078 #endif
00079 #ifdef GL_TRIANGLE_FAN
00080 modes << GL_TRIANGLE_FAN;
00081 #endif
00082 #ifdef GL_TRIANGLES
00083 modes << GL_TRIANGLES;
00084 #endif
00085 #ifdef GL_QUAD_STRIP
00086 modes << GL_QUAD_STRIP;
00087 #endif
00088 #ifdef GL_QUADS
00089 modes << GL_QUADS;
00090 #endif
00091 #ifdef GL_POLYGON
00092 modes << GL_POLYGON;
00093 #endif
00094 createProperty( this, "useProgram", BooleanStruct( & m_useProgram ) );
00095 createProperty( this, "directRendering", BooleanStruct( & m_directRendering ) );
00096 createProperty( this, "drawMode", GLenumStruct( & m_mode ), modes );
00097 createProperty( this, "size", & m_numVertices );
00098 createProperty( this, "attributes", & m_numAttributes );
00099 createProperty( this, "totalSize", & m_vertexSize );
00100 createProperty( this, "offsets", & m_offsets );
00101 createProperty( this, "sizes", & m_sizes );
00102 createProperty( this, "names", & m_names );
00103 }
00104
00105 const string Vertexbuffer::getTypeName( bool ofComponent ) const {
00106 return( "Vertexbuffer" );
00107 }
00108
00109 Vertexbuffer::~Vertexbuffer( void ){
00110 if( m_data ){
00111 free( m_data );
00112 }
00113 }
00114
00115 void Vertexbuffer::onInitialize( void ){
00116
00117 if( glIsBuffer( m_id ) == GL_FALSE ){
00118 glGenBuffers( 1, & m_id );
00119 }
00120
00121 resize();
00122 }
00123
00125 void Vertexbuffer::addAttribute( GLuint numFloats, const string name ){
00127 m_numAttributes++;
00129 m_offsets.push_back( m_vertexSize );
00130
00132 m_sizes.push_back( numFloats );
00134 m_names.push_back( name );
00136 m_vertexSize += numFloats;
00137
00139 if( isInitialized() ){
00140 resize();
00141 }
00142 }
00143
00144 GLuint Vertexbuffer::getNumAttributes( void ){
00145 return( m_numAttributes );
00146 }
00147
00148 GLuint Vertexbuffer::getVertexSize( void ){
00149 return( m_vertexSize );
00150 }
00151
00152 const vector< GLuint > & Vertexbuffer::getAttributeOffsets( void ){
00153 return( m_offsets );
00154 }
00155
00156 const vector< GLuint > & Vertexbuffer::getAttributeSizes( void ){
00157 return( m_sizes );
00158 }
00159
00160 const vector< string > & Vertexbuffer::getAttributeNames( void ){
00161 return( m_names );
00162 }
00163
00164 GLenum Vertexbuffer::getUsage( void ) const {
00165 return( m_usage );
00166 }
00167
00168 GLenum Vertexbuffer::getMode( void ) const {
00169 return( m_mode );
00170 }
00171
00172 GLuint Vertexbuffer::getNumVertices( void ) const {
00173 return( m_numVertices );
00174 }
00175
00176 void Vertexbuffer::setUsage( GLenum usage ){
00177 m_usage = usage;
00178 }
00179
00180 void Vertexbuffer::setMode( GLenum mode ){
00181 m_mode = mode;
00182 }
00183
00184 void Vertexbuffer::setNumVertices( GLuint numVertices ){
00185 if( isInitialized() ){
00186 if( numVertices != m_numVertices ){
00187 m_numVertices = numVertices;
00188 resize();
00189 }
00190 }
00191 else{
00192 m_numVertices = numVertices;
00193 }
00194 }
00195
00196 bool Vertexbuffer::getDirectRendering( void ) const {
00197 return( m_directRendering );
00198 }
00199
00200 void Vertexbuffer::setDirectRendering( bool state ){
00201 if( isInitialized() ){
00202 if( state != m_directRendering ){
00203 m_directRendering = state;
00204 resize();
00205 }
00206 }
00207 else{
00208 m_directRendering = state;
00209 }
00210 }
00211
00212 bool Vertexbuffer::getUseProgram( void ) const {
00213 return( m_useProgram );
00214 }
00215
00216 void Vertexbuffer::setUseProgram( bool state ){
00217 m_useProgram = state;
00218 }
00219
00221 void Vertexbuffer::setVertexAttribute( GLuint elementIndex, const string attribName, const GLfloat * data ){
00222 for( GLuint i = 0; i < m_numAttributes; i++ ){
00223 if( m_names[ i ] == attribName ){
00224 setVertexAttribute( elementIndex, i, data );
00225 return;
00226 }
00227 }
00228 }
00229
00231 void Vertexbuffer::setVertexAttribute( GLuint elementIndex, GLuint attribIndex, const GLfloat * data ){
00232 if( m_directRendering ){
00233 memcpy( & m_data[ elementIndex * m_vertexSize + m_offsets[ attribIndex ] ], data, m_sizes[ attribIndex ] * sizeof( GLfloat ) );
00234
00235 }
00236 else{
00238 GLintptr offset = ( elementIndex * m_vertexSize + m_offsets[ attribIndex ] ) * sizeof( GLfloat );
00239 GLsizeiptr size = m_sizes[ attribIndex ] * sizeof( GLfloat );
00240 glBindBuffer( GL_ARRAY_BUFFER, m_id );
00241 glBufferSubData( GL_ARRAY_BUFFER, offset, size, data );
00242 Error::assertNoErrors( __FILE__, __LINE__ );
00243 }
00244 }
00245
00247 void Vertexbuffer::resize( void ){
00248 if( m_directRendering ){
00249 m_data = ( GLfloat * )realloc( m_data, m_numVertices * m_vertexSize * sizeof( GLfloat ) );
00250 if( ! m_data ){
00251 Error::error( Error::MEMORY_ALLOCATION_FAILED, __FILE__, __LINE__ );
00252 }
00253 }
00254 else{
00255 glBindBuffer( GL_ARRAY_BUFFER, m_id );
00256 glBufferData( GL_ARRAY_BUFFER, m_numVertices * m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )0, m_usage );
00257 Error::assertNoErrors( __FILE__, __LINE__ );
00258 }
00259 }
00260
00261 void Vertexbuffer::onRender( void ){
00262 if( m_directRendering ){
00263 #if glBegin
00264 glBegin( m_mode );
00265 for( GLuint i = 0; i < m_numVertices; i++ ){
00266 for( GLuint j = 0; j < m_numAttributes; j++ ){
00267 if( m_names[ j ] == "texcoord" ){
00268 switch( m_sizes[ j ] ){
00269 case 1:
00270 glTexCoord1f( m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00271 break;
00272 case 2:
00273 glTexCoord2fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00274 break;
00275 case 3:
00276 glTexCoord3fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00277 break;
00278 case 4:
00279 glTexCoord4fv( & m_data[ i * m_vertexSize + m_offsets[ i ] ] );
00280 break;
00281 default:
00282 Error::error( Error::ELEMENT_SIZE_UNSUPPORTED, __FILE__, __LINE__, m_names[ j ] );
00283 break;
00284 }
00285 }
00286 else if( m_names[ j ] == "normal" ){
00287 switch( m_sizes[ j ] ){
00288 case 3:
00289 glNormal3fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00290 break;
00291 default:
00292 Error::error( Error::ELEMENT_SIZE_UNSUPPORTED, __FILE__, __LINE__, m_names[ j ] );
00293 break;
00294 }
00295 }
00296 else if( m_names[ j ] == "color" ){
00297 switch( m_sizes[ j ] ){
00298 case 3:
00299 glColor3fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00300 break;
00301 case 4:
00302 glColor4fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00303 break;
00304 default:
00305 Error::error( Error::ELEMENT_SIZE_UNSUPPORTED, __FILE__, __LINE__, m_names[ j ] );
00306 break;
00307 }
00308 }
00309 else if( m_names[ j ] == "vertex" ){
00310 switch( m_sizes[ j ] ){
00311 case 2:
00312 glVertex2fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00313 break;
00314 case 3:
00315 glVertex3fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00316
00317 break;
00318 case 4:
00319 glVertex4fv( & m_data[ i * m_vertexSize + m_offsets[ j ] ] );
00320 break;
00321 default:
00322 Error::error( Error::ELEMENT_SIZE_UNSUPPORTED, __FILE__, __LINE__, m_names[ j ] );
00323 break;
00324 }
00325 }
00326 else{
00327 Error::error( Error::ARRAY_TYPE_UNSUPPORTED, __FILE__, __LINE__, m_names[ j ] );
00328 }
00329 }
00330 }
00331 glEnd();
00332 #endif
00333 }
00334 else{
00336 glBindBuffer( GL_ARRAY_BUFFER, m_id );
00337
00338 #ifndef RT_GLES1
00339 if( m_useProgram ){
00341 ProgramPtr current = Program::getCurrent();
00342 if( current ){
00343 for( GLuint i = 0; i < m_numAttributes; i++ ){
00344 glBindAttribLocation( current->getProgramID(), i, m_names[ i ].c_str() );
00345 glEnableVertexAttribArray( i );
00346 glVertexAttribPointer( i, m_sizes[ i ], GL_FLOAT, GL_FALSE, m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )m_offsets[ i ] );
00347 }
00348 glLinkProgram( current->getProgramID() );
00349 glUseProgram( current->getProgramID() );
00350 }
00351 }
00352 else{
00353 #endif
00354 glDisableClientState( GL_VERTEX_ARRAY );
00355 glDisableClientState( GL_COLOR_ARRAY );
00356 glDisableClientState( GL_NORMAL_ARRAY );
00357 glDisableClientState( GL_TEXTURE_COORD_ARRAY );
00358
00359 for( GLuint i = 0; i < m_numAttributes; i++ ){
00360 if( m_names[ i ] == "vertex" ){
00361 glEnableClientState( GL_VERTEX_ARRAY );
00362 glVertexPointer( m_sizes[ i ], GL_FLOAT, m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )m_offsets[ i ] );
00363 }
00364 else if( m_names[ i ] == "color" ){
00365 glEnableClientState( GL_COLOR_ARRAY );
00366 glColorPointer( m_sizes[ i ], GL_FLOAT, m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )m_offsets[ i ] );
00367 }
00368 else if( m_names[ i ] == "normal" ){
00369 glEnableClientState( GL_NORMAL_ARRAY );
00370 glNormalPointer( GL_FLOAT, m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )m_offsets[ i ] );
00371 }
00372 else if( m_names[ i ] == "texcoord" ){
00373 glEnableClientState( GL_TEXTURE_COORD_ARRAY );
00374 glTexCoordPointer( m_sizes[ i ], GL_FLOAT, m_vertexSize * sizeof( GLfloat ), ( const GLvoid * )m_offsets[ i ] );
00375 }
00376 else{
00377 Error::error( Error::ARRAY_TYPE_UNSUPPORTED, __FILE__, __LINE__, m_names[ i ] );
00378 }
00379 }
00380 }
00381 glDrawArrays( m_mode, 0, m_numVertices );
00382 #ifndef RT_GLES1
00383 }
00384 #endif
00385
00386 Error::assertNoErrors( __FILE__, __LINE__ );
00387 }
00388
00389
00390 };
00391