Statistics
| Revision:

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

History | View | Annotate | Download (9.3 kB)

1
#! /usr/bin/env python
2
# -*- coding: utf8 -*-
3
"""Port of NeHe Lesson 19 by Ivan Izuver <izuver@users.sourceforge.net>
4

5
port NeHe tutorials from C\C++ to Python  
6
"""
7
from OpenGL.GL import *
8
from OpenGL.GLUT import *
9
from OpenGL.GLU import *
10
from Image import *
11
import sys,random
12

    
13
ESCAPE = '\033'
14

    
15
# global particles settings
16
MAX_PARTICLES=1000 # Number of particles create.
17
SPEED_PARTICLES=2.0 # particles speed
18
XSPEED=0.0 # speed OX
19
YSPEED=0.0 # speed OY
20
ZOOM=-30.0# zoom
21
LOOP=0 # loop particles
22
DELAY=0 # delay
23

    
24
# particle struct
25
class particle:
26
    def __init__(self):
27
        
28
        self.ACTIVE=1 # dead or live
29
        self.LIFE=0.0 # len of life
30
        self.FADE=0.0 # step of fade
31
    
32
        self.R=0.0 # red
33
        self.G=0.0 # green
34
        self.B=0.0 # blue
35
        
36
        self.X=0.0 # X position
37
        self.Y=0.0 # Y position
38
        self.Z=0.0 # Z position
39
        
40
        self.Xi=0.0 # X direction
41
        self.Yi=0.0 # Y direction
42
        self.Zi=0.0 # Z direction
43
        
44
        self.Xj=0.0 # X gravity
45
        self.Yj=0.0 # Y gravity
46
        self.Zj=0.0 # Z gravity
47

    
48
#        self.particle=[i for i in xrange(MAX_PARTICLES)]
49
        
50
prts=[]
51

    
52
for i in xrange(MAX_PARTICLES):
53
    particl=particle() 
54
    prts.append(particl)
55
    
56
colors= [[(1.0,0.5,0.5),(1.0,0.75,0.5),(1.0,1.0,0.5),(0.75,1.0,0.5)],
57
         [(0.5,1.0,0.5),(0.5,1.0,0.75),(0.5,1.0,1.0),(0.5,0.75,1.0)],
58
         [(0.5,0.5,1.0),(0.75,0.5,1.0),(1.0,0.5,1.0),(1.0,0.5,0.75)]]
59

    
60
window = 0 # Number of the glut window.
61

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

    
83
# A general OpenGL initialization function.  Sets all of the initial parameters. 
84
def InitGL(Width, Height):                # We call this right after our OpenGL window is created.
85
    LoadTextures()
86
    global LOOP
87
    glClearColor(0.0, 0.0, 0.0, 0.0)    # This Will Clear The Background Color To Black
88
    glClearDepth(1.0)                    # Enables Clearing Of The Depth Buffer
89
    glDepthFunc(GL_LESS)                # The Type Of Depth Test To Do
90
    glDisable(GL_DEPTH_TEST)                # Enables Depth Testing
91
    glEnable(GL_BLEND)         
92
    glShadeModel(GL_SMOOTH)                # Enables Smooth Color Shading
93
    
94
    glBlendFunc(GL_SRC_ALPHA,GL_ONE)          
95
    glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
96
    glHint(GL_POINT_SMOOTH_HINT,GL_NICEST);   
97
    glEnable(GL_TEXTURE_2D);                  
98
    
99
    for i in xrange(MAX_PARTICLES):
100
        prts[i]
101
        
102
        prts[i].LIFE=1.0
103
        prts[i].FADE=float(random.randrange(0,100))/1000.0+0.003
104
        
105
        prts[i].R=colors[i*(12/1000)][0]
106
        prts[i].G=colors[i*(12/1000)][1]
107
        prts[i].B=colors[i*(12/1000)][2]
108
        
109
        prts[i].Xi=(float(random.randrange(0,100)%50)-26.0)*10.0
110
        prts[i].Yi=(float(random.randrange(0,100)%50)-25.0)*10.0
111
        prts[i].Zi=(float(random.randrange(0,100)%50)-25.0)*10.0
112
        
113
        prts[i].Xj=0.0
114
        prts[i].Yj=-0.8
115
        prts[i].Zj=0.0
116
    
117
    glMatrixMode(GL_PROJECTION)
118
    glLoadIdentity()                    # Reset The Projection Matrix
119
                                        # Calculate The Aspect Ratio Of The Window
120
    gluPerspective(45.0, float(Width)/float(Height), 0.1, 200.0)
121

    
122
    glMatrixMode(GL_MODELVIEW)
123

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

    
129
    glViewport(0, 0, Width, Height)        # Reset The Current Viewport And Perspective Transformation
130
    glMatrixMode(GL_PROJECTION)
131
    glLoadIdentity()
132
    gluPerspective(45.0, float(Width)/float(Height), 0.1, 200.0)
133
    glMatrixMode(GL_MODELVIEW)
134

    
135
# The main drawing function. 
136
def DrawGLScene():
137
    
138
    # Clear The Screen And The Depth Buffer
139
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
140
    glLoadIdentity()                         # Reset The View
141
    
142
    for i in xrange(MAX_PARTICLES):
143
        if prts[i].ACTIVE==1:
144
            x=float(prts[i].X)
145
            y=float(prts[i].Y)
146
            z=float(prts[i].Z+ZOOM)
147
            
148
            glColor4f(prts[i].R==i,prts[i].G==i,prts[i].B==i,prts[i].LIFE)
149
            
