Lesson 11 NeHe as Pygame OpenGL

```#!/usr/bin/env python
# pygame + PyOpenGL version of Nehe's OpenGL lesson11

# Paul Furber 2001 - m@verick.co.za

# Extended by Paul Mohr to lesson 11 NeHe in Python March 2009

#// This code was created by Jeff Molofee '99 (ported to Linux/GLUT by Richard Campbell '99)
#//
#// If you've found this code useful, please let me know.
#//
#// Visit Jeff Molofee at www.demonews.com/hosted/nehe
#// (email Richard Campbell at ulmont@bellsouth.net)
#//

import os, random
from string import split
from math import sin, cos
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame, pygame.image, pygame.key
from pygame.locals import *
rangy=40

points = [[[0.0 for x in range(3)] for x in range(rangy)] for x in range (rangy)]

textures = []
filter = 0 #Specifies the selection of images from a set of 4

xpos = 0.0
zpos = 0.0

xrot = 0.3
yrot = 0.0
zrot = 0.0
wiggle_count = 0

lookupdown = 0.0
walkbias = 0.0
walkbiasangle = 0.0

LightAmbient  = [ 0.5, 0.5, 0.5, 1.0]
LightDiffuse  = [ 1.0, 1.0, 1.0, 1.0]
LightPosition = [ 0.0, 0.0, 2.0, 1.0]

piover180 = 0.0174532925

def resize((width, height)):
if height==0:
height=1.0
glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION)
gluPerspective(45, float(width)/height, 0.1, 100.0)
glMatrixMode(GL_MODELVIEW)

def init():
global lookupdown, walkbias, walkbiasangle
glEnable(GL_TEXTURE_2D)
glClearColor(0.0, 0.0, 0.0, 0.0)
glClearDepth(1.0)
glEnable(GL_DEPTH_TEST)
glDepthFunc(GL_LEQUAL)
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient )
glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse )
glLightfv( GL_LIGHT1, GL_POSITION, LightPosition )
glEnable( GL_LIGHT1 )
lookupdown    = 0.0
walkbias      = 0.0
walkbiasangle = 0.0
glColor4f( 1.0, 1.0, 1.0, 0.5)
xrot=0.0
yrot=0.0
zrot=0.0

def fill_array():
global points
float_x = 0.0
float_y = 0.0
while  float_x < (float) (rangy/5.1):
while float_y < (float) (rangy/5.0):
points[ int (float_x*5.0) ][ int (float_y*5.0) ][0] = float_x - 4.4;
points[ int (float_x*5.0) ][ int (float_y*5.0) ][1] = float_y - 4.4;
points[ int (float_x*5.0) ][ int (float_y*5.0) ][2] = \
(float) (sin( ( (float_x*5.0*20.0)/360.0 ) * 3.14159 * 2.0 ));
float_y += (float) (1.0/rangy)
float_x +=  (float) (1.0/rangy)
float_y = 0.0

global textures
texturefile = os.path.join('data','texture1.png')
textureData = pygame.image.tostring(textureSurface, "RGBX", 1)
texturefile = os.path.join('data','texture2.bmp')
textureData2 = pygame.image.tostring(textureSurface2, "RGBX", 1)
texturefile = os.path.join('data','texture3.png')
textureData3 = pygame.image.tostring(textureSurface3, "RGBX", 1)
texturefile = os.path.join('data','texture4.bmp')
textureData = pygame.image.tostring(textureSurface, "RGBX", 1)
textures = glGenTextures(3)
glBindTexture(GL_TEXTURE_2D, textures[0])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface.get_width(), textureSurface.get_height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, textureData )
glBindTexture(GL_TEXTURE_2D, textures[1])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface2.get_width(), textureSurface2.get_height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, textureData2 )
glBindTexture(GL_TEXTURE_2D, textures[2])
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, textureSurface3.get_width(), textureSurface3.get_height(), 0,
GL_RGBA, GL_UNSIGNED_BYTE, textureData3 )
gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, textureSurface3.get_width(), textureSurface3.get_height(),
GL_RGBA, GL_UNSIGNED_BYTE, textureData3 );

def drawWave():
global xrot, zrot, yrot, wiggle_count
global points
glPolygonMode( GL_BACK, GL_FILL )
glPolygonMode( GL_FRONT, GL_LINE )
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glTranslatef(0.0,0.0,-12.0)
glRotatef(xrot,1.0,0.0,0.0)
glRotatef(yrot,0.0,1.0,0.0)
glRotatef(zrot,0.0,0.0,1.0)
glBindTexture(GL_TEXTURE_2D, textures[filter])
x=0
while x < (rangy-1):
y=0
while y < (rangy-1):
float_x = float(x)/44.0
float_y = float(y)/44.0
float_xb = float(x+1)/44.0
float_yb = float(y+1)/44.0
glTexCoord2f( float_x, float_y)
glVertex3f( points[x][y][0], points[x][y][1], points[x][y][2] )
glTexCoord2f( float_x, float_yb )
glVertex3f( points[x][y+1][0], points[x][y+1][1], points[x][y+1][2] )
glTexCoord2f( float_xb, float_yb )
glVertex3f( points[x+1][y+1][0], points[x+1][y+1][1], points[x+1][y+1][2] )
glTexCoord2f( float_xb, float_y )
glVertex3f( points[x+1][y][0], points[x+1][y][1], points[x+1][y][2] )
y+=1
x+=1
glEnd()
y=0
x=0
if( wiggle_count == 2 ):
while  y < (rangy-1):
hold=points[0][y][2]
while x < (rangy-1):
points[x][y][2] = points[x+1][y][2]
x+=1
x=0
points[rangy-1][y][2]=hold
y +=1
wiggle_count = 0
wiggle_count +=1
xrot+=0.3
yrot+=0.2
# zrot+=0.4
return 0

def handle_keys(key):
global xpos, zpos, yrot, filter
global piover180, walkbiasangle, walkbias

if key==K_ESCAPE:
return 0

if key==K_f:
filter +=1
if filter == 3:
filter = 0
if key==K_RIGHT:
yrot -= 11.5
if key==K_LEFT:
yrot += 11.5
if key==K_UP:
xpos -= sin( yrot * piover180 ) * 0.3105
zpos -= cos( yrot * piover180 ) * 0.3105
if ( walkbiasangle >= 359.0 ):
walkbiasangle = 0.0
else:
walkbiasangle += 10.0
walkbias = sin( walkbiasangle * piover180 ) / 20.0
if key==K_DOWN:
xpos += sin( yrot * piover180 ) * 0.3105
zpos += cos( yrot * piover180 ) * 0.3105
if ( walkbiasangle <= 1.0 ):
walkbiasangle = 359.0
else:
walkbiasangle -= 10.0
walkbias = sin( walkbiasangle * piover180 ) / 20.0

return 1

def main():
global surface
video_flags = OPENGL|DOUBLEBUF
pygame.init()
surface = pygame.display.set_mode((1024,768), video_flags)
pygame.key.set_repeat(100,0)
random.seed()
resize((1024,768))
init()
fill_array()
frames = 0
done = 0
ticks = pygame.time.get_ticks()
while not done:
while 1:
event = pygame.event.poll()
if event.type == NOEVENT:
break
if event.type == KEYDOWN:
if handle_keys(event.key) == 0:
done = 1
if event.type == QUIT:
done = 1
drawWave()
pygame.display.flip()
frames += 1
print "fps:  %d" % ((frames*1000)/(pygame.time.get_ticks()-ticks))
if __name__ == '__main__': main()
```

This should be intuitive to a python user and I have played with the concept a little to allow changes in the granularity and speed.