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

Water.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  Water.c                                                                             */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description:                                                                        */
00006 /*                                                                                      */
00007 /*  Copyright (c) 1997, 1999, Eclipse Entertainment; All rights reserved.               */
00008 /*                                                                                      */
00009 /*  See the accompanying file LICENSE.TXT for terms on the use of this library.         */
00010 /*  This library is distributed in the hope that it will be useful but WITHOUT          */
00011 /*  ANY WARRANTY OF ANY KIND and without any implied warranty of MERCHANTABILITY        */
00012 /*  or FITNESS FOR ANY PURPOSE.  Refer to LICENSE.TXT for more details.                 */
00013 /*                                                                                      */
00014 /****************************************************************************************/
00015 #include <Assert.h>
00016 #include <Stdlib.h>
00017 #include <Math.h>
00018 
00019 #include "Procedural.h"
00020 #include "String.h"
00021 #include "Bitmap.h"
00022 #include "Ram.h"
00023 
00024 typedef struct Procedural
00025 {
00026         float           PosX;
00027         float           PosY;
00028         float           Angle;
00029         float           TimeToSplashWater;
00030 
00031         int32           NPage;
00032 
00033         uint16          *OriginalBits;
00034         int16           *WaterData[2];
00035 
00036         geBitmap        *Bitmap;
00037 
00038         int32           Width;
00039         int32           Height;
00040         int32           Size;
00041 
00042         uint8           BlendLut[32][32];
00043 } Procedural;
00044 
00045 Procedural *Water_Create(geBitmap **Bitmap, const char *StrParms);
00046 void Water_Destroy(Procedural *Water);
00047 geBoolean Water_Animate(Procedural *Water, float ElapsedTime);
00048 geBoolean Water_ApplyToBitmap(Procedural *Water);
00049 void Water_Update(Procedural *Water, float Time);
00050 void Water_BuildRGBLuts(Procedural *Water, float RScale, float GScale, float BScale);
00051 
00052 //====================================================================================
00053 //      Water_Create
00054 //====================================================================================
00055 Procedural *Water_Create(geBitmap **Bitmap, const char *StrParms)
00056 {
00057         Procedural      *Water;
00058 
00059         assert(Bitmap);
00060         //assert(ParmStart);    // Unremark this when implemented!!!!!
00061 
00062         Water = GE_RAM_ALLOCATE_STRUCT(Procedural);
00063 
00064         if (!Water)
00065                 goto ExitWithError;
00066 
00067         memset(Water, 0, sizeof(*Water));
00068 
00069         if (*Bitmap)
00070         {
00071                 Water->Bitmap = *Bitmap;
00072 
00073                 geBitmap_CreateRef(Water->Bitmap);
00074         }
00075         else
00076         {
00077                 // Must make bitmap for tha caller!!!
00078                 goto ExitWithError;
00079         }
00080 
00081         // We need this to be only 1 miplevel!!!
00082         if (!geBitmap_ClearMips(Water->Bitmap))
00083                 goto ExitWithError;
00084         
00085         {
00086                 // We need to change the format of this bitmap to a 565 in the world (hope he doesn't mind ;)
00087                 gePixelFormat   Format;
00088                 geBitmap_Info   Info;
00089                 int32                   i;
00090 
00091                 Format = GE_PIXELFORMAT_16BIT_565_RGB;
00092 
00093                 if (!geBitmap_SetFormat(Water->Bitmap, Format, GE_FALSE, 0, NULL))
00094                         goto ExitWithError;
00095 
00096                 if (!geBitmap_GetInfo(Water->Bitmap, &Info, NULL))
00097                         goto ExitWithError;
00098 
00099                 Water->Width = Info.Width;
00100                 Water->Height = Info.Height;
00101                 Water->Size = Water->Width*Water->Height;
00102 
00103                 Water->OriginalBits = GE_RAM_ALLOCATE_ARRAY(uint16, Water->Size);
00104 
00105                 if (!Water->OriginalBits)
00106                         goto ExitWithError;
00107 
00108                 for (i=0; i<2; i++)
00109                 {
00110                         Water->WaterData[i] = GE_RAM_ALLOCATE_ARRAY(int16, Water->Size);
00111 
00112                         if (!Water->WaterData[i])
00113                                 goto ExitWithError;
00114 
00115                         memset(Water->WaterData[i], 0, sizeof(int16)*Water->Size);
00116                 }
00117 
00118         }
00119 
00120         // Get the original bits...
00121         {
00122                 geBitmap                *Src;
00123                 uint16                  *pSrc16;
00124                 int32                   i;
00125                 geBitmap_Info   Info;
00126 
00127                 if (!geBitmap_GetInfo(Water->Bitmap, &Info, NULL))
00128                         goto ExitWithError;
00129 
00130                 if (!geBitmap_LockForRead(Water->Bitmap, &Src, 0, 0, Info.Format, GE_TRUE, 255))
00131                         goto ExitWithError;
00132                 
00133                 pSrc16 = geBitmap_GetBits(Src);
00134 
00135                 for (i=0; i<Water->Size; i++)
00136                         Water->OriginalBits[i] = pSrc16[i];
00137 
00138                 if (!geBitmap_UnLock(Src))
00139                         goto ExitWithError;
00140                 
00141         }
00142 
00143         Water_BuildRGBLuts(Water, 1.0f, 1.0f, 1.0f);
00144 
00145         return Water;
00146 
00147         ExitWithError:
00148         {
00149                 if (Water)
00150                         Water_Destroy(Water);
00151 
00152                 return NULL;
00153         }
00154 }
00155 
00156 //====================================================================================
00157 //      Water_Destroy
00158 //====================================================================================
00159 void Water_Destroy(Procedural *Water)
00160 {
00161         assert(Water);
00162 
00163         if (Water->Bitmap)
00164         {
00165                 geBitmap_Destroy(&Water->Bitmap);
00166                 Water->Bitmap = NULL;
00167         }
00168         
00169         if (Water->OriginalBits)
00170                 geRam_Free(Water->OriginalBits);
00171         Water->OriginalBits = NULL;
00172 
00173         if (Water->WaterData[0])
00174                 geRam_Free(Water->WaterData[0]);
00175         Water->WaterData[0] = NULL;
00176 
00177         if (Water->WaterData[1])
00178                 geRam_Free(Water->WaterData[1]);
00179         Water->WaterData[1] = NULL;
00180 
00181         geRam_Free(Water);
00182 }
00183 
00184 //====================================================================================
00185 //      Water_Animate
00186 //====================================================================================
00187 geBoolean Water_Animate(Procedural *Water, float ElapsedTime)
00188 {
00189         if (!Water->Bitmap)
00190                 return GE_TRUE;
00191 
00192         Water_Update(Water, ElapsedTime);
00193 
00194         if (!Water_ApplyToBitmap(Water))
00195                 return GE_FALSE;
00196 
00197         return GE_TRUE;
00198 }
00199 
00200 //====================================================================================
00201 //====================================================================================
00202 geBoolean Water_ApplyToBitmap(Procedural *Water)
00203 {
00204         geBitmap                *Dest;
00205         uint8                   *pBlendLut;
00206 
00207         assert(Water->Bitmap);
00208 
00209 #if 0 //@@ CB BUG Fix!
00210         {
00211         geBitmap_Info   MainInfo, Secondary;
00212         //if (!geBitmap_GetInfo(Water->Bitmap, &Secondary, &MainInfo))
00213         if (!geBitmap_GetInfo(Water->Bitmap, &MainInfo, &Secondary))
00214                 return GE_FALSE;
00215 
00216         assert(MainInfo.MaximumMip == 0);
00217 
00218         if (MainInfo.Format != GE_PIXELFORMAT_16BIT_565_RGB)
00219                 return GE_TRUE;                 // Oh well...
00220         
00221         if (!geBitmap_LockForWrite(Water->Bitmap, &Dest, 0, 0))
00222                 return GE_FALSE;
00223         }
00224 #else
00225         if (!geBitmap_LockForWriteFormat(Water->Bitmap, &Dest, 0, 0, GE_PIXELFORMAT_16BIT_565_RGB))
00226                 return GE_FALSE;
00227                 
00228 #endif
00229 
00230         pBlendLut = &Water->BlendLut[0][0];
00231         
00232         {
00233                 uint16                  *pSrc16, *pDest16;
00234                 int16                   *pWSrc16, *pOriginalWSrc16;
00235                 int32                   w, h, Extra, WMask, HMask;
00236                 geBitmap_Info   Info;
00237 
00238         //      if (!geBitmap_GetInfo(Dest, &Secondary, &Info)) // CB BUG Fix!
00239                 if (!geBitmap_GetInfo(Dest, &Info, NULL))
00240                         return GE_FALSE;
00241                 
00242                 assert(Info.Format == GE_PIXELFORMAT_16BIT_565_RGB);
00243 
00244                 Extra = Info.Stride - Info.Width;
00245 
00246                 WMask = Info.Width - 1;
00247                 HMask = Info.Height - 1;
00248                 
00249                 pSrc16 = Water->OriginalBits;
00250                 pOriginalWSrc16 = pWSrc16 = Water->WaterData[Water->NPage];
00251                 pDest16 = geBitmap_GetBits(Dest);
00252 
00253                 // For the love of God, write this in assembly
00254                 for (h=0; h< Info.Height; h++)
00255                 {
00256                         for (w=0; w< Info.Width; w++)
00257                         {
00258                                 int32   x, y, Val;
00259                                 uint16  r, g, b;
00260                                 uint16  Color;
00261 
00262                                 Val = pWSrc16[w];
00263                                  
00264                                 if (h < Info.Height-1)
00265                                         y = Val - pWSrc16[w+Info.Stride];
00266                                 else
00267                                         y = Val - pOriginalWSrc16[w];
00268 
00269                                 x = Val - pWSrc16[(w+1)&WMask];
00270                         #if 1
00271                                 Val = 127 - (y<<4);
00272 
00273                                 if (Val < 0) 
00274                                         Val = 0;
00275                                 else if (Val > 255) 
00276                                         Val = 255;
00277 
00278                                 Val >>= 3;
00279                                 Val <<= 5;
00280                         #endif
00281                                 
00282                                 x >>= 4;         
00283                                 y >>= 4;
00284 
00285                                 Color = pSrc16[((h+y)&HMask)*Info.Stride + ((w+x)&WMask)];
00286                                 
00287                         #if 1
00288                                 r = (uint16)pBlendLut[Val+((Color>>11)&31)];
00289                                 g = (uint16)pBlendLut[Val+((Color>>6)&31)];
00290                                 b = (uint16)pBlendLut[Val+(Color&31)];
00291                                 
00292                                 *pDest16++ = (r<<11) | (g<<6) | b;
00293                         #else
00294                                 *pDest16++ = Color;
00295                         #endif
00296 
00297                         }
00298 
00299                         pDest16 += Extra;
00300                         pWSrc16 += Info.Stride;//Extra;
00301                 }
00302                 
00303                 if (!geBitmap_UnLock(Dest))
00304                 {
00305                         return GE_FALSE;
00306                 }
00307         }
00308 
00309         return GE_TRUE;
00310 }
00311 
00312 //====================================================================================
00313 //====================================================================================
00314 static void CalcRippleData(int16 *Src, int16 *Dest, int16 Density, int32 W, int32 H)
00315 {
00316         int32   i,j;
00317         int16   Val;
00318 
00319         //Bottom = W * (H-1);
00320 
00321         for(i=0; i< H; i++)
00322         {
00323                 for(j=0; j< W; j++)
00324                 {
00325                         if (i > 0)                                                      // Get top
00326                                 Val = *(Dest - W);
00327                         else
00328                                 Val = *(Dest + W * (H-1));
00329 
00330                         if (i < H-1)                                            // Get bottom
00331                                 Val += *(Dest + W);
00332                         else
00333                                 Val += *(Dest - W * (H-1));
00334 
00335                         if (j > 0)                                                      // Get left
00336                                 Val += *(Dest - 1);
00337                         else
00338                                 Val += *(Dest + (W-1));
00339 
00340                         if (j < W-1)                                            // Get right
00341                                 Val += *(Dest + 1);
00342                         else
00343                                 Val += *(Dest - (W-1));
00344 
00345                         Val >>= 1;
00346                         Val -= *Src;
00347                         Val -= (Val >> Density);
00348                         /*
00349                         if (Val > 255)
00350                                 Val = 255;
00351                         else if (Val < -255)
00352                                 Val = -255;
00353                         */
00354                         *Src = Val;
00355 
00356                         Src++;
00357                         Dest++;
00358 
00359                 }
00360         }
00361 }
00362 
00363 
00364 //====================================================================================
00365 //      FloatMod
00366 //====================================================================================
00367 static float FloatMod(float In, float Wrap)
00368 {
00369         Wrap = (float)floor(fabs(In)/Wrap)*Wrap - Wrap;
00370 
00371         if (In > 0)
00372                 In -= Wrap;
00373         else if (In < 0)
00374                 In += Wrap;
00375 
00376         return In;
00377 }
00378 
00379 //====================================================================================
00380 //      Water_Update
00381 //====================================================================================
00382 void Water_Update(Procedural *Water, float Time)
00383 {
00384         int16           *Page1, *Page2, *Page3;
00385 
00386         Page1 = Water->WaterData[Water->NPage];
00387         Page2 = Water->WaterData[!Water->NPage];
00388 
00389         Page3 = Page2;
00390 
00391         Water->TimeToSplashWater += Time;
00392 #if 1
00393         if (Water->TimeToSplashWater > 0.8f)
00394         {
00395                 int32   px, py, cx, cy, c;
00396                 //int32         w, h;
00397                 
00398                 Water->TimeToSplashWater = 0.0f;
00399                 
00400                 
00401                 for (c=0; c< 2; c++)
00402                 {
00403                         px=(1+(rand()%(Water->Width-1-10)));
00404                         py=(1+(rand()%(Water->Height-1-10)));
00405 
00406                         for(cy=py; cy< (py+8); cy++)
00407                                 for(cx=px; cx< (px+8); cx++)
00408                                         Water->WaterData[!Water->NPage][cy * Water->Width + cx]=255;
00409                 }
00410                 /*
00411                 for (h=0; h<10; h++)
00412                         for (w=0; w<10; w++)
00413                                 Water->WaterData[!Water->NPage][(((int32)Water->PosY+h)%Water->Height)*Water->Width + (((int32)Water->PosX+w)%Water->Width)] = 255;
00414 
00415                 Water->PosX += 8.0f;
00416                 Water->PosY += 2.0f;
00417                 */
00418 
00419         }
00420 #else
00421         if (Water->TimeToSplashWater > 0.09f)
00422         {
00423                 int32           w, h;
00424 
00425                 Water->TimeToSplashWater = 0.0f;
00426                 
00427                 Water->PosX += (float)cos(Water->Angle)*16.0f;
00428                 Water->PosY += (float)sin(Water->Angle)*16.0f;
00429 
00430                 Water->Angle += ((float)rand()/RAND_MAX) * 0.5f - 0.1f;
00431 
00432                 Water->Angle = FloatMod(Water->Angle, 3.14159f);
00433 
00434                 Water->PosX = FloatMod(Water->PosX, (float)Water->Width);
00435                 Water->PosY = FloatMod(Water->PosY, (float)Water->Height);
00436 
00437                 //Water->WaterData[!Water->NPage][(int32)Water->PosY * Water->Width + (int32)Water->PosX]=255;
00438         
00439                 for (h=0; h<10; h++)
00440                         for (w=0; w<10; w++)
00441                                 Water->WaterData[!Water->NPage][(((int32)Water->PosY+h)%Water->Height)*Water->Width + (((int32)Water->PosX+w)%Water->Width)] = 255;
00442         }
00443 #endif
00444 
00445         CalcRippleData(Page1, Page2, 4, Water->Width, Water->Height);
00446 
00447         Water->NPage = !Water->NPage;
00448 }
00449 
00450 //====================================================================================
00451 //      Water_BuildRGBLuts
00452 //====================================================================================
00453 void Water_BuildRGBLuts(Procedural *Water, float RScale, float GScale, float BScale)
00454 {
00455         int32           i, j;
00456 
00457         for (i=0; i<32; i++)            // Shade
00458         {
00459                 for (j=0; j<32; j++)    // Color
00460                 {
00461                         int32   Val;
00462 
00463                         Val = (int32)(((float)(31 - i)/14) * (float)j);
00464 
00465                         //Val <<= 2;
00466                         
00467                         if (Val > 31)
00468                                 Val = 31;
00469 
00470                         Water->BlendLut[i][j] = (uint8)Val;
00471                 }
00472         }
00473 
00474 }
00475 
00476 //====================================================================================
00477 //====================================================================================
00478 static Procedural_Table Water_Table = 
00479 {
00480         Procedurals_Version,Procedurals_Tag,
00481         "Water",
00482         Water_Create,
00483         Water_Destroy,
00484         Water_Animate
00485 };
00486 
00487 /*
00488 //====================================================================================
00489 //====================================================================================
00490 DllExport Procedural_Table *GetProcedural_Table()
00491 {
00492         return Smoke_GetProcedural_Table();
00493 }
00494 */
00495 
00496 //====================================================================================
00497 //====================================================================================
00498 Procedural_Table *Water_GetProcedural_Table(void)
00499 {
00500         return &Water_Table; 
00501 }

Generated on Tue Sep 30 12:36:38 2003 for GTestAndEngine by doxygen 1.3.2