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

bumpmap.c

Go to the documentation of this file.
00001 
00002 #include "bumpmap.h"
00003 #include "genesis.h"
00004 #include "bitmap.h"
00005 #include "ram.h"
00006 #include <math.h>
00007 #include <Assert.h>
00008 #include <string.h>
00009 
00010 /**********************************************************/
00011 
00012 Procedural *BumpMap_Create(geBitmap **ppBitmap, const char *ParmStart);
00013 void            BumpMap_Destroy(Procedural *Proc);
00014 geBoolean       BumpMap_Animate(Procedural *BumpMap, float ElapsedTime);
00015 
00016 static Procedural_Table BumpMap_Table = 
00017 {
00018         Procedurals_Version,Procedurals_Tag,
00019         "BumpMap",
00020         BumpMap_Create,
00021         BumpMap_Destroy,
00022         BumpMap_Animate
00023 };
00024 
00025 Procedural_Table * BumpMap_GetProcedural_Table(void)
00026 {
00027         return &BumpMap_Table;
00028 }
00029 
00030 /**********************************************************/
00031 
00032 typedef struct Procedural
00033 {
00034         uint32          Frame;
00035         geBitmap *      Bitmap;
00036 } Procedural;
00037 
00038 geBoolean BumpMap_CreateFromHeightMap(geBitmap * HeightMap,geBitmap * BumpMap);
00039 geBoolean BumpMap_ComputePalette(geBitmap *BumpMap, geVec3d *Horizontal,geVec3d * Vertical, geVec3d *Pos, geVec3d *LightPos);
00040 
00041 /****/
00042 
00043 Procedural *BumpMap_Create(geBitmap **ppBitmap, const char *ParmStart)
00044 {
00045 Procedural * P;
00046 geBitmap * HeightMap;
00047 
00048         assert(ppBitmap);
00049 
00050         if ( ! *ppBitmap )
00051                 return NULL;
00052 
00053         P = geRam_Allocate(sizeof(Procedural));
00054         if ( ! P )
00055                 return NULL;
00056         assert(P);
00057         memset(P,0,sizeof(Procedural));
00058 
00059         P->Frame = 0;
00060 
00061         P->Bitmap = *ppBitmap;
00062 
00063         if ( geBitmap_ClearMips(P->Bitmap) )
00064         {
00065                 if ( geBitmap_SetColorKey(P->Bitmap,GE_FALSE,0,GE_FALSE) )
00066                 {
00067                         HeightMap = geBitmap_Create(geBitmap_Width(P->Bitmap),geBitmap_Height(P->Bitmap),1,GE_PIXELFORMAT_8BIT_GRAY);
00068                         if ( HeightMap )
00069                         {
00070                                 if ( geBitmap_BlitBitmap(P->Bitmap,HeightMap) )
00071                                 {
00072                                         if ( BumpMap_CreateFromHeightMap(HeightMap,P->Bitmap) )
00073                                         {
00074                                                 geBitmap_Destroy(&HeightMap);
00075                                                 return P;
00076                                         }
00077                                 }
00078                                 geBitmap_Destroy(&HeightMap);
00079                         }
00080                 }
00081         }
00082 
00083         geRam_Free(P);
00084         return NULL;
00085 }
00086 
00087 void BumpMap_Destroy(Procedural * P)
00088 {
00089         if ( ! P )
00090                 return;
00091         geRam_Free(P);
00092 }
00093 
00094 geBoolean BumpMap_Animate(Procedural * P,float time)
00095 {
00096 geVec3d Pos,LightPos,Horizontal,Vertical;
00097 geBoolean Ret;
00098 
00099         // <> these should be the sides of the poly we're drawing on,
00100         //              but we can't get that info easily...
00101         Horizontal.X = 1.0f;
00102         Horizontal.Y = 0.0f;
00103         Horizontal.Z = 0.0f;
00104         Vertical.X = 0.0f;
00105         Vertical.Y = 1.0f;
00106         Vertical.Z = 0.0f;
00107         Pos.X = 0.0f;
00108         Pos.Y = 0.0f;
00109         Pos.Z = 0.0f;
00110         LightPos.X = (geFloat)(100.0f * cos(P->Frame * 0.05f));
00111         LightPos.Y = (geFloat)(100.0f * sin(P->Frame * 0.05f));
00112         LightPos.Z = 100.0f;
00113 
00114         Ret = BumpMap_ComputePalette(P->Bitmap, &Horizontal,&Vertical, &Pos, &LightPos );
00115 
00116         P->Frame ++;
00117 return Ret;
00118 }
00119 
00120 /*****************************************************************/
00121 
00122 #define PI              ((double)3.14159265358979323846)
00123 #define TWOPI   (2.0*PI)
00124 #define PIOVER2 (PI*0.5)
00125 
00126 static int BumpTableInited = 0;
00127 static float BumpTableX[256];
00128 static float BumpTableY[256];
00129 static float BumpTableZ[256];
00130 
00131 geBoolean BumpMap_InitTables(void)
00132 {
00133 int p;
00134 double theta,phi;
00135 
00136         if ( BumpTableInited )
00137                 return GE_TRUE;
00138         BumpTableInited = 1;
00139 
00140         for(p=0;p<256;p++)
00141         {
00142                 theta = ((double)(p>>4) + 0.5)*PIOVER2/16.0;
00143                 phi   = ((double)(p&0x0F) + 0.5)*TWOPI/16.0;
00144 
00145                 assert( theta >= 0.0    && theta <= PIOVER2 );
00146                 assert( phi >= 0.0              && phi <= TWOPI );
00147 
00148                 BumpTableX[p] = (float)( sin(theta) * cos(phi));
00149                 BumpTableY[p] = (float)( sin(theta) * sin(phi));
00150                 BumpTableZ[p] = (float) cos(theta);
00151         }
00152 return GE_TRUE;
00153 }
00154 
00155 geBoolean BumpMap_CreateFromHeightMap(geBitmap * HeightMap,geBitmap * BumpMap)
00156 {
00157 geBitmap *HeightLock=NULL,*BumpLock=NULL;
00158 uint8 *HeightBits,*BumpBits;
00159 geBitmap_Info HeightInfo,BumpInfo;
00160 int w,h;
00161 
00162         assert(HeightMap && BumpMap);
00163 
00164         if ( ! geBitmap_SetFormat(BumpMap,GE_PIXELFORMAT_8BIT_PAL,GE_TRUE,255,NULL) )
00165                 goto fail;
00166 
00167         if ( ! geBitmap_LockForRead(HeightMap,&HeightLock,0,0,GE_PIXELFORMAT_8BIT_GRAY,0,0) )
00168                 goto fail;
00169 
00170         if ( ! geBitmap_GetInfo(HeightLock,&HeightInfo,NULL) )
00171                 goto fail;
00172 
00173         w = HeightInfo.Width;
00174         h = HeightInfo.Height;
00175 
00176         {
00177         geBitmap_Palette * Pal;
00178                 Pal = geBitmap_Palette_Create(GE_PIXELFORMAT_32BIT_ARGB,256);
00179                 if ( ! Pal )
00180                         goto fail;
00181                 if ( ! geBitmap_SetPalette(BumpMap,Pal) )
00182                         goto fail;
00183                 geBitmap_Palette_Destroy(&Pal);
00184         }
00185 
00186         if ( ! geBitmap_LockForWriteFormat(BumpMap,&BumpLock,0,0,GE_PIXELFORMAT_8BIT_PAL) )
00187                 goto fail;
00188 
00189         if ( ! geBitmap_GetInfo(BumpLock,&BumpInfo,NULL) )
00190                 goto fail;
00191 
00192         HeightBits      = geBitmap_GetBits(HeightLock);
00193         BumpBits        = geBitmap_GetBits(BumpLock);
00194 
00195         if ( ! HeightBits || ! BumpBits )
00196                 goto fail; 
00197 
00198 {
00199 int x,y,bs,hs;
00200 uint8 *hp,*bp;
00201 
00202         hp = HeightBits;
00203         bp = BumpBits;
00204         hs = HeightInfo.Stride;
00205         bs = BumpInfo.Stride;
00206 
00207         for(y=0;y<(h-1);y++)
00208         {
00209                 for(x=0;x<(w-1);x++)
00210                 {
00211                 int NW,SW,NE,SE,vx,vy;
00212                 double scale,nX,nY,nZ;
00213                 double theta,phi;
00214                 int _theta,_phi;
00215 
00216                         NW = hp[0];
00217                         SW = hp[hs];
00218                         hp++;
00219                         NE = hp[0];
00220                         SE = hp[hs];
00221 
00222                         vx = ((NW - NE) + (SW - SE) + 1)>>1;
00223                         vy = ((NW - SW) + (NE - SE) + 1)>>1;
00224 
00225                         scale = 1.0 / ( 1 + vx*vx + vy*vy );
00226                         scale = sqrt(scale);
00227 
00228                         nX = scale*vx;
00229                         nY = scale*vy;
00230                         nZ = scale;
00231 
00232                         // Z = cos(theta)
00233                         // X = sin(theta) * cos(phi)
00234                         // Y = sin(theta) * sin(phi)
00235 
00236                         theta = acos(nZ);
00237                         if ( fabs(nX) > fabs(nY) )
00238                         {
00239                         double cosphi;
00240                                 cosphi = nX / sin(theta);
00241                                 if ( cosphi > 1.0 )
00242                                         phi = 0.0;
00243                                 else if ( cosphi < -1.0 )
00244                                         phi = PI;
00245                                 else
00246                                         phi = acos( cosphi );
00247                                 // (phi in 0 -> PI)
00248                                 if ( nY < 0.0 )
00249                                         phi = TWOPI - phi;
00250                         }
00251                         else
00252                         {
00253                         double sinphi;
00254                                 sinphi = nY / sin(theta);
00255                                 if ( sinphi > 1.0 )
00256                                         phi = PIOVER2;
00257                                 else if ( sinphi < -1.0 )
00258                                         phi = - PIOVER2;
00259                                 else
00260                                         phi = asin( sinphi );
00261                                 // (phi in -PI/2 -> PI/2 )
00262                                 if ( nX < 0.0 )
00263                                         phi = PI - phi;
00264                                 if ( phi < 0.0 )
00265                                         phi += TWOPI;
00266                         }
00267 
00268                         assert( theta >= 0.0 && theta <= PIOVER2 );
00269                         assert( phi >= 0.0 && phi <= TWOPI );
00270 
00271                         theta   = theta * 16.0 / (PIOVER2);
00272                         phi             = phi   * 16.0 / (TWOPI);
00273 
00274                         // we add 0.5 when we go backwards, so don't do it here
00275                         _theta  = (int)theta;
00276                         _phi    = (int)phi;
00277                         assert( (_theta & 0xF) == _theta );
00278                         assert( (_phi & 0xF) == _phi );
00279 
00280                         *bp++ = (_theta << 4) | _phi;
00281                 }
00282                 // x == (w-1)
00283                 *bp = bp[-1];
00284                 bp++;
00285                 hp++;
00286 
00287                 hp += hs - w;
00288                 bp += bs - w;
00289         }
00290         //y == (h-1)
00291         for(x=0;x<w;x++)
00292         {
00293                 bp[x] = bp[x - bs];
00294         }
00295 }
00296 
00297         if ( ! geBitmap_UnLock(BumpLock) )
00298                 goto fail;
00299         if ( ! geBitmap_UnLock(HeightLock) )
00300                 goto fail;
00301         
00302         if ( ! BumpMap_InitTables() )
00303                 goto fail;
00304 
00305         geBitmap_SetPreferredFormat(BumpMap,GE_PIXELFORMAT_8BIT_PAL);
00306 
00307         return GE_TRUE;
00308 
00309 fail:
00310 
00311         if ( BumpLock )         geBitmap_UnLock(BumpLock);
00312         if ( HeightLock )       geBitmap_UnLock(HeightLock);
00313 
00314         return GE_FALSE;
00315 }
00316 
00317 geBoolean BumpMap_ComputePalette(geBitmap *BumpMap, geVec3d *pPlaneX,geVec3d *pPlaneY, geVec3d *pPos, geVec3d *pLightPos)
00318 {
00319 geBitmap_Palette *Pal;
00320 geVec3d LightRelPos,PlaneZ;
00321 geFloat LightDist;
00322 void * PalData = NULL;
00323 gePixelFormat PalFormat;
00324 int PalSize;
00325 
00326         assert(BumpMap && pPlaneX && pPlaneY && pPos &&  pLightPos);
00327         assert( geVec3d_DotProduct(pPlaneX,pPlaneY) == 0.0f );
00328 
00329         geBitmap_SetGammaCorrection(BumpMap, 1.0f, GE_FALSE);
00330 
00331         geVec3d_Subtract(pLightPos ,pPos,&LightRelPos );
00332         geVec3d_CrossProduct(pPlaneX,pPlaneY,&PlaneZ);
00333         geVec3d_Normalize(pPlaneX);
00334         geVec3d_Normalize(pPlaneY);
00335         geVec3d_Normalize(&PlaneZ);
00336         LightDist = geVec3d_Normalize(&LightRelPos);
00337 
00338         if ( ! (Pal = geBitmap_GetPalette(BumpMap)) )
00339                 goto fail;
00340 
00341         // if BumpMap is attached to a driver, then this Pal is actually on hardware!
00342 
00343         if ( ! geBitmap_Palette_Lock(Pal,&PalData, &PalFormat, &PalSize) )
00344                 goto fail;
00345         if ( PalSize < 256 )
00346                 goto fail;
00347 
00348         {
00349         int p,c;
00350         uint8 * PalPtr;
00351         float LightX,LightY,LightZ;
00352                 
00353                 LightX = geVec3d_DotProduct(&LightRelPos,pPlaneX) * 250.0f;
00354                 LightY = geVec3d_DotProduct(&LightRelPos,pPlaneY) * 250.0f;
00355                 LightZ = geVec3d_DotProduct(&LightRelPos,&PlaneZ) * 250.0f;
00356 
00357                 PalPtr = PalData;
00358                 for(p=0;p<256;p++)
00359                 {
00360                         
00361                         c = (int)(LightX * BumpTableX[p] + LightY * BumpTableY[p] + LightZ * BumpTableZ[p]);
00362                         if ( c < 0 )
00363                                 c = 0;
00364 
00365                         assert( c <= 255 );
00366 
00367                         gePixelFormat_PutColor(PalFormat,&PalPtr,c,c,c,0xFF);
00368                 }               
00369                 assert( ((uint32)PalPtr - (uint32)PalData) == 256 * gePixelFormat_BytesPerPel(PalFormat) );
00370         }
00371 
00372         PalData = NULL;
00373 
00374         if ( ! geBitmap_Palette_UnLock(Pal) )
00375                 return GE_FALSE;
00376 
00377         Pal = geBitmap_GetPalette(BumpMap);
00378         if ( ! Pal )
00379                 return GE_FALSE;
00380         if ( ! geBitmap_SetPalette(BumpMap,Pal) )
00381                 return GE_FALSE;
00382 
00383         return GE_TRUE;
00384 
00385 fail:
00386 
00387         if ( PalData )
00388                 geBitmap_Palette_UnLock(Pal);
00389 
00390         return GE_FALSE;
00391 }

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