Showing posts with label python opengl pyglet. Show all posts
Showing posts with label python opengl pyglet. Show all posts

Tuesday, November 06, 2007

Example 2-7: Marking Polygon Boundary Edges

An easy one this, especially since I now have learned how to create and pass suitable arrays to the gl*() functions.

Here's the code:

# Example 2-7 : Marking Polygon Boundary Edges

from pyglet.gl import *
from pyglet import window

# The OpenGL context is created only when you create a window. Any calls
# to OpenGL before a window is created will fail.
win = window.Window()

def display():
# vertices undefined in example
# adding a Z value of 1.0 (simply to remain in sync with the example,
# where glVertex3fv is called,
# i.e. 3 variables are required by the function

v0 = [0.0, 0.0, 1.0]
v1 = [100.0, 100.0, 1.0]
v2 = [150.0, 50.0, 1.0]

glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
glBegin(GL_POLYGON)
glEdgeFlag(GL_TRUE)
glVertex3fv((GLfloat * len(v0))(*v0))
glEdgeFlag(GL_FALSE)
glVertex2fv((GLfloat * len(v1))(*v1))
glEdgeFlag(GL_TRUE)
glVertex2fv((GLfloat * len(v2))(*v2))
glEnd()

def init():
glClearColor (0.0, 0.0, 0.0, 0.0)
glShadeModel (GL_FLAT)

while not win.has_exit:
win.dispatch_events()
win.clear()
display()
win.flip()


One thing to note perhaps is that instead of passing the values directly, we have used a pointer to an array this time.

The Red Book, example 2-6

I had some trouble translating example 2-6 from the red book (the code resides under the enlarged grid, to be found a few lines below this link). But here it is:

from pyglet.gl import *
from pyglet import window

# The OpenGL context is created only when you create a window. Any calls
# to OpenGL before a window is created will fail.
win = window.Window()

def drawOneLine(x1 , y1, x2, y2):
glBegin(GL_LINES)
glVertex2f ((x1),(y1))
glVertex2f ((x2),(y2))
glEnd()

def display():
fly = [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x06, 0xC0, 0x03, 0x60,
0x04, 0x60, 0x06, 0x20, 0x04, 0x30, 0x0C, 0x20,
0x04, 0x18, 0x18, 0x20, 0x04, 0x0C, 0x30, 0x20,
0x04, 0x06, 0x60, 0x20, 0x44, 0x03, 0xC0, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x44, 0x01, 0x80, 0x22, 0x44, 0x01, 0x80, 0x22,
0x66, 0x01, 0x80, 0x66, 0x33, 0x01, 0x80, 0xCC,
0x19, 0x81, 0x81, 0x98, 0x0C, 0xC1, 0x83, 0x30,
0x07, 0xe1, 0x87, 0xe0, 0x03, 0x3f, 0xfc, 0xc0,
0x03, 0x31, 0x8c, 0xc0, 0x03, 0x33, 0xcc, 0xc0,
0x06, 0x64, 0x26, 0x60, 0x0c, 0xcc, 0x33, 0x30,
0x18, 0xcc, 0x33, 0x18, 0x10, 0xc4, 0x23, 0x08,
0x10, 0x63, 0xC6, 0x08, 0x10, 0x30, 0x0c, 0x08,
0x10, 0x18, 0x18, 0x08, 0x10, 0x00, 0x00, 0x08]

halftone = [
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55,
0xAA, 0xAA, 0xAA, 0xAA, 0x55, 0x55, 0x55, 0x55]

glClear (GL_COLOR_BUFFER_BIT)
glColor3f (1.0, 1.0, 1.0)

# draw one solid, unstippled rectangle,
# then two stippled rectangles
glRectf (25.0, 25.0, 125.0, 125.0)
glEnable (GL_POLYGON_STIPPLE)

# convert the data to ctypes:
# Many thanks, Alex! (http://groups.google.be/group/pyglet-users/browse_thread/thread/10e304d4a5e77d97)
# Long version:
# array_type = (GLubyte * len(fly))
# fly = array_type(*fly)
# glPolygonStipple(fly)

# Short version:
glPolygonStipple( (GLubyte * len(fly))(*fly) )

glRectf (125.0, 25.0, 225.0, 125.0)
glPolygonStipple ( (GLubyte * len(halftone))(*halftone))

