00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <assert.h>
00020 #include <math.h>
00021
00022 #include "world.h"
00023 #include "trace.h"
00024
00025 #include "sprite.h"
00026
00027 #include "ErrorLog.h"
00028
00029
00030 #define BIG_DISTANCE 30000.0f
00031
00032 extern geBoolean geBitmap_IsValid(const geBitmap *Bmp);
00033
00034
00035 #define SPRITE_NUM_CORNERS 4
00036
00037
00038 #define UNIT_CORNERS { {0.5f, -0.5f}, {-0.5f, -0.5f}, {-0.5f, 0.5f}, {0.5f, 0.5f} }
00039 const geCoordinate UnitCorners[SPRITE_NUM_CORNERS] = UNIT_CORNERS;
00040
00041
00042
00043
00044 typedef struct geSprite_DynamicLight
00045 {
00046 geVec3d Normal;
00047 geColor Color;
00048 geFloat Distance;
00049 geFloat Radius;
00050 } geSprite_DynamicLight;
00051
00052 static geSprite_DynamicLight geSpriteDynamicLights[MAX_DYNAMIC_LIGHTS];
00053
00054
00055
00056
00057 #define MAX_TEMP_VERTS 30
00058
00059 static Surf_TexVert UnclippedUVRGBA[MAX_TEMP_VERTS];
00060
00061 static geVec3d FrustumClippedVertexes1[MAX_TEMP_VERTS];
00062 static Surf_TexVert FrustumClippedUVRGBA1[MAX_TEMP_VERTS];
00063 static geVec3d FrustumClippedVertexes2[MAX_TEMP_VERTS];
00064 static Surf_TexVert FrustumClippedUVRGBA2[MAX_TEMP_VERTS];
00065
00066 static int32 FrustumNumClippedTexturedLitVertices;
00067
00068 static Surf_TLVertex FrustumClippedTexturedLitVertexes[MAX_TEMP_VERTS];
00069
00070
00071 typedef struct geSprite
00072 {
00073
00074 int32 RefCount;
00075
00076
00077 geBitmap * Bitmap;
00078 geBitmap * BackfaceBitmap;
00079
00080
00081 geBoolean BackfaceEnabled;
00082 geBoolean BackfaceMirrorImage;
00083
00084
00085 geBoolean AlwaysFaceCamera;
00086
00087
00088 geXForm3d Transform;
00089
00090
00091
00092 geBoolean InternalTransformUsed;
00093 geXForm3d InternalTransform;
00094
00095
00096 geVec3d Position;
00097
00098
00099
00100 geFloat ScaleX;
00101 geFloat ScaleY;
00102
00103
00104
00105
00106 geCoordinate Corners[SPRITE_NUM_CORNERS];
00107 geVec3d Vertexes[SPRITE_NUM_CORNERS];
00108
00109
00110 geFloat TextureOffsetX;
00111 geFloat TextureOffsetY;
00112 geFloat TextureScaleX;
00113 geFloat TextureScaleY;
00114
00115
00116 geUV UVs[SPRITE_NUM_CORNERS];
00117 geUV BackfaceUVs[SPRITE_NUM_CORNERS];
00118
00119
00120
00121 geColor AmbientLight;
00122 geBoolean UseFillLight;
00123 geColor FillLight;
00124 geVec3d FillLightNormal;
00125 geBoolean UseLightFromFloor;
00126 int32 MaximumDynamicLightsToUse;
00127
00128
00129 GE_RGBA RGBA;
00130 GE_RGBA BackfaceRGBA;
00131
00132
00133 geVec3d SurfaceNormal;
00134 geBoolean LightingUsesSurfaceNormal;
00135
00136
00137 geVec3d BoundingBoxMinCorner;
00138 geVec3d BoundingBoxMaxCorner;
00139
00140
00141 void * UserData;
00142
00143
00144
00145 geBoolean TransformChanged;
00146 geBoolean LightingChanged;
00147
00148 } geSprite;
00149
00150
00151
00152 int32 geSprite_Count = 0;
00153 int32 geSprite_RefCount = 0;
00154
00155
00156 __inline static void geSprite_UpdatePosition(geSprite *S)
00157 {
00158 if (S->AlwaysFaceCamera)
00159 S->Position = S->Transform.Translation;
00160 else
00161 geVec3d_Add( &(S->Transform.Translation), &(S->InternalTransform.Translation), &(S->Position) );
00162 }
00163
00164
00165 __inline static void geSprite_UpdateCorners(geSprite *S)
00166 {
00167 int i;
00168
00169 for (i = 0; i < SPRITE_NUM_CORNERS; i++)
00170 {
00171 S->Corners[i].X = UnitCorners[i].X * S->ScaleX;
00172 S->Corners[i].Y = UnitCorners[i].Y * S->ScaleY;
00173 }
00174 }
00175
00176
00177 __inline static void geSprite_UpdateVertexes(geSprite *S)
00178 {
00179 int i;
00180
00181
00182 for (i = 0; i < SPRITE_NUM_CORNERS; i++)
00183 {
00184 S->Vertexes[i].X = S->Corners[i].X;
00185 S->Vertexes[i].Y = S->Corners[i].Y;
00186 S->Vertexes[i].Z = 0.0f;
00187 }
00188
00189
00190 if (S->InternalTransformUsed)
00191 geXForm3d_TransformArray(&(S->InternalTransform), S->Vertexes, S->Vertexes, SPRITE_NUM_CORNERS);
00192
00193
00194 geXForm3d_TransformArray(&(S->Transform), S->Vertexes, S->Vertexes, SPRITE_NUM_CORNERS);
00195 }
00196
00197
00198 __inline static void geSprite_UpdateVertexesToFaceCamera(geSprite *S, geCamera *Camera)
00199 {
00200 int i;
00201 const geXForm3d *CameraXForm;
00202 geVec3d Left;
00203 geVec3d Up;
00204 geVec3d In;
00205 geFloat Dot;
00206
00207
00208
00209
00210
00211
00212 CameraXForm = geCamera_GetWorldSpaceXForm(Camera);
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 In.X = CameraXForm->AZ;
00224 In.Y = CameraXForm->BZ;
00225 In.Z = CameraXForm->CZ;
00226
00227
00228 geXForm3d_GetUp(CameraXForm, &Up);
00229
00230 Dot = geVec3d_DotProduct(&Up, &In);
00231
00232 Up.X = Up.X - (Dot * In.X);
00233 Up.Y = Up.Y - (Dot * In.Y);
00234 Up.Z = Up.Z - (Dot * In.Z);
00235
00236 geVec3d_Normalize(&Up);
00237
00238
00239
00240
00241
00242
00243
00244 Left.X = (Up.Z * In.Y) - (Up.Y * In.Z);
00245 Left.Y = (Up.X * In.Z) - (Up.Z * In.X);
00246 Left.Z = (Up.Y * In.X) - (Up.X * In.Y);
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 for (i = 0; i < SPRITE_NUM_CORNERS; i++)
00257 {
00258
00259
00260
00261
00262
00263
00264
00265
00266 S->Vertexes[i].X = (S->Corners[i].X * Left.X) + (S->Corners[i].Y * Up.X) + S->Transform.Translation.X;
00267 S->Vertexes[i].Y = (S->Corners[i].X * Left.Y) + (S->Corners[i].Y * Up.Y) + S->Transform.Translation.Y;
00268 S->Vertexes[i].Z = (S->Corners[i].X * Left.Z) + (S->Corners[i].Y * Up.Z) + S->Transform.Translation.Z;
00269 }
00270 }
00271
00272
00273 __inline static void geSprite_UpdateSurfaceNormal(geSprite *S)
00274 {
00275 if (S->InternalTransformUsed)
00276 {
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 S->SurfaceNormal.X = -S->InternalTransform.AZ;
00288 S->SurfaceNormal.Y = -S->InternalTransform.BZ;
00289 S->SurfaceNormal.Z = -S->InternalTransform.CZ;
00290
00291
00292 geXForm3d_Rotate(&(S->Transform), &(S->SurfaceNormal), &(S->SurfaceNormal));
00293
00294 }
00295
00296 else
00297 {
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308 S->SurfaceNormal.X = -S->Transform.AZ;
00309 S->SurfaceNormal.Y = -S->Transform.BZ;
00310 S->SurfaceNormal.Z = -S->Transform.CZ;
00311 }
00312 }
00313
00314
00315 __inline static void geSprite_UpdateSurfaceNormalToFaceCamera(geSprite *S, geCamera *Camera)
00316 {
00317
00318 const geXForm3d *CameraXForm;
00319 CameraXForm = geCamera_GetWorldSpaceXForm(Camera);
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330 S->SurfaceNormal.X = CameraXForm->AZ;
00331 S->SurfaceNormal.Y = CameraXForm->BZ;
00332 S->SurfaceNormal.Z = CameraXForm->CZ;
00333 }
00334
00335
00336 __inline static void geSprite_CreateFrustumClippedScreenPoly(geSprite *S, geCamera *Camera, Frustum_Info *FInfo, geBoolean *Render, geBoolean *RenderBackface)
00337 {
00338 int i;
00339
00340 const geXForm3d *CameraXForm;
00341
00342 GFX_Plane *FPlanes;
00343
00344 geVec3d *pVerts1;
00345 geVec3d *pVerts2;
00346 Surf_TexVert *pTexs1;
00347 Surf_TexVert *pTexs2;
00348 int32 Length;
00349
00350 geVec3d CameraNormal;
00351
00352
00353
00354 if (S->AlwaysFaceCamera)
00355 {
00356 *RenderBackface = GE_FALSE;
00357 }
00358
00359
00360
00361 else
00362 {
00363
00364 CameraXForm = geCamera_GetWorldSpaceXForm(Camera);
00365
00366
00367 geVec3d_Subtract(&(S->Position), &(CameraXForm->Translation), &CameraNormal);
00368 geVec3d_Normalize(&CameraNormal);
00369
00370
00371
00372
00373 *RenderBackface = (geVec3d_DotProduct(&CameraNormal, &(S->SurfaceNormal)) > 0);
00374
00375
00376
00377 if ( (*RenderBackface) && (!S->BackfaceEnabled) )
00378 {
00379 *Render = GE_FALSE;
00380 return;
00381 }
00382 }
00383
00384
00385 if ( ((!(*RenderBackface)) && (S->RGBA.a == 0.0f)) ||
00386 ((*RenderBackface) && (S->BackfaceRGBA.a == 0.0f)) )
00387 {
00388 *Render = GE_FALSE;
00389 return;
00390 }
00391
00392
00393 if (*RenderBackface)
00394 {
00395 for (i = 0; i < SPRITE_NUM_CORNERS; i++)
00396 {
00397 UnclippedUVRGBA[i].u = S->BackfaceUVs[i].u;
00398 UnclippedUVRGBA[i].v = S->BackfaceUVs[i].v;
00399 }
00400 }
00401 else
00402 {
00403 for (i = 0; i < SPRITE_NUM_CORNERS; i++)
00404 {
00405 UnclippedUVRGBA[i].u = S->UVs[i].u;
00406 UnclippedUVRGBA[i].v = S->UVs[i].v;
00407 }
00408 }
00409
00410
00411 FPlanes = FInfo->Planes;
00412 pVerts1 = S->Vertexes;
00413 pTexs1 = UnclippedUVRGBA;
00414 pVerts2 = FrustumClippedVertexes1;
00415 pTexs2 = FrustumClippedUVRGBA1;
00416 Length = SPRITE_NUM_CORNERS;
00417
00418
00419 for (i = 0; i < FInfo->NumPlanes; i++, FPlanes++)
00420 {
00421
00422 if (!Frustum_ClipToPlaneUV(FPlanes, pVerts1, pVerts2, pTexs1, pTexs2, Length, &FrustumNumClippedTexturedLitVertices))
00423 break;
00424
00425 assert(FrustumNumClippedTexturedLitVertices < MAX_TEMP_VERTS);
00426
00427
00428
00429
00430 if (pVerts2 == FrustumClippedVertexes1)
00431 {
00432 pVerts1 = FrustumClippedVertexes1;
00433 pVerts2 = FrustumClippedVertexes2;
00434 pTexs1 = FrustumClippedUVRGBA1;
00435 pTexs2 = FrustumClippedUVRGBA2;
00436 }
00437 else
00438 {
00439 pVerts1 = FrustumClippedVertexes2;
00440 pVerts2 = FrustumClippedVertexes1;
00441 pTexs1 = FrustumClippedUVRGBA2;
00442 pTexs2 = FrustumClippedUVRGBA1;
00443 }
00444
00445 Length = FrustumNumClippedTexturedLitVertices;
00446 }
00447
00448 assert(FrustumNumClippedTexturedLitVertices < MAX_TEMP_VERTS);
00449
00450
00451 if ( (i != FInfo->NumPlanes) || (FrustumNumClippedTexturedLitVertices < 3) )
00452 {
00453 *Render = GE_FALSE;
00454 return;
00455 }
00456
00457
00458 geCamera_TransformArray(Camera, pVerts1, pVerts1, FrustumNumClippedTexturedLitVertices);
00459
00460
00461 Frustum_ProjectRGBA(pVerts1, pTexs1, (DRV_TLVertex*)&FrustumClippedTexturedLitVertexes, FrustumNumClippedTexturedLitVertices, Camera);
00462
00463 *Render = GE_TRUE;
00464 }
00465
00466
00467 __inline static void geSprite_UpdateBackfaceTextureMap(geSprite *S)
00468 {
00469 if (S->BackfaceMirrorImage)
00470 {
00471 S->BackfaceUVs[0].u = S->UVs[0].u;
00472 S->BackfaceUVs[0].v = S->UVs[0].v;
00473 S->BackfaceUVs[1].u = S->UVs[1].u;
00474 S->BackfaceUVs[1].v = S->UVs[1].v;
00475 S->BackfaceUVs[2].u = S->UVs[2].u;
00476 S->BackfaceUVs[2].v = S->UVs[2].v;
00477 S->BackfaceUVs[3].u = S->UVs[3].u;
00478 S->BackfaceUVs[3].v = S->UVs[3].v;
00479 }
00480 else
00481 {
00482 S->BackfaceUVs[0].u = S->UVs[1].u;
00483 S->BackfaceUVs[0].v = S->UVs[1].v;
00484 S->BackfaceUVs[1].u = S->UVs[0].u;
00485 S->BackfaceUVs[1].v = S->UVs[0].v;
00486 S->BackfaceUVs[2].u = S->UVs[3].u;
00487 S->BackfaceUVs[2].v = S->UVs[3].v;
00488 S->BackfaceUVs[3].u = S->UVs[2].u;
00489 S->BackfaceUVs[3].v = S->UVs[2].v;
00490 }
00491 }
00492
00493
00494 __inline static void geSprite_UpdateTextureMap(geSprite *S)
00495 {
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 S->UVs[3].u = S->UVs[0].u = S->TextureOffsetX;
00511 S->UVs[1].v = S->UVs[0].v = 1 - S->TextureOffsetY;
00512
00513 S->UVs[2].u = S->UVs[1].u = S->TextureOffsetX + S->TextureScaleX;
00514 S->UVs[1].v = 1 - S->TextureOffsetY;
00515
00516 S->UVs[3].v = S->UVs[2].v = 1 - S->TextureOffsetY - S->TextureScaleY;
00517
00518 geSprite_UpdateBackfaceTextureMap(S);
00519 }
00520
00521
00522 #pragma warning(disable : 4700 )
00523 __inline static void geSprite_UpdateLighting(geSprite *S, geWorld *World)
00524 {
00525 int32 i, j;
00526
00527 geFloat Intensity;
00528
00529 geBoolean DoBackface;
00530
00531 geSprite_DynamicLight TempSwap;
00532
00533 geFloat Scale;
00534
00535 geVec3d PositionBelowFloor;
00536
00537 geBoolean InsideWorldModel;
00538 geBoolean FloorBeneath;
00539
00540 geVec3d Impact;
00541 int32 Node;
00542 int32 Plane;
00543
00544 GFX_Node *GFXNodes;
00545 Surf_SurfInfo *Surf;
00546 GE_RGBA FaceLightmapColor;
00547
00548
00549
00550 S->RGBA.r = S->AmbientLight.r;
00551 S->RGBA.g = S->AmbientLight.g;
00552 S->RGBA.b = S->AmbientLight.b;
00553
00554
00555 DoBackface = ( (S->BackfaceEnabled) && !(S->AlwaysFaceCamera) );
00556 if (DoBackface)
00557 {
00558 S->BackfaceRGBA.r = S->AmbientLight.r;
00559 S->BackfaceRGBA.g = S->AmbientLight.g;
00560 S->BackfaceRGBA.b = S->AmbientLight.b;
00561 }
00562
00563
00564 if (S->UseFillLight)
00565 {
00566 Intensity = geVec3d_DotProduct( &(S->FillLightNormal), &(S->SurfaceNormal) );
00567
00568 if (Intensity < 0.0f)
00569 {
00570 S->RGBA.r -= (Intensity * S->FillLight.r);
00571 S->RGBA.g -= (Intensity * S->FillLight.g);
00572 S->RGBA.b -= (Intensity * S->FillLight.b);
00573 }
00574 else
00575 {
00576
00577 if (DoBackface)
00578 {
00579 S->BackfaceRGBA.r += (Intensity * S->FillLight.r);
00580 S->BackfaceRGBA.g += (Intensity * S->FillLight.g);
00581 S->BackfaceRGBA.b += (Intensity * S->FillLight.b);
00582 }
00583 }
00584 }
00585
00586 if (S->MaximumDynamicLightsToUse > 0)
00587 {
00588
00589 Light_DLight *DynamicLights = World->LightInfo->DynamicLights;
00590
00591
00592 int32 DLCount = 0;
00593
00594
00595 for (i = 0; i < MAX_DYNAMIC_LIGHTS; i++)
00596 {
00597 if (DynamicLights[i].Active)
00598 {
00599
00600 geVec3d Normal;
00601 geVec3d_Subtract(&(S->Position), &(DynamicLights[i].Pos), &Normal);
00602
00603
00604 geSpriteDynamicLights[DLCount].Distance = (Normal.X * Normal.X) +
00605 (Normal.Y * Normal.Y) +
00606 (Normal.Z * Normal.Z);
00607
00608
00609 if (geSpriteDynamicLights[DLCount].Distance < (DynamicLights[i].Radius * DynamicLights[i].Radius))
00610 {
00611 geSpriteDynamicLights[DLCount].Color.r = DynamicLights[i].Color.r;
00612 geSpriteDynamicLights[DLCount].Color.g = DynamicLights[i].Color.g;
00613 geSpriteDynamicLights[DLCount].Color.b = DynamicLights[i].Color.b;
00614 geSpriteDynamicLights[DLCount].Radius = DynamicLights[i].Radius;
00615
00616 geSpriteDynamicLights[DLCount].Normal = Normal;
00617 DLCount++;
00618 }
00619 }
00620 }
00621
00622
00623 if (DLCount > 1)
00624 {
00625
00626
00627 if ( (S->MaximumDynamicLightsToUse == 1) )
00628 {
00629 for (i = 1; i < DLCount; i++)
00630 {
00631 if (geSpriteDynamicLights[i].Distance < geSpriteDynamicLights[0].Distance)
00632 geSpriteDynamicLights[0] = geSpriteDynamicLights[i];
00633 }
00634 }
00635
00636
00637 else
00638 {
00639 for (i = 0; i < DLCount; i++)
00640 {
00641 for (j = 0; j < (DLCount - 1); j++)
00642 {
00643 if (geSpriteDynamicLights[j].Distance > geSpriteDynamicLights[j+1].Distance)
00644 {
00645 TempSwap = geSpriteDynamicLights[j];
00646 geSpriteDynamicLights[j] = geSpriteDynamicLights[j+1];
00647 geSpriteDynamicLights[j+1] = TempSwap;
00648 }
00649 }
00650 }
00651 }
00652 }
00653
00654
00655 if (DLCount > S->MaximumDynamicLightsToUse)
00656 DLCount = S->MaximumDynamicLightsToUse;
00657
00658
00659 for (i = 0; i < DLCount; i++)
00660 {
00661
00662 geVec3d *LightNormal = &(geSpriteDynamicLights[i].Normal);
00663
00664
00665 geFloat Distance = (geFloat)sqrt(geSpriteDynamicLights[i].Distance);
00666
00667
00668 if (Distance > 1.0f)
00669 geVec3d_Scale(LightNormal, (1.0f / Distance), LightNormal);
00670 else
00671 Distance = 1.0f;
00672
00673 Scale = 1.0f - (Distance / geSpriteDynamicLights[i].Radius);
00674
00675 Intensity = geVec3d_DotProduct( LightNormal, &(S->SurfaceNormal) );
00676
00677 if (Intensity < 0.0f)
00678 {
00679 S->RGBA.r -= (Intensity * geSpriteDynamicLights[i].Color.r * Scale);
00680 S->RGBA.g -= (Intensity * geSpriteDynamicLights[i].Color.g * Scale);
00681 S->RGBA.b -= (Intensity * geSpriteDynamicLights[i].Color.b * Scale);
00682 }
00683 else
00684 {
00685 if (DoBackface)
00686 {
00687 S->BackfaceRGBA.r += (Intensity * geSpriteDynamicLights[i].Color.r * Scale);
00688 S->BackfaceRGBA.g += (Intensity * geSpriteDynamicLights[i].Color.g * Scale);
00689 S->BackfaceRGBA.b += (Intensity * geSpriteDynamicLights[i].Color.b * Scale);
00690 }
00691 }
00692 }
00693 }
00694
00695 if (S->UseLightFromFloor)
00696 {
00697 PositionBelowFloor.X = S->Position.X;
00698 PositionBelowFloor.Y = S->Position.Y - BIG_DISTANCE;
00699 PositionBelowFloor.Z = S->Position.Z;
00700
00701
00702 InsideWorldModel = Trace_WorldCollisionExact2(World, &(S->Position), &(S->Position), &Impact, &Node, &Plane, NULL);
00703 FloorBeneath = Trace_WorldCollisionExact2(World, &(S->Position), &PositionBelowFloor, &Impact, &Node, &Plane, NULL);
00704
00705
00706 if ( (!InsideWorldModel) && FloorBeneath)
00707 {
00708
00709 GFXNodes = World->CurrentBSP->BSPData.GFXNodes;
00710
00711
00712 Surf = &(World->CurrentBSP->SurfInfo[GFXNodes[Node].FirstFace]);
00713
00714
00715 if (Surf->LInfo.Face >= 0)
00716 {
00717
00718 for (i = 0; i < GFXNodes[Node].NumFaces; i++)
00719 {
00720
00721
00722 if (Surf_InSurfBoundingBox(Surf, &Impact, 20.0f))
00723 {
00724
00725 Light_SetupLightmap(&Surf->LInfo, NULL);
00726
00727
00728
00729 if (Light_GetLightmapRGB(Surf, &Impact, &FaceLightmapColor))
00730 {
00731 S->RGBA.r += FaceLightmapColor.r;
00732 S->RGBA.g += FaceLightmapColor.g;
00733 S->RGBA.b += FaceLightmapColor.b;
00734
00735 if (DoBackface)
00736 {
00737 S->BackfaceRGBA.r += FaceLightmapColor.r;
00738 S->BackfaceRGBA.g += FaceLightmapColor.g;
00739 S->BackfaceRGBA.b += FaceLightmapColor.b;
00740 }
00741
00742 break;
00743 }
00744 }
00745
00746
00747 Surf++;
00748 }
00749 }
00750 }
00751 }
00752
00753
00754 if (S->RGBA.r > 255.0f)
00755 S->RGBA.r = 255.0f;
00756 else if (S->RGBA.r < 0.0f)
00757 S->RGBA.r = 0.0f;
00758
00759 if (S->RGBA.g > 255.0f)
00760 S->RGBA.g = 255.0f;
00761 else if (S->RGBA.g < 0.0f)
00762 S->RGBA.g = 0.0f;
00763
00764 if (S->RGBA.b > 255.0f)
00765 S->RGBA.b = 255.0f;
00766 else if (S->RGBA.b < 0.0f)
00767 S->RGBA.b = 0.0f;
00768
00769 if (DoBackface)
00770 {
00771
00772 if (S->BackfaceRGBA.r > 255.0f)
00773 S->BackfaceRGBA.r = 255.0f;
00774 else if (S->BackfaceRGBA.r < 0.0f)
00775 S->BackfaceRGBA.r = 0.0f;
00776
00777 if (S->BackfaceRGBA.g > 255.0f)
00778 S->BackfaceRGBA.g = 255.0f;
00779 else if (S->BackfaceRGBA.g < 0.0f)
00780 S->BackfaceRGBA.g = 0.0f;
00781
00782 if (S->BackfaceRGBA.b > 255.0f)
00783 S->BackfaceRGBA.b = 255.0f;
00784 else if (S->BackfaceRGBA.b < 0.0f)
00785 S->BackfaceRGBA.b = 0.0f;
00786 }
00787 }
00788 #pragma warning(default : 4700 )
00789
00790
00791 GENESISAPI int32 GENESISCC geSprite_GetCount()
00792 {
00793 return geSprite_Count;
00794 }
00795
00796
00797 GENESISAPI geSprite *GENESISCC geSprite_Create(geBitmap *SpriteBitmap, geBitmap *SpriteBackfaceBitmap)
00798 {
00799 geSprite *S;
00800
00801 if (SpriteBitmap)
00802 {
00803 if ( geBitmap_IsValid(SpriteBitmap) == GE_FALSE )
00804 {
00805 geErrorLog_Add( ERR_SPRITE_INVALIDBITMAP , NULL);
00806 return NULL;
00807 }
00808 }
00809
00810 if ( (SpriteBackfaceBitmap) && (SpriteBackfaceBitmap != SpriteBitmap) )
00811 {
00812 if ( geBitmap_IsValid(SpriteBackfaceBitmap) == GE_FALSE )
00813 {
00814 geErrorLog_Add( ERR_SPRITE_INVALIDBITMAP , NULL);
00815 return NULL;
00816 }
00817 }
00818
00819
00820 S = GE_RAM_ALLOCATE_STRUCT( geSprite );
00821 if ( S == NULL )
00822 {
00823 geErrorLog_Add( ERR_SPRITE_ENOMEM , NULL);
00824 return NULL;
00825 }
00826
00827 S->RefCount = 0;
00828
00829 S->Bitmap = SpriteBitmap;
00830 if (SpriteBitmap)
00831 geBitmap_CreateRef(SpriteBitmap);
00832
00833 S->BackfaceBitmap = SpriteBackfaceBitmap;
00834 if ( (SpriteBackfaceBitmap) && (SpriteBitmap != SpriteBackfaceBitmap) )
00835 geBitmap_CreateRef(SpriteBackfaceBitmap);
00836
00837 S->BackfaceEnabled = GE_TRUE;
00838 S->BackfaceMirrorImage = GE_TRUE;
00839
00840 S->AlwaysFaceCamera = GE_FALSE;
00841
00842 geXForm3d_SetIdentity(&(S->Transform));
00843
00844 S->InternalTransformUsed = GE_FALSE;
00845 geXForm3d_SetIdentity(&(S->InternalTransform));
00846
00847 geSprite_UpdatePosition(S);
00848
00849 S->ScaleX = 1.0f;
00850 S->ScaleY = 1.0f;
00851 geSprite_UpdateCorners(S);
00852
00853 S->TextureOffsetX = 0.0f;
00854 S->TextureOffsetY = 0.0f;
00855 S->TextureScaleX = 1.0f;
00856 S->TextureScaleY = 1.0f;
00857 geSprite_UpdateTextureMap(S);
00858
00859 geVec3d_Clear(&(S->BoundingBoxMinCorner));
00860 geVec3d_Clear(&(S->BoundingBoxMaxCorner));
00861
00862 S->AmbientLight.r = 0.1f;
00863 S->AmbientLight.g = 0.1f;
00864 S->AmbientLight.b = 0.1f;
00865 S->UseFillLight = GE_FALSE;
00866 S->UseLightFromFloor = GE_FALSE;
00867 S->MaximumDynamicLightsToUse = 0;
00868
00869 S->LightingUsesSurfaceNormal = GE_FALSE;
00870
00871 S->RGBA.a = 255.0f;
00872 S->BackfaceRGBA.a = 255.0f;
00873
00874 S->UserData = NULL;
00875
00876 S->TransformChanged = GE_TRUE;
00877 S->LightingChanged = GE_TRUE;
00878
00879 assert( geSprite_IsValid(S) );
00880
00881 geSprite_Count++;
00882
00883 return S;
00884 }
00885
00886
00887 GENESISAPI void GENESISCC geSprite_CreateRef(geSprite *S)
00888 {
00889 assert( geSprite_IsValid(S) );
00890
00891 S->RefCount++;
00892 geSprite_RefCount++;
00893 }
00894
00895
00896 GENESISAPI void GENESISCC geSprite_Destroy(geSprite **pS)
00897 {
00898 geSprite *S;
00899 assert( pS != NULL );
00900 assert( *pS != NULL );
00901 assert( geSprite_IsValid(*pS) );
00902
00903 S = *pS;
00904 if (S->RefCount > 0)
00905 {
00906 S->RefCount --;
00907 geSprite_RefCount--;
00908 return;
00909 }
00910
00911 if (S->Bitmap)
00912 {
00913 geBitmap_Destroy(&(S->Bitmap));
00914 }
00915
00916 if ( (S->BackfaceBitmap) && (S->BackfaceBitmap != S->Bitmap) )
00917 {
00918 geBitmap_Destroy(&(S->BackfaceBitmap));
00919 }
00920
00921 geRam_Free(*pS);
00922 geSprite_Count--;
00923 *pS = NULL;
00924 }
00925
00926
00927 GENESISAPI geBoolean GENESISCC geSprite_IsValid(const geSprite *S)
00928 {
00929 if (S == NULL)
00930 return GE_FALSE;
00931
00932 return GE_TRUE;
00933 }
00934
00935
00936 GENESISAPI geBitmap *GENESISCC geSprite_GetBitmap(const geSprite *S)
00937 {
00938 assert ( (S->Bitmap == NULL) || (geBitmap_IsValid(S->Bitmap)) );
00939
00940 return S->Bitmap;
00941 }
00942
00943
00944 GENESISAPI geBitmap *GENESISCC geSprite_GetBackfaceBitmap(const geSprite *S)
00945 {
00946 assert ( (S->BackfaceBitmap == NULL) || (geBitmap_IsValid(S->BackfaceBitmap)) );
00947
00948 return S->BackfaceBitmap;
00949 }
00950
00951
00952 GENESISAPI void GENESISCC geSprite_GetBackface(const geSprite *S, geBoolean *Enabled, geBoolean *MirrorImage)
00953 {
00954 assert ( Enabled );
00955 assert ( MirrorImage );
00956
00957 *Enabled = S->BackfaceEnabled;
00958 *MirrorImage = S->BackfaceMirrorImage;
00959 }
00960
00961
00962 GENESISAPI void GENESISCC geSprite_SetBackface(geSprite *S, const geBoolean Enabled, const geBoolean MirrorImage)
00963 {
00964 assert( geSprite_IsValid(S) );
00965
00966
00967
00968
00969 S->LightingChanged = (S->LightingChanged || ((Enabled) && (!S->BackfaceEnabled)) );
00970
00971
00972 if (S->BackfaceMirrorImage != MirrorImage)
00973 {
00974 S->BackfaceMirrorImage = MirrorImage;
00975 geSprite_UpdateBackfaceTextureMap(S);
00976 }
00977
00978 S->BackfaceEnabled = Enabled;
00979 }
00980
00981
00982 GENESISAPI void GENESISCC geSprite_GetFaceCamera(const geSprite *S, geBoolean *Enabled)
00983 {
00984 assert( geSprite_IsValid(S) );
00985 assert( Enabled != NULL );
00986
00987 *Enabled = S->AlwaysFaceCamera;
00988 }
00989
00990
00991 GENESISAPI void GENESISCC geSprite_SetFaceCamera(geSprite *S, geBoolean Enabled)
00992 {
00993 assert( geSprite_IsValid(S) );
00994
00995
00996
00997 if ( (S->AlwaysFaceCamera) && (!Enabled) )
00998 {
00999 S->TransformChanged = GE_TRUE;
01000 }
01001
01002 S->AlwaysFaceCamera = Enabled;
01003
01004 geSprite_UpdatePosition(S);
01005 }
01006
01007
01008 GENESISAPI void GENESISCC geSprite_GetPosition(const geSprite *S, geVec3d *Pos)
01009 {
01010 assert( geSprite_IsValid(S) );
01011 assert( Pos != NULL );
01012 assert( geXForm3d_IsOrthonormal(&(S->Transform)) );
01013
01014 *Pos = S->Transform.Translation;
01015 }
01016
01017
01018 GENESISAPI void GENESISCC geSprite_SetPosition(geSprite *S, const geVec3d *Pos)
01019 {
01020 assert( geSprite_IsValid(S) );
01021 assert( Pos != NULL );
01022 assert( geXForm3d_IsOrthonormal(&(S->Transform)) );
01023
01024 S->Transform.Translation = *Pos;
01025
01026 geSprite_UpdatePosition(S);
01027
01028 S->TransformChanged = GE_TRUE;
01029 }
01030
01031
01032 GENESISAPI void GENESISCC geSprite_GetTransform(const geSprite *S, geXForm3d *Transform)
01033 {
01034 assert( geSprite_IsValid(S) );
01035 assert( Transform!= NULL );
01036
01037 *Transform = S->Transform;
01038 }
01039
01040
01041 GENESISAPI void GENESISCC geSprite_SetTransform(geSprite *S, const geXForm3d *Transform)
01042 {
01043 assert( geSprite_IsValid(S) );
01044 assert( Transform );
01045
01046 S->Transform = *Transform;
01047
01048 geSprite_UpdatePosition(S);
01049
01050 S->TransformChanged = GE_TRUE;
01051 }
01052
01053
01054 GENESISAPI void GENESISCC geSprite_GetInternalTransform(const geSprite *S, geXForm3d *Transform)
01055 {
01056 assert( geSprite_IsValid(S) );
01057 assert( Transform );
01058
01059 *Transform = S->InternalTransform;
01060 }
01061
01062
01063 GENESISAPI void GENESISCC geSprite_SetInternalTransform(geSprite *S, const geXForm3d *Transform)
01064 {
01065 assert( geSprite_IsValid(S) );
01066 assert( Transform );
01067
01068 S->InternalTransform = *Transform;
01069 S->InternalTransformUsed = !( geXForm3d_IsIdentity(Transform) );
01070
01071 geSprite_UpdatePosition(S);
01072
01073 S->TransformChanged = GE_TRUE;
01074 }
01075
01076
01077 GENESISAPI void GENESISCC geSprite_GetScale(const geSprite *S, geFloat *ScaleX, geFloat *ScaleY)
01078 {
01079 assert( geSprite_IsValid(S)!=GE_FALSE );
01080
01081 *ScaleX = S->ScaleX;
01082 *ScaleY = S->ScaleY;
01083 }
01084
01085
01086 GENESISAPI void GENESISCC geSprite_SetScale(geSprite *S, geFloat ScaleX, geFloat ScaleY)
01087 {
01088 assert( geSprite_IsValid(S)!=GE_FALSE );
01089
01090 if ( (S->ScaleX != ScaleX) || (S->ScaleY != ScaleY) )
01091 {
01092 S->ScaleX = ScaleX;
01093 S->ScaleY = ScaleY;
01094
01095 geSprite_UpdateCorners(S);
01096
01097 S->TransformChanged = GE_TRUE;
01098 }
01099 }
01100
01101
01102 GENESISAPI void GENESISCC geSprite_GetExtBox(const geSprite *S, geExtBox *ExtBox)
01103 {
01104 assert( geSprite_IsValid(S) );
01105 assert( ExtBox != NULL );
01106 assert( geXForm3d_IsOrthonormal(&(S->Transform)) );
01107
01108 geVec3d_Add( &(S->Transform.Translation), &(S->BoundingBoxMinCorner), &(ExtBox->Min));
01109 geVec3d_Add( &(S->Transform.Translation), &(S->BoundingBoxMaxCorner), &(ExtBox->Max));
01110 }
01111
01112
01113 GENESISAPI void GENESISCC geSprite_GetNonWorldExtBox(const geSprite *S, geExtBox *ExtBox)
01114 {
01115 assert( geSprite_IsValid(S) );
01116 assert( ExtBox != NULL );
01117
01118 ExtBox->Min = S->BoundingBoxMinCorner;
01119 ExtBox->Max = S->BoundingBoxMaxCorner;
01120 }
01121
01122
01123 GENESISAPI void GENESISCC geSprite_SetExtBox(geSprite *S, const geExtBox *ExtBox)
01124 {
01125 assert( geSprite_IsValid(S) );
01126 assert( geExtBox_IsValid(ExtBox) );
01127
01128 S->BoundingBoxMinCorner = ExtBox->Min;
01129 S->BoundingBoxMaxCorner = ExtBox->Max;
01130 }
01131
01132
01133 GENESISAPI void GENESISCC geSprite_GetTextureParameters(const geSprite *S,
01134 geFloat *OffsetX,
01135 geFloat *OffsetY,
01136 geFloat *ScaleX,
01137 geFloat *ScaleY)
01138 {
01139 assert( geSprite_IsValid(S) );
01140 assert( OffsetX != NULL );
01141 assert( OffsetY != NULL );
01142 assert( ScaleX != NULL );
01143 assert( ScaleY != NULL );
01144
01145 *OffsetX = S->TextureOffsetX;
01146 *OffsetY = S->TextureOffsetY;
01147 *ScaleX = S->TextureScaleX;
01148 *ScaleY = S->TextureScaleY;
01149 }
01150
01151
01152 GENESISAPI void GENESISCC geSprite_SetTextureParameters(geSprite *S,
01153 geFloat OffsetX,
01154 geFloat OffsetY,
01155 geFloat ScaleX,
01156 geFloat ScaleY)
01157 {
01158 assert( geSprite_IsValid(S) );
01159
01160 S->TextureOffsetX = OffsetX;
01161 S->TextureOffsetY = OffsetY;
01162 S->TextureScaleX = ScaleX;
01163 S->TextureScaleY = ScaleY;
01164
01165 geSprite_UpdateTextureMap(S);
01166 }
01167
01168
01169 GENESISAPI void GENESISCC geSprite_GetLightingOptions(const geSprite *S,
01170 geFloat *AmbientLightRed,
01171 geFloat *AmbientLightGreen,
01172 geFloat *AmbientLightBlue,
01173 geBoolean *UseFillLight,
01174 geVec3d *FillLightNormal,
01175 geFloat *FillLightRed,
01176 geFloat *FillLightGreen,
01177 geFloat *FillLightBlue,
01178 geBoolean *UseLightFromFloor,
01179 int32 *MaximumDynamicLightsToUse)
01180 {
01181 assert( geSprite_IsValid(S) );
01182
01183 assert( AmbientLightRed != NULL );
01184 assert( AmbientLightGreen != NULL );
01185 assert( AmbientLightBlue != NULL );
01186 assert( UseFillLight != NULL );
01187 assert( FillLightNormal != NULL );
01188 assert( FillLightRed != NULL );
01189 assert( FillLightGreen != NULL );
01190 assert( FillLightBlue != NULL );
01191 assert( UseLightFromFloor != NULL );
01192 assert( MaximumDynamicLightsToUse != NULL );
01193
01194 *AmbientLightRed = S->AmbientLight.r;
01195 *AmbientLightGreen = S->AmbientLight.g;
01196 *AmbientLightBlue = S->AmbientLight.b;
01197 *UseFillLight = S->UseFillLight;
01198 *FillLightNormal = S->FillLightNormal;
01199 *FillLightRed = S->FillLight.r;
01200 *FillLightGreen = S->FillLight.g;
01201 *FillLightBlue = S->FillLight.b;
01202 *UseLightFromFloor = S->UseLightFromFloor;
01203 *MaximumDynamicLightsToUse = S->MaximumDynamicLightsToUse;
01204 }
01205
01206
01207 GENESISAPI void GENESISCC geSprite_SetLightingOptions(geSprite *S,
01208 geFloat AmbientLightRed,
01209 geFloat AmbientLightGreen,
01210 geFloat AmbientLightBlue,
01211 geBoolean UseFillLight,
01212 const geVec3d *FillLightNormal,
01213 geFloat FillLightRed,
01214 geFloat FillLightGreen,
01215 geFloat FillLightBlue,
01216 geBoolean UseLightFromFloor,
01217 int32 MaximumDynamicLightsToUse
01218 )
01219 {
01220 assert( geSprite_IsValid(S) );
01221 assert( geVec3d_IsValid(FillLightNormal) );
01222
01223 S->AmbientLight.r = AmbientLightRed;
01224 S->AmbientLight.g = AmbientLightGreen;
01225 S->AmbientLight.b = AmbientLightBlue;
01226 S->UseFillLight = UseFillLight;
01227 S->FillLightNormal = *FillLightNormal;
01228 S->FillLight.r = FillLightRed;
01229 S->FillLight.g = FillLightGreen;
01230 S->FillLight.b = FillLightBlue;
01231 S->UseLightFromFloor = UseLightFromFloor;
01232 S->MaximumDynamicLightsToUse = MaximumDynamicLightsToUse;
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242 if ( (!S->TransformChanged) &&
01243 (!S->AlwaysFaceCamera) &&
01244 (!S->LightingUsesSurfaceNormal) && ((UseFillLight) || (MaximumDynamicLightsToUse > 0)) )
01245 geSprite_UpdateSurfaceNormal(S);
01246
01247
01248 S->LightingUsesSurfaceNormal = (S->UseFillLight) || (S->MaximumDynamicLightsToUse > 0);
01249 }
01250
01251
01252 GENESISAPI void GENESISCC geSprite_GetAlpha(const geSprite *S, geFloat *Alpha, geFloat *BackfaceAlpha)
01253 {
01254 assert( geSprite_IsValid(S) );
01255 assert( Alpha );
01256 assert( BackfaceAlpha );
01257
01258 *Alpha = S->RGBA.a;
01259 *BackfaceAlpha = S->BackfaceRGBA.a;
01260 }
01261
01262
01263 GENESISAPI void GENESISCC geSprite_SetAlpha(geSprite *S, geFloat Alpha, geFloat BackfaceAlpha)
01264 {
01265 assert( geSprite_IsValid(S) );
01266
01267 S->RGBA.a = Alpha;
01268 S->BackfaceRGBA.a = BackfaceAlpha;
01269
01270
01271 if (S->RGBA.a < 0)
01272 S->RGBA.a = 0.0f;
01273 else if (S->RGBA.a > 255.0f)
01274 S->RGBA.a = 255.0f;
01275 if (S->BackfaceRGBA.a < 0)
01276 S->BackfaceRGBA.a = 0.0f;
01277 else if (S->BackfaceRGBA.a > 255.0f)
01278 S->BackfaceRGBA.a = 255.0f;
01279 }
01280
01281
01282 GENESISAPI void *GENESISCC geSprite_GetUserData(const geSprite *S)
01283 {
01284 assert( geSprite_IsValid(S) );
01285
01286 return S->UserData;
01287 }
01288
01289
01290 GENESISAPI void GENESISCC geSprite_SetUserData(geSprite *S, void *UserData)
01291 {
01292 assert( geSprite_IsValid(S) );
01293
01294 S->UserData = UserData;
01295 }
01296
01297
01298 geBoolean GENESISCC geSprite_RenderPrep(geSprite *S, geWorld *World)
01299 {
01300 assert( geSprite_IsValid(S) );
01301
01302
01303 if (S->Bitmap)
01304 {
01305 if ( geWorld_AddBitmap(World, S->Bitmap) == GE_FALSE )
01306 {
01307 geErrorLog_AddString(-1, "Sprite_RenderPrep : World_AddBitmap", NULL);
01308 return GE_FALSE;
01309 }
01310 }
01311
01312
01313
01314 if ( (S->BackfaceBitmap) && (S->BackfaceBitmap != S->Bitmap) )
01315 {
01316 if ( geWorld_AddBitmap(World, S->Bitmap) == GE_FALSE )
01317 {
01318 geErrorLog_AddString(-1, "Sprite_RenderPrep : World_AddBitmap", NULL);
01319 return GE_FALSE;
01320 }
01321 }
01322
01323 return GE_TRUE;
01324 }
01325
01326
01327 geBoolean GENESISCC geSprite_RenderThroughFrustum(geSprite *S, geEngine *Engine, geWorld *World, geCamera *Camera, Frustum_Info *FInfo)
01328 {
01329 int i;
01330 geBoolean Render;
01331 geBoolean RenderBackface;
01332
01333 assert( geSprite_IsValid(S) );
01334
01335
01336
01337 if (S->AlwaysFaceCamera)
01338 {
01339
01340
01341 geSprite_UpdateVertexesToFaceCamera(S, Camera);
01342
01343
01344 if (S->LightingUsesSurfaceNormal)
01345 {
01346 geSprite_UpdateSurfaceNormalToFaceCamera(S, Camera);
01347 S->LightingChanged = GE_TRUE;
01348 }
01349
01350
01351
01352 else if ( (S->TransformChanged) && (S->UseLightFromFloor) )
01353 {
01354 S->LightingChanged = GE_TRUE;
01355 }
01356 }
01357
01358
01359 else if (S->TransformChanged)
01360 {
01361
01362
01363 geSprite_UpdateVertexes(S);
01364
01365
01366
01367 geSprite_UpdateSurfaceNormal(S);
01368
01369
01370
01371
01372
01373
01374 if ( (S->LightingUsesSurfaceNormal) || (S->UseLightFromFloor) )
01375 {
01376 S->LightingChanged = GE_TRUE;
01377 }
01378
01379 S->TransformChanged = GE_FALSE;
01380 }
01381
01382
01383 geSprite_CreateFrustumClippedScreenPoly(S, Camera, FInfo, &Render, &RenderBackface);
01384
01385
01386 if (Render)
01387 {
01388
01389
01390
01391
01392 if ( (S->LightingChanged) || (S->MaximumDynamicLightsToUse > 0) )
01393 {
01394 geSprite_UpdateLighting(S, World);
01395 S->LightingChanged = GE_FALSE;
01396 }
01397
01398
01399 if (RenderBackface)
01400 {
01401
01402 for (i = 0; i < FrustumNumClippedTexturedLitVertices; i++)
01403 {
01404 FrustumClippedTexturedLitVertexes[i].r = S->BackfaceRGBA.r;
01405 FrustumClippedTexturedLitVertexes[i].g = S->BackfaceRGBA.g;
01406 FrustumClippedTexturedLitVertexes[i].b = S->BackfaceRGBA.b;
01407 FrustumClippedTexturedLitVertexes[i].a = S->BackfaceRGBA.a;
01408 }
01409
01410
01411 geEngine_RenderPoly(Engine, (GE_TLVertex*)FrustumClippedTexturedLitVertexes, FrustumNumClippedTexturedLitVertices, S->BackfaceBitmap, 0);
01412 }
01413 else
01414 {
01415
01416 for (i = 0; i < FrustumNumClippedTexturedLitVertices; i++)
01417 {
01418 FrustumClippedTexturedLitVertexes[i].r = S->RGBA.r;
01419 FrustumClippedTexturedLitVertexes[i].g = S->RGBA.g;
01420 FrustumClippedTexturedLitVertexes[i].b = S->RGBA.b;
01421 FrustumClippedTexturedLitVertexes[i].a = S->RGBA.a;
01422 }
01423
01424
01425 geEngine_RenderPoly(Engine, (GE_TLVertex*)FrustumClippedTexturedLitVertexes, FrustumNumClippedTexturedLitVertices, S->Bitmap, 0);
01426 }
01427 }
01428
01429 return GE_TRUE;
01430 }