150
            glBegin(GL_TRIANGLE_STRIP)
151
            glTexCoord2d(1,1); glVertex3f(x+0.5,y+0.5,z); # upper right
152
            glTexCoord2d(0,1); glVertex3f(x-0.5,y+0.5,z); # upper left
153
            glTexCoord2d(1,0); glVertex3f(x+0.5,y-0.5,z); # bottom right 
154
            glTexCoord2d(0,0); glVertex3f(x-0.5,y-0.5,z); # bottom left
155
            glEnd()
156

    
157
            prts[i].X+=prts[i].Xi/(SPEED_PARTICLES*1000)
158
            prts[i].Y+=prts[i].Yi/(SPEED_PARTICLES*1000)
159
            prts[i].Z+=prts[i].Zi/(SPEED_PARTICLES*1000)
160
            
161
            prts[i].Xi+=prts[i].Xj
162
            prts[i].Yi+=prts[i].Yj
163
            prts[i].Zi+=prts[i].Zj
164
            
165
            prts[i].LIFE-=prts[i].FADE
166
            if prts[i].LIFE<0.0:
167
                prts[i].LIFE=1.0
168
                prts[i].FADE=float(random.randrange(0,100)%100)/1000.0+0.003
169
                
170
                prts[i].X=0.0
171
                prts[i].Y=0.0
172
                prts[i].Z=0.0
173
                
174
                prts[i].Xi=XSPEED+float((random.randrange(0,100)%60)-32.0)
175
                prts[i].Yi=XSPEED+float((random.randrange(0,100)%60)-30.0)
176
                prts[i].Zi=float((random.randrange(0,100)%60)-32.0)
177
                
178
        else:
179
            prts[i].ACTIVE=1
180
            prts[i].FADE=float(random.randrange(0,100))/1000.0+0.003;
181
            
182
            prts[i].X=0.0
183
            prts[i].Y=0.0
184
            prts[i].Z=0.0
185
            
186
    #  since this is double buffered, swap the buffers to display what just got drawn. 
187
    glutSwapBuffers()
188

    
189
# The function called whenever a key is pressed. Note the use of Python tuples to pass in: (key, x, y)  
190
def keyPressed(key, x, y):
191
    global window,ZOOM
192
    # If escape is pressed, kill everything.
193
    key = string.upper(key)
194
    prt=particle()
195
    
196
    if key == ESCAPE:
197
        sys.exit()
198
    elif key == 'W':
199
        for i in xrange(MAX_PARTICLES):
200
            if prts[i].Yj<1.5:
201
                prts[i].Yj+=0.1
202
    elif key == 'S':
203
        for i in xrange(MAX_PARTICLES):
204
            if prts[i].Yj>-1.5:
205
                prts[i].Yj-=0.1
206
    elif key == 'A':
207
        for i in xrange(MAX_PARTICLES):
208
            if prts[i].Xj>-1.5:
209
                prts[i].Xj-=0.1
210
    elif key == 'D':
211
        for i in xrange(MAX_PARTICLES):
212
            if prts[i].Xj<1.5:
213
                prts[i].Xj+=0.1
214
    elif key == 'F':
215
        for i in xrange(MAX_PARTICLES):    
216
            prts[i].X=0.0
217
            prts[i].Y=0.0
218
            prts[i].Z=0.0
219
            
220
            prts[i].Xi=float((random.randrange(0,100)%50)-26.0)*10.0
221
            prts[i].Yi=float((random.randrange(0,100)%50)-25.0)*10.0
222
            prts[i].Yi=float((random.randrange(0,100)%50)-25.0)*10.0
223
    elif key == 'Z':
224
        ZOOM+=1.0
225
    elif key == 'X':
226
        ZOOM-=1.0   
227
     
228
def main():
229
    global window
230
    # pass arguments to init
231
    glutInit(sys.argv)
232

    
233
    # Select type of Display mode:   
234
    #  Double buffer 
235
    #  RGBA color
236
    # Alpha components supported 
237
    # Depth buffer
238
    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
239
    
240
    # get a 640 x 480 window 
241
    glutInitWindowSize(800, 600)
242
    
243
    # the window starts at the upper left corner of the screen 
244
    glutInitWindowPosition(100, 100)
245
    
246
    # Okay, like the C version we retain the window id to use when closing, but for those of you new
247
    # to Python (like myself), remember this assignment would make the variable local and not global
248
    # if it weren't for the global declaration at the start of main.
249
    window = glutCreateWindow("Particles by RISC")
250

    
251
    # Register the drawing function with glut, BUT in Python land, at least using PyOpenGL, we need to
252
    # set the function pointer and invoke a function to actually register the callback, otherwise it
253
    # would be very much like the C version of the code.    
254
    glutDisplayFunc(DrawGLScene)
255
    
256
    # Uncomment this line to get full screen.
257
    #glutFullScreen()
258

    
259
    # When we are doing nothing, redraw the scene.
260
    glutIdleFunc(DrawGLScene)
261
    
262
    # Register the function called when our window is resized.
263
    glutReshapeFunc(ReSizeGLScene)
264
    
265
    # Register the function called when the keyboard is pressed.  
266
    glutKeyboardFunc(keyPressed)
267

    
268
    # Initialize our window. 
269
    InitGL(640, 480)
270

    
271
    # Start Event Processing Engine    
272
    glutMainLoop()
273

    
274
# Print message to console, and kick off the main to get it rolling.
275
if __name__ == "__main__":
276
    print "Hit ESC key to quit."
277
    print 'other commands: WASD (direction) ZX (zoom)'
278
    main()