root / PyOpenGLDemo / 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 looktoward direction vector. Move down the looktoward 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 