Statistics
| Revision:

root / PyOpenGL-Demo / NeHe / lesson44 / glCamera.py @ 1

History | View | Annotate | Download (32.1 kB)

1
# // Code writen by: Vic Hollis 09/07/2003
2
# // I don't mind if you use this class in your own code. All I ask is 
3
# // that you give me credit for it if you do.  And plug NeHe while your
4
# // at it! :P  Thanks go to David Steere, Cameron Tidwell, Bert Sammons,
5
# // and Brannon Martindale for helping me test all the code!  Enjoy.
6
# //////////////////////////////////////////////////////////////////////
7
# // glCamera.h: interface for the glCamera class.
8
# //////////////////////////////////////////////////////////////////////
9
# 
10
# //////////////////////////////////////////////////////////////////////
11
# // Some minimal additions by rIO.Spinning Kids 
12
# // For testing flares against occluding objects.
13
# // Not using proprietary extensions, this is PURE OpenGL1.1
14
# //
15
# // Just call the IsOccluded function, passing it the glPoint to check
16
# //
17
# //////////////////////////////////////////////////////////////////////
18
#
19
# Ported to Python, PyOpenGL by Brian Leair 2004.
20
# The numarray python module can perform matrix math more effieciently 
21
# than direct python code. However, for this tutorial the differnce
22
# in performance isn't huge and it makes for a better tutorial to see
23
# the math operations directly.
24

    
25
from OpenGL.GL import *
26
from OpenGL.GLU import *
27
from OpenGL.GLUT import *
28
from glPoint import *
29
from glVector import *
30
from math import sqrt, fabs
31

    
32
try:
33
        import numpy as Numeric
34
except ImportError, err:
35
        try: 
36
                import Numeric
37
        except ImportError, err:
38
                print "This demo requires the numpy or Numeric extension, sorry"
39
                import sys
40
                sys.exit()
41
import copy
42

    
43
class glCamera:
44
        # //////////// CONSTRUCTORS /////////////////////////////////////////
45
        def __init__ (self):
46
                # // Initalize all our member varibles.
47
                self.m_MaxPitchRate                        = 0.0;
48
                self.m_MaxHeadingRate                = 0.0;
49
                self.m_HeadingDegrees                = 0.0;
50
                self.m_PitchDegrees                        = 0.0;
51
                self.m_MaxForwardVelocity        = 0.0;
52
                self.m_ForwardVelocity                = 0.0;
53
                self.m_GlowTexture          = None;
54
                # bleair: NOTE that glCamera.cpp has a bug. m_BigGlowTexture isn't initialized.
55
                # Very minor bug because only in the case where we fail to get an earlier
56
                # texture will the class potentially read from the uninited memory. Most of
57
                # the time the field is assigned to straight away in InitGL ().
58
                self.m_BigGlowTexture       = None;
59
                self.m_HaloTexture                        = None;
60
                self.m_StreakTexture                = None;
61
                self.m_MaxPointSize                        = 0.0;
62
                self.m_Frustum = Numeric.zeros ( (6,4), 'f')
63

    
64
                self.m_LightSourcePos                 = glPoint ()
65
                self.m_Position = glPoint ()
66
                self.m_DirectionVector = glVector ()
67
                self.m_ptIntersect = glPoint ()
68

    
69

    
70

    
71

    
72
        def __del__ (self):
73
                self.release ()
74
                return
75

    
76
        def release (self):
77
                if (self.m_GlowTexture != None):
78
                        glDeleteTextures (self.m_GlowTexture)
79
                if (self.m_HaloTexture != None):
80
                        glDeleteTextures (self.m_HaloTexture)
81
                if (self.m_BigGlowTexture != None):
82
                        glDeleteTextures (self.m_BigGlowTexture)
83
                if (self.m_StreakTexture != None):
84
                        glDeleteTextures (self.m_StreakTexture)
85
                return
86

    
87
        def ChangePitch (self, degrees):
88
                if (fabs (degrees) < fabs (self.m_MaxPitchRate)):
89
                        # // Our pitch is less than the max pitch rate that we 
90
                        # // defined so lets increment it.
91
                        self.m_PitchDegrees += degrees;
92
                else:
93
                        # // Our pitch is greater than the max pitch rate that
94
                        # // we defined so we can only increment our pitch by the 
95
                        # // maximum allowed value.
96
                        if(degrees < 0):
97
                                # // We are pitching down so decrement
98
                                self.m_PitchDegrees -= self.m_MaxPitchRate;
99
                        else:
100
                                # // We are pitching up so increment
101
                                self.m_PitchDegrees += self.m_MaxPitchRate;
102

    
103
                # // We don't want our pitch to run away from us. Although it
104
                # // really doesn't matter I prefer to have my pitch degrees
105
                # // within the range of -360.0f to 360.0f
106
                if (self.m_PitchDegrees > 360.0):
107
                        self.m_PitchDegrees -= 360.0;
108
                elif (self.m_PitchDegrees < -360.0):
109
                        self.m_PitchDegrees += 360.0;
110

    
111
                return
112

    
113
        def ChangeHeading (self, degrees):
