Statistics
| Revision:

root / PyOpenGL-Demo / NeHe / lesson18.py @ 1

History | View | Annotate | Download (11.3 kB)

1
#!
2

    
3
# This is statement is required by the build system to query build info
4
if __name__ == '__build__':
5
        raise Exception
6

    
7
import string
8
__version__ = string.split('$Revision: 1.1.1.1 $')[1]
9
__date__ = string.join(string.split('$Date: 2007/02/15 19:25:20 $')[1:3], ' ')
10
__author__ = 'Tarn Weisner Burton <twburton@users.sourceforge.net>'
11

    
12
#
13
# Ported to PyOpenGL 2.0 by Tarn Weisner Burton 10May2001
14
#
15
# This code was created by Richard Campbell '99 (ported to Python/PyOpenGL by John Ferguson 2000)
16
#
17
# The port was based on the lesson5 tutorial module by Tony Colston (tonetheman@hotmail.com).  
18
#
19
# If you've found this code useful, please let me know (email John Ferguson at hakuin@voicenet.com).
20
#
21
# See original source and C based tutorial at http:#nehe.gamedev.net
22
#
23
# Note:
24
# -----
25
# Now, I assume you've read the prior tutorial notes and know the deal here.  The one major, new requirement
26
# is to have a working version of PIL (Python Image Library) on your machine.
27
#
28
# General Users:
29
# --------------
30
# I think to use textures at all you need Nunmeric Python, I tried without it and BAM Python didn't "like" the texture API.
31
#
32
# Win32 Users:
33
# ------------
34
# Well, here's the install I used to get it working:
35
# [1] py152.exe - include the TCL install!
36
# [2] PyOpenGL.EXE - probably the latest, the Vaults notes should give you a clue.
37
# [3] Distutils-0.9.win32.exe for step #4
38
# [4] Numerical-15.3.tgz - run the setup.py (need VC++ on your machine, otherwise, have fun with #3, it looks fixable to use gCC).
39
#
40
# Win98 users (yes Win98, I have Mandrake on the other partition okay?), you need to the Tcl bin directory in your PATH, not PYTHONPATH,
41
# just the DOS PATH.
42
#
43
# BTW, since this is Python make sure you use tabs or spaces to indent, I had numerous problems since I 
44
# was using editors that were not sensitive to Python.
45
#
46
from OpenGL.GL import *
47
from OpenGL.GLUT import *
48
from OpenGL.GLU import *
49
import sys
50
from Image import *
51

    
52
# Some api in the chain is translating the keystrokes to this octal string
53
# so instead of saying: ESCAPE = 27, we use the following.
54
ESCAPE = '\033'
55

    
56
# Number of the glut window.
57
window = 0
58

    
59
# Rotations for cube. 
60
xrot = yrot = zrot = 0.0
61

    
62
texture_num = 2
63
object = 0
64
light = 0
65

    
66
def LoadTextures():
67
        global texture_num, textures
68
        image = open("Wall.bmp")
69
        
70
        ix = image.size[0]
71
        iy = image.size[1]
72
        image = image.tostring("raw", "RGBX", 0, -1)
73
        
74
        # Create Texture
75
        textures = glGenTextures(3)
76
        glBindTexture(GL_TEXTURE_2D, int(textures[0]))   # 2d texture (x and y size)
77
        
78
        glPixelStorei(GL_UNPACK_ALIGNMENT,1)
79
        glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
80
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
81
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
82
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
83
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
84
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
85
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
86
        glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL)
87

    
88
        # Create Linear Filtered Texture 
89
        glBindTexture(GL_TEXTURE_2D, int(textures[1]))
90
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
91
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
92
        glTexImage2D(GL_TEXTURE_2D, 0, 3, ix, iy, 0, GL_RGBA, GL_UNSIGNED_BYTE, image)
93

    
94
        # Create MipMapped Texture
95
        glBindTexture(GL_TEXTURE_2D, int(textures[2]))
96
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
97
        glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_NEAREST)
98
        gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ix, iy, GL_RGBA, GL_UNSIGNED_BYTE, image)
99

    
100

    
101

    
102
# A general OpenGL initialization function.  Sets all of the initial parameters. 
103
def InitGL(Width, Height):                                # We call this right after our OpenGL window is created.
104
        global quadratic
105
        
106
        LoadTextures()
107

    
108
        quadratic = gluNewQuadric()
109
        gluQuadricNormals(quadratic, GLU_SMOOTH)                # Create Smooth Normals (NEW) 
110
        gluQuadricTexture(quadratic, GL_TRUE)                        # Create Texture Coords (NEW) 
111
 
112
        glEnable(GL_TEXTURE_2D)
113
        glClearColor(0.0, 0.0, 0.0, 0.0)        # This Will Clear The Background Color To Black