glRectf (225.0, 25.0, 325.0, 125.0)
glDisable (GL_POLYGON_STIPPLE)

# glFlush() unnecessary, as we call flip() during the main loop.
# glFlush ()

def init():
glClearColor (0.0, 0.0, 0.0, 0.0)
glShadeModel (GL_FLAT)

while not win.has_exit:
win.dispatch_events()
win.clear()
display()
win.flip()

As I have but a fleeting knowledge of how C handles variables, I was at a loss at how to pass an array of unsigned bytes to the glPolygonStipple() function. Help came via the people at the pyglet newsgroup. The solution boils down to (also see the comments in the code above):

  • Defining the array type (GLubyte * lenght of data list)

  • Converting the (elements of the) list to an array of the above defined type

  • Passing this array to the glPolygonStipple() function

As you see in the above code, these three steps can be easily factored into one single line: glPolygonStipple((GLubyte * len(fly))(*fly)).

Monday, November 05, 2007

First steps in OpenGL with Python

I have always wanted to sink my teeth in OpenGL (ever since the days of the first Voodoo graphics cards). It always seemed to be the best tool for graphics programming on the PC (but boy, how I still miss my A1200's blitter chip!).

My main problem has always been my penchant for scripting languages ever since I switched from the Amiga (AmigaE and 68k assembler) to the PC. Which can be translated as: I never learned C, or C++ for that matter.

Python's been my latest love for the last few years now. First as a simple scripting language, then some GUI stuff with Tkinter, later Django came along and now I feel confident enough to tackle OpenGL.

As I started reading the red book (the online version for OpenGL 1.1 can be found here), I tried to convert some of the examples found there to Python, using pyglet (I like its easy way of setting up screens and windows compared to pygame's).

Here's a translation of example 2-5 (found near here):

from pyglet import window
from pyglet.gl import *

def drawOneLine(x1,y1,x2,y2):
glBegin(GL_LINES)
glVertex2f ((x1),(y1))
glVertex2f ((x2),(y2))
glEnd()

def init():
glClearColor (0.0, 0.0, 0.0, 0.0)
glShadeModel (GL_FLAT)

def display():
i = 0

glClear (GL_COLOR_BUFFER_BIT)
# select white for all lines
glColor3f (1.0, 1.0, 1.0)

# in 1st row, 3 lines, each with a different stipple
glEnable (GL_LINE_STIPPLE)

glLineStipple (1, 0x0101) # dotted
drawOneLine (50.0, 125.0, 150.0, 125.0)
glLineStipple (1, 0x00FF) # dashed
drawOneLine (150.0, 125.0, 250.0, 125.0)
glLineStipple (1, 0x1C47) # dash/dot/dash
drawOneLine (250.0, 125.0, 350.0, 125.0)
# in 2nd row, 3 wide lines, each with different stipple
glLineWidth (5.0)
glLineStipple (1, 0x0101) # dotted
drawOneLine (50.0, 100.0, 150.0, 100.0)
glLineStipple (1, 0x00FF) # dashed
drawOneLine (150.0, 100.0, 250.0, 100.0)
glLineStipple (1, 0x1C47) # dash/dot/dash
drawOneLine (250.0, 100.0, 350.0, 100.0)
glLineWidth (1.0)

# in 3rd row, 6 lines, with dash/dot/dash stipple
# as part of a single connected line strip
glLineStipple (1, 0x1C47) # dash/dot/dash

glBegin (GL_LINE_STRIP)
for i in range(0, 7):
glVertex2f (50.0 + (i * 50.0), 75.0)
glEnd ()

# in 4th row, 6 independent lines with same stipple
for i in range(0, 5):
drawOneLine (50.0 + (i * 50.0), 50.0, 50.0 + ((i+1) * 50.0), 50.0)


# in 5th row, 1 line, with dash/dot/dash stipple
# and a stipple repeat factor of 5
glLineStipple (5, 0x1C47) # dash/dot/dash
drawOneLine (50.0, 25.0, 350.0, 25.0)

glDisable (GL_LINE_STIPPLE)

# glFlush ()
# glFlush() is unnecessary, as flip() is called on window (ie double buffered window).

win = window.Window()
init()

while not win.has_exit:
win.dispatch_events()
win.clear()
display()
win.flip()