114
                if(fabs(degrees) < fabs(self.m_MaxHeadingRate)):
115
                        # // Our Heading is less than the max heading rate that we 
116
                        # // defined so lets increment it but first we must check
117
                        # // to see if we are inverted so that our heading will not
118
                        # // become inverted.
119
                        if (self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270 or 
120
                                (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):
121
                                self.m_HeadingDegrees -= degrees;
122
                        else:
123
                                self.m_HeadingDegrees += degrees;
124
                else:
125
                        # // Our heading is greater than the max heading rate that
126
                        # // we defined so we can only increment our heading by the 
127
                        # // maximum allowed value.
128
                        if(degrees < 0):
129
                                # // Check to see if we are upside down.
130
                                if ((self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270) or
131
                                        (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):
132
                                        # // Ok we would normally decrement here but since we are upside
133
                                        # // down then we need to increment our heading
134
                                        self.m_HeadingDegrees += self.m_MaxHeadingRate;
135
                                else:
136
                                        # // We are not upside down so decrement as usual
137
                                        self.m_HeadingDegrees -= self.m_MaxHeadingRate;
138
                        else:
139
                                # // Check to see if we are upside down.
140
                                if (self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270 or
141
                                        (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):
142
                                        # // Ok we would normally increment here but since we are upside
143
                                        # // down then we need to decrement our heading.
144
                                        self.m_HeadingDegrees -= self.m_MaxHeadingRate;
145
                                else:
146
                                        # // We are not upside down so increment as usual.
147
                                        self.m_HeadingDegrees += self.m_MaxHeadingRate;
148
        
149
                # // We don't want our heading to run away from us either. Although it
150
                # // really doesn't matter I prefer to have my heading degrees
151
                # // within the range of -360.0f to 360.0f
152
                if(self.m_HeadingDegrees > 360.0):
153
                        self.m_HeadingDegrees -= 360.0;
154
                elif(self.m_HeadingDegrees < -360.0):
155
                        self.m_HeadingDegrees += 360.0;
156

    
157
                return
158

    
159
        # //////////// FUNCTIONS TO CHANGE CAMERA ORIENTATION AND SPEED /////
160
        def ChangeVelocity(self, vel):
161
                if(fabs(vel) < fabs(self.m_MaxForwardVelocity)):
162
                        # // Our velocity is less than the max velocity increment that we 
163
                        # // defined so lets increment it.
164
                        self.m_ForwardVelocity += vel;
165
                else:
166
                        # // Our velocity is greater than the max velocity increment that
167
                        # // we defined so we can only increment our velocity by the 
168
                        # // maximum allowed value.
169
                        if(vel < 0):
170
                                # // We are slowing down so decrement
171
                                self.m_ForwardVelocity -= -self.m_MaxForwardVelocity;
172
                        else:
173
                                # // We are speeding up so increment
174
                                self.m_ForwardVelocity += self.m_MaxForwardVelocity;
175

    
176
                return
177

    
178
        def UpdateFrustum(self):
179
                """ // I found this code here: http://www.markmorley.com/opengl/frustumculling.html
180
                // and decided to make it part of
181
                // the camera class just in case I might want to rotate
182
                // and translate the projection matrix. This code will
183
                // make sure that the Frustum is updated correctly but
184
                // this member is computational expensive with:
185
                // 82 muliplications, 72 additions, 24 divisions, and
186
                // 12 subtractions for a total of 190 operations. Ouch! """
187

    
188
                # /* Get the current PROJECTION matrix from OpenGL */
189
                proj = glGetFloatv( GL_PROJECTION_MATRIX);
190

    
191
                # /* Get the current MODELVIEW matrix from OpenGL */
192
                modl = glGetFloatv( GL_MODELVIEW_MATRIX);
193

    
194
                # /* Combine the two matrices (multiply projection by modelview) */
195
                # Careful, Note, that replication is simple scalars is OK, but replicate of objects
196
                # and lists is very bad.
197
                clip = [None,] * 16
198
                # clip = Numeric.zeros ( (16), 'f')
199
                clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
200
                clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
201
                clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
202
                clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];
203

    
204
                clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
205
                clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
206
                clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
207
                clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];
208

    
209
                clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
210
                clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
211
                clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
212
                clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];
213

    
214
                clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
215
                clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
216
                clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
217
                clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];
218

    
219
                # ### Use a shortened name to reference to our camera's Frustum (does 
220
                # ### not copy anything, just a ref to make code less wordy
221
                Frustum = self.m_Frustum
222

    
223
                # /* Extract the numbers for the RIGHT plane */
224
                Frustum[0][0] = clip[ 3] - clip[ 0];
225
                Frustum[0][1] = clip[ 7] - clip[ 4];
226
                Frustum[0][2] = clip[11] - clip[ 8];
227
                Frustum[0][3] = clip[15] - clip[12];
228

    
229
            # /* Normalize the result */
230
                t = (sqrt( Frustum[0][0] * Frustum[0][0] + \
231
                Frustum[0][1] * Frustum[0][1] + Frustum[0][2] * Frustum[0][2] ));