114
        glClearDepth(1.0)                                        # Enables Clearing Of The Depth Buffer
115
        glDepthFunc(GL_LESS)                                # The Type Of Depth Test To Do
116
        glEnable(GL_DEPTH_TEST)                                # Enables Depth Testing
117
        glShadeModel(GL_SMOOTH)                                # Enables Smooth Color Shading
118
        
119
        glMatrixMode(GL_PROJECTION)
120
        glLoadIdentity()                                        # Reset The Projection Matrix
121
                                                                                # Calculate The Aspect Ratio Of The Window
122
        gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
123

    
124
        glMatrixMode(GL_MODELVIEW)
125

    
126
        glLightfv(GL_LIGHT0, GL_AMBIENT, (0.5, 0.5, 0.5, 1.0))                # Setup The Ambient Light 
127
        glLightfv(GL_LIGHT0, GL_DIFFUSE, (1.0, 1.0, 1.0, 1.0))                # Setup The Diffuse Light 
128
        glLightfv(GL_LIGHT0, GL_POSITION, (0.0, 0.0, 2.0, 1.0))        # Position The Light 
129
        glEnable(GL_LIGHT0)                                        # Enable Light One 
130

    
131

    
132

    
133
# The function called when our window is resized (which shouldn't happen if you enable fullscreen, below)
134
def ReSizeGLScene(Width, Height):
135
        if Height == 0:                                                # Prevent A Divide By Zero If The Window Is Too Small 
136
                Height = 1
137

    
138
        glViewport(0, 0, Width, Height)                # Reset The Current Viewport And Perspective Transformation
139
        glMatrixMode(GL_PROJECTION)
140
        glLoadIdentity()
141
        gluPerspective(45.0, float(Width)/float(Height), 0.1, 100.0)
142
        glMatrixMode(GL_MODELVIEW)
143

    
144

    
145
def DrawCube():
146
        glBegin(GL_QUADS)                                # Start Drawing The Cube
147
        
148
        # Front Face (note that the texture's corners have to match the quad's corners)
149
        glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0,  1.0)        # Bottom Left Of The Texture and Quad
150
        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0,  1.0)        # Bottom Right Of The Texture and Quad
151
        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0,  1.0)        # Top Right Of The Texture and Quad
152
        glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0,  1.0)        # Top Left Of The Texture and Quad
153
        
154
        # Back Face
155
        glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0)        # Bottom Right Of The Texture and Quad
156
        glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0, -1.0)        # Top Right Of The Texture and Quad
157
        glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0, -1.0)        # Top Left Of The Texture and Quad
158
        glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0, -1.0)        # Bottom Left Of The Texture and Quad
159
        
160
        # Top Face
161
        glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0)        # Top Left Of The Texture and Quad
162
        glTexCoord2f(0.0, 0.0); glVertex3f(-1.0,  1.0,  1.0)        # Bottom Left Of The Texture and Quad
163
        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0,  1.0,  1.0)        # Bottom Right Of The Texture and Quad
164
        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0)        # Top Right Of The Texture and Quad
165
        
166
        # Bottom Face           
167
        glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0)        # Top Right Of The Texture and Quad
168
        glTexCoord2f(0.0, 1.0); glVertex3f( 1.0, -1.0, -1.0)        # Top Left Of The Texture and Quad
169
        glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0)        # Bottom Left Of The Texture and Quad
170
        glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0)        # Bottom Right Of The Texture and Quad
171
        
172
        # Right face
173
        glTexCoord2f(1.0, 0.0); glVertex3f( 1.0, -1.0, -1.0)        # Bottom Right Of The Texture and Quad
174
        glTexCoord2f(1.0, 1.0); glVertex3f( 1.0,  1.0, -1.0)        # Top Right Of The Texture and Quad
175
        glTexCoord2f(0.0, 1.0); glVertex3f( 1.0,  1.0,  1.0)        # Top Left Of The Texture and Quad
176
        glTexCoord2f(0.0, 0.0); glVertex3f( 1.0, -1.0,  1.0)        # Bottom Left Of The Texture and Quad
177
        
178
        # Left Face
179
        glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0)        # Bottom Left Of The Texture and Quad
180
        glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0,  1.0)        # Bottom Right Of The Texture and Quad
181
        glTexCoord2f(1.0, 1.0); glVertex3f(-1.0,  1.0,  1.0)        # Top Right Of The Texture and Quad
182
        glTexCoord2f(0.0, 1.0); glVertex3f(-1.0,  1.0, -1.0)        # Top Left Of The Texture and Quad
183
        
184
        glEnd();                                # Done Drawing The Cube
185

    
186

    
187
# The main drawing function. 
188
def DrawGLScene():
189
        global xrot, yrot, zrot, textures, texture_num, object, quadratic, light
