I want to know the simplest method for using vbo's in OpenGL... I have tried running a few examples that work but are clouded with all other information thats making it really confusing me... at the moment this is what i have
GLuint vboId = 0;
const int trisize = (m_tris.size()/2)*3;//m_tris is an index array for verts and normals
GLfloat* vertices = new GLfloat[trisize];
GLfloat* normals = new GLfloat[trisize];
int j=0;
for (int i=0; i<m_tris.size(); i+=2) {
normals[j] = m_normals[m_tris[i+1]*3];
vertices[j++] = m_vertices[m_tris[i]*3];
normals[j] = m_normals[m_tris[i+1]*3+1];
vertices[j++] = m_vertices[m_tris[i]*3+1];
normals[j] = m_normals[m_tris[i+1]*3+2];
vertices[j++] = m_vertices[m_tris[i]*3+2];
} //im pretty sure this loop is right as its what i used before to display mesh correctly without vbo's using glVertex3f
glGenBuffersARB(1, &vboId);
glBindBufferARB(GL_ARRAY_BUFFER_ARB, vboId);
glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices)+sizeof(normals), 0, GL_STATIC_DRAW_ARB);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(vertices), vertices);
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, sizeof(vertices), sizeof(normals), normals);
glVertexPointer(sizeof(vertices), GL_FLOAT, 3, 0);
glNormalPointer(GL_FLOAT, 3, (void*)sizeof(vertices));
in a render method i have
glDrawArrays(GL_TRIANGLES, 0, this->getTriNum()); //0 is the vboId?
also i have a method that runs once...
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
when i try to run my code i get "EXC_BAD_ACCESS"
any advice on what im doing wrong... or a very simple implementation of a vbo would be very helpful
What you are doing looks right, except sizeof(vertices) gives you the size of the address, not the size of the array. So, when you call glBufferData, you are allocating 8 bytes and when you call glBufferSubData, you fill those 8 bytes with the first four bytes of the vertices array and then the first four bytes of the normals array. Then, when you go to call glDrawArrays, the first indice causes an array index out of bounds exception (Hence the EXC_BAD_ACCESS).
// Data
GLuint geometry_array = 0;
GLuint indice_array = 0;
GLfloat *geometry;
GLuint *indices;
You can do this initialization differently, but I interleave all my data into a 32 bytes per vertice array. Any way you choose to set up your array works, as long as you use glVertexPointer, glNormalPointer, and glTexCoordPointer correctly.
// Initialize
geometry = new GLfloat[8*num_geometry];
indices = new GLuint[num_indices];
/* Fill geometry: 0, 1, 2 = vertex_xyz
* 3, 4, 5 = normal_xyz
* 6, 7 = tex_coord_uv
*/
glGenBuffers(1, &geometry_array);
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*8*num_geometry, NULL, GL_DYNAMIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(GLfloat)*8*num_geometry, geometry);
glGenBuffers(1, &indice_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*num_indices, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(GLuint)*num_indices, indices);
The render function is five steps. First, bind the buffers so OpenGL knows where to find your geometry and indice data. Second, Enable the various client states for each type of data. If you leave one out, that type of data will not be rendered, and if leave all of them out, your entire object will not be rendered. Third, you have to tell OpenGL where each type of data is contained in your array. In this case the 32 byte geometry data starts with 12 bytes of vertex data, so the starting offset should be zero or NULL. Since each vertex-normal-texcoord combo is 32 bytes, that is the step size. "sizeof(GLfloat)8" says 32 bytes from offset NULL, there will be another vertice xyz group. In the case of the normals, each normal xyz group is 12 bytes after the offset for the vertice xyz group, hence "(float)(sizeof(GLfloat)*3)" as the starting offset. Again, the step size is 32 bytes. Fourth, you have to tell it to draw all of the triangles associated with the indice array. Finally, you should disable the client states, in case you want to use a different method of rendering.
//Render
// Step 1
glBindBuffer(GL_ARRAY_BUFFER, geometry_array);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indice_array);
// Step 2
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// Step 3
glTexCoordPointer(3, GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*5));
glNormalPointer(GL_FLOAT, sizeof(GLfloat)*8, (float*)(sizeof(GLfloat)*3));
glVertexPointer(3, GL_FLOAT, sizeof(GLfloat)*8, NULL);
// Step 4
glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, NULL);
// Step 5
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With