232
                Frustum[0][0] /= t;
233
                Frustum[0][1] /= t;
234
                Frustum[0][2] /= t;
235
                Frustum[0][3] /= t;
236

    
237
                # /* Extract the numbers for the LEFT plane */
238
                Frustum[1][0] = clip[ 3] + clip[ 0];
239
                Frustum[1][1] = clip[ 7] + clip[ 4];
240
                Frustum[1][2] = clip[11] + clip[ 8];
241
                Frustum[1][3] = clip[15] + clip[12];
242

    
243
                # /* Normalize the result */
244
                t = sqrt( Frustum[1][0] * Frustum[1][0] + Frustum[1][1] * Frustum[1][1] + Frustum[1][2] * Frustum[1][2] );
245
                Frustum[1][0] /= t;
246
                Frustum[1][1] /= t;
247
                Frustum[1][2] /= t;
248
                Frustum[1][3] /= t;
249

    
250
                # /* Extract the BOTTOM plane */
251
                Frustum[2][0] = clip[ 3] + clip[ 1];
252
                Frustum[2][1] = clip[ 7] + clip[ 5];
253
                Frustum[2][2] = clip[11] + clip[ 9];
254
                Frustum[2][3] = clip[15] + clip[13];
255

    
256
                # /* Normalize the result */
257
                t = sqrt( Frustum[2][0] * Frustum[2][0] + Frustum[2][1] * Frustum[2][1] + Frustum[2][2] * Frustum[2][2] );
258
                Frustum[2][0] /= t;
259
                Frustum[2][1] /= t;
260
                Frustum[2][2] /= t;
261
                Frustum[2][3] /= t;
262

    
263
                # /* Extract the TOP plane */
264
                Frustum[3][0] = clip[ 3] - clip[ 1];
265
                Frustum[3][1] = clip[ 7] - clip[ 5];
266
                Frustum[3][2] = clip[11] - clip[ 9];
267
                Frustum[3][3] = clip[15] - clip[13];
268

    
269
            # /* Normalize the result */
270
                t = sqrt( Frustum[3][0] * Frustum[3][0] + Frustum[3][1] * Frustum[3][1] + Frustum[3][2] * Frustum[3][2] )
271
                Frustum[3][0] /= t;
272
                Frustum[3][1] /= t;
273
                Frustum[3][2] /= t;
274
                Frustum[3][3] /= t;
275

    
276
                 # /* Extract the FAR plane */
277
                 Frustum[4][0] = clip[ 3] - clip[ 2];
278
                 Frustum[4][1] = clip[ 7] - clip[ 6];
279
                 Frustum[4][2] = clip[11] - clip[10];
280
                Frustum[4][3] = clip[15] - clip[14];
281

    
282
                # /* Normalize the result */
283
                 t = sqrt( Frustum[4][0] * Frustum[4][0] + Frustum[4][1] * Frustum[4][1] + Frustum[4][2] * Frustum[4][2] )
284
                 Frustum[4][0] /= t;
285
                 Frustum[4][1] /= t;
286
                 Frustum[4][2] /= t;
287
                 Frustum[4][3] /= t;
288

    
289
                 # /* Extract the NEAR plane */
290
                 Frustum[5][0] = clip[ 3] + clip[ 2];
291
                 Frustum[5][1] = clip[ 7] + clip[ 6];
292
                 Frustum[5][2] = clip[11] + clip[10];
293
                 Frustum[5][3] = clip[15] + clip[14];
294

    
295
                 # /* Normalize the result */
296
                 t = sqrt( Frustum[5][0] * Frustum[5][0] + Frustum[5][1] * Frustum[5][1] + Frustum[5][2] * Frustum[5][2] );
297
                 Frustum[5][0] /= t;
298
                 Frustum[5][1] /= t;
299
                 Frustum[5][2] /= t;
300
                 Frustum[5][3] /= t;
301

    
302
                return
303

    
304
        # //////////// FUNCTIONS TO UPDATE THE FRUSTUM //////////////////////
305
        def UpdateFrustumFaster (self):
306
                """ // This is the much faster version of the above member 
307
                // function, however the speed increase is not gained 
308
                // without a cost. If you rotate or translate the projection
309
                // matrix then this member will not work correctly. That is acceptable
310
                // in my book considering I very rarely do such a thing.
311
                // This function has far fewer operations in it and I 
312
                // shaved off 2 square root functions by passing in the
313
                // near and far values. This member has:
314
                // 38 muliplications, 28 additions, 24 divisions, and
315
                // 12 subtractions for a total of 102 operations. Still hurts
316
                // but at least it is decent now. In practice this will 
317
                // run about 2 times faster than the above function. """
318

    
319
                # /* Get the current PROJECTION matrix from OpenGL */
320
                proj = glGetFloatv( GL_PROJECTION_MATRIX);
321
        
322
                # /* Get the current MODELVIEW matrix from OpenGL */
323
                modl = glGetFloatv( GL_MODELVIEW_MATRIX);
324
        
