Saturday 24 November 2007

"With" statement comes handy with OpenGL

OpenGL programming in python may be painful in some situations. The reason for that is openGL's specific interface. Let me show you:

// C code that draws a triangle
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glEnd();


# the same code in python
glBegin(GL_TRIANGLES)
glVertex3f( 0, 1, 0)
glVertex3f(-1, -1, 0)
glVertex3f( 1, -1, 0)
glEnd()

Now we can make this code a bit clearer using the 'with' statement. Let's wrap glBegin and make it return a context which calls glEnd() after exiting the 'with' block. Having done that, we can write

# python code that draws a triangle
with glBegin(GL_TRIANGLES):
glVertex3f( 0, 1, 0)
glVertex3f(-1, -1, 0)
glVertex3f( 1, -1, 0)

Implementing such behaviour is very easy

from pyglet import gl as pyglet_gl

class GlEndCallingContext(object):
def __enter__(*_): pass
def __exit__(*_): pyglet_gl.glEnd()

def glBegin(*args):
pyglet_gl.glBegin(*args)
return GlEndCallingContext()

In fact, we can go even further and make all glFunctions return some dummy context. We could then add indentation after functions that don't need closing, just in case the overall view of the code should benefit:

with glColorf3(1, 0, 0):
glVertexf(0, 0, 0)
...

I implemented first 5 nehe tutorials in that way, using a wonderful pyglet library.

No comments: