title: iPhone Cheetah 3D OpenGL ES Vertex Buffer Object (VBO) Example
body: <p>I'd like to use Vertex Buffer Objects (VBOs) to improved my rendering of somewhat complicated models in my Open GL ES 1.1 game for iPhone. After reading several posts on SO and this (http://playcontrol.net/ewing/jibberjabber/opengl_vertex_buffer_object.html) tutorial, I'm still having trouble understanding VBOs and how to implement them given my Cheetah 3D export model format. Could someone please give me an example of implementing a VBO and using it to draw my vertices with the given data structure and explain the syntax? I greatly appreciate any help!</p>
  
  <pre><code>#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}
  }
  </code></pre>
  
  <p>I've written the following code with the help of Chapter 9 from Pro OpenGL ES (Appress). I'm getting EXC_BAD_ACCESS with the DrawElements command and I'm not sure why. Could someone please shed some light? Thanks -</p>
  
  <pre><code>// First thing we do is create / setup the index buffer
  glGenBuffers(1, &amp;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, &amp;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);
  </code></pre>
  
  <p>Here are the drawing commands where I'm getting the exception:</p>
  
  <pre><code>    // 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);
  </code></pre>