325
                # /* Combine the two matrices (multiply projection by modelview) 
326
                   # but keep in mind this function will only work if you do NOT
327
                   # rotate or translate your projection matrix                  */
328
                clip = [0,] * 16
329
                modl_row1 = modl [0]
330
                clip[ 0] = modl [0] [0] * proj[0][0];
331
                clip[ 1] = modl  [0][ 1] * proj[1][1];
332
                clip[ 2] = modl [0][ 2] * proj[2][2] + modl_row1[ 3] * proj[3][2]
333
                clip[ 3] = modl [0][ 2] * proj[2][3]
334
        
335
                modl_row2 = modl [1]
336
                clip[ 4] = modl_row2[ 0] * proj[0][0]
337
                clip[ 5] = modl_row2[ 1] * proj[1][1]
338
                clip[ 6] = modl_row2[ 2] * proj[2][2] + modl_row2[ 3] * proj[3][2]
339
                clip[ 7] = modl_row2[ 2] * proj[2][3]
340
        
341
                modl_row3 = modl [2]
342
                clip[ 8] = modl_row3[ 0] * proj[0][0];
343
                clip[ 9] = modl_row3[ 1] * proj[1][1]
344
                clip[10] = modl_row3[2] * proj[2][2] + modl_row3[3] * proj[3][2]
345
                clip[11] = modl_row3[2] * proj[2][3]
346
        
347
                modl_row4 = modl [3]
348
                clip[12] = modl_row4[0] * proj[0][0]
349
                clip[13] = modl_row4[1] * proj[1][1]
350
                clip[14] = modl_row4[2] * proj[2][2] + modl_row4[3] * proj[3][2]
351
                clip[15] = modl_row4[2] * proj[2][3]
352
        
353
                # ### Use a shortened name to reference to our camera's Frustum (does 
354
                # ### not copy anything, just a ref to make code less wordy
355
                Frustum = self.m_Frustum
356

    
357
                # /* Extract the numbers for the RIGHT plane */
358
                Frustum[0][0] = clip[ 3] - clip[ 0];
359
                Frustum[0][1] = clip[ 7] - clip[ 4];
360
                Frustum[0][2] = clip[11] - clip[ 8];
361
                Frustum[0][3] = clip[15] - clip[12];
362
        
363
                # /* Normalize the result */
364
                t = sqrt( (Frustum[0][0] * Frustum[0][0]) + (Frustum[0][1] * Frustum[0][1]) + (Frustum[0][2] * Frustum[0][2]) );
365
                Frustum[0][0] /= t;
366
                Frustum[0][1] /= t;
367
                Frustum[0][2] /= t;
368
                Frustum[0][3] /= t;
369
        
370
                 # /* Extract the numbers for the LEFT plane */
371
                 Frustum[1][0] = clip[ 3] + clip[ 0];
372
                 Frustum[1][1] = clip[ 7] + clip[ 4];
373
                 Frustum[1][2] = clip[11] + clip[ 8];
374
                 Frustum[1][3] = clip[15] + clip[12];
375
        
376
            # /* Normalize the result */
377
                 t = sqrt( Frustum[1][0] * Frustum[1][0] + Frustum[1][1] * Frustum[1][1] + Frustum[1][2] * Frustum[1][2] );
378
                 Frustum[1][0] /= t;
379
                 Frustum[1][1] /= t;
380
                 Frustum[1][2] /= t;
381
                 Frustum[1][3] /= t;
382
        
383
                # /* Extract the BOTTOM plane */
384
                Frustum[2][0] = clip[ 3] + clip[ 1];
385
                Frustum[2][1] = clip[ 7] + clip[ 5];
386
                Frustum[2][2] = clip[11] + clip[ 9];
387
                Frustum[2][3] = clip[15] + clip[13];
388
        
389
            # /* Normalize the result */
390
                t = sqrt( Frustum[2][0] * Frustum[2][0] + Frustum[2][1] * Frustum[2][1] + Frustum[2][2] * Frustum[2][2] );
391
                Frustum[2][0] /= t;
392
                Frustum[2][1] /= t;
393
                Frustum[2][2] /= t;
394
                Frustum[2][3] /= t;
395
        
396
            # /* Extract the TOP plane */
397
                 Frustum[3][0] = clip[ 3] - clip[ 1];
398
                 Frustum[3][1] = clip[ 7] - clip[ 5];
399
                 Frustum[3][2] = clip[11] - clip[ 9];
400
                 Frustum[3][3] = clip[15] - clip[13];
401
        
402
            # /* Normalize the result */
403
                 t = sqrt( Frustum[3][0] * Frustum[3][0] + Frustum[3][1] * Frustum[3][1] + Frustum[3][2] * Frustum[3][2] );
404
                 Frustum[3][0] /= t;
405
                 Frustum[3][1] /= t;
406
                 Frustum[3][2] /= t;
407
                 Frustum[3][3] /= t;
408
        
409
            # /* Extract the FAR plane */
410
                 Frustum[4][0] = clip[ 3] - clip[ 2];
411
                 Frustum[4][1] = clip[ 7] - clip[ 6];
