Hi,
I’m sorry to ask another VBO question, but I’ve not found an example to do what I want. I currently have a vertex format that holds various vertex attributes in a single array. I’d like to know how to write the correct enable/disable client code, and what are the correct arguments to pass to functions like glVertexPointer and glTexCoordPointer. The pointer functions seem like the hardest part with the interleaved vertex format, so I assume that’s what I’m messing up. It’s funny that the same code that is messed up for interleaved arrays works fine if I only have vertex positions and no other attributes. Anyway, here is what I’m trying:
[b]void drawVBO( const GMesh& mesh )
{
// bind VBO for the vertex array
{
size_t vert_size = CalculateVertexLength( &(mesh._vertex_decl._elements[0]), mesh._vertex_decl._elements.size() );
unsigned int accum_length = 0;
unsigned int accum_texture_unit = 0;
glBindBufferARB(GL_ARRAY_BUFFER_ARB, mesh._vbo.id); // for vertex coordinates
// call enableclientstate and vertex attribute pointer functions
for( unsigned int index_sem=0; index_sem<mesh._vertex_decl._elements.size(); ++index_sem )
{
unsigned int semantic = mesh._vertex_decl._elements[index_sem];
switch( semantic )
{
case GVES_POSITION_3:
{
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer(3, GL_FLOAT, vert_size, BUFFER_OFFSET(accum_length));
accum_length += CalculateVertexElementLength(semantic)*sizeof(float);
} break;
case GVES_TEXTURE_COORDINATE:
{
//glClientActiveTextureARB( GL_TEXTURE0_ARB + accum_texture_unit );
//// TODO: problem here if a crazy Mesh defines more texture units than are available
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glTexCoordPointer(2, GL_FLOAT, vert_size, BUFFER_OFFSET(accum_length));
accum_length += CalculateVertexElementLength(semantic)*sizeof(float);
} break;
}
}
}
// bind IBO for index array AND draw
for( unsigned int index_sub=0; index_sub<mesh._submesh_array.size(); ++index_sub)
{
GSubmesh* sub = mesh._submesh_array[index_sub];
setMaterialState( sub->_material );
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.id); // for indices
// draw
glDrawElements( GL_TRIANGLES, sub->_index_array_length, GL_UNSIGNED_SHORT, 0);
}
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); // unbind
// call disableclientstate
for( unsigned int index_sem=0; index_sem<mesh._vertex_decl._elements.size(); ++index_sem )
{
unsigned int semantic = mesh._vertex_decl._elements[index_sem];
switch( semantic )
{
case GVES_POSITION_3:
{
glDisableClientState( GL_VERTEX_ARRAY );
} break;
case GVES_TEXTURE_COORDINATE:
{
glDisableClientState( GL_TEXTURE_COORD_ARRAY );
} break;
}
}
glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); // unbind
}[/b]
In case its important, here’s how I created the BOs:
[b]void createVBO( GMesh& mesh )
{
size_t vert_size = CalculateVertexLength( &(mesh._vertex_decl._elements[0]), mesh._vertex_decl._elements.size() );
size_t num_verts = mesh._vertex_array_length / vert_size;
// the vertex array
{
mesh._vbo.size_bytes = num_verts * vert_size * sizeof(float); // 4 bytes for each floating point value
glGenBuffersARB( 1, &(mesh._vbo.id) );
glBindBufferARB( GL_ARRAY_BUFFER_ARB, mesh._vbo.id ); // vertex data
glBufferDataARB( GL_ARRAY_BUFFER_ARB, mesh._vbo.size_bytes, NULL, GL_STATIC_DRAW_ARB ); // static, draw only
glBufferSubDataARB( GL_ARRAY_BUFFER_ARB, 0, mesh._vbo.size_bytes, mesh._vertex_array );
}
// the index arrays
for( unsigned int index_sub=0; index_sub<mesh._submesh_array.size(); ++index_sub )
{
GSubmesh* sub = mesh._submesh_array[index_sub];
sub->_ibo.size_bytes = sub->_index_array_length * sizeof(unsigned short); // Mesh structure is currently hard coded to store using 'ushort16' (2 bytes)
glGenBuffersARB( 1, &(sub->_ibo.id) );
glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.id ); // index data
glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, sub->_ibo.size_bytes, NULL, GL_STATIC_DRAW_ARB );
glBufferSubDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0, sub->_ibo.size_bytes, sub->_index_array );
}
}[/b]