IPhone Cheetah 3D OpenGL ES Vertex Buffer Object (VBO) Example

I would like to use Vertex Buffer Objects (VBOs) to improve my rendering of several complex models in my Open GL ES 1.1 game for iPhone. After reading a few posts in SO and this tutorial (http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html), I still can't figure out the VBOs and how to implement them, given my Cheetah 3D export model format. Can someone please give an example of VBO implementation and use it to draw my vertices with this data structure and explain the syntax? I am very grateful for any help!

#define body_vertexcount 434 #define body_polygoncount 780 // The vertex data is saved in the following format: // u0,v0,normalx0,normaly0,normalz0,x0,y0,z0 float body_vertex[body_vertexcount][8]={ {0.03333, 0.00000, -0.68652, -0.51763, 0.51063, 0.40972, -0.25028, -1.31418}, {...}, {...} } GLushort body_index[body_polygoncount][3]={ {0, 1, 2}, {2, 3, 0} } 

I wrote the following code using chapter 9 of Pro OpenGL ES (Appress). I get EXC_BAD_ACCESS with the DrawElements command, and I'm not sure why. Can anyone shed some light? Thanks -

 // First thing we do is create / setup the index buffer glGenBuffers(1, &bodyIBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bodyIBO); // For constrast, instead of glBufferSubData and glMapBuffer, // we can directly supply the data in one-shot glBufferData(GL_ELEMENT_ARRAY_BUFFER, body_polygoncount*sizeof(GLubyte), body_index, GL_STATIC_DRAW); // Define our data structure int numXYZElements = 3; int numNormalElements = 3; int numTextureCoordElements = 2; long totalXYZBytes; long totalNormalBytes; long totalTexCoordinateBytes; int numBytesPerVertex; // Allocate a new buffer glGenBuffers(1, &bodyVBO); // Bind the buffer object to use glBindBuffer(GL_ARRAY_BUFFER, bodyVBO); // Tally up the size of the data components numBytesPerVertex = numXYZElements; numBytesPerVertex += numNormalElements; numBytesPerVertex += numTextureCoordElements; numBytesPerVertex *= sizeof(GLfloat); // Actually allocate memory on the GPU ( Data is static here ) glBufferData(GL_ARRAY_BUFFER, numBytesPerVertex * body_vertexcount, 0, GL_STATIC_DRAW); // Upload data to the cache ( memory mapping ) GLubyte *vboBuffer = (GLubyte *)glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); // Caclulate the total number of bytes for each data type totalXYZBytes = numXYZElements * body_vertexcount * sizeof(GLfloat); totalNormalBytes = numNormalElements * body_vertexcount * sizeof(GLfloat); totalTexCoordinateBytes = numTextureCoordElements * body_vertexcount * sizeof(GLfloat); // Set the total bytes property for the body self.bodyTotalBytes = totalXYZBytes + totalNormalBytes + totalTexCoordinateBytes; // Setup the copy of the buffer(s) using memcpy() memcpy(vboBuffer, body_vertex, self.bodyTotalBytes); // Perform the actual copy glUnmapBufferOES(GL_ARRAY_BUFFER); 

Here are the drawing commands where I get the exception:

  // Activate the VBOs to draw glBindBuffer(GL_ARRAY_BUFFER, bodyVBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bodyIBO); // Setup drawing glMatrixMode(GL_MODELVIEW); glEnable(GL_TEXTURE_2D); glClientActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D,lightGreyInt); // Setup pointers glVertexPointer(3, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 0 ); glTexCoordPointer(2, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 12 ); glNormalPointer(GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 24 ); // Now draw the body glDrawElements(GL_TRIANGLES, body_polygoncount,GL_UNSIGNED_SHORT, (GLvoid*)((char*)NULL)); //glDrawElements(GL_TRIANGLES, body_polygoncount, GL_UNSIGNED_SHORT, nil); //glDrawElements(GL_TRIANGLES,body_polygoncount*3,GL_UNSIGNED_SHORT,body_index); 
+4
source share
1 answer

Well, first of all, your index buffer is too small, you have not only body_polygoncount indices, but body_polygoncount * 3 indices. You also messed up the type, since they are short, you need GLushort , not GLubyte , so it should be

 glBufferData(GL_ELEMENT_ARRAY_BUFFER, body_polygoncount*3*sizeof(GLushort), body_index, GL_STATIC_DRAW); 

And then you messed up the offsets of your attributes, since your data contains texture coords first, then normal, and then the position for each vertex, it should be

 glVertexPointer(3, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 20 ); //3rd, after 5*4 byte glTexCoordPointer(2, GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 0 ); //1st glNormalPointer(GL_FLOAT, sizeof(vertexStruct), (char *)NULL + 8 ); //2nd, after 2*4 bytes 

And finally, when you call glDrawElements you do not specify the number of triangles, but the number of elements (indices), so it should be

 glDrawElements(GL_TRIANGLES, body_polygoncount*3, GL_UNSIGNED_SHORT, (GLvoid*)((char*)NULL)); 

Otherwise, your code looks reasonable (of course, the mapping was pointless, and you could just use glBufferData again, but I think you did it for training), and if you understand everything it does, there is nothing more.

But I'm curious that all of these errors would also occur if you only used client-side vertex arrays without VBOs, and I thought OpenGL ES 1.1 did not have glBegin/glEnd immediate mode. Therefore, I wonder why your game worked previously without VBOs, if you do not know about these errors.

+3
source

Source: https://habr.com/ru/post/1402035/


All Articles