412
                 Frustum[4][2] = clip[11] - clip[10];
413
                 Frustum[4][3] = clip[15] - clip[14];
414
        
415
            # /* Normalize the result */
416
                 t = sqrt( (Frustum[4][0] * Frustum[4][0]) + (Frustum[4][1] * Frustum[4][1]) + (Frustum[4][2] * Frustum[4][2]) );
417
                 Frustum[4][0] /= t;
418
                 Frustum[4][1] /= t;
419
                 Frustum[4][2] /= t;
420
                 Frustum[4][3] /= t;
421
        
422
            # /* Extract the NEAR plane */
423
                 Frustum[5][0] = clip[ 3] + clip[ 2];
424
                 Frustum[5][1] = clip[ 7] + clip[ 6];
425
                 Frustum[5][2] = clip[11] + clip[10];
426
                 Frustum[5][3] = clip[15] + clip[14];
427
        
428
                 # /* Normalize the result */
429
                 t = sqrt( Frustum[5][0] * Frustum[5][0] + Frustum[5][1] * Frustum[5][1] + Frustum[5][2] * Frustum[5][2] );
430
                 Frustum[5][0] /= t;
431
                 Frustum[5][1] /= t;
432
                 Frustum[5][2] /= t;
433
                 Frustum[5][3] /= t;
434

    
435
                return
436
        
437
        
438

    
439
        # //////////// FRUSTUM TESTING FUNCTIONS ////////////////////////////
440
        def SphereInFrustum(self, p, Radius):
441
                """ // This member function checks to see if a sphere is in
442
                        // the viewing volume.   """
443

    
444
                Frustum = self.m_Frustum
445
                # // The idea here is the same as the PointInFrustum function.
446
                if (Radius != 0):
447
                        for i in xrange (6):
448
                        # // If the point is outside of the plane then its not in the viewing volume.
449
                                if(Frustum[i][0] * p.x + Frustum[i][1] * p.y + Frustum[i][2] * p.z + Frustum[i][3] <= -Radius):
450
                                        return(False);
451
                else:
452
                        # // The idea here is the same as the PointInFrustum function.
453
                        for i in xrange (6):
454
                                # // If the point is outside of the plane then its not in the viewing volume.
455
                                if(Frustum[i][0] * p.x + Frustum[i][1] * p.y + Frustum[i][2] * p.z + Frustum[i][3] <= 0):
456
                                        return(False);
457

    
458
                return(True);
459

    
460
        def PointInFrustum(self, x,y,z):
461
                """ // This member fuction checks to see if a point is in
462
                        // the viewing volume. """
463

    
464
                # // The idea behind this algorithum is that if the point
465
                # // is inside all 6 clipping planes then it is inside our
466
                # // viewing volume so we can return true.
467

    
468
                Frustum = self.m_Frustum
469
                # // Loop through all our clipping planes
470
                for i in xrange (6):
471
                        # // If the point is outside of the plane then its not in the viewing volume.
472
                        if(Frustum[i][0] * x + Frustum[i][1] * y + Frustum[i][2] * z + Frustum[i][3] <= 0):
473
                                return(False);
474

    
475
                return(True);
476

    
477
        # /////////// OCCLUSION TESTING FUNCTIONS ///////////////////////////
478
        def IsOccluded (self, p):
479
                # // Now we will ask OGL to project some geometry for us using the gluProject function.
480
                # // Practically we ask OGL to guess where a point in space will be projected in our current viewport,
481
                # // using arbitrary viewport and transform matrices we pass to the function.
482
                # // If we pass to the function the current matrices  (retrievede with the glGet funcs)
483
                # // we will have the real position on screen where the dot will be drawn.
484
                # // The interesting part is that we also get a Z value back, this means that 
485
                # // reading the REAL buffer for Z values we can discover if the flare is in front or
486
                # // if it's occluded by some objects.
487
                # ### This function should be a flat function, not a function of the camera as we
488
                # ### use the immediate GL rendering state entirely.
489

    
490

    
491
                # ### Viewport is the rectangle of window pixels that OpenGL is rasterizing into.
492
                viewport = glGetIntegerv (GL_VIEWPORT);                                                # //get actual viewport
493
                  mvmatrix = glGetDoublev (GL_MODELVIEW_MATRIX);                                # //get actual model view matrix
494
                  projmatrix = glGetDoublev (GL_PROJECTION_MATRIX);                        # //get actual projiection matrix
495

    
496
                # // this asks OGL to guess the 2d position of a 3d point inside the viewport
497
                winx, winy, winz = gluProject(p.x, p.y, p.z, mvmatrix, projmatrix, viewport)
498
                flareZ = winz;
499

    
500
                # // we read back one pixel from th depth buffer (exactly where our flare should be drawn)
501
                glPixelStorei(GL_PACK_ALIGNMENT, 1)
502

    
503
                # PyOpenGL 2.0.1.07 bug, Only the type clarified function works.
504
                # bufferZ = glReadPixels(int(winx), int(winy),1,1,GL_DEPTH_COMPONENT, GL_FLOAT)
