NeHe Translations: OpenGLContext Timers (NeHe 6 Based)
#! /usr/bin/env python
from OpenGLContext import testingcontext
BaseContext = testingcontext.getInteractive()
from OpenGL.GL import *
from OpenGLContext.arrays import array
import string
from OpenGLContext.events.timer import Timer
from OpenGLContext import texture
class TestContext( BaseContext ):
"""Timer-based control of animation (OpenGLContext timers)
"""
initialPosition = (0,0,0)
drawPollTimeout = 0.01
def OnInit( self ):
"""Load the image on initial load of the application"""
self.image = self.loadImage ()
print """You should see a slowly rotating textured cube
The animation is provided by a timer, rather than the
crude time-module based animation we use for the other
NeHe tutorials."""
print ' <r> reverse the time-sequence'
print ' <s> make time pass more slowly'
print ' <f> make time pass faster'
Here we will register key-press handlers for the various
operations the user can perform.
self.addEventHandler( "keypress", name="r", function = self.OnReverse)
self.addEventHandler( "keypress", name="s", function = self.OnSlower)
self.addEventHandler( "keypress", name="f", function = self.OnFaster)
We'll create a Timer object. The duration is the total
cycle length for the timer, the repeating flag tells the
timer to continue running.
self.time = Timer( duration = 8.0, repeating = 1 )
The timer generates events for "fractions" as well as for
cycles. We use the fraction value to generate a smooth
animation.
self.time.addEventHandler( "fraction", self.OnTimerFraction )
Registering and starting the timer are only necessary because
the node is not part of a scenegraph.
self.time.register (self)
self.time.start ()
As with the time.time() mechanism, we need to track our
current rotation so that the rendering pass can perform the
rotation calculated by the timer callback.
self.rotation = 0
Timer callback
def OnTimerFraction( self, event ):
self.rotation = event.fraction()* -360
Keyboard callbacks. Each of these simply modifies the timer's
internal-timer multiplier. Each Timer node has an internal timer
which provides the low-level events that the timer interprets. By
changing the multiplier on this internal timer we change the
perceived passage of time for the user.
def OnReverse( self, event ):
self.time.internal.multiplier = -self.time.internal.multiplier
print "reverse",self.time.internal.multiplier
def OnSlower( self, event ):
self.time.internal.multiplier = self.time.internal.multiplier /2.0
print "slower",self.time.internal.multiplier
def OnFaster( self, event ):
self.time.internal.multiplier = self.time.internal.multiplier * 2.0
print "faster",self.time.internal.multiplier
def Render( self, mode):
"""Render scene geometry"""
BaseContext.Render( self, mode )
glDisable( GL_LIGHTING) # context lights by default
glTranslatef(1.5,0.0,-6.0);
glRotated( self.rotation, 1,0,0)
glRotated( self.rotation, 0,1,0)
glRotated( self.rotation, 0,0,1)
self.setupTexture()
self.drawCube()
def loadImage( self, imageName = "nehe_wall.bmp" ):
"""Load an image file as a 2D texture using PIL
"""
try:
from PIL.Image import open
except ImportError, err:
from Image import open
im = texture.Texture( open(imageName) )
return im
def setupTexture( self ):
# texture-mode setup, was global in original
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
self.image()
def drawCube( self ):
"""Draw a cube with texture coordinates"""
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, 1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0);
glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0);
glTexCoord2f(1.0, 1.0); glVertex3f( 1.0, 1.0, -1.0);
glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, 1.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, 1.0);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0);
glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0);
glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0);
glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0);
glEnd()
if __name__ == "__main__":
TestContext.ContextMainLoop()
Author:
Jeff Molofee (aka NeHe)
COPYRIGHT AND DISCLAIMER: (c)2000 Jeff Molofee
If you plan to put this program on your web page or a cdrom of
any sort, let me know via email, I'm curious to see where
it ends up :)
If you use the code for your own projects please give me
credit, or mention my web site somewhere in your program
or it's docs.
OpenGLContext Timers (NeHe 6 Based)