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  # // I don't mind if you use this class in your own code. All I ask is  # // that you give me credit for it if you do. And plug NeHe while your  # // at it! :P Thanks go to David Steere, Cameron Tidwell, Bert Sammons,  # // and Brannon Martindale for helping me test all the code! Enjoy.  # //////////////////////////////////////////////////////////////////////  # // glCamera.h: interface for the glCamera class.  # //////////////////////////////////////////////////////////////////////  #  # //////////////////////////////////////////////////////////////////////  # // Some minimal additions by rIO.Spinning Kids  # // For testing flares against occluding objects.  # // Not using proprietary extensions, this is PURE OpenGL1.1  # //  # // Just call the IsOccluded function, passing it the glPoint to check  # //  # //////////////////////////////////////////////////////////////////////  #  # Ported to Python, PyOpenGL by Brian Leair 2004.  # The numarray python module can perform matrix math more effieciently  # than direct python code. However, for this tutorial the differnce  # in performance isn't huge and it makes for a better tutorial to see  # the math operations directly.  from OpenGL.GL import *  from OpenGL.GLU import *  from OpenGL.GLUT import *  from glPoint import *  from glVector import *  from math import sqrt, fabs  try:   import numpy as Numeric  except ImportError, err:   try:   import Numeric   except ImportError, err:   print "This demo requires the numpy or Numeric extension, sorry"   import sys   sys.exit()  import copy  class glCamera:   # //////////// CONSTRUCTORS /////////////////////////////////////////   def __init__ (self):   # // Initalize all our member varibles.   self.m_MaxPitchRate = 0.0;   self.m_MaxHeadingRate = 0.0;   self.m_HeadingDegrees = 0.0;   self.m_PitchDegrees = 0.0;   self.m_MaxForwardVelocity = 0.0;   self.m_ForwardVelocity = 0.0;   self.m_GlowTexture = None;   # bleair: NOTE that glCamera.cpp has a bug. m_BigGlowTexture isn't initialized.   # Very minor bug because only in the case where we fail to get an earlier   # texture will the class potentially read from the uninited memory. Most of   # the time the field is assigned to straight away in InitGL ().   self.m_BigGlowTexture = None;   self.m_HaloTexture = None;   self.m_StreakTexture = None;   self.m_MaxPointSize = 0.0;   self.m_Frustum = Numeric.zeros ( (6,4), 'f')   self.m_LightSourcePos = glPoint ()   self.m_Position = glPoint ()   self.m_DirectionVector = glVector ()   self.m_ptIntersect = glPoint ()   def __del__ (self):   self.release ()   return   def release (self):   if (self.m_GlowTexture != None):   glDeleteTextures (self.m_GlowTexture)   if (self.m_HaloTexture != None):   glDeleteTextures (self.m_HaloTexture)   if (self.m_BigGlowTexture != None):   glDeleteTextures (self.m_BigGlowTexture)   if (self.m_StreakTexture != None):   glDeleteTextures (self.m_StreakTexture)   return   def ChangePitch (self, degrees):   if (fabs (degrees) < fabs (self.m_MaxPitchRate)):   # // Our pitch is less than the max pitch rate that we   # // defined so lets increment it.   self.m_PitchDegrees += degrees;   else:   # // Our pitch is greater than the max pitch rate that   # // we defined so we can only increment our pitch by the   # // maximum allowed value.   if(degrees < 0):   # // We are pitching down so decrement   self.m_PitchDegrees -= self.m_MaxPitchRate;   else:   # // We are pitching up so increment   self.m_PitchDegrees += self.m_MaxPitchRate;   # // We don't want our pitch to run away from us. Although it   # // really doesn't matter I prefer to have my pitch degrees   # // within the range of -360.0f to 360.0f   if (self.m_PitchDegrees > 360.0):   self.m_PitchDegrees -= 360.0;   elif (self.m_PitchDegrees < -360.0):   self.m_PitchDegrees += 360.0;   return   def ChangeHeading (self, degrees):   if(fabs(degrees) < fabs(self.m_MaxHeadingRate)):   # // Our Heading is less than the max heading rate that we   # // defined so lets increment it but first we must check   # // to see if we are inverted so that our heading will not   # // become inverted.   if (self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270 or   (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):   self.m_HeadingDegrees -= degrees;   else:   self.m_HeadingDegrees += degrees;   else:   # // Our heading is greater than the max heading rate that   # // we defined so we can only increment our heading by the   # // maximum allowed value.   if(degrees < 0):   # // Check to see if we are upside down.   if ((self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270) or   (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):   # // Ok we would normally decrement here but since we are upside   # // down then we need to increment our heading   self.m_HeadingDegrees += self.m_MaxHeadingRate;   else:   # // We are not upside down so decrement as usual   self.m_HeadingDegrees -= self.m_MaxHeadingRate;   else:   # // Check to see if we are upside down.   if (self.m_PitchDegrees > 90 and self.m_PitchDegrees < 270 or   (self.m_PitchDegrees < -90 and self.m_PitchDegrees > -270)):   # // Ok we would normally increment here but since we are upside   # // down then we need to decrement our heading.   self.m_HeadingDegrees -= self.m_MaxHeadingRate;   else:   # // We are not upside down so increment as usual.   self.m_HeadingDegrees += self.m_MaxHeadingRate;     # // We don't want our heading to run away from us either. Although it   # // really doesn't matter I prefer to have my heading degrees   # // within the range of -360.0f to 360.0f   if(self.m_HeadingDegrees > 360.0):   self.m_HeadingDegrees -= 360.0;   elif(self.m_HeadingDegrees < -360.0):   self.m_HeadingDegrees += 360.0;   return   # //////////// FUNCTIONS TO CHANGE CAMERA ORIENTATION AND SPEED /////   def ChangeVelocity(self, vel):   if(fabs(vel) < fabs(self.m_MaxForwardVelocity)):   # // Our velocity is less than the max velocity increment that we   # // defined so lets increment it.   self.m_ForwardVelocity += vel;   else:   # // Our velocity is greater than the max velocity increment that   # // we defined so we can only increment our velocity by the   # // maximum allowed value.   if(vel < 0):   # // We are slowing down so decrement   self.m_ForwardVelocity -= -self.m_MaxForwardVelocity;   else:   # // We are speeding up so increment   self.m_ForwardVelocity += self.m_MaxForwardVelocity;   return   def UpdateFrustum(self):   """ // I found this code here: http://www.markmorley.com/opengl/frustumculling.html   // and decided to make it part of   // the camera class just in case I might want to rotate   // and translate the projection matrix. This code will   // make sure that the Frustum is updated correctly but   // this member is computational expensive with:   // 82 muliplications, 72 additions, 24 divisions, and   // 12 subtractions for a total of 190 operations. Ouch! """   # /* Get the current PROJECTION matrix from OpenGL */   proj = glGetFloatv( GL_PROJECTION_MATRIX);   # /* Get the current MODELVIEW matrix from OpenGL */   modl = glGetFloatv( GL_MODELVIEW_MATRIX);   # /* Combine the two matrices (multiply projection by modelview) */   # Careful, Note, that replication is simple scalars is OK, but replicate of objects   # and lists is very bad.   clip = [None,] * 16   # clip = Numeric.zeros ( (16), 'f')   clip[ 0] = modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];   clip[ 1] = modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];   clip[ 2] = modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];   clip[ 3] = modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];   clip[ 4] = modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];   clip[ 5] = modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];   clip[ 6] = modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];   clip[ 7] = modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];   clip[ 8] = modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];   clip[ 9] = modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];   clip[10] = modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];   clip[11] = modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];   clip[12] = modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];   clip[13] = modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];   clip[14] = modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];   clip[15] = modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];   # ### Use a shortened name to reference to our camera's Frustum (does   # ### not copy anything, just a ref to make code less wordy   Frustum = self.m_Frustum   # /* Extract the numbers for the RIGHT plane */   Frustum[0][0] = clip[ 3] - clip[ 0];   Frustum[0][1] = clip[ 7] - clip[ 4];   Frustum[0][2] = clip[11] - clip[ 8];   Frustum[0][3] = clip[15] - clip[12];   # /* Normalize the result */   t = (sqrt( Frustum[0][0] * Frustum[0][0] + \   Frustum[0][1] * Frustum[0][1] + Frustum[0][2] * Frustum[0][2] ));   Frustum[0][0] /= t;   Frustum[0][1] /= t;   Frustum[0][2] /= t;   Frustum[0][3] /= t;   # /* Extract the numbers for the LEFT plane */   Frustum[1][0] = clip[ 3] + clip[ 0];   Frustum[1][1] = clip[ 7] + clip[ 4];   Frustum[1][2] = clip[11] + clip[ 8];   Frustum[1][3] = clip[15] + clip[12];   # /* Normalize the result */   t = sqrt( Frustum[1][0] * Frustum[1][0] + Frustum[1][1] * Frustum[1][1] + Frustum[1][2] * Frustum[1][2] );   Frustum[1][0] /= t;   Frustum[1][1] /= t;   Frustum[1][2] /= t;   Frustum[1][3] /= t;   # /* Extract the BOTTOM plane */   Frustum[2][0] = clip[ 3] + clip[ 1];   Frustum[2][1] = clip[ 7] + clip[ 5];   Frustum[2][2] = clip[11] + clip[ 9];   Frustum[2][3] = clip[15] + clip[13];   # /* Normalize the result */   t = sqrt( Frustum[2][0] * Frustum[2][0] + Frustum[2][1] * Frustum[2][1] + Frustum[2][2] * Frustum[2][2] );   Frustum[2][0] /= t;   Frustum[2][1] /= t;   Frustum[2][2] /= t;   Frustum[2][3] /= t;   # /* Extract the TOP plane */   Frustum[3][0] = clip[ 3] - clip[ 1];   Frustum[3][1] = clip[ 7] - clip[ 5];   Frustum[3][2] = clip[11] - clip[ 9];   Frustum[3][3] = clip[15] - clip[13];   # /* Normalize the result */   t = sqrt( Frustum[3][0] * Frustum[3][0] + Frustum[3][1] * Frustum[3][1] + Frustum[3][2] * Frustum[3][2] )   Frustum[3][0] /= t;   Frustum[3][1] /= t;   Frustum[3][2] /= t;   Frustum[3][3] /= t;   # /* Extract the FAR plane */   Frustum[4][0] = clip[ 3] - clip[ 2];   Frustum[4][1] = clip[ 7] - clip[ 6];   Frustum[4][2] = clip[11] - clip[10];   Frustum[4][3] = clip[15] - clip[14];   # /* Normalize the result */   t = sqrt( Frustum[4][0] * Frustum[4][0] + Frustum[4][1] * Frustum[4][1] + Frustum[4][2] * Frustum[4][2] )   Frustum[4][0] /= t;   Frustum[4][1] /= t;   Frustum[4][2] /= t;   Frustum[4][3] /= t;   # /* Extract the NEAR plane */   Frustum[5][0] = clip[ 3] + clip[ 2];   Frustum[5][1] = clip[ 7] + clip[ 6];   Frustum[5][2] = clip[11] + clip[10];   Frustum[5][3] = clip[15] + clip[14];   # /* Normalize the result */   t = sqrt( Frustum[5][0] * Frustum[5][0] + Frustum[5][1] * Frustum[5][1] + Frustum[5][2] * Frustum[5][2] );   Frustum[5][0] /= t;   Frustum[5][1] /= t;   Frustum[5][2] /= t;   Frustum[5][3] /= t;   return   # //////////// FUNCTIONS TO UPDATE THE FRUSTUM //////////////////////   def UpdateFrustumFaster (self):   """ // This is the much faster version of the above member   // function, however the speed increase is not gained   // without a cost. If you rotate or translate the projection   // matrix then this member will not work correctly. That is acceptable   // in my book considering I very rarely do such a thing.   // This function has far fewer operations in it and I   // shaved off 2 square root functions by passing in the   // near and far values. This member has:   // 38 muliplications, 28 additions, 24 divisions, and   // 12 subtractions for a total of 102 operations. Still hurts   // but at least it is decent now. In practice this will   // run about 2 times faster than the above function. """   # /* Get the current PROJECTION matrix from OpenGL */   proj = glGetFloatv( GL_PROJECTION_MATRIX);     # /* Get the current MODELVIEW matrix from OpenGL */   modl = glGetFloatv( GL_MODELVIEW_MATRIX);     # /* Combine the two matrices (multiply projection by modelview)   # but keep in mind this function will only work if you do NOT   # rotate or translate your projection matrix */   clip = [0,] * 16   modl_row1 = modl [0]   clip[ 0] = modl [0] [0] * proj[0][0];   clip[ 1] = modl [0][ 1] * proj[1][1];   clip[ 2] = modl [0][ 2] * proj[2][2] + modl_row1[ 3] * proj[3][2]   clip[ 3] = modl [0][ 2] * proj[2][3]     modl_row2 = modl [1]   clip[ 4] = modl_row2[ 0] * proj[0][0]   clip[ 5] = modl_row2[ 1] * proj[1][1]   clip[ 6] = modl_row2[ 2] * proj[2][2] + modl_row2[ 3] * proj[3][2]   clip[ 7] = modl_row2[ 2] * proj[2][3]     modl_row3 = modl [2]   clip[ 8] = modl_row3[ 0] * proj[0][0];   clip[ 9] = modl_row3[ 1] * proj[1][1]   clip[10] = modl_row3[2] * proj[2][2] + modl_row3[3] * proj[3][2]   clip[11] = modl_row3[2] * proj[2][3]     modl_row4 = modl [3]   clip[12] = modl_row4[0] * proj[0][0]   clip[13] = modl_row4[1] * proj[1][1]   clip[14] = modl_row4[2] * proj[2][2] + modl_row4[3] * proj[3][2]   clip[15] = modl_row4[2] * proj[2][3]     # ### Use a shortened name to reference to our camera's Frustum (does   # ### not copy anything, just a ref to make code less wordy   Frustum = self.m_Frustum   # /* Extract the numbers for the RIGHT plane */   Frustum[0][0] = clip[ 3] - clip[ 0];   Frustum[0][1] = clip[ 7] - clip[ 4];   Frustum[0][2] = clip[11] - clip[ 8];   Frustum[0][3] = clip[15] - clip[12];     # /* Normalize the result */   t = sqrt( (Frustum[0][0] * Frustum[0][0]) + (Frustum[0][1] * Frustum[0][1]) + (Frustum[0][2] * Frustum[0][2]) );   Frustum[0][0] /= t;   Frustum[0][1] /= t;   Frustum[0][2] /= t;   Frustum[0][3] /= t;     # /* Extract the numbers for the LEFT plane */   Frustum[1][0] = clip[ 3] + clip[ 0];   Frustum[1][1] = clip[ 7] + clip[ 4];   Frustum[1][2] = clip[11] + clip[ 8];   Frustum[1][3] = clip[15] + clip[12];     # /* Normalize the result */   t = sqrt( Frustum[1][0] * Frustum[1][0] + Frustum[1][1] * Frustum[1][1] + Frustum[1][2] * Frustum[1][2] );   Frustum[1][0] /= t;   Frustum[1][1] /= t;   Frustum[1][2] /= t;   Frustum[1][3] /= t;     # /* Extract the BOTTOM plane */   Frustum[2][0] = clip[ 3] + clip[ 1];   Frustum[2][1] = clip[ 7] + clip[ 5];   Frustum[2][2] = clip[11] + clip[ 9];   Frustum[2][3] = clip[15] + clip[13];     # /* Normalize the result */   t = sqrt( Frustum[2][0] * Frustum[2][0] + Frustum[2][1] * Frustum[2][1] + Frustum[2][2] * Frustum[2][2] );   Frustum[2][0] /= t;   Frustum[2][1] /= t;   Frustum[2][2] /= t;   Frustum[2][3] /= t;     # /* Extract the TOP plane */   Frustum[3][0] = clip[ 3] - clip[ 1];   Frustum[3][1] = clip[ 7] - clip[ 5];   Frustum[3][2] = clip[11] - clip[ 9];   Frustum[3][3] = clip[15] - clip[13];     # /* Normalize the result */   t = sqrt( Frustum[3][0] * Frustum[3][0] + Frustum[3][1] * Frustum[3][1] + Frustum[3][2] * Frustum[3][2] );   Frustum[3][0] /= t;   Frustum[3][1] /= t;   Frustum[3][2] /= t;   Frustum[3][3] /= t;     # /* Extract the FAR plane */   Frustum[4][0] = clip[ 3] - clip[ 2];   Frustum[4][1] = clip[ 7] - clip[ 6];   Frustum[4][2] = clip[11] - clip[10];   Frustum[4][3] = clip[15] - clip[14];     # /* Normalize the result */   t = sqrt( (Frustum[4][0] * Frustum[4][0]) + (Frustum[4][1] * Frustum[4][1]) + (Frustum[4][2] * Frustum[4][2]) );   Frustum[4][0] /= t;   Frustum[4][1] /= t;   Frustum[4][2] /= t;   Frustum[4][3] /= t;     # /* Extract the NEAR plane */   Frustum[5][0] = clip[ 3] + clip[ 2];   Frustum[5][1] = clip[ 7] + clip[ 6];   Frustum[5][2] = clip[11] + clip[10];   Frustum[5][3] = clip[15] + clip[14];     # /* Normalize the result */   t = sqrt( Frustum[5][0] * Frustum[5][0] + Frustum[5][1] * Frustum[5][1] + Frustum[5][2] * Frustum[5][2] );   Frustum[5][0] /= t;   Frustum[5][1] /= t;   Frustum[5][2] /= t;   Frustum[5][3] /= t;   return       # //////////// FRUSTUM TESTING FUNCTIONS ////////////////////////////   def SphereInFrustum(self, p, Radius):   """ // This member function checks to see if a sphere is in   // the viewing volume. """   Frustum = self.m_Frustum   # // The idea here is the same as the PointInFrustum function.   if (Radius != 0):   for i in xrange (6):   # // If the point is outside of the plane then its not in the viewing volume.   if(Frustum[i][0] * p.x + Frustum[i][1] * p.y + Frustum[i][2] * p.z + Frustum[i][3] <= -Radius):   return(False);   else:   # // The idea here is the same as the PointInFrustum function.   for i in xrange (6):   # // If the point is outside of the plane then its not in the viewing volume.   if(Frustum[i][0] * p.x + Frustum[i][1] * p.y + Frustum[i][2] * p.z + Frustum[i][3] <= 0):   return(False);   return(True);   def PointInFrustum(self, x,y,z):   """ // This member fuction checks to see if a point is in   // the viewing volume. """   # // The idea behind this algorithum is that if the point   # // is inside all 6 clipping planes then it is inside our   # // viewing volume so we can return true.   Frustum = self.m_Frustum   # // Loop through all our clipping planes   for i in xrange (6):   # // If the point is outside of the plane then its not in the viewing volume.   if(Frustum[i][0] * x + Frustum[i][1] * y + Frustum[i][2] * z + Frustum[i][3] <= 0):   return(False);   return(True);   # /////////// OCCLUSION TESTING FUNCTIONS ///////////////////////////   def IsOccluded (self, p):   # // Now we will ask OGL to project some geometry for us using the gluProject function.   # // Practically we ask OGL to guess where a point in space will be projected in our current viewport,   # // using arbitrary viewport and transform matrices we pass to the function.   # // If we pass to the function the current matrices (retrievede with the glGet funcs)   # // we will have the real position on screen where the dot will be drawn.   # // The interesting part is that we also get a Z value back, this means that   # // reading the REAL buffer for Z values we can discover if the flare is in front or   # // if it's occluded by some objects.   # ### This function should be a flat function, not a function of the camera as we   # ### use the immediate GL rendering state entirely.   # ### Viewport is the rectangle of window pixels that OpenGL is rasterizing into.   viewport = glGetIntegerv (GL_VIEWPORT); # //get actual viewport   mvmatrix = glGetDoublev (GL_MODELVIEW_MATRIX); # //get actual model view matrix   projmatrix = glGetDoublev (GL_PROJECTION_MATRIX); # //get actual projiection matrix   # // this asks OGL to guess the 2d position of a 3d point inside the viewport   winx, winy, winz = gluProject(p.x, p.y, p.z, mvmatrix, projmatrix, viewport)   flareZ = winz;   # // we read back one pixel from th depth buffer (exactly where our flare should be drawn)   glPixelStorei(GL_PACK_ALIGNMENT, 1)   # PyOpenGL 2.0.1.07 bug, Only the type clarified function works.   # bufferZ = glReadPixels(int(winx), int(winy),1,1,GL_DEPTH_COMPONENT, GL_FLOAT)   bufferZ = glReadPixelsf(int(winx), int(winy),1,1,GL_DEPTH_COMPONENT)   # // if the buffer Z is lower than our flare guessed Z then don't draw   # // this means there is something in front of our flare   if (bufferZ [0] [0] < flareZ):   return True;   else:   return False;   # //////////// FUNCTIONS TO RENDER LENS FLARES //////////////////////   def RenderLensFlare(self):   # // Draw the flare only If the light source is in our line of sight (inside the Frustum)   if (self.SphereInFrustum(self.m_LightSourcePos, 1.0) == True):   # Vector pointing from the light's position toward the camera's position (the camera might   # be pointing elsewhere, this vector is pointing from the light to the camera)   self.vLightSourceToCamera = self.m_Position - self.m_LightSourcePos; # // Lets compute the vector that points to the camera from   # // the light source.   Length = self.vLightSourceToCamera.Magnitude () # // Save the length we will need it in a minute   # Move down our look-toward direction vector. Move down the look-toward the same dist. as the   # distance between camera and the light.   intersect = self.m_DirectionVector * Length   self.m_ptIntersect = glPoint (intersect.i, intersect.j, intersect.k)   # // Now lets find an point along the cameras direction   # // vector that we can use as an intersection point.   # // Lets translate down this vector the same distance   # // that the camera is away from the light source.   ptIntersect = self.m_ptIntersect   # Did the motion in the correct direction above, now translate the intersection position   # relative to our camera location.   ptIntersect += self.m_Position;   self.vLightSourceToIntersect = ptIntersect - self.m_LightSourcePos; # // Lets compute the vector that points to the Intersect   # // point from the light source     Length = self.vLightSourceToIntersect.Magnitude(); # // Save the length we will need it later.   self.vLightSourceToIntersect.Normalize(); # // Normalize the vector so its unit length   vLightSourceToIntersect = self.vLightSourceToIntersect     glEnable(GL_BLEND); # // You should already know what this does   glBlendFunc(GL_SRC_ALPHA, GL_ONE); # // You should already know what this does   glDisable(GL_DEPTH_TEST); # // You should already know what this does   glEnable(GL_TEXTURE_2D); # // You should already know what this does     # /////////// Differenet Color Glows & Streaks /////////////////////   # //RenderBigGlow(1.0f, 1.0f, 1.0f, 1.0f, m_LightSourcePos, 1.0f);   # //RenderStreaks(1.0f, 1.0f, 0.8f, 1.0f, m_LightSourcePos, 0.7f);   # //   # //RenderBigGlow(1.0f, 0.9f, 1.0f, 1.0f, m_LightSourcePos, 1.0f);   # //RenderStreaks(1.0f, 0.9f, 1.0f, 1.0f, m_LightSourcePos, 0.7f);   # //////////////////////////////////////////////////////////////////   # //########################## NEW STUFF ##################################   if (not self.IsOccluded(self.m_LightSourcePos)): # //Check if the center of the flare is occluded   # // Render the large hazy glow   self.RenderBigGlow(0.60, 0.60, 0.8, 1.0, self.m_LightSourcePos, 16.0);   # // Render the streaks   self.RenderStreaks(0.60, 0.60, 0.8, 1.0, self.m_LightSourcePos, 16.0);   # // Render the small Glow   self.RenderGlow(0.8, 0.8, 1.0, 0.5, self.m_LightSourcePos, 3.5);   pt = glPoint (vLightSourceToIntersect * (Length * 0.1)); # // Lets compute a point that is 20%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.9, 0.6, 0.4, 0.5, pt, 0.6); # // Render the small Glow   pt = glPoint (vLightSourceToIntersect * (Length * 0.15)); # // Lets compute a point that is 30%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.8, 0.5, 0.6, 0.5, pt, 1.7); # // Render the a Halo     pt = glPoint (vLightSourceToIntersect * (Length * 0.175)); # // Lets compute a point that is 35%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.9, 0.2, 0.1, 0.5, pt, 0.83); # // Render the a Halo   pt = glPoint (vLightSourceToIntersect * (Length * 0.285)); # // Lets compute a point that is 57%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.7, 0.7, 0.4, 0.5, pt, 1.6); # // Render the a Halo     pt = glPoint (vLightSourceToIntersect * (Length * 0.2755)); # // Lets compute a point that is 55.1%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.9, 0.9, 0.2, 0.5, pt, 0.8); # // Render the small Glow   pt = glPoint (vLightSourceToIntersect * (Length * 0.4775)); # // Lets compute a point that is 95.5%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.93, 0.82, 0.73, 0.5, pt, 1.0); # // Render the small Glow     pt = glPoint (vLightSourceToIntersect * (Length * 0.49)); # // Lets compute a point that is 98%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.7, 0.6, 0.5, 0.5, pt, 1.4); # // Render the a Halo   pt = glPoint (vLightSourceToIntersect * (Length * 0.65)); # // Lets compute a point that is 130%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.7, 0.8, 0.3, 0.5, pt, 1.8); # // Render the small Glow     pt = glPoint (vLightSourceToIntersect * (Length * 0.63)); # // Lets compute a point that is 126%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.4, 0.3, 0.2, 0.5, pt, 1.4); # // Render the small Glow   pt = glPoint (vLightSourceToIntersect * (Length * 0.8)); # // Lets compute a point that is 160%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.7, 0.5, 0.5, 0.5, pt, 1.4); # // Render the a Halo     pt = glPoint (vLightSourceToIntersect * (Length * 0.7825)); # // Lets compute a point that is 156.5%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.   self.RenderGlow(0.8, 0.5, 0.1, 0.5, pt, 0.6); # // Render the small Glow   pt = glPoint (vLightSourceToIntersect * (Length * 1.0)); # // Lets compute a point that is 200%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderHalo(0.5, 0.5, 0.7, 0.5, pt, 1.7); # // Render the a Halo     pt = glPoint (vLightSourceToIntersect * (Length * 0.975)); # // Lets compute a point that is 195%   pt += self.m_LightSourcePos; # // away from the light source in the   # // direction of the intersection point.     self.RenderGlow(0.4, 0.1, 0.9, 0.5, pt, 2.0); # // Render the small Glow   glDisable(GL_BLEND ); # // You should already know what this does   glEnable(GL_DEPTH_TEST); # // You should already know what this does   glDisable(GL_TEXTURE_2D); # // You should already know what this does   return   def RenderHalo (self, r, g, b, a, p, scale):   self.RenderFlareTexture (self.m_HaloTexture, r, g, b, a, p, scale)   return   def RenderGlow (self, r, g, b, a, p, scale):   self.RenderFlareTexture (self.m_GlowTexture, r, g, b, a, p, scale)   return   def RenderBigGlow (self, r, g, b, a, p, scale):   self.RenderFlareTexture (self.m_BigGlowTexture, r, g, b, a, p, scale)   return   def RenderStreaks (self, r, g, b, a, p, scale):   self.RenderFlareTexture (self.m_StreakTexture, r, g, b, a, p, scale)   return   def RenderFlareTexture (self, tex_ID, r, g, b, a, p, scale):   # bleair: Duplicate functions all the same except for the texture to bind to.   q = []   q.append (glPoint ())   q.append (glPoint ())   q.append (glPoint ())   q.append (glPoint ())   # // Basically we are just going to make a 2D box   # // from four points we don't need a z coord because   # // we are rotating the camera by the inverse so the   # // texture mapped quads will always face us.   q[0].x = (p.x - scale); # // Set the x coordinate -scale units from the center point.   q[0].y = (p.y - scale); # // Set the y coordinate -scale units from the center point.     q[1].x = (p.x - scale); # // Set the x coordinate -scale units from the center point.   q[1].y = (p.y + scale); # // Set the y coordinate scale units from the center point.     q[2].x = (p.x + scale); # // Set the x coordinate scale units from the center point.   q[2].y = (p.y - scale); # // Set the y coordinate -scale units from the center point.     q[3].x = (p.x + scale); # // Set the x coordinate scale units from the center point.   q[3].y = (p.y + scale); # // Set the y coordinate scale units from the center point.     glPushMatrix(); # // Save the model view matrix   glTranslatef(p.x, p.y, p.z); # // Translate to our point   glRotatef(-self.m_HeadingDegrees, 0.0, 1.0, 0.0);   glRotatef(-self.m_PitchDegrees, 1.0, 0.0, 0.0);   glBindTexture(GL_TEXTURE_2D, tex_ID); # // Bind to the Big Glow texture   glColor4f(r, g, b, a); # // Set the color since the texture is a gray scale     glBegin(GL_TRIANGLE_STRIP); # // Draw the Big Glow on a Triangle Strip   glTexCoord2f(0.0, 0.0);   glVertex2f(q[0].x, q[0].y);   glTexCoord2f(0.0, 1.0);   glVertex2f(q[1].x, q[1].y);   glTexCoord2f(1.0, 0.0);   glVertex2f(q[2].x, q[2].y);   glTexCoord2f(1.0, 1.0);   glVertex2f(q[3].x, q[3].y);   glEnd();   glPopMatrix(); # // Restore the model view matrix   return   def SetPrespective (self):   # Matrix = [0] * 16 # // A (list) array to hold the model view matrix.   # However the MODELVIEW was oriented, we now rotate it based upon our Camer object's state.   # // Going to use glRotate to calculate our direction vector   glRotatef(self.m_HeadingDegrees, 0.0, 1.0, 0.0); # turn your head left/right (around y axe)   glRotatef(self.m_PitchDegrees, 1.0, 0.0, 0.0); # nod your head up/down (around x axe)   # // Get the resulting matrix from OpenGL it will have our   # // direction vector in the 3rd row.   Matrix = glGetFloatv(GL_MODELVIEW_MATRIX);   # // Get the direction vector from the matrix. Element 10 must   # // be inverted!   self.m_DirectionVector.i = Matrix[2] [0] #[8];   self.m_DirectionVector.j = Matrix[2] [1] #[9];   self.m_DirectionVector.k = -Matrix[2] [2] #[10];   # #### bleair: no need to do this as this. Previous rotates already here (because   # #### all invocations have the modelview at identity.   # #### Suspect this was just a bit of code that was mvoed up and not deleted here.   # // Ok erase the results of the last computation.   glLoadIdentity();   # // Rotate the scene to get the right orientation.   glRotatef(self.m_PitchDegrees, 1.0, 0.0, 0.0);   glRotatef(self.m_HeadingDegrees, 0.0, 1.0, 0.0);   # // A vector to hold our cameras direction * the forward velocity   # // we don't want to destory the Direction vector by using it instead.   # // Scale the direction by our speed.   v = copy.copy (self.m_DirectionVector);   v *= self.m_ForwardVelocity;   # // Increment our position by the vector   self.m_Position.x += v.i;   self.m_Position.y += v.j;   self.m_Position.z += v.k;   # // Translate to our new position.   glTranslatef(-self.m_Position.x, -self.m_Position.y, -self.m_Position.z);   return    """   //////////// MEMBER VARIBLES //////////////////////////////////////   glVector vLightSourceToCamera, vLightSourceToIntersect;   glPoint ptIntersect, pt;   GLsizei m_WindowHeight;   GLsizei m_WindowWidth;   GLuint m_StreakTexture;   GLuint m_HaloTexture;   GLuint m_GlowTexture;   GLuint m_BigGlowTexture;   GLfloat m_MaxPointSize;   GLfloat m_Frustum[6][4];   glPoint m_LightSourcePos;   GLfloat m_MaxPitchRate;   GLfloat m_MaxHeadingRate;   GLfloat m_HeadingDegrees;   GLfloat m_PitchDegrees;   GLfloat m_MaxForwardVelocity;   GLfloat m_ForwardVelocity;   glPoint m_Position;   glVector m_DirectionVector;  """