505
                bufferZ = glReadPixelsf(int(winx), int(winy),1,1,GL_DEPTH_COMPONENT)
506

    
507
                # // if the buffer Z is lower than our flare guessed Z then don't draw 
508
                # // this means there is something in front of our flare
509
                if (bufferZ [0] [0] < flareZ):
510
                        return True;
511
                else:
512
                        return False;
513

    
514
        # //////////// FUNCTIONS TO RENDER LENS FLARES //////////////////////
515
        def RenderLensFlare(self):
516
                # // Draw the flare only If the light source is in our line of sight (inside the Frustum)
517
                if (self.SphereInFrustum(self.m_LightSourcePos, 1.0) == True):
518

    
519
                        # Vector pointing from the light's position toward the camera's position (the camera might
520
                        # be pointing elsewhere, this vector is pointing from the light to the camera)
521
                        self.vLightSourceToCamera = self.m_Position - self.m_LightSourcePos;                # // Lets compute the vector that points to the camera from
522
                                                                                                                                                                                # // the light source.
523

    
524
                        Length = self.vLightSourceToCamera.Magnitude ()                                                 # // Save the length we will need it in a minute
525

    
526
                        # Move down our look-toward direction vector. Move down the look-toward the same dist. as the
527
                        # distance between camera and the light.
528
                        intersect = self.m_DirectionVector * Length
529
                        self.m_ptIntersect = glPoint (intersect.i, intersect.j, intersect.k)
530
                                                                                                                                                # // Now lets find an point along the cameras direction
531
                                                                                                                                                # // vector that we can use as an intersection point. 
532
                                                                                                                                                # // Lets translate down this vector the same distance
533
                                                                                                                                                # // that the camera is away from the light source.
534
                        ptIntersect = self.m_ptIntersect
535
                        # Did the motion in the correct direction above, now translate the intersection position 
536
                        # relative to our camera location.
537
                        ptIntersect += self.m_Position;
538

    
539

    
540
                        self.vLightSourceToIntersect = ptIntersect - self.m_LightSourcePos;                # // Lets compute the vector that points to the Intersect
541
                                                                                                                                        # // point from the light source
542
                                        
543
                        Length = self.vLightSourceToIntersect.Magnitude();                # // Save the length we will need it later.
544
                        self.vLightSourceToIntersect.Normalize();                                # // Normalize the vector so its unit length
545
                        vLightSourceToIntersect = self.vLightSourceToIntersect
546
                
547
                        glEnable(GL_BLEND);                                                                                # // You should already know what this does
548
                        glBlendFunc(GL_SRC_ALPHA, GL_ONE);                                                # // You should already know what this does
549
                        glDisable(GL_DEPTH_TEST);                                                                # // You should already know what this does
550
                        glEnable(GL_TEXTURE_2D);                                                                # // You should already know what this does
551
                        
552
                        # /////////// Differenet Color Glows & Streaks /////////////////////
553
                        # //RenderBigGlow(1.0f, 1.0f, 1.0f, 1.0f, m_LightSourcePos, 1.0f);
554
                        # //RenderStreaks(1.0f, 1.0f, 0.8f, 1.0f, m_LightSourcePos, 0.7f);
555
                        # //
556
                        # //RenderBigGlow(1.0f, 0.9f, 1.0f, 1.0f, m_LightSourcePos, 1.0f);
557
                        # //RenderStreaks(1.0f, 0.9f, 1.0f, 1.0f, m_LightSourcePos, 0.7f);
558
                        # //////////////////////////////////////////////////////////////////
559

    
560

    
561
                        # //########################## NEW STUFF ##################################
562

    
563
                        if (not self.IsOccluded(self.m_LightSourcePos)):                #        //Check if the center of the flare is occluded
564
                                # // Render the large hazy glow
565
                                self.RenderBigGlow(0.60, 0.60, 0.8, 1.0, self.m_LightSourcePos, 16.0);
566
                                # // Render the streaks
567
                                self.RenderStreaks(0.60, 0.60, 0.8, 1.0, self.m_LightSourcePos, 16.0);
568
                                # // Render the small Glow
569
                                self.RenderGlow(0.8, 0.8, 1.0, 0.5, self.m_LightSourcePos, 3.5);
570

    
571
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.1));        # // Lets compute a point that is 20%
572
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
573
                                                                                                                                                        # // direction of the intersection point.
574
                
575
                                self.RenderGlow(0.9, 0.6, 0.4, 0.5, pt, 0.6);                                        # // Render the small Glow
576

    
577
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.15));        # // Lets compute a point that is 30%
578
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
579
                                                                                                                                                        # // direction of the intersection point.                
580
                
581
                                self.RenderHalo(0.8, 0.5, 0.6, 0.5, pt, 1.7);                                        # // Render the a Halo
582
                
583
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.175));                        # // Lets compute a point that is 35%
584
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
585
                                                                                                                                                        # // direction of the intersection point.                
586
                
587
                                self.RenderHalo(0.9, 0.2, 0.1, 0.5, pt, 0.83);                                        # // Render the a Halo
