Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

fire.c

Go to the documentation of this file.
00001 
00002 #define SMOOTH_WRAP (GE_FALSE)
00003 
00004 //#define DO_TIMER
00005 
00006 #include "Fire.h"
00007 #include "genesis.h"
00008 #include "ram.h"
00009 #include "gebmutil.h"
00010 #include "proceng.h"
00011 #include "procutil.h"
00012 #include <stdlib.h>
00013 #include <string.h>
00014 #include <assert.h>
00015 #include <math.h>
00016 
00017 #ifdef DO_TIMER
00018 #include "timer.h"
00019 TIMER_VARS(Fire);
00020 TIMER_VARS(Fire_Smooth);
00021 TIMER_VARS(Fire_UnLock);
00022 TIMER_VARS(Fire_Rands);
00023 #endif
00024 
00025 #define BM_WIDTH        (128)
00026 #define BM_HEIGHT       (128)
00027 
00028 #define SeedLines       (1)
00029 
00030 geBoolean FireAnimator_CreateFire(Procedural * Proc);
00031 
00032 /**************************************************************/
00033 
00034 // optimized with ProcUtil_Rand() :
00035 //Fire                 : 0.000820 = 1221 fps
00036 //
00037 // about 700 fps with ProcUtil_Rand()
00038 // about 200 with the clib rand()
00039 
00040 #define myrand(max)     ProcUtil_Rand(max)
00041 
00042 /**************************************************************/
00043 
00044 Procedural *Fire_Create(geBitmap **ppBitmap, const char *ParmStart);
00045 void            Fire_Destroy(Procedural *Proc);
00046 geBoolean       Fire_Animate(Procedural *Fire, float ElapsedTime);
00047 
00048 static Procedural_Table Fire_Table = 
00049 {
00050         Procedurals_Version,Procedurals_Tag,
00051         "Fire",
00052         Fire_Create,
00053         Fire_Destroy,
00054         Fire_Animate
00055 };
00056 
00057 Procedural_Table * Fire_GetProcedural_Table(void)
00058 {
00059         return &Fire_Table;
00060 }
00061 
00062 /**********************************************************/
00063 
00064 typedef struct Procedural
00065 {
00066         geBitmap * Bitmap;
00067         uint32 Frame;
00068         geBoolean DoJets;
00069 } Procedural;
00070 
00071 /****/
00072 
00073 Procedural *Fire_Create(geBitmap **ppBitmap, const char *ParmStart)
00074 {
00075 Procedural * P;
00076 
00077         P = geRam_Allocate(sizeof(Procedural));
00078         if ( ! P )
00079                 return NULL;
00080         assert(P);
00081         memset(P,0,sizeof(Procedural));
00082 
00083         P->Frame = 0;
00084 
00085         if ( strlen(ParmStart) < 10 )
00086         {
00087                 ParmStart = "F, pow, 400,280,200,530, 0.3,0.6,1.0,0.8";
00088                 //ParmStart = "F, pow, 230,230,255,300, 0.2,0.5,1.0,0.4";
00089         }
00090 
00091         if ( ! *ppBitmap )
00092         {
00093                 *ppBitmap = geBitmap_Create(BM_WIDTH,BM_HEIGHT,1, GE_PIXELFORMAT_8BIT_PAL);
00094                 if ( ! *ppBitmap )
00095                 {
00096                         geRam_Free(P);
00097                         return NULL;
00098                 }
00099         }
00100         else
00101         {
00102                 geBitmap_CreateRef(*ppBitmap);
00103         }
00104 
00105         if ( ! geBitmap_SetFormat(*ppBitmap,GE_PIXELFORMAT_8BIT_PAL,GE_TRUE,255,NULL) )
00106         {
00107                 geRam_Free(P);
00108                 return NULL;
00109         }
00110 
00111         geBitmap_ClearMips(*ppBitmap);
00112 
00113         geBitmap_SetPreferredFormat(*ppBitmap,GE_PIXELFORMAT_16BIT_4444_ARGB);
00114 
00115         P->Bitmap = *ppBitmap;
00116 
00117         {
00118         char ParmWork[100];
00119         char *ptr;
00120         int len;
00121                 strncpy(ParmWork,ParmStart,100);
00122                 ptr = strtok(ParmWork," \t\n\r,");
00123                 if ( toupper(*ptr) == 'T' )
00124                         P->DoJets = 1;
00125                 else
00126                         P->DoJets = atol(ptr);
00127                 ptr = strtok(NULL," \t\n\r,");
00128                 len = (int)(ptr - ParmWork);
00129                 ParmStart += len;
00130         }
00131 
00132         if ( ! ProcUtil_SetPaletteFromString(P->Bitmap,(char **)&ParmStart) )
00133         {
00134                 geRam_Free(P);
00135                 return NULL;
00136         }
00137 
00138         assert( SeedLines == 1 ||SeedLines == 2 );
00139 
00140         #ifdef DO_TIMER
00141                 timerFP = fopen("q:\\timer.log","at+");
00142                 Timer_Start();
00143         #endif
00144 
00145 return P;
00146 }
00147 
00148 void Fire_Destroy(Procedural * P)
00149 {
00150         if ( ! P )
00151                 return;
00152                 
00153         #ifdef DO_TIMER
00154         Timer_Stop();
00155         if ( timerFP )
00156         {
00157                 TIMER_REPORT(Fire);
00158                 TIMER_REPORT(Fire_Smooth);
00159                 TIMER_REPORT(Fire_UnLock);
00160                 TIMER_REPORT(Fire_Rands);
00161         }
00162         #endif
00163 
00164         if ( P->Bitmap )
00165                 geBitmap_Destroy(&(P->Bitmap));
00166 
00167         geRam_Free(P);
00168 }
00169 
00170 geBoolean Fire_Animate(Procedural * P,float time)
00171 {
00172 
00173 #ifdef DO_TIMER
00174         TIMER_P(Fire);
00175 #endif
00176 
00177         if ( ! FireAnimator_CreateFire(P) )
00178                 return GE_FALSE;
00179 
00180 #ifdef DO_TIMER
00181         TIMER_Q(Fire);
00182         TIMER_COUNT();
00183 #endif
00184         
00185         P->Frame ++;
00186 
00187 return GE_TRUE;
00188 }
00189 
00190 geBoolean FireAnimator_CreateFire(Procedural * Proc)
00191 {
00192 geBitmap *FireLock=NULL;
00193 geBitmap_Info FireInfo;
00194 uint8 *FireBits,*bPtr;
00195 int x,y,w,h,s;
00196 geBitmap *Bitmap;
00197 
00198         Bitmap = Proc->Bitmap;
00199         assert(Bitmap);
00200 
00201         geBitmap_SetGammaCorrection(Bitmap, 1.0f, GE_FALSE);
00202 
00203         if ( ! geBitmap_LockForWriteFormat(Bitmap,&FireLock,0,0,GE_PIXELFORMAT_8BIT_PAL) )
00204                 goto fail;
00205 
00206         if ( ! geBitmap_GetInfo(FireLock,&FireInfo,NULL) )
00207                 goto fail;
00208 
00209         FireBits = geBitmap_GetBits(FireLock);
00210 
00211         if ( ! FireBits )
00212                 goto fail; 
00213 
00214         w = FireInfo.Width;
00215         h = FireInfo.Height;
00216         s = FireInfo.Stride;
00217 
00218         if ( Proc->Frame == 0 )
00219                 memset(FireBits,0,s*h);
00220 
00221 #ifdef DO_TIMER
00222         TIMER_P(Fire_Rands);
00223 #endif
00224 
00225         {
00226         int r;
00227         uint8 * bPtr;
00228                 bPtr = FireBits + (h - SeedLines)*s;
00229                 // seed hot points
00230                 memset(bPtr,0,s* SeedLines);
00231                 for(r=20*SeedLines;r--;)
00232                 {
00233                         x = myrand(s*SeedLines);
00234                         bPtr[x] = 254;
00235                 }
00236         }
00237 
00238 #if 1   // clear some points to avoid static junk
00239         {
00240         int r;
00241         uint8 * bPtr;
00242                 for(y=0;y<h;y++)
00243                 {
00244                         bPtr = FireBits + y*s;
00245                         for(r=10;r--;)
00246                         {
00247                                 x = myrand(w);
00248                                 if ( bPtr[x] )
00249                                 {
00250                                         bPtr[x] -= ((bPtr[x])>>4) + 1;
00251                                 }
00252                         }
00253                 }
00254         }
00255 #endif
00256 
00257 #ifdef DO_TIMER
00258         TIMER_Q(Fire_Rands);
00259 #endif
00260 
00261         if ( Proc->DoJets )
00262         {
00263         uint8 *pbPtr,*ppbPtr;
00264         int a;
00265         int randval,randbits;
00266                 
00267                 // now do a diffusion bleed
00268 
00269                 randbits = 0;
00270 
00271                 if ( SeedLines < 2 )
00272                 {
00273                         memcpy(FireBits + (h-2)*s,FireBits + (h-1)*s,s);
00274                 }
00275 
00276                 bPtr = FireBits + s;
00277                 for(y=h-3;y--;)
00278                 {
00279                          pbPtr =  bPtr + s;
00280                         ppbPtr = pbPtr + s;
00281                         for(x=w;x--;)
00282                         {
00283                                 a = (bPtr[-1] + pbPtr[0] + pbPtr[1] + pbPtr[-1] + pbPtr[-2] +
00284                                         ppbPtr[0] + ppbPtr[1] + ppbPtr[-1])>>3;
00285                                 if ( a )
00286                                 {
00287                                         if ( ! randbits )
00288                                         {
00289                                                 randval = myrand(1024);
00290                                                 randbits = 10;
00291                                         }
00292                                         switch( randval & 1 )
00293                                         {
00294                                                 case 0:
00295                                                         *bPtr = (a + pbPtr[1])>>1;
00296                                                         break;
00297                                                 case 1:
00298                                                         *bPtr = (a + pbPtr[-1])>>1;
00299                                                         break;
00300                                         }
00301                                         randval >>= 1;
00302                                         randbits --;
00303                                 }
00304                                 else
00305                                 {
00306                                         *bPtr = 0;
00307                                 }
00308                                 bPtr++;
00309                                 pbPtr++;
00310                                 ppbPtr++;
00311                         }
00312                         bPtr += s - w;
00313                 }
00314         }
00315         else
00316         {
00317         
00318 #ifdef DO_TIMER
00319                 TIMER_P(Fire_Smooth);
00320 #endif
00321 
00322                 FireInfo.Height --;
00323                 if ( ! geBitmapUtil_SmoothBits(&FireInfo,FireBits + s,FireBits,2,SMOOTH_WRAP) )
00324                         goto fail;
00325                         
00326 #ifdef DO_TIMER
00327                 TIMER_Q(Fire_Smooth);
00328 #endif
00329         }
00330         
00331         // fix up top lines
00332         {
00333         uint8 *sPtr;
00334         int passes,MaxY;
00335 
00336                 passes = 2;
00337 
00338                 if ( Proc->DoJets )
00339                         MaxY = 4;
00340                 else
00341                         MaxY = 2;
00342         
00343                 while(passes--)
00344                 {
00345                         for(y=1;y<= MaxY;y++)
00346                         {
00347                                 bPtr = FireBits + (h-y)*s;
00348                                 sPtr = bPtr - s;
00349                                 *bPtr++ = (bPtr[0] + bPtr[1] + sPtr[0] + sPtr[1])>>2;
00350                                 sPtr++;
00351                                 for(x=w-2;x--;)
00352                                 {
00353                                         *bPtr++ = (bPtr[0] + bPtr[1] + bPtr[-1] + sPtr[0] + sPtr[1] + sPtr[-1] + sPtr[-2] + sPtr[2])>>3;
00354                                         sPtr++;
00355                                 }
00356                                 *bPtr++ = (bPtr[0] + bPtr[-1] + sPtr[0] + sPtr[-1])>>2;
00357                                 sPtr++;
00358                         }
00359                 }
00360         }
00361 
00362 #ifdef DO_TIMER
00363                 TIMER_P(Fire_UnLock);
00364 #endif
00365 
00366         if ( ! geBitmap_UnLock(FireLock) )
00367                 goto fail;
00368 
00369 #ifdef DO_TIMER
00370                 TIMER_Q(Fire_UnLock);
00371 #endif
00372 
00373         return GE_TRUE;
00374 fail:
00375 
00376         if ( FireLock )         geBitmap_UnLock(FireLock);
00377 
00378         return GE_FALSE;
00379 }
00380 

Generated on Tue Sep 30 12:35:43 2003 for GTestAndEngine by doxygen 1.3.2