00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
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
00054
00055 Procedural *Water_Create(geBitmap **Bitmap, const char *StrParms)
00056 {
00057 Procedural *Water;
00058
00059 assert(Bitmap);
00060
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
00078 goto ExitWithError;
00079 }
00080
00081
00082 if (!geBitmap_ClearMips(Water->Bitmap))
00083 goto ExitWithError;
00084
00085 {
00086
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
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
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
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
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;
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
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
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;
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
00320
00321 for(i=0; i< H; i++)
00322 {
00323 for(j=0; j< W; j++)
00324 {
00325 if (i > 0)
00326 Val = *(Dest - W);
00327 else
00328 Val = *(Dest + W * (H-1));
00329
00330 if (i < H-1)
00331 Val += *(Dest + W);
00332 else
00333 Val += *(Dest - W * (H-1));
00334
00335 if (j > 0)
00336 Val += *(Dest - 1);
00337 else
00338 Val += *(Dest + (W-1));
00339
00340 if (j < W-1)
00341 Val += *(Dest + 1);
00342 else
00343 Val += *(Dest - (W-1));
00344
00345 Val >>= 1;
00346 Val -= *Src;
00347 Val -= (Val >> Density);
00348
00349
00350
00351
00352
00353
00354 *Src = Val;
00355
00356 Src++;
00357 Dest++;
00358
00359 }
00360 }
00361 }
00362
00363
00364
00365
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
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
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
00412
00413
00414
00415
00416
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
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
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++)
00458 {
00459 for (j=0; j<32; j++)
00460 {
00461 int32 Val;
00462
00463 Val = (int32)(((float)(31 - i)/14) * (float)j);
00464
00465
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
00491
00492
00493
00494
00495
00496
00497
00498 Procedural_Table *Water_GetProcedural_Table(void)
00499 {
00500 return &Water_Table;
00501 }