588

    
589
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.285));                        # // Lets compute a point that is 57%
590
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
591
                                                                                                                                                        # // direction of the intersection point.                
592
                
593
                                self.RenderHalo(0.7, 0.7, 0.4, 0.5, pt, 1.6);                                        # // Render the a Halo
594
                
595
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.2755));                        # // Lets compute a point that is 55.1%
596
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
597
                                                                                                                                                        # // direction of the intersection point.                
598
                
599
                                self.RenderGlow(0.9, 0.9, 0.2, 0.5, pt, 0.8);                                        # // Render the small Glow
600

    
601
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.4775));                        # // Lets compute a point that is 95.5%
602
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
603
                                                                                                                                                        # // direction of the intersection point.                
604
                
605
                                self.RenderGlow(0.93, 0.82, 0.73, 0.5, pt, 1.0);                                        # // Render the small Glow
606
                
607
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.49));                                # // Lets compute a point that is 98%
608
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
609
                                                                                                                                                        # // direction of the intersection point.                
610
                
611
                                self.RenderHalo(0.7, 0.6, 0.5, 0.5, pt, 1.4);                                        # // Render the a Halo
612

    
613
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.65));                                # // Lets compute a point that is 130%
614
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
615
                                                                                                                                                        # // direction of the intersection point.                
616
                
617
                                self.RenderGlow(0.7, 0.8, 0.3, 0.5, pt, 1.8);                                        # // Render the small Glow
618
                
619
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.63));                                # // Lets compute a point that is 126%
620
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
621
                                                                                                                                                        # // direction of the intersection point.                
622
                
623
                                self.RenderGlow(0.4, 0.3, 0.2, 0.5, pt, 1.4);                                        # // Render the small Glow
624

    
625
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.8));                                # // Lets compute a point that is 160%
626
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
627
                                                                                                                                                        # // direction of the intersection point.                
628
                
629
                                self.RenderHalo(0.7, 0.5, 0.5, 0.5, pt, 1.4);                                        # // Render the a Halo
630
                
631
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.7825));                        # // Lets compute a point that is 156.5%
632
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
633
                                                                                                                                                        # // direction of the intersection point.
634

    
635
                                self.RenderGlow(0.8, 0.5, 0.1, 0.5, pt, 0.6);                                        # // Render the small Glow
636

    
637
                                pt = glPoint (vLightSourceToIntersect * (Length * 1.0));                                # // Lets compute a point that is 200%
638
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
639
                                                                                                                                                        # // direction of the intersection point.                
640
                
641
                                self.RenderHalo(0.5, 0.5, 0.7, 0.5, pt, 1.7);                                        # // Render the a Halo
642
                
643
                                pt = glPoint (vLightSourceToIntersect * (Length * 0.975));                        # // Lets compute a point that is 195%
644
                                pt += self.m_LightSourcePos;                                                                # // away from the light source in the
645
                                                                                                                                                        # // direction of the intersection point.                
646
                
647
                                self.RenderGlow(0.4, 0.1, 0.9, 0.5, pt, 2.0);                                        # // Render the small Glow
648

    
649
                        glDisable(GL_BLEND );                                                                                        # // You should already know what this does
650
                        glEnable(GL_DEPTH_TEST);                                                                                # // You should already know what this does
651
                        glDisable(GL_TEXTURE_2D);                                                                                # // You should already know what this does
652
                return
653

    
654
        def RenderHalo (self, r, g, b, a, p, scale):
655
                self.RenderFlareTexture (self.m_HaloTexture, r, g, b, a, p, scale)
656
                return
657

    
658
        def RenderGlow (self, r, g, b, a, p, scale):
659
                self.RenderFlareTexture (self.m_GlowTexture, r, g, b, a, p, scale)
660
                return
661

    
662
        def RenderBigGlow (self, r, g, b, a, p, scale):
663
                self.RenderFlareTexture (self.m_BigGlowTexture, r, g, b, a, p, scale)
664
                return
665

    
666
        def RenderStreaks (self, r, g, b, a, p, scale):
667
                self.RenderFlareTexture (self.m_StreakTexture, r, g, b, a, p, scale)
668
                return
669

    
670
        def RenderFlareTexture (self, tex_ID, r, g, b, a, p, scale):
671
                # bleair: Duplicate functions all the same except for the texture to bind to.
672

    
673
                q = []
674
                q.append (glPoint ())
675
                q.append (glPoint ())
676
                q.append (glPoint ())
677
                q.append (glPoint ())
678
                # // Basically we are just going to make a 2D box
679
                # // from four points we don't need a z coord because
680
                # // we are rotating the camera by the inverse so the 
681
                # // texture mapped quads will always face us.
682

    
683
                q[0].x = (p.x - scale);                                                                                        # // Set the x coordinate -scale units from the center point.
684
                q[0].y = (p.y - scale);                                                                                        # // Set the y coordinate -scale units from the center point.
685
                
686
                q[1].x = (p.x - scale);                                                                                        # // Set the x coordinate -scale units from the center point.
687
                q[1].y = (p.y + scale);                                                                                        # // Set the y coordinate scale units from the center point.
688
                