190

    
191
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)        # Clear The Screen And The Depth Buffer
192
        glLoadIdentity()                                        # Reset The View
193
        glTranslatef(0.0,0.0,-5.0)                        # Move Into The Screen
194

    
195
        glRotatef(xrot,1.0,0.0,0.0)                        # Rotate The Cube On It's X Axis
196
        glRotatef(yrot,0.0,1.0,0.0)                        # Rotate The Cube On It's Y Axis
197
        glRotatef(zrot,0.0,0.0,1.0)                        # Rotate The Cube On It's Z Axis
198
        
199
        glBindTexture(GL_TEXTURE_2D, int(textures[texture_num]))
200

    
201
        if light:
202
                glEnable(GL_LIGHTING)
203
        else:
204
                glDisable(GL_LIGHTING)
205

    
206
        if object == 0:
207
                DrawCube()
208
        elif object == 1:
209
                glTranslatef(0.0,0.0,-1.5)                        # Center The Cylinder 
210
                gluCylinder(quadratic,1.0,1.0,3.0,32,32)        # A Cylinder With A Radius Of 0.5 And A Height Of 2 
211
        elif object == 2:
212
                gluDisk(quadratic,0.5,1.5,32,32)
213
                # Draw A Disc (CD Shape) With An 
214
                # Inner Radius Of 0.5, And An 
215
                # Outer Radius Of 2.  Plus A Lot Of Segments  
216
        elif object == 3:
217
                gluSphere(quadratic,1.3,32,32) # Draw A Sphere With A Radius Of 1 And 16 Longitude And 16 Latitude Segments 
218
        elif object == 4:
219
                glTranslatef(0.0,0.0,-1.5)                        # Center The Cone
220
                # A Cone With A Bottom Radius Of .5 And A Height Of 2 
221
                gluCylinder(quadratic,1.0,0.0,3.0,32,32)        
222
        elif object == 5:
223
                gluPartialDisk(quadratic,0.5,1.5,32,32,0,300)        # A Disk Like The One Before 
224
        elif object == 6:
225
                glutSolidTeapot(1.0)
226

    
227
        xrot  = xrot + 0.2                                # X rotation
228
        yrot = yrot + 0.2                                 # Y rotation
229
        zrot = zrot + 0.2                                 # Z rotation
230

    
231
        #  since this is double buffered, swap the buffers to display what just got drawn. 
232
        glutSwapBuffers()
233

    
234

    
235
# The function called whenever a key is pressed
236
def keyPressed(key, x, y):
237
        global object, texture_num, light
238
        # If escape is pressed, kill everything.
239
        key = string.upper(key)
240
        if key == ESCAPE:
241
                sys.exit()
242
        elif key == 'L':
243
                light = not light
244
        elif key == 'T': #  switch the texture
245
                texture_num = (texture_num + 1) % 3
246
        elif key == 'O': #  switch the object
247
                object = (object + 1) % 7
248

    
249

    
250
def main():
251
        usage = """Press L to toggle Lighting
252
Press T to change textures
253
Press O to change objects"""
254
        print usage
255
        global window
256
        glutInit(sys.argv)
257

    
258
        # Select type of Display mode:   
259
        #  Double buffer 
260
        #  RGBA color
261
        # Alpha components supported 
262
        # Depth buffer
263
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
264
        
265
        # get a 640 x 480 window 
266
        glutInitWindowSize(640, 480)
267
        
268
        # the window starts at the upper left corner of the screen 
269
        glutInitWindowPosition(0, 0)
270
        
271
        # Okay, like the C version we retain the window id to use when closing, but for those of you new
272
        # to Python (like myself), remember this assignment would make the variable local and not global
273
        # if it weren't for the global declaration at the start of main.
274
        window = glutCreateWindow("Jeff Molofee's GL Code Tutorial ... NeHe '99")
275

    
276
           # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
277
        # set the function pointer and invoke a function to actually register the callback, otherwise it
278
        # would be very much like the C version of the code.        
279
        glutDisplayFunc(DrawGLScene)
280
        
281
        # Uncomment this line to get full screen.
282
        # glutFullScreen()
283

    
284
        # When we are doing nothing, redraw the scene.
285
        glutIdleFunc(DrawGLScene)
286
        
287
        # Register the function called when our window is resized.
288
        glutReshapeFunc(ReSizeGLScene)
289
        
290
        # Register the function called when the keyboard is pressed.  
291
        glutKeyboardFunc(keyPressed)
292

    
293
        # Initialize our window. 
294
        InitGL(640, 480)
295

    
296
        # Start Event Processing Engine        
297
        glutMainLoop()
298

    
299

    
300
# Print message to console, and kick off the main to get it rolling.
301
print "Hit ESC key to quit."
302
main()
303