Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

flare.cpp

Go to the documentation of this file.
00001 /* Copyright (C) Yossarian King, 2000. 
00002  * All rights reserved worldwide.
00003  *
00004  * This software is provided "as is" without express or implied
00005  * warranties. You may freely copy and compile this source into
00006  * applications you distribute provided that the copyright text
00007  * below is included in the resulting source code, for example:
00008  * "Portions Copyright (C) Yossarian King, 2000"
00009  */
00010 /************************************************************
00011 
00012     Game Programming Gems
00013     Lens Flare Demo
00014 
00015     Y. King / May 2000
00016     Electronic Arts Canada, Inc.
00017 
00018  ************************************************************/
00019 
00020 // Modified by Alan Baylis 20/10/2002
00021 
00022 #include <GL/gl.h>
00023 #include <stdio.h>
00024 #include <stdlib.h>
00025 #include <memory.h>
00026 #include <math.h>
00027 #include <string.h>
00028 #include <time.h>
00029 
00030 #include "flare.h"
00031 #include "texture.h"
00032 #include "vector.h"
00033 #include "camera.h"
00034 
00035 extern float SunPosition[3];
00036 extern TEXTURE* texture;
00037 extern CAMERA* camera;
00038 extern int currentCamera;
00039 extern HWND hWnd;
00040 extern RECT screen;
00041 extern PAINTSTRUCT ps;
00042 
00043 /************************************************************
00044     Defines.
00045  ************************************************************/
00046 
00047 // Get height from width, assuming certain aspect ratio.
00048 #define HEIGHTFROMWIDTH(w)  ((w)*SCREENheight/SCREENwidth)
00049 
00050 #define isqrt(x)        (int)((double)(x))
00051 
00052 /************************************************************
00053     Texture management.
00054  ************************************************************/
00055 
00056 typedef struct TEXTURE_DEF
00057 {
00058     char* filename;
00059     TEXTURE* FlareTexture;
00060 }
00061     TEXTURE_DEF;
00062 
00063 // Texture enumeration -- matches the data that gets loaded.
00064 enum
00065 {
00066     TEX_CRCL,
00067     TEX_HXGN,
00068     TEX_RING,
00069     TEX_FLAR,
00070     NPIECETEXTURES,
00071     TEX_SUN = NPIECETEXTURES,
00072     TEX_BACK,
00073     NTEXTURES
00074 };
00075 
00076 
00077 // Source files for textures.
00078 TEXTURE_DEF gTextures[ NTEXTURES ] =
00079             {
00080                 { "crcl.tga" },
00081                 { "hxgn.tga" },
00082                 { "ring.tga" },
00083                 { "flar.tga" },
00084                 { "sun.tga"  },
00085                 { "back.tga" }
00086             };
00087 TEXTURE_DEF *TM_getNthTexture( int n );
00088 TEXTURE_DEF *TM_getNamedTexture( char *name );
00089 void        TM_loadTextures( void );
00090 void        TM_setTexture( TEXTURE_DEF *tex );
00091 
00092 /************************************************************
00093     Internal function prototypes.
00094  ************************************************************/
00095 
00096 void    drawQuad( int x, int y, int width, int height, TEXTURE_DEF *tex, unsigned int colour );
00097 
00098 /************************************************************
00099     Global variables.
00100  ************************************************************/
00101 
00102 int     SCREENwidth = screen.right;
00103 int     SCREENheight = screen.bottom;
00104 
00105 /************************************************************
00106 
00107     Public:
00108         FLARE_randomize
00109 
00110     Description:
00111         Generate a random lens flare.
00112 
00113  ************************************************************/
00114 
00115 void    FLARE_randomize(FLARE_DEF *flare,
00116                         int nTextures,
00117                         int nPieces,
00118                         float fMaxSize,
00119                         unsigned int minColour,
00120                         unsigned int maxColour)
00121 {
00122     int             i;
00123     float           fFracDist;
00124     float           fEnvelopeSize;
00125     FLARE_ELEMENT_DEF *element;
00126 
00127     srand((unsigned)time(NULL));
00128 
00129     // Initialize flare with requested number of elements, with
00130     // random placement, colour, and size of elements.
00131     flare->nPieces = nPieces;
00132     flare->fScale = fMaxSize;
00133     flare->fMaxSize = fMaxSize;
00134     fFracDist = 1.0f/(float)(flare->nPieces - 1);
00135     
00136     for (i = 0; i < flare->nPieces; ++i)
00137     {
00138         element = &flare->element[i];
00139         element->fDistance = (fFracDist*i) + FLARE_FRANGE(0,fFracDist);
00140 
00141         // Envelope size is maximum at ends of line, minimum in the middle (i.e. two
00142         // cones, touching at the tips).
00143         fEnvelopeSize = (float)fabs(1.0f - 2*element->fDistance);
00144 
00145         element->fSize = FLARE_FRANGE(0.6f, 1.0f) * fEnvelopeSize;
00146         element->argb = FLARE_RANGE(minColour & 0xff000000, maxColour & 0xff000000) |
00147                         FLARE_RANGE(minColour & 0x00ff0000, maxColour & 0x00ff0000) |
00148                         FLARE_RANGE(minColour & 0x0000ff00, maxColour & 0x0000ff00) |
00149                         FLARE_RANGE(minColour & 0x000000ff, maxColour & 0x000000ff);
00150         element->texture = TM_getNthTexture( FLARE_RANGE(0, nTextures - 1) );
00151     }
00152 }
00153 
00154 /************************************************************
00155 
00156     Public:
00157         FLARE_render
00158 
00159     Description:
00160         Draw lens flare with specified (lx,ly) light position
00161         in screen coordinates, for given (cx,cy) position of
00162         center of screen.
00163 
00164  ************************************************************/
00165 
00166 void    FLARE_render(FLARE_DEF *flare, int lx, int ly, int cx, int cy)
00167 {
00168     int     dx, dy;          // Screen coordinates of "destination"
00169     int     px, py;          // Screen coordinates of flare element
00170     int     maxflaredist, flaredist, flaremaxsize, flarescale;
00171     int     width, height, alpha;    // Piece parameters;
00172     int     i;
00173     FLARE_ELEMENT_DEF    *element;
00174 
00175     // Compute how far off-center the flare source is.
00176     maxflaredist = isqrt(cx*cx + cy*cy);
00177     flaredist = isqrt((lx - cx)*(lx - cx)+
00178                       (ly - cy)*(ly - cy));
00179     flaredist = (maxflaredist - flaredist);
00180     flaremaxsize = (int)(SCREENwidth * flare->fMaxSize);
00181     flarescale = (int)(SCREENwidth * flare->fScale);
00182 
00183     // Destination is opposite side of centre from source
00184     dx = cx + (cx - lx);
00185     dy = cy + (cy - ly);
00186 
00187     // Render each element.
00188     for (i = 0; i < flare->nPieces; ++i)
00189     {
00190         element = &flare->element[i];
00191 
00192         // Position is interpolated along line between start and destination.
00193         px = (int)((1.0f - element->fDistance)*lx + element->fDistance*dx);
00194         py = (int)((1.0f - element->fDistance)*ly + element->fDistance*dy);
00195 
00196         // Piece size are 0 to 1; flare size is proportion of
00197         // screen width; scale by flaredist/maxflaredist.
00198         width = (int)((flaredist*flarescale*element->fSize)/maxflaredist);
00199 
00200         // Width gets clamped, to allows the off-axis flares
00201         // to keep a good size without letting the elements get
00202         // too big when centered.
00203         if (width > flaremaxsize)
00204         {
00205             width = flaremaxsize;
00206         }
00207 
00208         // Flare elements are square (round) so height is just
00209         // width scaled by aspect ratio.
00210         height = HEIGHTFROMWIDTH(width);
00211         alpha = (flaredist*(element->argb >> 24))/maxflaredist;
00212 
00213         if ( width > 1 )
00214         {
00215             unsigned int    argb = (alpha << 24 ) | (element->argb & 0x00ffffff);
00216 
00217             drawQuad( px - width/2, py - height/2, width, height, element->texture, argb );
00218         }
00219     }
00220 }
00221 
00222 /*
00223     drawQuad -- used to draw individual elements of the lens flare
00224     in 2D. This is the main thing that needs to be changed to render
00225     with a different engine (e.g. D3D instead of OpenGL).
00226 */
00227 
00228 void    drawQuad( int x, int y, int width, int height, TEXTURE_DEF *tex, unsigned int colour )
00229 {
00230     glBindTexture(GL_TEXTURE_2D, tex->FlareTexture->TexID);
00231 
00232     glBegin(GL_QUADS);
00233 
00234     glColor4ub( (GLbyte)(colour >> 16 & 0xff),
00235                 (GLbyte)(colour >>  8 & 0xff),
00236                 (GLbyte)(colour >>  0 & 0xff),
00237                 (GLbyte)(colour >> 24 & 0xff) );
00238 
00239     glTexCoord2f( 0.0f, 0.0f );
00240     glVertex3f( x, y, 1.0);
00241     glTexCoord2f( 1.0f, 0.0f );
00242     glVertex3f( x + width, y, 1.0);
00243     glTexCoord2f( 1.0f, 1.0f );
00244     glVertex3f( x + width, y + height, 1.0);
00245     glTexCoord2f( 0.0f, 1.0f );
00246     glVertex3f( x, y + height, 1.0);
00247 
00248     glEnd();
00249 }
00250 
00251 
00252 // -------------- texture manager ---------------
00253 
00254 TEXTURE_DEF *TM_getNthTexture( int n )
00255 {
00256     if ( ( n < 0 ) || ( n >= NTEXTURES ) )
00257         return NULL;
00258 
00259     return &gTextures[n];
00260 }
00261 
00262 TEXTURE_DEF *TM_getNamedTexture( char *name )
00263 {
00264     int     i;
00265 
00266     for ( i = 0; i < NTEXTURES; ++i )
00267     {
00268         if ( strncmp( name, gTextures[i].FlareTexture->TexName, strlen( name ) ) == 0 )
00269             return &gTextures[i];
00270     }
00271 
00272     return NULL;
00273 }
00274 
00275 void    TM_loadTextures( void )
00276 {
00277     int             i;
00278 
00279     TEXTURE_DEF *tex = &gTextures[0];
00280 
00281     for ( i = 0; i < NTEXTURES; ++i, ++tex )
00282     {
00283         tex->FlareTexture->LoadTGA();            
00284     }
00285 }
00286 
00287 #define FLARE_MINCOLOUR        MAKEID(60, 255, 200, 0)
00288 #define FLARE_MAXCOLOUR        MAKEID(220, 235, 235, 64)
00289 #define FLARE_MINELEMENTSPERFLARE         8
00290 #define FLARE_MAXSIZE                   0.2f
00291 
00292 FLARE_DEF       renderFlare;    // Flare to render.
00293 
00294 void    loadFlareFile( FLARE_DEF *flare, char *filename )
00295 {
00296     int     n = 0;
00297     FILE    *f;
00298     char    buf[256];
00299 
00300     memset( flare, 0, sizeof( FLARE_DEF ) );
00301 
00302     f = fopen( filename, "r" );
00303     if ( f )
00304     {
00305         fgets( buf, sizeof( buf ), f );
00306         sscanf( buf, "%f %f", &flare->fScale, &flare->fMaxSize );
00307 
00308         while ( !feof(f) )
00309         {
00310             char            name[8] = { '\0', };
00311             double          dDist = 0.0, dSize = 0.0;
00312             unsigned int    a = 0, r = 0, g = 0, b = 0;
00313 
00314             fgets( buf, sizeof( buf ), f );
00315             if ( sscanf( buf, "%s %lf %lf ( %d %d %d %d )",
00316                     name, &dDist, &dSize, &a, &r, &g, &b ) )
00317             {
00318                 flare->element[ n ].texture = TM_getNamedTexture( name );
00319                 flare->element[ n ].fDistance = (float)dDist;
00320                 flare->element[ n ].fSize = (float)dSize;
00321                 flare->element[ n ].argb = ( a << 24 ) | ( r << 16 ) | ( g << 8 ) | ( b << 0 );
00322 
00323                 ++n;
00324             }
00325         }
00326 
00327         flare->nPieces = n;
00328 
00329         fclose( f );
00330     }
00331 }
00332 
00333 void    newFlare( int bFromFile )
00334 {
00335     if ( bFromFile )
00336         loadFlareFile( &renderFlare, "flare.txt" );
00337     else
00338         FLARE_randomize(&renderFlare, NPIECETEXTURES, FLARE_RANGE(FLARE_MINELEMENTSPERFLARE, FLARE_MAXELEMENTSPERFLARE), FLARE_MAXSIZE, FLARE_MINCOLOUR, FLARE_MAXCOLOUR);
00339 }
00340 
00341 void  DrawLensFlare()
00342 {       
00343     VECTOR suns_position(25.0 + camera[currentCamera].Position.x, 20.0 + camera[currentCamera].Position.y, -35.0 + camera[currentCamera].Position.z);
00344 
00345     SunPosition[1] = -1.0;
00346     SunPosition[2] = -1.0;
00347 
00348     glRenderMode(GL_FEEDBACK);
00349     glBegin(GL_POINTS);
00350         glVertex3fv(&suns_position.x);
00351     glEnd();
00352     glRenderMode(GL_RENDER);
00353 
00354     SunPosition[2] = screen.bottom - SunPosition[2];
00355 
00356 //  Set for orthographic projection.
00357     glPushMatrix();
00358     glMatrixMode(GL_PROJECTION);
00359     glPushMatrix();
00360        gluOrtho2D(0, SCREENwidth, SCREENheight, 0);
00361     glMatrixMode(GL_MODELVIEW);
00362     glLoadIdentity();
00363 
00364     glDisable(GL_DEPTH_TEST);
00365     glDisable(GL_LIGHTING);
00366     glDisable(GL_CULL_FACE);
00367     glEnable(GL_BLEND);
00368     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00369 
00370     if ((SunPosition[1] != -1.0))
00371     {
00372         // Calculate alpha value for sun glare
00373         int position[2];
00374         position[1] = abs((int)SunPosition[1] - 400);
00375         position[2] = abs((int)SunPosition[2] - 300);
00376         float glare_distance = sqrt(position[1] * position[1] + position[2] * position[2]);
00377         float alpha = 1.0 - glare_distance / 500.0;
00378 
00379         // Render sun glare - I know it's a 32 bit texture but this is just a demo
00380         glBindTexture(GL_TEXTURE_2D, texture[6].TexID);
00381 
00382         glBegin(GL_QUADS);
00383 
00384         glColor4f(1.0, 1.0, 1.0, alpha - 0.3);
00385 
00386         glTexCoord2f( 0.0f, 0.0f );
00387         glVertex3f(0, 0, 1.0);
00388         glTexCoord2f( 1.0f, 0.0f );
00389         glVertex3f(800, 0, 1.0);
00390         glTexCoord2f( 1.0f, 1.0f );
00391         glVertex3f(800, 600, 1.0);
00392         glTexCoord2f( 0.0f, 1.0f );
00393         glVertex3f(0, 600, 1.0);
00394 /*
00395         glTexCoord2f( 0.0f, 0.0f );
00396         glVertex3f(SunPosition[1] - 400, SunPosition[2] - 300, 2.0);
00397         glTexCoord2f( 1.0f, 0.0f );
00398         glVertex3f(SunPosition[1] + 400, SunPosition[2] - 300, 2.0);
00399         glTexCoord2f( 1.0f, 1.0f );
00400         glVertex3f(SunPosition[1] + 400, SunPosition[2] + 300, 2.0);
00401         glTexCoord2f( 0.0f, 1.0f );
00402         glVertex3f(SunPosition[1] - 400, SunPosition[2] + 300, 2.0);
00403 */
00404         glEnd();
00405         
00406         FLARE_render(&renderFlare, (int)SunPosition[1], (int)SunPosition[2], SCREENwidth/2, SCREENheight/2);
00407     }
00408 
00409     glMatrixMode(GL_PROJECTION);
00410     glPopMatrix();
00411     glMatrixMode(GL_MODELVIEW);
00412     glPopMatrix();
00413 
00414     glEnable(GL_DEPTH_TEST);
00415     glEnable(GL_LIGHTING);
00416     glEnable(GL_CULL_FACE);
00417     glDisable(GL_BLEND);
00418 }
00419 
00420 void InitializeLensFlare()
00421 {
00422     SCREENwidth = screen.right;
00423     SCREENheight = screen.bottom;
00424 
00425     for (int loop = 0; loop < NTEXTURES; loop++)
00426     {
00427         gTextures[loop].FlareTexture = new TEXTURE;
00428         sprintf(gTextures[loop].FlareTexture->TexName, "%s", gTextures[loop].filename);
00429     }
00430     TM_loadTextures();
00431     newFlare( 0 );
00432 
00433     glFeedbackBuffer(3, GL_2D, SunPosition);
00434 }
00435 
00436 void ResetLensFlare()
00437 {
00438     FLARE_randomize(&renderFlare, NPIECETEXTURES, FLARE_RANGE(FLARE_MINELEMENTSPERFLARE, FLARE_MAXELEMENTSPERFLARE), FLARE_MAXSIZE, FLARE_MINCOLOUR, FLARE_MAXCOLOUR);
00439 }
00440 
00441 void CleanupLensFlare()
00442 {
00443     for (int loop = 0; loop < NTEXTURES; loop++)
00444     {
00445         delete gTextures[loop].FlareTexture;
00446     }
00447 }

Generated on Fri Dec 23 05:21:20 2005 for Skybox by doxygen1.2.15