689
                q[2].x = (p.x + scale);                                                                                        # // Set the x coordinate scale units from the center point.
690
                q[2].y = (p.y - scale);                                                                                        # // Set the y coordinate -scale units from the center point.
691
                
692
                q[3].x = (p.x + scale);                                                                                        # // Set the x coordinate scale units from the center point.
693
                q[3].y = (p.y + scale);                                                                                        # // Set the y coordinate scale units from the center point.
694
                
695
                glPushMatrix();                                                                                                        # // Save the model view matrix
696
                glTranslatef(p.x, p.y, p.z);                                                                        # // Translate to our point
697
                glRotatef(-self.m_HeadingDegrees, 0.0, 1.0, 0.0);
698
                glRotatef(-self.m_PitchDegrees, 1.0, 0.0, 0.0);
699
                glBindTexture(GL_TEXTURE_2D, tex_ID);                                                        # // Bind to the Big Glow texture
700
                glColor4f(r, g, b, a);                                                                                        # // Set the color since the texture is a gray scale
701
        
702
                glBegin(GL_TRIANGLE_STRIP);                                                                                # // Draw the Big Glow on a Triangle Strip
703
                glTexCoord2f(0.0, 0.0);                                        
704
                glVertex2f(q[0].x, q[0].y);
705
                glTexCoord2f(0.0, 1.0);
706
                glVertex2f(q[1].x, q[1].y);
707
                glTexCoord2f(1.0, 0.0);
708
                glVertex2f(q[2].x, q[2].y);
709
                glTexCoord2f(1.0, 1.0);
710
                glVertex2f(q[3].x, q[3].y);
711
                glEnd();                                                                                
712
                glPopMatrix();                                                                                                        # // Restore the model view matrix
713
                return
714

    
715

    
716

    
717

    
718
        def SetPrespective (self):
719
                # Matrix = [0] * 16                                         # // A (list) array to hold the model view matrix.
720

    
721
                # However the MODELVIEW was oriented, we now rotate it based upon our Camer object's state.
722
                # // Going to use glRotate to calculate our direction vector
723
                glRotatef(self.m_HeadingDegrees, 0.0, 1.0, 0.0);                # turn your head left/right (around y axe)
724
                glRotatef(self.m_PitchDegrees, 1.0, 0.0, 0.0);                        # nod your head up/down (around x axe)
725

    
726
                # // Get the resulting matrix from OpenGL it will have our
727
                # // direction vector in the 3rd row.
728
                Matrix = glGetFloatv(GL_MODELVIEW_MATRIX);
729

    
730
                # // Get the direction vector from the matrix. Element 10 must
731
                # // be inverted!
732
                self.m_DirectionVector.i = Matrix[2] [0]        #[8];
733
                self.m_DirectionVector.j = Matrix[2] [1]        #[9];
734
                self.m_DirectionVector.k = -Matrix[2] [2]         #[10];
735

    
736
                # #### bleair: no need to do this as this. Previous rotates already here (because
737
                # #### all invocations have the modelview at identity.
738
                # #### Suspect this was just a bit of code that was mvoed up and not deleted here.
739
                # // Ok erase the results of the last computation.
740
                glLoadIdentity();
741

    
742
                # // Rotate the scene to get the right orientation.
743
                glRotatef(self.m_PitchDegrees, 1.0, 0.0, 0.0);
744
                glRotatef(self.m_HeadingDegrees, 0.0, 1.0, 0.0);
745

    
746
                # // A vector to hold our cameras direction * the forward velocity
747
                # // we don't want to destory the Direction vector by using it instead.
748
                # // Scale the direction by our speed.
749
                v = copy.copy (self.m_DirectionVector);
750
                v *= self.m_ForwardVelocity;
751

    
752
                # // Increment our position by the vector
753
                self.m_Position.x += v.i;
754
                self.m_Position.y += v.j;
755
                self.m_Position.z += v.k;
756

    
757
                # // Translate to our new position.
758
                glTranslatef(-self.m_Position.x, -self.m_Position.y, -self.m_Position.z);
759
                return
760
                
761

    
762
"""
763
        //////////// MEMBER VARIBLES //////////////////////////////////////
764
        glVector vLightSourceToCamera, vLightSourceToIntersect;
765
        glPoint ptIntersect, pt;
766
        GLsizei m_WindowHeight;
767
        GLsizei m_WindowWidth;
768
        GLuint m_StreakTexture;
769
        GLuint m_HaloTexture;
770
        GLuint m_GlowTexture;
771
        GLuint m_BigGlowTexture;
772
        GLfloat m_MaxPointSize;
773
        GLfloat m_Frustum[6][4];
774
        glPoint m_LightSourcePos;
775
        GLfloat m_MaxPitchRate;
776
        GLfloat m_MaxHeadingRate;
777
        GLfloat m_HeadingDegrees;
778
        GLfloat m_PitchDegrees;
779
        GLfloat m_MaxForwardVelocity;
780
        GLfloat m_ForwardVelocity;
781
        glPoint m_Position;
782
        glVector m_DirectionVector;
783
"""
784