00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <Assert.h>
00023 #include <Windows.h>
00024 #include <Math.h>
00025
00026 #include "BaseType.h"
00027 #include "Ram.h"
00028 #include "System.h"
00029 #include "Vec3d.h"
00030 #include "Light.h"
00031 #include "Surface.h"
00032 #include "GBSPFile.h"
00033 #include "Plane.h"
00034 #include "World.h"
00035
00036 #include "Trace.h"
00037
00038 #define LIGHT_FRACT 8
00039
00040
00041
00042 static geEngine *CEngine = NULL;
00043 static geWorld *CWorld = NULL;
00044 static World_BSP *CBSP;
00045 static GBSP_BSPData *BSPData;
00046 static Light_LightInfo *LightInfo;
00047 static Surf_SurfInfo *GSurfInfo;
00048
00049
00050 static DRV_RGB BlankRGB[MAX_LMAP_SIZE*MAX_LMAP_SIZE];
00051 static DRV_RGB TempRGB[MAX_LMAP_SIZE*MAX_LMAP_SIZE];
00052 static int32 TempRGB32[MAX_LMAP_SIZE*MAX_LMAP_SIZE*3];
00053 static DRV_RGB TempRGBFog[MAX_LMAP_SIZE*MAX_LMAP_SIZE];
00054 static int32 TempRGB32Fog[MAX_LMAP_SIZE*MAX_LMAP_SIZE*3];
00055
00056
00057
00058
00059
00060
00061 #define MOST_SIG_OFFSET 1
00062
00063
00064
00065 #define SQRT_TAB_SIZE 16384
00066
00067
00068
00069
00070
00071
00072 #define MANT_SHIFTS 7
00073
00074 #define FastSqrtFloat double
00075 #define EXP_BIAS 1023 // Exponents are always positive
00076 #define EXP_SHIFTS 20 // Shifs exponent to least sig. bits
00077 #define EXP_LSB (1<<EXP_SHIFTS) //0x00100000 // 1 << EXP_SHIFTS
00078 #define MANT_MASK (EXP_LSB-1) //0x000FFFFF // Mask to extract mantissa
00079
00080
00081
00082
00083
00084
00085
00086
00087 int32 SqrtTab[SQRT_TAB_SIZE];
00088
00089
00090
00091 static void UpdateLTypeTables(geWorld *World);
00092 static int32 FastDist(int32 dx, int32 dy, int32 dz);
00093 static void SetupWavyColorLight1(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh);
00094 static void SetupWavyColorLight2(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh);
00095 static void SetupColorLight1(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh, geFloat intensity);
00096 static void SetupColorLight2(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh, geFloat intensity);
00097 static BOOL CombineDLightWithRGBMap(int32 *LightData, Light_DLight *Light, GFX_Face *Face, Surf_SurfInfo *SInfo);
00098 static BOOL CombineDLightWithRGBMapWithShadow(int32 *LightData, Light_DLight *Light, GFX_Face *Face, Surf_SurfInfo *SInfo);
00099 static void BuildLightLUTS(geEngine *Engine);
00100 static void SetupDynamicLight_r(Light_DLight *pLight, geVec3d *Pos, int32 LNum, int32 Node);
00101
00102 static void AddLightType0(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh);
00103 static void AddLightType(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh, int32 Intensity);
00104 static void AddLightType1(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh, int32 Intensity);
00105 static void AddLightTypeWavy1(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh);
00106 static void AddLightTypeWavy(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh);
00107
00108 static void InitSqrtTab(void);
00109 static FastSqrtFloat FastSqrt(FastSqrtFloat f);
00110
00111
00112
00113
00114
00115
00116
00117 geBoolean Light_EngineInit(geEngine *Engine)
00118 {
00119 BuildLightLUTS(Engine);
00120
00121 InitSqrtTab();
00122
00123 return GE_TRUE;
00124 }
00125
00126
00127
00128
00129 void Light_EngineShutdown(geEngine *Engine)
00130 {
00131 CEngine = NULL;
00132 CWorld = NULL;
00133 BSPData = NULL;
00134 }
00135
00136
00137
00138
00139 geBoolean Light_WorldInit(geWorld *World)
00140 {
00141 assert(World != NULL);
00142
00143 World->LightInfo = GE_RAM_ALLOCATE_STRUCT(Light_LightInfo);
00144
00145 if (!World->LightInfo)
00146 {
00147 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00148 return GE_FALSE;
00149 }
00150
00151 memset(World->LightInfo, 0, sizeof(Light_LightInfo));
00152
00153 UpdateLTypeTables(World);
00154
00155 return GE_TRUE;
00156 }
00157
00158
00159
00160
00161 void Light_WorldShutdown(geWorld *World)
00162 {
00163 assert(World != NULL);
00164
00165 if (!World->LightInfo)
00166 return;
00167
00168 geRam_Free(World->LightInfo);
00169
00170 World->LightInfo = NULL;
00171 }
00172
00173
00174
00175
00176
00177 geBoolean Light_SetEngine(geEngine *Engine)
00178 {
00179 assert (Engine != NULL);
00180
00181 CEngine = Engine;
00182
00183 return GE_TRUE;
00184 }
00185
00186
00187
00188
00189
00190 geBoolean Light_SetWorld(geWorld *World)
00191 {
00192 assert(World != NULL);
00193
00194 CWorld = World;
00195
00196 LightInfo = World->LightInfo;
00197 GSurfInfo = World->CurrentBSP->SurfInfo;
00198
00199 return GE_TRUE;
00200 }
00201
00202
00203
00204
00205 geBoolean Light_SetGBSP(World_BSP *BSP)
00206 {
00207 assert(BSP != NULL);
00208
00209
00210 CBSP = BSP;
00211 BSPData = &BSP->BSPData;
00212
00213 return GE_TRUE;
00214 }
00215
00216
00217
00218
00219 void Light_FogVerts(const geFog *Fog, const geVec3d *POV, const geVec3d *Verts, Surf_TexVert *TexVerts, int32 NumVerts)
00220 {
00221 geVec3d FogRay;
00222 geFloat Radius, RadiusSq, FogRayDot, OneOverRadiusDotBright;
00223 geFloat EyeDist;
00224 int32 i;
00225
00226 Radius = Fog->VolumeRadius;
00227 RadiusSq = Fog->VolumeRadiusSquared;
00228 OneOverRadiusDotBright = (1.0f/Radius)*Fog->VolumeBrightness;
00229
00230 geVec3d_Subtract(&Fog->Pos, POV, &FogRay);
00231 FogRayDot = geVec3d_DotProduct(&FogRay,&FogRay);
00232 EyeDist = (geFloat)sqrt(FogRayDot);
00233
00234 for (i=0; i< NumVerts; i++, Verts++, TexVerts++)
00235 {
00236 geVec3d Ray, Ray2, Impact1, Impact2;
00237 geFloat DistSq, Dist, Disc, v;
00238 geFloat t0, t1, t, VertDist, d, d2;
00239
00240 geVec3d_Subtract(Verts, POV, &Ray);
00241 geVec3d_Normalize(&Ray);
00242
00243 v = geVec3d_DotProduct(&FogRay, &Ray);
00244
00245 Disc = (RadiusSq) - (FogRayDot - (v*v));
00246
00247 if (Disc <= 0)
00248 continue;
00249
00250 d = (geFloat)sqrt(Disc);
00251
00252 t0 = v - d;
00253 t1 = v + d;
00254
00255 if (t0 > 0)
00256 t = t0;
00257 else if (t1 > 0)
00258 t = t1;
00259 else
00260 continue;
00261
00262 geVec3d_Subtract(Verts, &Fog->Pos, &Ray2);
00263 DistSq = geVec3d_DotProduct(&Ray2, &Ray2);
00264 VertDist = (geFloat)sqrt(DistSq);
00265
00266 if (EyeDist < Radius && VertDist < Radius)
00267 {
00268 Impact1 = *Verts;
00269 Impact2 = *POV;
00270 }
00271 else if (EyeDist < Radius)
00272 {
00273 Impact1 = *POV;
00274 geVec3d_AddScaled(POV, &Ray, t, &Impact2);
00275 }
00276 else if (VertDist < Radius)
00277 {
00278 Impact1 = *Verts;
00279 geVec3d_AddScaled(POV, &Ray, t, &Impact2);
00280 }
00281 else
00282 {
00283 geVec3d_AddScaled(POV, &Ray, t0, &Impact1);
00284 geVec3d_AddScaled(POV, &Ray, t1, &Impact2);
00285 geVec3d_Subtract(&Impact1, POV, &Ray);
00286
00287 d2 = geVec3d_DotProduct(&Ray, &Ray);
00288
00289 if (d2 > DistSq)
00290 continue;
00291 }
00292 geVec3d_Subtract(&Impact1, &Impact2, &Ray);
00293
00294 Dist = geVec3d_Length(&Ray)*OneOverRadiusDotBright;
00295
00296 #if 1
00297
00298 TexVerts->r += Dist*Fog->Color.r;
00299 TexVerts->g += Dist*Fog->Color.g;
00300 TexVerts->b += Dist*Fog->Color.b;
00301 #else
00302 TexVerts->r = 255.0f;
00303 TexVerts->g = 255.0f;
00304 TexVerts->b = 255.0f;
00305 #endif
00306 }
00307 }
00308
00309 extern int32 MirrorRecursion;
00310 geVec3d GlobalEyePos = {100.0f, 0.0f, 0.0f};
00311
00312
00313
00314
00315
00316 static geBoolean FogLightmap1(geFog *Fog, int32 *LightData, GFX_Face *Face, Surf_SurfInfo *SInfo)
00317 {
00318 int32 w, h;
00319 geBoolean Hit;
00320 geVec3d Start, UV, Ray;
00321 int32 Light1, Light2, Light3;
00322 geFloat Dist, d2, UVDist, DistSq;
00323 geVec3d FogRay, Ray2;
00324 geFloat v,disc, d;
00325 geVec3d Impact1, Impact2;
00326 geFloat Radius, Red, Grn, Blu, EyeDist;
00327 geFloat RadiusSq, FogRayDot, Radius2;
00328 geVec3d UAdd, VAdd, FogPos;
00329 int32 Width, Height;
00330
00331 Hit = GE_FALSE;
00332
00333 Start = UV = SInfo->TexOrg;
00334
00335 FogPos = Fog->Pos;
00336
00337 geVec3d_Subtract(&FogPos, &GlobalEyePos, &FogRay);
00338
00339 Ray2 = FogRay;
00340 EyeDist = geVec3d_Normalize(&Ray2);
00341
00342 Radius = Fog->VolumeRadius;
00343 RadiusSq = Fog->VolumeRadiusSquared;
00344 Radius2 = Fog->VolumeRadius2;
00345
00346 FogRayDot = geVec3d_DotProduct(&FogRay,&FogRay);
00347
00348 Red = Fog->Color.r;
00349 Grn = Fog->Color.g;
00350 Blu = Fog->Color.b;
00351
00352
00353
00354
00355 UAdd = SInfo->T2WVecs[0];
00356 VAdd = SInfo->T2WVecs[1];
00357
00358 Width = SInfo->LInfo.Width;
00359 Height = SInfo->LInfo.Height;
00360
00361 for (h=0; h< Height; h++)
00362 {
00363 for (w=0; w< Width; w++)
00364 {
00365 geFloat OneOver;
00366
00367 Ray.X = UV.X - GlobalEyePos.X;
00368 Ray.Y = UV.Y - GlobalEyePos.Y;
00369 Ray.Z = UV.Z - GlobalEyePos.Z;
00370
00371 DistSq = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00372 Dist = (geFloat)FastSqrt(DistSq);
00373
00374 OneOver = 1.0f / Dist;
00375 Ray.X *= OneOver;
00376 Ray.Y *= OneOver;
00377 Ray.Z *= OneOver;
00378
00379 v = FogRay.X*Ray.X + FogRay.Y*Ray.Y + FogRay.Z*Ray.Z;
00380
00381 disc = (RadiusSq) - (FogRayDot - (v*v));
00382
00383 if (disc > 0)
00384 {
00385 geFloat t0, t1, t;
00386
00387 d = (geFloat)FastSqrt(disc);
00388
00389 t0 = v - d;
00390 t1 = v + d;
00391
00392 if (t0 > 0)
00393 t = t0;
00394 else if (t1 > 0)
00395 t = t1;
00396 else
00397 {
00398 *LightData++ = 0;
00399 *LightData++ = 0;
00400 *LightData++ = 0;
00401
00402 UV.X += UAdd.X;
00403 UV.Y += UAdd.Y;
00404 UV.Z += UAdd.Z;
00405 continue;
00406 }
00407
00408 #if 1
00409 Ray2.X = UV.X - FogPos.X;
00410 Ray2.Y = UV.Y - FogPos.Y;
00411 Ray2.Z = UV.Z - FogPos.Z;
00412
00413
00414 UVDist = (geFloat)FastSqrt(Ray2.X*Ray2.X + Ray2.Y*Ray2.Y + Ray2.Z*Ray2.Z);
00415
00416 if (EyeDist < Radius && UVDist < Radius)
00417 {
00418 Impact1 = UV;
00419 Impact2 = GlobalEyePos;
00420 }
00421 else if (EyeDist < Radius)
00422 {
00423 Impact1 = GlobalEyePos;
00424
00425 Impact2.X = GlobalEyePos.X + t*Ray.X;
00426 Impact2.Y = GlobalEyePos.Y + t*Ray.Y;
00427 Impact2.Z = GlobalEyePos.Z + t*Ray.Z;
00428 }
00429 else if (UVDist < Radius)
00430 {
00431 Impact1 = UV;
00432
00433 Impact2.X = GlobalEyePos.X + t*Ray.X;
00434 Impact2.Y = GlobalEyePos.Y + t*Ray.Y;
00435 Impact2.Z = GlobalEyePos.Z + t*Ray.Z;
00436
00437 }
00438 else
00439 {
00440 Impact1.X = GlobalEyePos.X + t0*Ray.X;
00441 Impact1.Y = GlobalEyePos.Y + t0*Ray.Y;
00442 Impact1.Z = GlobalEyePos.Z + t0*Ray.Z;
00443
00444 Impact2.X = GlobalEyePos.X + t1*Ray.X;
00445 Impact2.Y = GlobalEyePos.Y + t1*Ray.Y;
00446 Impact2.Z = GlobalEyePos.Z + t1*Ray.Z;
00447
00448 Ray.X = Impact1.X - GlobalEyePos.X;
00449 Ray.Y = Impact1.Y - GlobalEyePos.Y;
00450 Ray.Z = Impact1.Z - GlobalEyePos.Z;
00451
00452
00453
00454 d2 = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00455
00456 if (d2 > DistSq)
00457 {
00458
00459
00460
00461
00462
00463
00464
00465
00466 {
00467 *LightData++ = 0;
00468 *LightData++ = 0;
00469 *LightData++ = 0;
00470
00471 UV.X += UAdd.X;
00472 UV.Y += UAdd.Y;
00473 UV.Z += UAdd.Z;
00474 continue;
00475 }
00476 }
00477
00478 }
00479 #endif
00480
00481
00482
00483 Ray.X = Impact1.X - Impact2.X;
00484 Ray.Y = Impact1.Y - Impact2.Y;
00485 Ray.Z = Impact1.Z - Impact2.Z;
00486
00487
00488
00489
00490 d = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00491 d = ((RadiusSq / d)*18);
00492 Dist = (Fog->VolumeBrightness) / (d);
00493
00494
00495 Hit = GE_TRUE;
00496
00497 Light1 = (int32)(Dist*Red);
00498 Light2 = (int32)(Dist*Grn);
00499 Light3 = (int32)(Dist*Blu);
00500
00501 *LightData++ = Light1;
00502 *LightData++ = Light2;
00503 *LightData++ = Light3;
00504 }
00505 else
00506 {
00507 *LightData++ = 0;
00508 *LightData++ = 0;
00509 *LightData++ = 0;
00510 }
00511
00512 UV.X += UAdd.X;
00513 UV.Y += UAdd.Y;
00514 UV.Z += UAdd.Z;
00515
00516 }
00517
00518 Start.X += VAdd.X;
00519 Start.Y += VAdd.Y;
00520 Start.Z += VAdd.Z;
00521 UV = Start;
00522 }
00523
00524 return Hit;
00525 }
00526
00527
00528
00529
00530
00531 static geBoolean FogLightmap2(geFog *Fog, int32 *LightData, GFX_Face *Face, Surf_SurfInfo *SInfo)
00532 {
00533 int32 w, h;
00534 geBoolean Hit;
00535 geVec3d Start, UV, Ray;
00536 int32 Light1, Light2, Light3;
00537 geFloat Dist, d2, UVDist, DistSq;
00538 geVec3d FogRay, Ray2;
00539 geFloat v,disc, d;
00540 geVec3d Impact1, Impact2;
00541 geFloat Radius, Red, Grn, Blu, EyeDist;
00542 geFloat RadiusSq, FogRayDot, Radius2;
00543 geVec3d UAdd, VAdd, FogPos;
00544 int32 LightAdd, Width, Height;
00545
00546 Hit = GE_FALSE;
00547
00548 Start = UV = SInfo->TexOrg;
00549
00550 FogPos = Fog->Pos;
00551
00552 geVec3d_Subtract(&FogPos, &GlobalEyePos, &FogRay);
00553
00554 Ray2 = FogRay;
00555 EyeDist = geVec3d_Normalize(&Ray2);
00556
00557 Radius = Fog->VolumeRadius;
00558 RadiusSq = Fog->VolumeRadiusSquared;
00559 Radius2 = Fog->VolumeRadius2;
00560
00561 FogRayDot = geVec3d_DotProduct(&FogRay,&FogRay);
00562
00563 Red = Fog->Color.r;
00564 Grn = Fog->Color.g;
00565 Blu = Fog->Color.b;
00566
00567
00568
00569
00570 UAdd = SInfo->T2WVecs[0];
00571 VAdd = SInfo->T2WVecs[1];
00572
00573 Width = SInfo->LInfo.Width;
00574 Height = SInfo->LInfo.Height;
00575
00576 LightAdd = (SInfo->LInfo.Width - Width)*3;
00577
00578 for (h=0; h< Height; h++)
00579 {
00580 for (w=0; w< Width; w++)
00581 {
00582 geFloat OneOver;
00583
00584 Ray.X = UV.X - GlobalEyePos.X;
00585 Ray.Y = UV.Y - GlobalEyePos.Y;
00586 Ray.Z = UV.Z - GlobalEyePos.Z;
00587
00588
00589 DistSq = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00590 Dist = (geFloat)FastSqrt(DistSq);
00591
00592 OneOver = 1.0f / Dist;
00593 Ray.X *= OneOver;
00594 Ray.Y *= OneOver;
00595 Ray.Z *= OneOver;
00596
00597 v = FogRay.X*Ray.X + FogRay.Y*Ray.Y + FogRay.Z*Ray.Z;
00598
00599 disc = (RadiusSq) - (FogRayDot - (v*v));
00600
00601 if (disc > 0)
00602 {
00603 geFloat t0, t1, t;
00604
00605 d = (geFloat)FastSqrt(disc);
00606
00607
00608 t0 = v - d;
00609 t1 = v + d;
00610
00611 if (t0 > 0)
00612 t = t0;
00613 else if (t1 > 0)
00614 t = t1;
00615 else
00616 {
00617 LightData+=3;
00618
00619 UV.X += UAdd.X;
00620 UV.Y += UAdd.Y;
00621 UV.Z += UAdd.Z;
00622 continue;
00623 }
00624
00625 #if 1
00626 Ray2.X = UV.X - FogPos.X;
00627 Ray2.Y = UV.Y - FogPos.Y;
00628 Ray2.Z = UV.Z - FogPos.Z;
00629
00630
00631 UVDist = (geFloat)FastSqrt(Ray2.X*Ray2.X + Ray2.Y*Ray2.Y + Ray2.Z*Ray2.Z);
00632
00633 if (EyeDist < Radius && UVDist < Radius)
00634 {
00635 Impact1 = UV;
00636 Impact2 = GlobalEyePos;
00637 }
00638 else if (EyeDist < Radius)
00639 {
00640 Impact1 = GlobalEyePos;
00641
00642 Impact2.X = GlobalEyePos.X + t*Ray.X;
00643 Impact2.Y = GlobalEyePos.Y + t*Ray.Y;
00644 Impact2.Z = GlobalEyePos.Z + t*Ray.Z;
00645 }
00646 else if (UVDist < Radius)
00647 {
00648 Impact1 = UV;
00649
00650 Impact2.X = GlobalEyePos.X + t*Ray.X;
00651 Impact2.Y = GlobalEyePos.Y + t*Ray.Y;
00652 Impact2.Z = GlobalEyePos.Z + t*Ray.Z;
00653
00654 }
00655 else
00656 {
00657 Impact1.X = GlobalEyePos.X + t0*Ray.X;
00658 Impact1.Y = GlobalEyePos.Y + t0*Ray.Y;
00659 Impact1.Z = GlobalEyePos.Z + t0*Ray.Z;
00660
00661 Impact2.X = GlobalEyePos.X + t1*Ray.X;
00662 Impact2.Y = GlobalEyePos.Y + t1*Ray.Y;
00663 Impact2.Z = GlobalEyePos.Z + t1*Ray.Z;
00664
00665 Ray.X = Impact1.X - GlobalEyePos.X;
00666 Ray.Y = Impact1.Y - GlobalEyePos.Y;
00667 Ray.Z = Impact1.Z - GlobalEyePos.Z;
00668
00669
00670
00671 d2 = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00672
00673 if (d2 > DistSq)
00674 {
00675
00676
00677
00678
00679
00680
00681
00682
00683 {
00684 LightData+=3;
00685
00686 UV.X += UAdd.X;
00687 UV.Y += UAdd.Y;
00688 UV.Z += UAdd.Z;
00689 continue;
00690 }
00691 }
00692
00693 }
00694 #endif
00695
00696
00697
00698 Ray.X = Impact1.X - Impact2.X;
00699 Ray.Y = Impact1.Y - Impact2.Y;
00700 Ray.Z = Impact1.Z - Impact2.Z;
00701
00702
00703
00704
00705 d = Ray.X*Ray.X + Ray.Y*Ray.Y + Ray.Z*Ray.Z;
00706 d = ((RadiusSq / d)*18);
00707 Dist = (Fog->VolumeBrightness) / (d);
00708
00709
00710 Hit = GE_TRUE;
00711
00712 Light1 = (int32)(Dist*Red);
00713 Light2 = (int32)(Dist*Grn);
00714 Light3 = (int32)(Dist*Blu);
00715
00716 *LightData += Light1;
00717 LightData++;
00718 *LightData += Light2;
00719 LightData++;
00720 *LightData += Light3;
00721 LightData++;
00722 }
00723 else
00724 {
00725 LightData+=3;
00726 }
00727
00728 UV.X += UAdd.X;
00729 UV.Y += UAdd.Y;
00730 UV.Z += UAdd.Z;
00731
00732 }
00733
00734 Start.X += VAdd.X;
00735 Start.Y += VAdd.Y;
00736 Start.Z += VAdd.Z;
00737 UV = Start;
00738
00739 LightData += LightAdd;
00740
00741 }
00742
00743 return Hit;
00744 }
00745
00746
00747
00748
00749 void Light_SetupLightmap(DRV_LInfo *LInfo, BOOL *Dynamic)
00750 {
00751 int32 LightOffset;
00752 geBoolean IsDyn, HasDLight;
00753 int32 NumLTypes;
00754 int32 i, Ln;
00755 Surf_SurfInfo *SInfo;
00756 GFX_Face *Face;
00757 int32 Intensity;
00758 uint8 *LightData;
00759 int32 lWidth, lHeight, LMapSize, MapNum, SIndex;
00760 int32 *pRGB1;
00761 DRV_RGB *pRGB2;
00762
00763 assert (CBSP != NULL);
00764 assert(BSPData != NULL);
00765 assert(BSPData->GFXFaces != NULL);
00766 assert(BSPData->GFXLightData != NULL);
00767 assert(BSPData->GFXTexInfo != NULL);
00768 assert(CWorld->LightInfo != NULL);
00769
00770 SInfo = &CBSP->SurfInfo[LInfo->Face];
00771 Face = &BSPData->GFXFaces[LInfo->Face];
00772
00773 NumLTypes = SInfo->NumLTypes;
00774
00775 LightOffset = Face->LightOfs;
00776
00777 lWidth = LInfo->Width;
00778 lHeight = LInfo->Height;
00779 LMapSize = lHeight * lWidth;
00780
00781 IsDyn = HasDLight = GE_FALSE;
00782
00783 if (SInfo->DLightFrame == CWorld->CurFrameDynamic)
00784 if (LightInfo->NumDynamicLights > 0 && !(BSPData->GFXTexInfo[Face->TexInfo].Flags & TEXINFO_FULLBRIGHT))
00785 HasDLight = GE_TRUE;
00786
00787
00788 if (!HasDLight && !(SInfo->Flags & SURFINFO_LTYPED))
00789 {
00790 if (LightOffset >=0)
00791 LInfo->RGBLight[0] = (DRV_RGB*)&BSPData->GFXLightData[LightOffset+1];
00792 else
00793 LInfo->RGBLight[0] = BlankRGB;
00794 goto FogOnly;
00795 }
00796
00797 CEngine->DebugInfo.LMap1++;
00798
00799
00800 if (LightOffset >=0)
00801 {
00802
00803
00804 LightData = &BSPData->GFXLightData[LightOffset+1];
00805
00806
00807 for (MapNum = 0; MapNum < 4; MapNum++)
00808 {
00809 SIndex = Face->LTypes[MapNum];
00810
00811 if (SIndex == 255)
00812 break;
00813
00814 if (LightInfo->LTypeDynamic[SIndex])
00815 IsDyn = GE_TRUE;
00816
00817 Intensity = LightInfo->LTypeIntensities[SIndex];
00818
00819 if (SIndex == 11)
00820 {
00821 if (MapNum == 0)
00822 AddLightTypeWavy1(TempRGB32, LightData, lWidth, lHeight);
00823 else
00824 AddLightTypeWavy(TempRGB32, LightData, lWidth, lHeight);
00825
00826 IsDyn = GE_TRUE;
00827 }
00828 else
00829 {
00830 if (SIndex == 0)
00831 AddLightType0(TempRGB32, LightData, lWidth, lHeight);
00832 else
00833 {
00834 if (MapNum == 0)
00835 AddLightType1(TempRGB32, LightData, lWidth, lHeight, Intensity);
00836 else
00837 AddLightType(TempRGB32, LightData, lWidth, lHeight, Intensity);
00838 }
00839 }
00840
00841 LightData += LMapSize*3;
00842 }
00843 }
00844 else
00845 memset(TempRGB32, 0, LMapSize*3*sizeof(TempRGB32[0]));
00846
00847
00848 if (HasDLight)
00849 {
00850 Light_DLight *DLights = LightInfo->DynamicLights;
00851
00852 for (Ln = 0; Ln <MAX_DYNAMIC_LIGHTS; Ln++, DLights++)
00853 {
00854 if (!DLights->Active)
00855 continue;
00856
00857 if (!(SInfo->DLights & (1<<Ln)))
00858 continue;
00859
00860 CEngine->DebugInfo.NumDLights++;
00861
00862 if (DLights->CastShadow)
00863 {
00864 if (CombineDLightWithRGBMapWithShadow(TempRGB32, DLights, Face, SInfo))
00865 IsDyn = GE_TRUE;
00866 }
00867 else
00868 {
00869 if (CombineDLightWithRGBMap(TempRGB32, DLights, Face, SInfo))
00870 IsDyn = GE_TRUE;
00871 }
00872 }
00873 }
00874
00875
00876 pRGB1 = TempRGB32;
00877 pRGB2 = TempRGB;
00878 for (i=0; i< LMapSize; i++)
00879 {
00880 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00881 if (Intensity > 255)
00882 Intensity = 255;
00883 else if (Intensity < 0 )
00884 Intensity = 0;
00885 pRGB2->r = (uint8)Intensity;
00886
00887 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00888 if (Intensity > 255)
00889 Intensity = 255;
00890 else if (Intensity < 0 )
00891 Intensity = 0;
00892 pRGB2->g = (uint8)Intensity;
00893
00894 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00895 if (Intensity > 255)
00896 Intensity = 255;
00897 else if (Intensity < 0 )
00898 Intensity = 0;
00899 pRGB2->b = (uint8)Intensity;
00900
00901 pRGB2++;
00902 }
00903
00904
00905 LInfo->RGBLight[0] = TempRGB;
00906
00907 FogOnly:
00908
00909
00910
00911
00912 LInfo->RGBLight[1] = NULL;
00913
00914 #if 1
00915 if (!MirrorRecursion)
00916 {
00917 geFog *Fog;
00918 geBoolean WasFog;
00919
00920 WasFog = GE_FALSE;
00921
00922 if (CWorld->NumVisibleFog)
00923 {
00924 for (i=0; i< CWorld->NumVisibleFog; i++)
00925 {
00926 Fog = CWorld->VisibleFog[i];
00927
00928 if (i == 0)
00929 {
00930 if (FogLightmap1(Fog, TempRGB32Fog, Face, SInfo))
00931 WasFog = GE_TRUE;
00932 }
00933 else
00934 {
00935 if (FogLightmap2(Fog, TempRGB32Fog, Face, SInfo))
00936 WasFog = GE_TRUE;
00937 }
00938 }
00939 }
00940
00941 if (WasFog)
00942 {
00943 CEngine->DebugInfo.LMap2++;
00944
00945
00946 pRGB1 = TempRGB32Fog;
00947 pRGB2 = TempRGBFog;
00948 for (i=0; i< LMapSize; i++)
00949 {
00950 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00951 if (Intensity > 255)
00952 Intensity = 255;
00953 pRGB2->r = (uint8)Intensity;
00954
00955 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00956 if (Intensity > 255)
00957 Intensity = 255;
00958 pRGB2->g = (uint8)Intensity;
00959
00960 Intensity = (*pRGB1++) >> LIGHT_FRACT;
00961 if (Intensity > 255)
00962 Intensity = 255;
00963 pRGB2->b = (uint8)Intensity;
00964
00965 pRGB2++;
00966 }
00967 IsDyn = TRUE;
00968 LInfo->RGBLight[1] = TempRGBFog;
00969 }
00970 }
00971 #endif
00972
00973 if (Dynamic)
00974 {
00975 *Dynamic = IsDyn;
00976 }
00977 }
00978
00979
00980
00981
00982 static void AddLightType(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh, int32 Intensity)
00983 {
00984 int32 h;
00985
00986 assert(LightDest != NULL);
00987 assert(LightData != NULL);
00988
00989 for (h = 0; h < lw*lh; h++)
00990 {
00991 *LightDest++ += *LightData++ * Intensity;
00992 *LightDest++ += *LightData++ * Intensity;
00993 *LightDest++ += *LightData++ * Intensity;
00994 }
00995 }
00996
00997
00998
00999
01000 static void AddLightType0(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh)
01001 {
01002 int32 h;
01003
01004 assert(LightDest != NULL);
01005 assert(LightData != NULL);
01006
01007 for (h = 0; h < lw*lh; h++)
01008 {
01009 *LightDest++ = (*LightData++) << LIGHT_FRACT;
01010 *LightDest++ = (*LightData++) << LIGHT_FRACT;
01011 *LightDest++ = (*LightData++) << LIGHT_FRACT;
01012 }
01013 }
01014
01015
01016
01017
01018 static void AddLightType1(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh, int32 Intensity)
01019 {
01020 int32 h;
01021
01022 assert(LightDest != NULL);
01023 assert(LightData != NULL);
01024
01025 for (h = 0; h < lw*lh; h++)
01026 {
01027 *LightDest++ = *LightData++ * Intensity;
01028 *LightDest++ = *LightData++ * Intensity;
01029 *LightDest++ = *LightData++ * Intensity;
01030 }
01031 }
01032
01033
01034
01035
01036 static BOOL CombineDLightWithRGBMap(int32 *LightData, Light_DLight *Light, GFX_Face *Face, Surf_SurfInfo *SInfo)
01037 {
01038 BOOL Hit;
01039 geFloat Radius, Dist;
01040 GFX_Plane *Plane;
01041 GFX_TexInfo *TexInfo;
01042 geVec3d LPos;
01043 int32 Sx, Sy, x, y, u, v, Val;
01044 int32 ColorR, ColorG, ColorB, Radius2, Dist2;
01045 int32 FixedX, FixedY, XStep, YStep;
01046
01047 assert(BSPData != NULL);
01048 assert(BSPData->GFXTexInfo != NULL);
01049 assert(BSPData->GFXPlanes != NULL);
01050
01051 TexInfo = &BSPData->GFXTexInfo[Face->TexInfo];
01052
01053 Radius = Light->Radius;
01054 Plane = &BSPData->GFXPlanes[Face->PlaneNum];
01055
01056 geVec3d_Copy(&Light->Pos, &LPos);
01057
01058 Dist = geVec3d_DotProduct(&LPos, &Plane->Normal) - Plane->Dist;
01059
01060
01061 Radius -= (geFloat)fabs(Dist);
01062
01063 if (Radius <= 0)
01064 return FALSE;
01065
01066
01067 Sx = (int32)(geVec3d_DotProduct(&LPos, &TexInfo->Vecs[0]));
01068 Sy = (int32)(geVec3d_DotProduct(&LPos, &TexInfo->Vecs[1]));
01069
01070
01071 Sx -= SInfo->LInfo.MinU;
01072 Sy -= SInfo->LInfo.MinV;
01073
01074
01075 Sx *= SInfo->XScale;
01076 Sy *= SInfo->YScale;
01077
01078 Hit = FALSE;
01079
01080 ColorR = Light->FColorR;
01081 ColorG = Light->FColorG;
01082 ColorB = Light->FColorB;
01083
01084 Radius2 = (int32)Radius;
01085
01086 XStep = SInfo->XStep;
01087 YStep = SInfo->YStep;
01088
01089 FixedY = Sy;
01090
01091 for (v=0; v< SInfo->LInfo.Height; v++)
01092 {
01093 y = FixedY >> 10;
01094
01095 if (y < 0)
01096 y = -y;
01097
01098 FixedX = Sx;
01099
01100 for (u=0; u< SInfo->LInfo.Width; u++)
01101 {
01102 x = FixedX >> 10;
01103
01104 if (x<0)
01105 x = -x;
01106
01107 if (x > y)
01108 Dist2 = (x + (y>>1));
01109 else
01110 Dist2 = (y + (x>>1));
01111
01112 if (Dist2 < Radius2)
01113 {
01114 Hit = TRUE;
01115
01116 Val = (Radius2 - Dist2);
01117
01118 *LightData++ += (int32)(Val * ColorR);
01119 *LightData++ += (int32)(Val * ColorG);
01120 *LightData++ += (int32)(Val * ColorB);
01121 }
01122 else
01123 LightData+=3;
01124
01125 FixedX -= XStep;
01126 }
01127
01128 FixedY -= YStep;
01129 }
01130
01131 return Hit;
01132 }
01133
01134
01135
01136
01137 static BOOL CombineDLightWithRGBMapWithShadow(int32 *LightData, Light_DLight *Light, GFX_Face *Face, Surf_SurfInfo *SInfo)
01138 {
01139 BOOL Hit;
01140 geFloat Radius, Dist;
01141 GFX_Plane *Plane;
01142 GFX_TexInfo *TexInfo;
01143 geVec3d LPos, LMapPos, Right, Down, Start;
01144 int32 Sx, Sy, x, y, u, v, Val;
01145 int32 ColorR, ColorG, ColorB, Radius2, Dist2;
01146 int32 FixedX, FixedY, XStep, YStep;
01147
01148 assert(BSPData != NULL);
01149 assert(BSPData->GFXTexInfo != NULL);
01150 assert(BSPData->GFXPlanes != NULL);
01151
01152 TexInfo = &BSPData->GFXTexInfo[Face->TexInfo];
01153
01154 Radius = Light->Radius;
01155 Plane = &BSPData->GFXPlanes[Face->PlaneNum];
01156
01157 geVec3d_Copy(&Light->Pos, &LPos);
01158
01159 Dist = geVec3d_DotProduct(&LPos, &Plane->Normal) - Plane->Dist;
01160
01161
01162 Radius -= (geFloat)fabs(Dist);
01163
01164 if (Radius <= 0)
01165 return FALSE;
01166
01167
01168 Sx = (int32)(geVec3d_DotProduct(&LPos, &TexInfo->Vecs[0]));
01169 Sy = (int32)(geVec3d_DotProduct(&LPos, &TexInfo->Vecs[1]));
01170
01171
01172 Sx -= SInfo->LInfo.MinU;
01173 Sy -= SInfo->LInfo.MinV;
01174
01175
01176 Sx *= SInfo->XScale;
01177 Sy *= SInfo->YScale;
01178
01179 Hit = FALSE;
01180
01181 ColorR = Light->FColorR;
01182 ColorG = Light->FColorG;
01183 ColorB = Light->FColorB;
01184
01185 Radius2 = (int32)Radius;
01186
01187 XStep = SInfo->XStep;
01188 YStep = SInfo->YStep;
01189
01190 FixedY = Sy;
01191
01192 LMapPos = Start = SInfo->TexOrg;
01193 Right = SInfo->T2WVecs[0];
01194 Down = SInfo->T2WVecs[1];
01195
01196 Trace_SetupIntersect(CWorld);
01197
01198 for (v=0; v< SInfo->LInfo.Height; v++)
01199 {
01200 y = FixedY >> 10;
01201
01202 if (y < 0)
01203 y = -y;
01204
01205 FixedX = Sx;
01206
01207 for (u=0; u< SInfo->LInfo.Width; u++)
01208 {
01209 x = FixedX >> 10;
01210
01211 if (x<0)
01212 x = -x;
01213
01214 if (x > y)
01215 Dist2 = (x + (y>>1));
01216 else
01217 Dist2 = (y + (x>>1));
01218
01219 if (Dist2 < Radius2)
01220 {
01221 if (Trace_IntersectWorldBSP(&LPos, &LMapPos, 0))
01222 {
01223 LightData += 3;
01224 FixedX -= XStep;
01225 geVec3d_Add(&LMapPos, &Right, &LMapPos);
01226 continue;
01227 }
01228
01229 Hit = TRUE;
01230
01231 Val = (Radius2 - Dist2);
01232
01233 *LightData++ += (int32)(Val * ColorR);
01234 *LightData++ += (int32)(Val * ColorG);
01235 *LightData++ += (int32)(Val * ColorB);
01236 }
01237 else
01238 LightData+=3;
01239
01240 geVec3d_Add(&LMapPos, &Right, &LMapPos);
01241
01242 FixedX -= XStep;
01243 }
01244
01245 geVec3d_Add(&Start, &Down, &Start);
01246 LMapPos = Start;
01247
01248 FixedY -= YStep;
01249 }
01250
01251 return Hit;
01252 }
01253
01254
01255
01256
01257
01258 geBoolean Light_SetupLights(geWorld *World)
01259 {
01260 int32 i, Node;
01261 Light_DLight *DLights;
01262
01263 assert(World != NULL);
01264
01265 assert(BSPData != NULL);
01266 assert(BSPData->GFXModels != NULL);
01267 assert(LightInfo != NULL);
01268
01269
01270 UpdateLTypeTables(World);
01271
01272 DLights = LightInfo->DynamicLights;
01273
01274 #if 0
01275 Node = BSPData->GFXModels[0].RootNode[0];
01276
01277 for (i=0; i< MAX_DYNAMIC_LIGHTS; i++, DLights++)
01278 {
01279 if (!DLights->Active)
01280 continue;
01281
01282 SetupDynamicLight_r(DLights, &DLights->Pos, i, Node);
01283 }
01284 #else
01285 for (i=0; i< MAX_DYNAMIC_LIGHTS; i++, DLights++)
01286 {
01287 int32 m;
01288 geVec3d NewPos;
01289 geWorld_Model *Model;
01290
01291 if (!DLights->Active)
01292 continue;
01293
01294 Model = CBSP->Models;
01295
01296 for (m=0; m< BSPData->NumGFXModels; m++, Model++)
01297 {
01298 if (Model->VisFrame != World->CurFrameDynamic)
01299 continue;
01300
01301 Node = BSPData->GFXModels[m].RootNode[0];
01302
01303 geVec3d_Subtract(&DLights->Pos, &Model->Pivot, &NewPos);
01304
01305 geXForm3d_TransposeTransform(&Model->XForm, &NewPos, &NewPos);
01306
01307 geVec3d_Add(&NewPos , &Model->Pivot, &NewPos);
01308
01309 SetupDynamicLight_r(DLights, &NewPos, i, Node);
01310 }
01311 }
01312 #endif
01313
01314 return GE_TRUE;
01315 }
01316
01317
01318
01319 char Light_WorldGetLTypeCurrent(geWorld *World, int32 LType)
01320 {
01321 Light_LightInfo *LInfo;
01322 assert( World != NULL );
01323 assert( LType >= 0 );
01324 assert( LType < MAX_LTYPES );
01325
01326 LInfo = World->LightInfo;
01327 assert( LInfo != NULL );
01328
01329 return (LInfo->LTypeTable[LType][LInfo->IPos[LType]]) ;
01330 }
01331
01332
01333
01334
01335
01336 static void UpdateLTypeTables(geWorld *World)
01337 {
01338 int32 s;
01339 geFloat i;
01340 Light_LightInfo *LInfo;
01341
01342 LInfo = World->LightInfo;
01343
01344 for (s =0; s <MAX_LTYPES; s++)
01345 {
01346 LInfo->IPos[s]++;
01347
01348 if (LInfo->LTypeTable[s][LInfo->IPos[s]] == 0)
01349 LInfo->IPos[s] = 0;
01350
01351 i = (geFloat)(LInfo->LTypeTable[s][LInfo->IPos[s]]-96) / 27.0f;
01352
01353 LInfo->LTypeIntensities[s] = (int32)(i * (1<<LIGHT_FRACT));
01354
01355 if (LInfo->LTypeIntensities2[s] != LInfo->LTypeTable[s][LInfo->IPos[s]]-96)
01356 LInfo->LTypeDynamic[s] = TRUE;
01357 else
01358 LInfo->LTypeDynamic[s] = FALSE;
01359
01360 LInfo->LTypeIntensities2[s] = LInfo->LTypeTable[s][LInfo->IPos[s]]-96;
01361 }
01362 }
01363
01364
01365
01366
01367 Light_DLight *Light_WorldAddLight(geWorld *World)
01368 {
01369 Light_LightInfo *LInfo;
01370 Light_DLight *DLights;
01371 int32 i;
01372
01373 assert(World != NULL);
01374
01375 LInfo = World->LightInfo;
01376
01377 assert(LInfo);
01378
01379 DLights = LInfo->DynamicLights;
01380
01381 for (i=0; i< MAX_DYNAMIC_LIGHTS; i++, DLights++)
01382 {
01383 if (!DLights->Active)
01384 break;
01385 }
01386
01387 if (i >= MAX_DYNAMIC_LIGHTS)
01388 {
01389 geErrorLog_Add(GE_ERR_RENDERQ_OVERFLOW, NULL);
01390 return NULL;
01391 }
01392
01393
01394 memset(DLights, 0, sizeof(Light_DLight));
01395
01396 DLights->Active = GE_TRUE;
01397 LInfo->NumDynamicLights++;
01398
01399
01400 return DLights;
01401 }
01402
01403
01404
01405
01406 void Light_WorldRemoveLight(geWorld *World, Light_DLight *DLight)
01407 {
01408 assert(World);
01409 assert(World->LightInfo);
01410 assert(DLight);
01411 assert(DLight->Active);
01412
01413 if (!DLight->Active)
01414 return;
01415
01416 DLight->Active = GE_FALSE;
01417 World->LightInfo->NumDynamicLights--;
01418 }
01419
01420
01421
01422
01423 geBoolean Light_SetAttributes( Light_DLight *Light,
01424 const geVec3d *Pos,
01425 const GE_RGBA *RGBA,
01426 geFloat Radius,
01427 geBoolean CastShadow)
01428 {
01429 assert(Light != NULL);
01430
01431 Light->Pos = *Pos;
01432 Light->Color = *RGBA;
01433 Light->Radius = Radius;
01434
01435
01436 Light->FColorR = (int32)((Light->Color.r/195.0f) * (1<<LIGHT_FRACT));
01437 Light->FColorG = (int32)((Light->Color.g/195.0f) * (1<<LIGHT_FRACT));
01438 Light->FColorB = (int32)((Light->Color.b/195.0f) * (1<<LIGHT_FRACT));
01439
01440 Light->CastShadow = CastShadow;
01441
01442 return GE_TRUE;
01443 }
01444
01445
01446
01447
01448 geBoolean Light_WorldSetLTypeTable(geWorld *World, int32 LType, const char *Table)
01449 {
01450 assert(World != NULL);
01451 assert(World->LightInfo != NULL);
01452
01453 if (LType < 0 || LType >= MAX_LTYPES)
01454 {
01455 geErrorLog_Add(GE_ERR_INVALID_LTYPE, NULL);
01456 return GE_FALSE;
01457 }
01458
01459 assert(strlen(Table) < 70);
01460
01461 strcpy(World->LightInfo->LTypeTable[LType], Table);
01462
01463 return GE_TRUE;
01464 }
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474 static int32 FastDist(int32 dx, int32 dy, int32 dz)
01475 {
01476 int32 Max, Med, Min;
01477 int32 Tmp;
01478
01479 Max = (dx < 0) ? -dx : dx;
01480 Med = (dz < 0) ? -dz : dz;
01481 Min = (dy < 0) ? -dy : dy;
01482
01483 if (Max < Med)
01484 {
01485 Tmp = Max; Max = Med; Med = Tmp;
01486 }
01487 if (Max < Min)
01488 {
01489 Tmp = Max; Max = Min; Min = Tmp;
01490 }
01491 Max <<= 2;
01492 Max += Med + Min;
01493 return Max>>2;
01494 }
01495
01496 #define A_MOD 7 // How much to modulus the anim too
01497
01498
01499
01500
01501 static void SetupWavyColorLight1(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh)
01502 {
01503 int32 h;
01504 DRV_RGB *rgb;
01505 U16 r,g,b, II;
01506 DRV_RGB *lm;
01507 uint16 Index;
01508 uint8 *SLUT;
01509 int16 *WaveTable;
01510
01511 assert(light1 != NULL);
01512 assert(RGBM != NULL);
01513
01514 assert(CEngine != NULL);
01515
01516 WaveTable = CEngine->WaveTable;
01517
01518 lm = light1;
01519 rgb = RGBM;
01520 Index = 0;
01521
01522 SLUT = CEngine->StyleLUT1[0];
01523
01524 for (h = 0; h < lh*lw; h++)
01525 {
01526
01527 II = WaveTable[Index++];
01528 if (Index > A_MOD)
01529 Index -= A_MOD;
01530
01531 II >>= 2;
01532 if (II > 63) II = 63;
01533 II <<= 8;
01534 r = SLUT[II + lm->r];
01535 g = SLUT[II + lm->g];
01536 b = SLUT[II + lm->b];
01537
01538 rgb->r = (uint8)r;
01539 rgb->g = (uint8)g;
01540 rgb->b = (uint8)b;
01541
01542 lm++;
01543 rgb++;
01544 }
01545 }
01546
01547
01548
01549
01550 static void SetupWavyColorLight2(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh)
01551 {
01552 int32 h;
01553 DRV_RGB *rgb;
01554 U16 r,g,b, II;
01555 DRV_RGB *lm;
01556 uint16 Index;
01557 uint8 *SLUT;
01558 int16 *WaveTable;
01559
01560 assert(light1 != NULL);
01561 assert(RGBM != NULL);
01562
01563 assert(CEngine != NULL);
01564
01565 WaveTable = CEngine->WaveTable;
01566
01567 lm = light1;
01568 rgb = RGBM;
01569 Index = 0;
01570
01571 SLUT = CEngine->StyleLUT1[0];
01572
01573 for (h = 0; h < lh*lw; h++)
01574 {
01575
01576 II = WaveTable[Index++];
01577 if (Index > A_MOD)
01578 Index -= A_MOD;
01579
01580 II >>= 2;
01581 if (II > 63)
01582 II = 63;
01583 II <<= 8;
01584
01585 r = rgb->r + SLUT[II + lm->r];
01586 g = rgb->g + SLUT[II + lm->g];
01587 b = rgb->b + SLUT[II + lm->b];
01588
01589 if (r > 255) r = 255;
01590 if (g > 255) g = 255;
01591 if (b > 255) b = 255;
01592
01593 rgb->r = (uint8)r;
01594 rgb->g = (uint8)g;
01595 rgb->b = (uint8)b;
01596
01597 lm++;
01598 rgb++;
01599 }
01600 }
01601
01602
01603
01604
01605 static void SetupColorLight1(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh, geFloat intensity)
01606 {
01607 int32 h;
01608 DRV_RGB *rgb;
01609 uint16 r,g,b;
01610 DRV_RGB *lm;
01611 uint16 II;
01612 uint8 *SLUT;
01613
01614 assert(light1 != NULL);
01615 assert(RGBM != NULL);
01616 assert(CEngine != NULL);
01617
01618 lm = light1;
01619 rgb = RGBM;
01620 II = (uint16)(intensity * 63);
01621
01622 if (II > 63) II = 63;
01623
01624 SLUT = &CEngine->StyleLUT1[II][0];
01625
01626 for (h = 0; h < lh*lw; h++)
01627 {
01628 r = SLUT[lm->r];
01629 g = SLUT[lm->g];
01630 b = SLUT[lm->b];
01631
01632 rgb->r = (uint8)r;
01633 rgb->g = (uint8)g;
01634 rgb->b = (uint8)b;
01635
01636 lm++;
01637 rgb++;
01638 }
01639 }
01640
01641
01642
01643
01644 static void SetupColorLight2(DRV_RGB *light1, DRV_RGB *RGBM, int32 lw, int32 lh, geFloat intensity)
01645 {
01646 int32 h;
01647 DRV_RGB *rgb;
01648 uint16 r,g,b;
01649 DRV_RGB *lm;
01650 uint16 II;
01651 uint8 *SLUT;
01652
01653 assert(light1 != NULL);
01654 assert(RGBM != NULL);
01655 assert(CEngine != NULL);
01656
01657 lm = light1;
01658 rgb = RGBM;
01659 II = (uint16)(intensity * 63);
01660
01661 if (II > 63)
01662 II = 63;
01663
01664 SLUT = &CEngine->StyleLUT1[II][0];
01665
01666 for (h = 0; h < lh*lw; h++)
01667 {
01668
01669 r = rgb->r + SLUT[lm->r];
01670 g = rgb->g + SLUT[lm->g];
01671 b = rgb->b + SLUT[lm->b];
01672
01673 if (r > 255) r = 255;
01674 if (g > 255) g = 255;
01675 if (b > 255) b = 255;
01676
01677 rgb->r = (uint8)r;
01678 rgb->g = (uint8)g;
01679 rgb->b = (uint8)b;
01680
01681 lm++;
01682 rgb++;
01683 }
01684 }
01685
01686
01687
01688
01689 static void AddLightTypeWavy1(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh)
01690 {
01691 uint16 *WaveTable, II;
01692 int32 Index, h;
01693 uint8 *SLUT;
01694
01695 assert(LightDest != NULL);
01696 assert(LightData != NULL);
01697 assert(CEngine != NULL);
01698
01699 WaveTable = CEngine->WaveTable;
01700
01701 Index = 0;
01702
01703 SLUT = CEngine->StyleLUT1[0];
01704
01705 for (h = 0; h < lh*lw; h++)
01706 {
01707
01708 II = WaveTable[Index++];
01709
01710 if (Index > A_MOD)
01711 Index -= A_MOD;
01712
01713 II >>= 2;
01714 if (II > 30) II = 30;
01715 II <<= 8;
01716
01717 *LightDest++ = SLUT[II + *LightData++] << (LIGHT_FRACT);
01718 *LightDest++ = SLUT[II + *LightData++] << (LIGHT_FRACT);
01719 *LightDest++ = SLUT[II + *LightData++] << (LIGHT_FRACT);
01720 }
01721 }
01722
01723
01724
01725
01726 static void AddLightTypeWavy(int32 *LightDest, uint8 *LightData, int32 lw, int32 lh)
01727 {
01728 uint16 *WaveTable, II;
01729 int32 Index, h;
01730 uint8 *SLUT;
01731
01732 assert(LightDest != NULL);
01733 assert(LightData != NULL);
01734 assert(CEngine != NULL);
01735
01736 WaveTable = CEngine->WaveTable;
01737
01738 Index = 0;
01739
01740 SLUT = CEngine->StyleLUT1[0];
01741
01742 for (h = 0; h < lh*lw; h++)
01743 {
01744
01745 II = WaveTable[Index++];
01746
01747 if (Index > A_MOD)
01748 Index -= A_MOD;
01749
01750 II >>= 2;
01751 if (II > 30) II = 30;
01752 II <<= 8;
01753
01754 *LightDest++ += SLUT[II + *LightData++] << (LIGHT_FRACT);
01755 *LightDest++ += SLUT[II + *LightData++] << (LIGHT_FRACT);
01756 *LightDest++ += SLUT[II + *LightData++] << (LIGHT_FRACT);
01757 }
01758 }
01759
01760
01761
01762
01763 static void BuildLightLUTS(geEngine *Engine)
01764 {
01765 S32 i, k;
01766
01767 for (i=0; i< 256; i++)
01768 {
01769 for (k=0; k< 64; k++)
01770 {
01771 geFloat ii = (geFloat)i;
01772 geFloat kk = (geFloat)k;
01773 geFloat Intensity = (ii * (kk / 62.0f));
01774 if (Intensity > 255)
01775 Intensity = 255.0f;
01776 Engine->StyleLUT1[k][i] = (U8)Intensity;
01777 }
01778 }
01779 }
01780
01781
01782
01783
01784 static void SetupDynamicLight_r(Light_DLight *pLight, geVec3d *Pos, int32 LNum, int32 Node)
01785 {
01786 geFloat Dist;
01787 GFX_Plane *pPlane;
01788 GFX_Node *pNode;
01789 Surf_SurfInfo *pSInfo;
01790 int32 i;
01791
01792 if (Node < 0)
01793 return;
01794
01795 pNode = &BSPData->GFXNodes[Node];
01796 pPlane = &BSPData->GFXPlanes[pNode->PlaneNum];
01797
01798 Dist = Plane_PlaneDistanceFast(pPlane, Pos);
01799
01800 if (Dist > pLight->Radius)
01801 {
01802 SetupDynamicLight_r(pLight, Pos, LNum, BSPData->GFXNodes[Node].Children[0]);
01803 return;
01804 }
01805 if (Dist <-pLight->Radius)
01806 {
01807 SetupDynamicLight_r(pLight, Pos, LNum, BSPData->GFXNodes[Node].Children[1]);
01808 return;
01809 }
01810
01811
01812 pSInfo = &CBSP->SurfInfo[pNode->FirstFace];
01813 for (i=0; i< pNode->NumFaces; i++, pSInfo++)
01814 {
01815 if (!Surf_InSurfBoundingBox(pSInfo, Pos, pLight->Radius) )
01816 continue;
01817
01818 if (pSInfo->DLightFrame != CWorld->CurFrameDynamic)
01819 {
01820 pSInfo->DLightFrame = CWorld->CurFrameDynamic;
01821 pSInfo->DLights = 0;
01822 }
01823
01824
01825 pSInfo->DLights |= 1<<LNum;
01826 }
01827
01828 SetupDynamicLight_r(pLight, Pos, LNum, BSPData->GFXNodes[Node].Children[0]);
01829 SetupDynamicLight_r(pLight, Pos, LNum, BSPData->GFXNodes[Node].Children[1]);
01830 }
01831
01832
01833
01834
01835
01836
01837
01838 geBoolean Light_GetLightmapRGB(Surf_SurfInfo *Surf, geVec3d *Pos, GE_RGBA *RGBA)
01839 {
01840
01841 DRV_RGB *RGBLight;
01842 geFloat fr = 0.0f, fg = 0.0f, fb = 0.0f;
01843 geVec3d VecU, VecV;
01844 geFloat TexU, TexV;
01845 int32 Index, Width, Height;
01846
01847
01848 if (!(Surf->Flags & SURFINFO_LIGHTMAP))
01849 return GE_FALSE;
01850
01851 RGBLight = Surf->LInfo.RGBLight[0];
01852
01853 if (!RGBLight)
01854 return GE_FALSE;
01855
01856 VecU = BSPData->GFXTexInfo[Surf->TexInfo].Vecs[0];
01857 VecV = BSPData->GFXTexInfo[Surf->TexInfo].Vecs[1];
01858
01859
01860 TexU = geVec3d_DotProduct(Pos, &VecU) + BSPData->GFXTexInfo[Surf->TexInfo].Shift[0];
01861 TexV = geVec3d_DotProduct(Pos, &VecV) + BSPData->GFXTexInfo[Surf->TexInfo].Shift[1];
01862
01863
01864 TexU -= Surf->LInfo.MinU;
01865 TexV -= Surf->LInfo.MinV;
01866
01867 if (TexU < 0 || TexV < 0)
01868 return GE_FALSE;
01869
01870 if (TexU > Surf->LInfo.Width<<4 || TexV > Surf->LInfo.Height<<4)
01871 return GE_FALSE;
01872
01873
01874 TexU /= (16);
01875 TexV /= (16);
01876
01877 Width = Surf->LInfo.Width;
01878 Height = Surf->LInfo.Height;
01879
01880
01881 if (TexU > Width) TexU = (geFloat)Width;
01882 if (TexV > Height) TexV = (geFloat)Height;
01883 if (TexU < 0) TexU = 0.0f;
01884 if (TexV < 0) TexV = 0.0f;
01885
01886 Index = (int32)TexV * Width + (int32)TexU;
01887
01888
01889 RGBA->r = (geFloat)RGBLight[Index].r;
01890 RGBA->g = (geFloat)RGBLight[Index].g;
01891 RGBA->b = (geFloat)RGBLight[Index].b;
01892
01893 return GE_TRUE;
01894 }
01895
01896
01897
01898
01899 geBoolean Light_GetLightmapRGBBlended(Surf_SurfInfo *Surf, geVec3d *Pos, GE_RGBA *RGBA)
01900 {
01901
01902 DRV_RGB *RGBLight;
01903 geFloat fr = 0.0f, fg = 0.0f, fb = 0.0f;
01904 geVec3d VecU, VecV;
01905 geFloat TexU, TexV;
01906 int32 Index, Width, Height;
01907
01908
01909 if (!(Surf->Flags & SURFINFO_LIGHTMAP))
01910 return GE_FALSE;
01911
01912 RGBLight = Surf->LInfo.RGBLight[0];
01913
01914 if (!RGBLight)
01915 return GE_FALSE;
01916
01917 TexU = geVec3d_DotProduct(Pos, &VecU) + BSPData->GFXTexInfo[Surf->TexInfo].Shift[0];
01918 TexV = geVec3d_DotProduct(Pos, &VecV) + BSPData->GFXTexInfo[Surf->TexInfo].Shift[1];
01919
01920
01921 TexU -= Surf->LInfo.MinU;
01922 TexV -= Surf->LInfo.MinV;
01923
01924 if (TexU < 0 || TexV < 0)
01925 return GE_FALSE;
01926
01927 if (TexU > Surf->LInfo.Width<<4 || TexV > Surf->LInfo.Height<<4)
01928 return GE_FALSE;
01929
01930
01931 TexU /= (16);
01932 TexV /= (16);
01933
01934 Width = Surf->LInfo.Width;
01935 Height = Surf->LInfo.Height;
01936
01937
01938 if (TexU > Width) TexU = (geFloat)Width;
01939 if (TexV > Height) TexV = (geFloat)Height;
01940 if (TexU < 0) TexU = 0.0f;
01941 if (TexV < 0) TexV = 0.0f;
01942
01943 Index = (int32)TexV * Width + (int32)TexU;
01944
01945
01946 RGBA->r = (geFloat)RGBLight[Index].r;
01947 RGBA->g = (geFloat)RGBLight[Index].g;
01948 RGBA->b = (geFloat)RGBLight[Index].b;
01949
01950 return GE_TRUE;
01951 }
01952
01953
01954
01955 static void InitSqrtTab(void)
01956 {
01957 int32 i;
01958 double f;
01959 int32 *fi = (int32*) &f + MOST_SIG_OFFSET;
01960
01961 for (i = 0; i < SQRT_TAB_SIZE/2; i++)
01962 {
01963 f = 0;
01964 *fi = (i << MANT_SHIFTS) | (EXP_BIAS << EXP_SHIFTS);
01965 f = sqrt(f);
01966 SqrtTab[i] = *fi & MANT_MASK;
01967
01968 f = 0;
01969 *fi = (i << MANT_SHIFTS) | ((EXP_BIAS + 1) << EXP_SHIFTS);
01970 f = sqrt(f);
01971 SqrtTab[i + SQRT_TAB_SIZE/2] = *fi & MANT_MASK;
01972 }
01973 }
01974
01975
01976
01977 static FastSqrtFloat FastSqrt(FastSqrtFloat f)
01978 {
01979 int32 e;
01980 int32 *fi = (int32*) &f + MOST_SIG_OFFSET;
01981
01982
01983
01984 if (f == (FastSqrtFloat)0.0)
01985 return((FastSqrtFloat)0.0);
01986
01987 e = (*fi >> EXP_SHIFTS) - EXP_BIAS;
01988 *fi &= MANT_MASK;
01989
01990 if (e & 1)
01991 *fi |= EXP_LSB;
01992
01993 e >>= 1;
01994 *fi = (SqrtTab[*fi >> MANT_SHIFTS]) | ((e + EXP_BIAS) << EXP_SHIFTS);
01995
01996 return(f);
01997 }
01998 #if 0
01999
02000
02001 void DumpSqrtTab()
02002 {
02003 int32 i, nl = 0;
02004
02005 printf("unsigned int SqrtTab[] = {\n");
02006
02007 for (i = 0; i < SQRT_TAB_SIZE-1; i++)
02008 {
02009 printf("0x%x,", sqrt_tab[i]);
02010 nl++;
02011 if (nl > 8)
02012 {
02013 nl = 0;
02014 putchar('\n');
02015 }
02016 }
02017 printf("0x%x\n", SqrtTab[SQRT_TAB_SIZE-1]);
02018 printf("};\n");
02019 }
02020 #endif