title: Vertex Buffer Objects in PyOpenGL - vertex, index and colour
body: <p>OSX 10.8.3, Python, PyOpenGL.</p>
  
  <p>I'm trying to put together a basic terrain-drawing function in PyOpenGL using VBOs. Having a couple of problems I don't know how to resolve, mostly because I don't fully understand the way VBOs work. This is a basic test sandbox I started when I had too much difficulty changing my project over to VBOs, so it's sloppy in places (see: frame counter).</p>
  
  <ul>
  <li>I've hardcoded a basic 3x3 terrain array and corresponding index array, but it seems to be only drawing two of three rows (it does the y=0 row and y=0.5 but not y=2.0). I'm not entirely comfortable with numpy, so that might be the cause.</li>
  <li>The contents of the colour array have only erratic bearing on the final colours: assigning numpy.zeros() to the array produces a black screen, assigning numpy.ones() produces green and purple stripes rather than the white surface I'm expecting. Was initially using random colours but that didn't do anything different from ones(). I don't really understand how OpenGL is supposed to determine that this is a color VBO rather than anything else.</li>
  <li>The triangle-drawing algorithm will be problematic, when I get to it - I don't know how best to draw multiple rows without using GL_PRIMITIVE_RESTART, which isn't available in GLUT (I'd rather only change to GLFW or similar as a last resort). Right now, I'm not too concerned about it. Drawing in strips like this isn't quite what I want: http:// www.matrix44.net/cms/notes/opengl-3d-graphics/understanding-gl_triangle_strip (sorry, don't have 10 reputation)</li>
  </ul>
  
  <p>How it currently looks, when rotating: <a href="http://i.imgur.com/4Db4qYJ.png" rel="nofollow">http://i.imgur.com/4Db4qYJ.png</a></p>
  
  <p>Have been using <a href="http://www.mbsoftworks.sk/index.php?page=tutorials&amp;series=1&amp;tutorial=8" rel="nofollow">http://www.mbsoftworks.sk/index.php?page=tutorials&amp;series=1&amp;tutorial=8</a> as my most successful guide.</p>
  
  <p>I'd really appreciate some guidance with this - no single resource I've found on the web has explained it all, and this isn't exactly a complex topic.</p>
  
  <pre><code>from OpenGL.GL import *
  from OpenGL.GLUT import *
  from OpenGL.GLU import *
  from OpenGL.arrays import vbo
  from math import sin, cos, tan, radians, sqrt
  from numpy import *
  from random import random
  
  hWindow = 0
  
  frameno = 0
  sr2 = sqrt(0.75)
  
  def InitGL( nWidth, nHeight ):
      glClearColor( 0.0, 0.0, 0.0, 0.0 )
      glClearDepth( 1.0 )
      glDepthFunc( GL_LESS )
      glEnable( GL_DEPTH_TEST )
      glShadeModel( GL_SMOOTH )
  
      print str(glGetString( GL_VERSION ))
  
      global terrain_vbo, index_vbo, color_vbo
  
      # these two will produce a working (huge) triangle
      #terrain_array = array([[ 0,0,0 ], [ 9,0,0 ], [ 0,9,0 ], [ 0,0,9 ]], dtype=float32)
      #index_array = array([ 0,1, 0,2, 0,3, 2,3, 2,1],dtype=ubyte)
  
  
      terrain_array = array([ [[0,0,0], [0,0,1], [0,0,2]], 
                              [[1,0.5,0], [1,0.5,1], [1,0.5,2]], 
                              [[2,2,0], [2,2,1], [2,2,2]] ], dtype=float32)
  
  
      index_array = array([   0, 3, 1, 4, 2, 5,
                              8, 4, 7, 3, 6 ], dtype=ubyte )
  
      color_array = zeros( (9, 3) )
  
      for i in range(9):
          color_array[i] += (1.0, 1.0, 1.0)
      '''
      color_array[0] = [1.0, 0.0, 0.0]
      color_array[1] = [0.0, 1.0, 0.0]
      color_array[2] = [0.0, 0.0, 1.0]
      color_array[3] = [1.0, 1.0, 1.0]
      color_array[4] = [1.0, 1.0, 0.0]
      '''
      #for i in range(len(terrain_array)):
          #index_array[i][0] = i
      for i in range(len(terrain_array)):
          print terrain_array[i]
  
      terrain_vbo = vbo.VBO(terrain_array)
      #index_vbo = vbo.VBO( zeros((1,3)), target=GL_ELEMENT_ARRAY_BUFFER )
      index_vbo = vbo.VBO(index_array, target=GL_ELEMENT_ARRAY_BUFFER)
      color_vbo = vbo.VBO(color_array)
  
  
      ResizeGLScene( nWidth, nHeight )
  
  
  def ResizeGLScene( nWidth, nHeight ):
      # prevent a divide-by-zero error if the window is too small
      if nHeight == 0:
          nHeight = 1
  
      # reset the current viewport and recalculate the perspective transformation
      # for the projection matrix
      glViewport( 0, 0, nWidth, nHeight )
      glMatrixMode( GL_PROJECTION )
      glLoadIdentity( )
      gluPerspective( 45.0, float( nWidth )/float( nHeight ), 0.1, 100.0 )
  
      # return to the modelview matrix mode
      glMatrixMode( GL_MODELVIEW )
  
  #
  # Draw the scene.
  #
  def DrawGLScene( ):
      # clear the screen and depth buffer
      glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT )
  
      # reset the matrix stack with the identity matrix
      glLoadIdentity( )
  
      global frameno
      frameno = frameno + 1
  
      glTranslatef( 0.0, -0.2, -2.0 )
  
      glRotatef( frameno/6, 0.0, sr2, 0.0 )
  
      # draw code
      #glTranslatef( 0.0, 0.0, -3.0 )
      glScalef( 0.5, 0.5, 0.5 )
      glColor3f( 1.0, 1.0, 1.0 )
  
  
      global index_vbo, terrain_vbo, color_vbo
  
      color_vbo.bind()
      glEnableClientState( GL_COLOR_ARRAY )
      glColorPointer( 3, GL_FLOAT, 0, color_vbo )
  
      terrain_vbo.bind()
      glEnableClientState(GL_VERTEX_ARRAY)
      glVertexPointer( 3, GL_FLOAT, 0, None )
  
      index_vbo.bind()
  
      glDrawElements(GL_TRIANGLE_STRIP, 6, GL_UNSIGNED_BYTE,None)
  
      glDisableClientState( GL_COLOR_ARRAY )
      glDisableClientState( GL_VERTEX_ARRAY )
  
      index_vbo.unbind()
      terrain_vbo.unbind()
      color_vbo.unbind()
  
      glutSwapBuffers( )
  
  def KeyPressed( key, x, y ):
      key = ord(key)
  
      if key == 27:
          glutDestroyWindow( hWindow )
          sys.exit( )
  
  def main( ):
      global hWindow
  
      # initialise GLUT and a few other things
      glutInit( "" )
      glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA | GLUT_DEPTH )
      glutInitWindowSize( 640, 480 )
      glutInitWindowPosition( 0, 0 )
  
      # create our window
      hWindow = glutCreateWindow( "VBO testing" )
  
      # setup the display function callback
      glutDisplayFunc( DrawGLScene )
  
      # go full-screen if we want to
      glutFullScreen( )
  
      # setup the idle function callback -- if we idle, we just want to keep
      # drawing the screen
      glutIdleFunc( DrawGLScene )
      # setup the window resize callback -- this is only needed if we arent going
      # full-screen
      glutReshapeFunc( ResizeGLScene )
      # setup the keyboard function callback to handle key presses
      glutKeyboardFunc( KeyPressed )
  
      # call our init function
      InitGL( 640, 480 )
  
      # enter the window's main loop to set things rolling
      glutMainLoop( )
  
  
  print "Hit ESC key to quit."
  main( )
  </code></pre>