Blogs  Python  Flash  Windows C++ 

October 25 2014

Lapmaster Download Path Finding 
Rocketeer Online
 Elite, The New Kind

Python, Pygame, and PyOpenGL 

July 23 2019 
Python is an interpretive programming language that is easy to learn and use. With pygame, you can get control of the display using a straightforward well documented interface. Pygame is primarily a 2D graphics tool. It allows you to open a window, display images, draw lines and polygons, including shaded polygons upon the screen. It does not provide functions to perform line clipping, texturing, or projection of a 3d object onto the screen. You could conceivably write python code to perform all these functions, but not only would it be a lot of code, performance would suffer since 3d graphics involves a lot of computation and python is too slow for that level of arithmetical manipulation. With PyOpenGL, however, the amount of additional code required to do 3D graphics is greatly reduced and performance is enhanced enormously by moving most of the cpu intensive computational work from the cpu to the graphics card.
This means that you can write some very complex 3D video games in python and still achieve frame rates of 30 fps or better. There are alot of tutorials available for beginners on opengl. First they show you how to draw lines, then how to move the camera, then how to shade surfaces with vertex colors. A lot of beginner tutorials stop here, but to make really cool graphics ou need to be able to apply texures to your solid objects. So this is my beginners tutorial on that subject.
Basic questions: Here is a python program to draw a square on the screen using pygame and pyopengl. The square is assumed to be 40 feet long and 24 feet wide. The camera is looking along the minus z axis (into the screen) from a height of 4 feet above the square. The up and down keys move the square forward and back relative to the observer. import pygame, OpenGL from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import * import time pygame.init() pygame.display.set_mode((640,480), DOUBLEBUFOPENGL) # x positive right # y positive up # z positive back lanewidth = 12 # typical roadway lanes are 12 feet wide height = 4 # height of camera above roadway aspect = 1.0 # aspect ratio (width/height) length = 40 # length of a section of roadway vertices = ( (lanewidth,height,0), (lanewidth,height,length), (lanewidth,height,length), (lanewidth,height,0) ) # function to draw a line between a pair of vertices at location x,y,z def line(n,m,x,y,z): (x1,y1,z1) = vertices[n] (x2,y2,z2) = vertices[m] glVertex3f(x1+x,y1+y,z1+z) glVertex3f(x2+x,y2+y,z2+z) def slab(z): glLineWidth(2) glBegin(GL_LINES) line(0,1,x,y,z) line(1,2,x,y,z) line(2,3,x,y,z) line(3,0,x,y,z) glEnd() clock = pygame.time.Clock() (x,y,z) = (0,0,10) twait = 0 tstart = time.time() i = 0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: tstop = time.time() elapsed = tstoptstart print 'elapsed time = ',elapsed print 'wait time = ',twait print 'pct free = ',100*twait/elapsed exit() # pygame.quit() elif event.type == KEYDOWN: if event.key == K_UP: i = i + 1 print i,i*length elif event.key == K_DOWN: i = i  1 print i,i*length glLoadIdentity() gluPerspective(45,aspect,1,1000) glClear(GL_COLOR_BUFFER_BITGL_DEPTH_BUFFER_BIT) glTranslate(0,height,0) # for i in range(500): # slab(i*length) slab(i*length) pygame.display.flip() t1 = time.time() clock.tick(30) t2 = time.time() twait = twait + t2t1 # print z The display screen shows:
Pressing the up arrow move the square forty feet away from the camera and you see this.
As you move the square forward it gets smaller and smaller due to perspective. The clipping region for the camera is set to 1000 so if you push it out beyond that distance, the square disappears.
Next, here is a program to display a textured square on the screen.
import pygame, OpenGL from pygame.locals import * from OpenGL.GL import * from OpenGL.GLU import * import time pygame.init() pygame.display.set_mode((640,480), DOUBLEBUFOPENGL) img = pygame.image.load('image1.png') textureData =pygame.image.tostring(img,"RGB",1) width = img.get_width() height = img.get_height() im = glGenTextures(1) glBindTexture(GL_TEXTURE_2D,im) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, textureData) glEnable(GL_TEXTURE_2D) # x positive right # y positive up # z positive back lanewidth = 12 # typical roadway lanes are 12 feet wide height = 4 # height of camera above roadway aspect = 1.0 # aspect ratio (width/height) length = 40 # length of a section of roadway vertices = ( (lanewidth,height,0), (lanewidth,height,length), (lanewidth,height,length), (lanewidth,height,0) ) # Draw a shaded polygon def centerline(x,y,z): glLineWidth(2) glBegin(GL_LINES) glColor3f(1,1,1) (x1,y1,z1) = (0,height,z40) glVertex3f(x1,y1,z1) (x2,y2,z2) = (0,height,z30) glVertex3f(x2,y2,z2) glEnd() def slab(x,y,z): glBegin(GL_QUADS) glTexCoord2f(0,0) glVertex3f(lanewidth,height,z) glTexCoord2f(0,1) glVertex3f(lanewidth,height,length+z) glTexCoord2f(1,1) glVertex3f(lanewidth,height,length+z) glTexCoord2f(1,0) glVertex3f(lanewidth,height,z) glEnd() clock = pygame.time.Clock() (x,y,z) = (0,0,10) twait = 0 tstart = time.time() i = 0 while True: for event in pygame.event.get(): if event.type == pygame.QUIT: tstop = time.time() elapsed = tstoptstart print 'elapsed time = ',elapsed print 'wait time = ',twait print 'pct free = ',100*twait/elapsed exit() # pygame.quit() elif event.type == KEYDOWN: if event.key == K_UP: i = i + 1 print i,i*length elif event.key == K_DOWN: i = i  1 print i,i*length glLoadIdentity() gluPerspective(45,aspect,1,1000) glClear(GL_COLOR_BUFFER_BITGL_DEPTH_BUFFER_BIT) glTranslate(0,height,0) # for i in range(500): # slab(i*length) slab(x,y,i*length) pygame.display.flip() t1 = time.time() clock.tick(30) t2 = time.time() twait = twait + t2t1 # print z The display screen shows:
If you press the up arrow to move the slab away from the camera, you see this:

Return to Main Page 