00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define SHADOW_MAP
00024
00025
00026 #include <math.h>
00027 #include <assert.h>
00028
00029 #include "light.h"
00030 #include "world.h"
00031 #include "trace.h"
00032 #include "surface.h"
00033
00034 #include "xfarray.h"
00035 #include "puppet.h"
00036 #include "pose.h"
00037 #include "ErrorLog.h"
00038 #include "ram.h"
00039 #include "tclip.h"
00040
00041 #include "Frustum.h"
00042 #include "ExtBox.h"
00043 #include "bodyinst.h"
00044
00045 #ifdef PROFILE
00046 #include "rdtsc.h"
00047 #endif
00048
00049 #include "bitmap.h"
00050 #include "bitmap._h"
00051
00052 #define PUPPET_DEFAULT_MAX_DYNAMIC_LIGHTS 3
00053
00054 typedef struct gePuppet_Color
00055 {
00056 geFloat Red,Green,Blue;
00057 } gePuppet_Color;
00058
00059 typedef struct gePuppet_Material
00060 {
00061 gePuppet_Color Color;
00062 geBoolean UseTexture;
00063 geBitmap *Bitmap;
00064 const char *TextureName;
00065 const char *MaterialName;
00066 const char *AlphaName;
00067 } gePuppet_Material;
00068
00069 typedef struct gePuppet
00070 {
00071 geVFile * TextureFileContext;
00072 geBodyInst *BodyInstance;
00073 int MaterialCount;
00074 gePuppet_Material *MaterialArray;
00075 int MaxDynamicLightsToUse;
00076 int LightReferenceBoneIndex;
00077
00078 geVec3d FillLightNormal;
00079 gePuppet_Color FillLightColor;
00080 geBoolean UseFillLight;
00081
00082 geEnvironmentOptions internal_env;
00083 gePuppet_Color AmbientLightIntensity;
00084 geBoolean AmbientLightFromFloor;
00085
00086 geBoolean PerBoneLighting;
00087
00088 geBoolean DoShadow;
00089 geFloat ShadowScale;
00090 const geBitmap *ShadowMap;
00091 int ShadowBoneIndex;
00092
00093
00094 geFloat OverallAlpha ;
00095
00096 #pragma message ("this goes away!: World")
00097 geWorld *World;
00098 geBoolean AmbientLightFromStaticLights;
00099 geBoolean DoTestRayCollision;
00100 int MaxStaticLightsToUse;
00101 } gePuppet;
00102
00103 typedef struct
00104 {
00105 geVec3d Normal;
00106 gePuppet_Color Color;
00107 geFloat Distance;
00108 geFloat Radius;
00109 } gePuppet_Light;
00110
00111 typedef struct
00112 {
00113 geBoolean UseFillLight;
00114 geVec3d FillLightNormal;
00115 gePuppet_Color MaterialColor;
00116 gePuppet_Color FillLightColor;
00117 gePuppet_Color Ambient;
00118 geVec3d SurfaceNormal;
00119 gePuppet_Light StaticLights[MAX_DYNAMIC_LIGHTS];
00120 int StaticLightCount;
00121 gePuppet_Light Lights[MAX_DYNAMIC_LIGHTS];
00122 int LightCount;
00123 geBoolean PerBoneLighting;
00124 } gePuppet_LightParamGroup;
00125
00126 typedef struct
00127 {
00128 gePuppet_Light Lights[MAX_DYNAMIC_LIGHTS];
00129 int LightCount;
00130 } gePuppet_BoneLight;
00131
00132
00133 gePuppet_LightParamGroup gePuppet_StaticLightGrp;
00134 gePuppet_BoneLight *gePuppet_StaticBoneLightArray=NULL;
00135 int gePuppet_StaticBoneLightArraySize=0;
00136 int gePuppet_StaticPuppetCount=0;
00137 int gePuppet_StaticFlags[2]={1768710981,560296816};
00138
00139 static geBoolean GENESISCC gePuppet_FetchTextures(gePuppet *P, const geBody *B)
00140 {
00141 int i;
00142 assert( P );
00143
00144 P->MaterialCount = geBody_GetMaterialCount(B);
00145 if (P->MaterialCount <= 0)
00146 {
00147 return GE_TRUE;
00148 }
00149
00150 P->MaterialArray = GE_RAM_ALLOCATE_ARRAY(gePuppet_Material, P->MaterialCount);
00151 if (P->MaterialArray == NULL)
00152 {
00153 geErrorLog_Add(ERR_PUPPET_ENOMEM, NULL);
00154 return GE_FALSE;
00155 }
00156
00157 for (i=0; i<P->MaterialCount; i++)
00158 {
00159 const char *Name;
00160 geBitmap *Bitmap;
00161 gePuppet_Material *M = &(P->MaterialArray[i]);
00162 geBody_GetMaterial( B, i, &(Name), &(Bitmap),
00163 &(M->Color.Red),&(M->Color.Green),&(M->Color.Blue));
00164
00165 if (Bitmap == NULL )
00166 {
00167 M->Bitmap = NULL;
00168 M->UseTexture = GE_FALSE;
00169 }
00170 else
00171 {
00172 M->UseTexture = GE_TRUE;
00173 assert( P->World );
00174
00175 M->Bitmap = Bitmap;
00176 geBitmap_CreateRef(Bitmap);
00177
00178 if ( ! geWorld_AddBitmap(P->World,Bitmap) )
00179 {
00180 geErrorLog_AddString(-1,"Puppet_FetchTextures : World_AddBitmap", NULL);
00181 geRam_Free(P->MaterialArray);
00182 P->MaterialArray = NULL;
00183 P->MaterialCount = 0;
00184 return GE_FALSE;
00185 }
00186 }
00187 M->MaterialName = Name;
00188 }
00189
00190 return GE_TRUE;
00191 }
00192
00193 int GENESISCC gePuppet_GetMaterialCount( gePuppet *P )
00194 {
00195 assert( P );
00196 return P->MaterialCount;
00197 }
00198
00199 geBoolean GENESISCC gePuppet_GetMaterial( gePuppet *P, int MaterialIndex,
00200 geBitmap **Bitmap,
00201 geFloat *Red, geFloat *Green, geFloat *Blue)
00202 {
00203 assert( P );
00204 assert( Red );
00205 assert( Green );
00206 assert( Blue );
00207 assert( Bitmap );
00208 assert( MaterialIndex >= 0 );
00209 assert( MaterialIndex < P->MaterialCount );
00210
00211 {
00212 gePuppet_Material *M = &(P->MaterialArray[MaterialIndex]);
00213 *Bitmap = M->Bitmap;
00214 *Red = M->Color.Red;
00215 *Green = M->Color.Green;
00216 *Blue = M->Color.Blue;
00217 }
00218 return GE_TRUE;
00219 }
00220
00221
00222 geBoolean GENESISCC gePuppet_SetMaterial(gePuppet *P, int MaterialIndex, geBitmap *Bitmap,
00223 geFloat Red, geFloat Green, geFloat Blue)
00224 {
00225 assert( P );
00226 assert( MaterialIndex >= 0 );
00227 assert( MaterialIndex < P->MaterialCount );
00228
00229 {
00230 geBitmap * OldBitmap;
00231 gePuppet_Material *M = P->MaterialArray + MaterialIndex;
00232
00233 OldBitmap = M->Bitmap;
00234
00235 M->Bitmap = Bitmap;
00236 M->Color.Red = Red;
00237 M->Color.Green = Green;
00238 M->Color.Blue = Blue;
00239
00240 if ( OldBitmap != Bitmap )
00241 {
00242 if ( OldBitmap )
00243 {
00244 assert( M->UseTexture );
00245 geWorld_RemoveBitmap( P->World, OldBitmap );
00246 geBitmap_Destroy( &(OldBitmap) );
00247 }
00248
00249 M->UseTexture = GE_FALSE;
00250
00251 if ( Bitmap )
00252 {
00253 geBitmap_CreateRef(Bitmap);
00254
00255 M->UseTexture = GE_TRUE;
00256
00257 if ( ! geWorld_AddBitmap(P->World,Bitmap) )
00258 {
00259 geErrorLog_AddString(-1,"Puppet_SetMaterial : World_AddBitmap", NULL);
00260 return GE_FALSE;
00261 }
00262 }
00263 }
00264 }
00265
00266 return GE_TRUE;
00267 }
00268
00269
00270 gePuppet *GENESISCC gePuppet_Create(geVFile *TextureFS, const geBody *B, geWorld *World)
00271 {
00272 gePuppet *P;
00273
00274 assert( geBody_IsValid(B)!=GE_FALSE );
00275 #pragma message ("Need geWorld_IsValid()")
00276
00277 P = GE_RAM_ALLOCATE_STRUCT(gePuppet);
00278 if (P==NULL)
00279 {
00280 geErrorLog_Add(ERR_PUPPET_ENOMEM, NULL);
00281 return NULL;
00282 }
00283
00284 memset(P,0,sizeof(*P));
00285
00286 P->BodyInstance = NULL;
00287 P->MaxDynamicLightsToUse = PUPPET_DEFAULT_MAX_DYNAMIC_LIGHTS;
00288 P->LightReferenceBoneIndex = GE_POSE_ROOT_JOINT;
00289
00290 P->FillLightNormal.X = -0.2f;
00291 P->FillLightNormal.Y = 1.0f;
00292 P->FillLightNormal.Z = 0.4f;
00293 geVec3d_Normalize(&(P->FillLightNormal));
00294 P->FillLightColor.Red = 0.25f;
00295 P->FillLightColor.Green = 0.25f;
00296 P->FillLightColor.Blue = 0.25f;
00297 P->UseFillLight = GE_TRUE;
00298
00299 P->OverallAlpha = 255.0f ;
00300
00301 P->AmbientLightIntensity.Red = 0.1f;
00302 P->AmbientLightIntensity.Green = 0.1f;
00303 P->AmbientLightIntensity.Blue = 0.1f;
00304 P->AmbientLightFromFloor = GE_TRUE;
00305
00306 P->DoShadow = GE_FALSE;
00307 P->ShadowScale = 0.0f;
00308 P->ShadowBoneIndex = GE_POSE_ROOT_JOINT;
00309 P->TextureFileContext = TextureFS;
00310
00311 P->World = World;
00312
00313 P->AmbientLightFromStaticLights = GE_FALSE;
00314 P->DoTestRayCollision = GE_FALSE;
00315 P->MaxStaticLightsToUse = PUPPET_DEFAULT_MAX_DYNAMIC_LIGHTS;
00316
00317
00318 P->internal_env.PercentEnvironment = 0.0f;
00319 P->internal_env.PercentPuppet = 1.0f;
00320 P->internal_env.PercentMaterial = 1.0f;
00321 P->internal_env.UseEnvironmentMapping = GE_FALSE;
00322 P->internal_env.Supercede = GE_TRUE;
00323
00324 if (gePuppet_FetchTextures(P,B)==GE_FALSE)
00325 {
00326 geRam_Free(P);
00327 return NULL;
00328 }
00329
00330 P->BodyInstance = geBodyInst_Create(B);
00331 if (P->BodyInstance == NULL)
00332 {
00333 geErrorLog_Add(ERR_PUPPET_ENOMEM, NULL);
00334 gePuppet_Destroy( &P );
00335 return NULL;
00336 }
00337 gePuppet_StaticPuppetCount++;
00338 return P;
00339 }
00340
00341
00342 void GENESISCC gePuppet_Destroy(gePuppet **P)
00343 {
00344 assert( P );
00345 assert( *P );
00346 if ( (*P)->BodyInstance )
00347 {
00348 geBodyInst_Destroy( &((*P)->BodyInstance) );
00349 (*P)->BodyInstance = NULL;
00350 }
00351 if ( (*P)->MaterialArray )
00352 {
00353 gePuppet_Material *M;
00354 int i;
00355
00356 for (i=0; i<(*P)->MaterialCount; i++)
00357 {
00358 M = &((*P)->MaterialArray[i]);
00359 if (M->UseTexture )
00360 {
00361 assert( M->Bitmap );
00362 geWorld_RemoveBitmap( (*P)->World, M->Bitmap );
00363 geBitmap_Destroy( &(M->Bitmap) );
00364 M->UseTexture = GE_FALSE;
00365 }
00366 }
00367
00368
00369 geRam_Free( (*P)->MaterialArray );
00370 (*P)->BodyInstance = NULL;
00371 }
00372 if ( (*P)->ShadowMap )
00373 {
00374 geBitmap_Destroy((geBitmap **)&((*P)->ShadowMap));
00375 (*P)->ShadowMap = NULL;
00376 }
00377
00378 geRam_Free( (*P) );
00379 *P = NULL;
00380
00381
00382 gePuppet_StaticPuppetCount--;
00383 if (gePuppet_StaticPuppetCount==0)
00384 {
00385 if (gePuppet_StaticBoneLightArray!=NULL)
00386 geRam_Free(gePuppet_StaticBoneLightArray);
00387 gePuppet_StaticBoneLightArray=NULL;
00388 gePuppet_StaticBoneLightArraySize = 0;
00389 }
00390 }
00391
00392 void GENESISCC gePuppet_GetStaticLightingOptions(const gePuppet *P, geBoolean *UseAmbientLightFromStaticLights, geBoolean *TestRayCollision, int *MaxStaticLightsToUse )
00393 { assert( P != NULL);
00394 assert( UseAmbientLightFromStaticLights );
00395 assert( MaxStaticLightsToUse );
00396 *UseAmbientLightFromStaticLights = P->AmbientLightFromStaticLights;
00397 *TestRayCollision = P->DoTestRayCollision;
00398 *MaxStaticLightsToUse = P->MaxStaticLightsToUse;
00399 }
00400
00401 void GENESISCC gePuppet_SetStaticLightingOptions(gePuppet *P, geBoolean UseAmbientLightFromStaticLights, geBoolean TestRayCollision, int MaxStaticLightsToUse )
00402 { assert( P!= NULL);
00403 P->AmbientLightFromStaticLights = UseAmbientLightFromStaticLights;
00404 P->DoTestRayCollision = TestRayCollision;
00405 P->MaxStaticLightsToUse = MaxStaticLightsToUse;
00406 }
00407
00408 void GENESISCC gePuppet_GetLightingOptions(const gePuppet *P,
00409 geBoolean *UseFillLight,
00410 geVec3d *FillLightNormal,
00411 geFloat *FillLightRed,
00412 geFloat *FillLightGreen,
00413 geFloat *FillLightBlue,
00414 geFloat *AmbientLightRed,
00415 geFloat *AmbientLightGreen,
00416 geFloat *AmbientLightBlue,
00417 geBoolean *UseAmbientLightFromFloor,
00418 int *MaximumDynamicLightsToUse,
00419 int *LightReferenceBoneIndex,
00420 geBoolean *PerBoneLighting
00421 )
00422 {
00423 geFloat Scaler;
00424 assert( P != NULL);
00425 assert( UseFillLight );
00426 assert( FillLightNormal );
00427 assert( FillLightRed );
00428 assert( FillLightGreen );
00429 assert( FillLightBlue );
00430 assert( AmbientLightRed );
00431 assert( AmbientLightGreen );
00432 assert( AmbientLightBlue );
00433 assert( UseAmbientLightFromFloor );
00434 assert( MaximumDynamicLightsToUse );
00435 assert( LightReferenceBoneIndex );
00436
00437 *UseFillLight = P->UseFillLight;
00438
00439 *FillLightNormal = P->FillLightNormal;
00440
00441 Scaler = 255.0f;
00442 *FillLightRed = P->FillLightColor.Red * Scaler;
00443 *FillLightGreen = P->FillLightColor.Green * Scaler;
00444 *FillLightBlue = P->FillLightColor.Blue * Scaler;
00445
00446 *AmbientLightRed = P->AmbientLightIntensity.Red * Scaler;
00447 *AmbientLightGreen = P->AmbientLightIntensity.Green * Scaler;
00448 *AmbientLightBlue = P->AmbientLightIntensity.Blue * Scaler;
00449
00450 *UseAmbientLightFromFloor = P->AmbientLightFromFloor;
00451 *MaximumDynamicLightsToUse = P->MaxDynamicLightsToUse;
00452 *LightReferenceBoneIndex = P->LightReferenceBoneIndex;
00453 *PerBoneLighting = P->PerBoneLighting;
00454 }
00455
00456 void GENESISCC gePuppet_SetLightingOptions(gePuppet *P,
00457 geBoolean UseFillLight,
00458 const geVec3d *FillLightNormal,
00459 geFloat FillLightRed,
00460 geFloat FillLightGreen,
00461 geFloat FillLightBlue,
00462 geFloat AmbientLightRed,
00463 geFloat AmbientLightGreen,
00464 geFloat AmbientLightBlue,
00465 geBoolean UseAmbientLightFromFloor,
00466 int MaximumDynamicLightsToUse,
00467 int LightReferenceBoneIndex,
00468 geBoolean PerBoneLighting
00469 )
00470 {
00471 geFloat Scaler;
00472 assert( P!= NULL);
00473 assert( FillLightNormal );
00474 assert( geVec3d_IsNormalized(FillLightNormal) );
00475 assert( MaximumDynamicLightsToUse >= 0 );
00476 assert( (LightReferenceBoneIndex >=0) || (LightReferenceBoneIndex==GE_POSE_ROOT_JOINT));
00477
00478 P->UseFillLight = UseFillLight;
00479
00480 P->FillLightNormal = *FillLightNormal;
00481
00482 Scaler = 1.0f/255.0f;
00483
00484 P->FillLightColor.Red = FillLightRed * Scaler;
00485 P->FillLightColor.Green = FillLightGreen * Scaler;
00486 P->FillLightColor.Blue = FillLightBlue * Scaler;
00487
00488 P->AmbientLightIntensity.Red = AmbientLightRed * Scaler;
00489 P->AmbientLightIntensity.Green = AmbientLightGreen * Scaler;
00490 P->AmbientLightIntensity.Blue = AmbientLightBlue * Scaler;
00491
00492 P->AmbientLightFromFloor =UseAmbientLightFromFloor;
00493 P->MaxDynamicLightsToUse = MaximumDynamicLightsToUse;
00494 P->LightReferenceBoneIndex = LightReferenceBoneIndex;
00495 P->PerBoneLighting = PerBoneLighting;
00496 }
00497
00498
00499 static int GENESISCC gePuppet_PrepLights(const gePuppet *P,
00500 geWorld *World,
00501 gePuppet_Light *LP,
00502 const geVec3d *ReferencePoint)
00503 {
00504 int i,j,cnt;
00505
00506 Light_LightInfo *L;
00507 assert( P );
00508 assert( LP );
00509
00510 L = (World->LightInfo);
00511 for (i=0,cnt=0; i<MAX_DYNAMIC_LIGHTS; i++)
00512 {
00513 if (L->DynamicLights[i].Active)
00514 {
00515 geVec3d *Position = &(L->DynamicLights[i].Pos);
00516 geVec3d Normal;
00517
00518 geVec3d_Subtract(Position,ReferencePoint,&Normal);
00519
00520 LP[cnt].Distance = Normal.X * Normal.X +
00521 Normal.Y * Normal.Y +
00522 Normal.Z * Normal.Z;
00523 if (LP[cnt].Distance < L->DynamicLights[i].Radius*L->DynamicLights[i].Radius)
00524 {
00525 LP[cnt].Color.Red = L->DynamicLights[i].Color.r;
00526 LP[cnt].Color.Green = L->DynamicLights[i].Color.g;
00527 LP[cnt].Color.Blue = L->DynamicLights[i].Color.b;
00528 LP[cnt].Radius = L->DynamicLights[i].Radius;
00529 LP[cnt].Normal = Normal;
00530 cnt++;
00531 }
00532 }
00533 }
00534
00535
00536 for(i=0; i<P->MaxDynamicLightsToUse && i<cnt; i++)
00537 for(j=i+1; j<cnt; j++)
00538 {
00539 if (LP[i].Distance > LP[j].Distance)
00540 {
00541 gePuppet_Light Swap = LP[j];
00542 LP[j] = LP[i];
00543 LP[i] = Swap;
00544 }
00545 }
00546
00547
00548 for (i=0; i<cnt; i++)
00549 {
00550 geFloat Distance = (geFloat)sqrt(LP[i].Distance);
00551 geFloat OneOverDistance;
00552 geFloat Scale;
00553 if (Distance < 1.0f)
00554 Distance = 1.0f;
00555 OneOverDistance = 1.0f / Distance;
00556 LP[i].Normal.X *= OneOverDistance;
00557 LP[i].Normal.Y *= OneOverDistance;
00558 LP[i].Normal.Z *= OneOverDistance;
00559
00560 LP[i].Distance = Distance;
00561
00562
00563
00564 Scale = 1.0f - Distance / LP[i].Radius ;
00565 Scale *= (1.0f/255.0f);
00566 LP[i].Color.Red *= Scale;
00567 LP[i].Color.Green *= Scale;
00568 LP[i].Color.Blue *= Scale;
00569 }
00570
00571 return cnt;
00572 }
00573
00574 static int GENESISCC gePuppet_ComputeAmbientLight(
00575 const gePuppet *P,
00576 const geWorld *World,
00577 gePuppet_Color *Ambient,
00578 gePuppet_Light *LP,
00579 const geVec3d *ReferencePoint)
00580 {
00581 assert( P );
00582 assert( World );
00583 assert( Ambient );
00584
00585 if (P->AmbientLightFromFloor != GE_FALSE)
00586 {
00587 #define GE_PUPPET_MAX_AMBIENT (0.3f)
00588 int32 Node, Plane, i;
00589 geVec3d Pos1, Pos2, Impact;
00590 GFX_Node *GFXNodes;
00591 Surf_SurfInfo *Surf;
00592 GE_RGBA RGBA;
00593
00594
00595 GFXNodes = World->CurrentBSP->BSPData.GFXNodes;
00596
00597 Pos1 = *ReferencePoint;
00598
00599 Pos2 = Pos1;
00600
00601 Pos2.Y -= 30000.0f;
00602
00603 if(!Trace_WorldCollisionExact2((geWorld*)World, &Pos1, &Pos1, &Impact, &Node, &Plane, NULL))
00604 {
00605
00606 if (Trace_WorldCollisionExact2((geWorld*)World, &Pos1, &Pos2, &Impact, &Node, &Plane, NULL))
00607 {
00608 Surf = &(World)->CurrentBSP->SurfInfo[GFXNodes[Node].FirstFace];
00609 if (Surf->LInfo.Face<0)
00610 {
00611 Ambient->Red = Ambient->Green = Ambient->Blue = 0.0f;
00612 }
00613 else
00614 {
00615 for (i=0; i< GFXNodes[Node].NumFaces; i++)
00616 {
00617 if (Surf_InSurfBoundingBox(Surf, &Impact, 20.0f))
00618 {
00619 Light_SetupLightmap(&Surf->LInfo, NULL);
00620
00621 if (Light_GetLightmapRGB(Surf, &Impact, &RGBA))
00622 {
00623 geFloat Scale = 1.0f / 255.0f;
00624 Ambient->Red = RGBA.r * Scale;
00625 Ambient->Green = RGBA.g * Scale;
00626 Ambient->Blue = RGBA.b * Scale;
00627 if (Ambient->Red > GE_PUPPET_MAX_AMBIENT)
00628 {
00629 Ambient->Red = GE_PUPPET_MAX_AMBIENT;
00630 }
00631 if (Ambient->Green > GE_PUPPET_MAX_AMBIENT)
00632 {
00633 Ambient->Green = GE_PUPPET_MAX_AMBIENT;
00634 }
00635 if (Ambient->Blue > GE_PUPPET_MAX_AMBIENT)
00636 {
00637 Ambient->Blue = GE_PUPPET_MAX_AMBIENT;
00638 }
00639 break;
00640 }
00641 }
00642 Surf++;
00643 }
00644 }
00645 }
00646 }
00647 }
00648
00649 if(P->AmbientLightFromStaticLights != GE_FALSE)
00650 {
00651 int i,j,cnt;
00652 geEntity_EntitySet * entitySet = NULL;
00653 geEntity * entity = NULL;
00654 light * aLight;
00655 entitySet = geWorld_GetEntitySet(World, "light");
00656 if (entitySet != NULL)
00657 entity = geEntity_EntitySetGetNextEntity(entitySet, entity);
00658
00659
00660 for (i=0,cnt=0; entity != NULL && cnt<MAX_DYNAMIC_LIGHTS; i++)
00661 {
00662 geVec3d *Position;
00663 geVec3d Normal;
00664 geBoolean keepLight = GE_TRUE;
00665 aLight = (light*)geEntity_GetUserData(entity);
00666 Position = &(aLight->origin);
00667 geVec3d_Subtract(Position,ReferencePoint,&Normal);
00668 LP[cnt].Distance = Normal.X * Normal.X +
00669 Normal.Y * Normal.Y +
00670 Normal.Z * Normal.Z;
00671 if (LP[cnt].Distance < aLight->light * aLight->light)
00672 {
00673 if (P->DoTestRayCollision == GE_TRUE)
00674 {
00675 if (!Trace_WorldCollisionExact2((geWorld*)World, ReferencePoint, Position, NULL, NULL, NULL, NULL))
00676 {
00677 LP[cnt].Color.Red = aLight->color.r;
00678 LP[cnt].Color.Green = aLight->color.g;
00679 LP[cnt].Color.Blue = aLight->color.b;
00680 LP[cnt].Radius = (float)aLight->light;
00681 LP[cnt].Normal = Normal;
00682 cnt++;
00683 }
00684 }
00685 else
00686 {
00687 LP[cnt].Color.Red = aLight->color.r;
00688 LP[cnt].Color.Green = aLight->color.g;
00689 LP[cnt].Color.Blue = aLight->color.b;
00690 LP[cnt].Radius = (float)aLight->light;
00691 LP[cnt].Normal = Normal;
00692 cnt++;
00693 }
00694 }
00695 entity = geEntity_EntitySetGetNextEntity(entitySet, entity);
00696 }
00697
00698
00699 for(i=0; i<P->MaxDynamicLightsToUse && i<cnt; i++)
00700 for(j=i+1; j<cnt; j++)
00701 {
00702 if (LP[i].Distance > LP[j].Distance)
00703 {
00704 gePuppet_Light Swap = LP[j];
00705 LP[j] = LP[i];
00706 LP[i] = Swap;
00707 }
00708 }
00709
00710 for (i=0; i<cnt; i++)
00711 {
00712 geFloat Distance = (geFloat)sqrt(LP[i].Distance);
00713 geFloat OneOverDistance;
00714 geFloat Scale;
00715 if (Distance < 1.0f)
00716 Distance = 1.0f;
00717 OneOverDistance = 1.0f / Distance;
00718 LP[i].Normal.X *= OneOverDistance;
00719 LP[i].Normal.Y *= OneOverDistance;
00720 LP[i].Normal.Z *= OneOverDistance;
00721 LP[i].Distance = Distance;
00722 Scale = 1.0f - Distance / LP[i].Radius ;
00723 Scale *= (1.0f/255.0f);
00724 LP[i].Color.Red *= Scale;
00725 LP[i].Color.Green *= Scale;
00726 LP[i].Color.Blue *= Scale;
00727 }
00728 return cnt;
00729 }
00730
00731 if (P->AmbientLightFromFloor == GE_FALSE && P->AmbientLightFromStaticLights == GE_FALSE)
00732 {
00733 *Ambient = P->AmbientLightIntensity;
00734 }
00735 return 0;
00736 }
00737
00738 static void GENESISCC gePuppet_SetVertexColor(
00739 GE_LVertex *v,int BoneIndex)
00740 {
00741 geFloat RedIntensity,GreenIntensity,BlueIntensity;
00742 geFloat Color;
00743 int l;
00744
00745 assert( v );
00746
00747 RedIntensity = gePuppet_StaticLightGrp.Ambient.Red;
00748 GreenIntensity = gePuppet_StaticLightGrp.Ambient.Green;
00749 BlueIntensity = gePuppet_StaticLightGrp.Ambient.Blue;
00750
00751 if (gePuppet_StaticLightGrp.UseFillLight)
00752 {
00753 geFloat Intensity;
00754 Intensity = gePuppet_StaticLightGrp.FillLightNormal.X * gePuppet_StaticLightGrp.SurfaceNormal.X +
00755 gePuppet_StaticLightGrp.FillLightNormal.Y * gePuppet_StaticLightGrp.SurfaceNormal.Y +
00756 gePuppet_StaticLightGrp.FillLightNormal.Z * gePuppet_StaticLightGrp.SurfaceNormal.Z;
00757 if (Intensity > 0.0)
00758 {
00759 RedIntensity += Intensity * gePuppet_StaticLightGrp.FillLightColor.Red;
00760 GreenIntensity += Intensity * gePuppet_StaticLightGrp.FillLightColor.Green;
00761 BlueIntensity += Intensity * gePuppet_StaticLightGrp.FillLightColor.Blue;
00762 }
00763 }
00764
00765 if (gePuppet_StaticLightGrp.PerBoneLighting)
00766 {
00767 gePuppet_BoneLight *L;
00768 L=&(gePuppet_StaticBoneLightArray[BoneIndex]);
00769
00770 for (l=0; l<L->LightCount; l++)
00771 {
00772 geVec3d *LightNormal;
00773 geFloat Intensity;
00774
00775 LightNormal = &(L->Lights[l].Normal);
00776
00777 Intensity= LightNormal->X * gePuppet_StaticLightGrp.SurfaceNormal.X +
00778 LightNormal->Y * gePuppet_StaticLightGrp.SurfaceNormal.Y +
00779 LightNormal->Z * gePuppet_StaticLightGrp.SurfaceNormal.Z;
00780 if (Intensity > 0.0f)
00781 {
00782 RedIntensity += Intensity * L->Lights[l].Color.Red;
00783 GreenIntensity += Intensity * L->Lights[l].Color.Green;
00784 BlueIntensity += Intensity * L->Lights[l].Color.Blue;
00785 }
00786 }
00787 }
00788 else
00789 {
00790 for (l=0; l<gePuppet_StaticLightGrp.LightCount; l++)
00791 {
00792 geVec3d *LightNormal;
00793 geFloat Intensity;
00794
00795 LightNormal = &(gePuppet_StaticLightGrp.Lights[l].Normal);
00796
00797 Intensity= LightNormal->X * gePuppet_StaticLightGrp.SurfaceNormal.X +
00798 LightNormal->Y * gePuppet_StaticLightGrp.SurfaceNormal.Y +
00799 LightNormal->Z * gePuppet_StaticLightGrp.SurfaceNormal.Z;
00800 if (Intensity > 0.0f)
00801 {
00802 RedIntensity += Intensity * gePuppet_StaticLightGrp.Lights[l].Color.Red;
00803 GreenIntensity += Intensity * gePuppet_StaticLightGrp.Lights[l].Color.Green;
00804 BlueIntensity += Intensity * gePuppet_StaticLightGrp.Lights[l].Color.Blue;
00805 }
00806 }
00807 }
00808 for (l=0; l<gePuppet_StaticLightGrp.StaticLightCount; l++)
00809 {
00810 geVec3d *LightNormal;
00811 float Intensity;
00812
00813 LightNormal = &(gePuppet_StaticLightGrp.StaticLights[l].Normal);
00814 Intensity= LightNormal->X * gePuppet_StaticLightGrp.SurfaceNormal.X +
00815 LightNormal->Y * gePuppet_StaticLightGrp.SurfaceNormal.Y +
00816 LightNormal->Z * gePuppet_StaticLightGrp.SurfaceNormal.Z;
00817 if (Intensity > 0.0f)
00818 {
00819 RedIntensity += Intensity * gePuppet_StaticLightGrp.StaticLights[l].Color.Red;
00820 GreenIntensity += Intensity * gePuppet_StaticLightGrp.StaticLights[l].Color.Green;
00821 BlueIntensity += Intensity * gePuppet_StaticLightGrp.StaticLights[l].Color.Blue;
00822 }
00823 }
00824
00825 Color = gePuppet_StaticLightGrp.MaterialColor.Red * RedIntensity;
00826 if (Color > 255.0f)
00827 Color = 255.0f;
00828 if (Color < 0.0f)
00829 Color = 0.0f;
00830 v->r = Color;
00831
00832 Color = gePuppet_StaticLightGrp.MaterialColor.Green * GreenIntensity;
00833 if (Color > 255.0f)
00834 Color = 255.0f;
00835 if (Color < 0.0f)
00836 Color = 0.0f;
00837 v->g = Color;
00838
00839 Color = gePuppet_StaticLightGrp.MaterialColor.Blue * BlueIntensity;
00840 if (Color > 255.0f)
00841 Color = 255.0f;
00842 if (Color < 0.0f)
00843 Color = 0.0f;
00844 v->b = Color;
00845
00846 }
00847
00848
00849 static void GENESISCC gePuppet_DrawShadow(const gePuppet *P,
00850 const gePose *Joints,
00851 geEngine *Engine,
00852 geWorld *World,
00853 const geCamera *Camera)
00854 {
00855 GE_LVertex v[3];
00856
00857 geVec3d Impact;
00858 geBoolean GoodImpact;
00859 GFX_Plane Plane;
00860 geXForm3d RootTransform;
00861
00862 assert( P );
00863 assert( World );
00864 assert( Camera );
00865 assert( Joints );
00866
00867 assert( (P->ShadowBoneIndex < gePose_GetJointCount(Joints)) || (P->ShadowBoneIndex ==GE_POSE_ROOT_JOINT));
00868 assert( (P->ShadowBoneIndex >=0) || (P->ShadowBoneIndex ==GE_POSE_ROOT_JOINT));
00869
00870 gePose_GetJointTransform(Joints,P->ShadowBoneIndex,&RootTransform);
00871
00872 {
00873 geVec3d Pos1, Pos2;
00874 GE_Collision Collision;
00875
00876 Pos1 = RootTransform.Translation;
00877
00878 Pos2 = Pos1;
00879
00880 Pos2.Y -= 30000.0f;
00881
00882
00883 GoodImpact = Trace_GEWorldCollision(World,
00884 NULL,
00885 NULL,
00886 &Pos1,
00887 &Pos2,
00888 GE_CONTENTS_SOLID_CLIP,
00889 GE_COLLIDE_MODELS,
00890 0,
00891 NULL,
00892 NULL,
00893 &Collision);
00894
00895
00896 Impact = Collision.Impact;
00897
00898
00899 }
00900
00901 Impact.Y += 1.0f;
00902
00903 v[0].r = v[0].b = v[0].g = 0.0f;
00904 v[1].r = v[1].b = v[1].g = 0.0f;
00905 v[2].r = v[2].b = v[2].g = 0.0f;
00906
00907 #ifdef SHADOW_MAP
00908 {
00909 int i;
00910 GE_LVertex s[4];
00911 geVec3d ws[4];
00912 geVec3d In,Left;
00913 geVec3d Up;
00914 geVec3d Zero = {0.0f,0.0f,0.0f};
00915
00916 geVec3d_Subtract(&Impact,&(RootTransform.Translation),&Up);
00917 geVec3d_Normalize(&Up);
00918 geVec3d_CrossProduct(&(Plane.Normal),&Up,&Left);
00919 if (geVec3d_Compare(&Left,&Zero,0.001f)!=GE_FALSE)
00920 {
00921 geXForm3d_GetLeft(&(RootTransform),&Left);
00922 }
00923 geVec3d_CrossProduct(&Left,&(Plane.Normal),&In);
00924
00925 geVec3d_Normalize(&Left);
00926 geVec3d_Normalize(&In);
00927
00928 s[0].r = s[0].b = s[0].g = 0.0f;
00929 s[1].r = s[1].b = s[1].g = 0.0f;
00930 s[2].r = s[2].b = s[2].g = 0.0f;
00931 s[3].r = s[3].b = s[3].g = 0.0f;
00932
00933 geVec3d_Scale(&In ,P->ShadowScale,&In);
00934 geVec3d_Scale(&Left,P->ShadowScale,&Left);
00935
00936 s[0].a = s[1].a = s[2].a = s[3].a = 160.0f;
00937
00938 s[0].u = 0.0f; s[0].v = 0.0f;
00939 s[1].u = 1.0f; s[1].v = 0.0f;
00940 s[2].u = 1.0f; s[2].v = 1.0f;
00941 s[3].u = 0.0f; s[3].v = 1.0f;
00942 ws[0].Y = ws[1].Y = ws[2].Y = ws[3].Y = Impact.Y;
00943
00944 ws[0].X = RootTransform.Translation.X + Left.X - In.X;
00945 ws[0].Z = RootTransform.Translation.Z + Left.Z - In.Z;
00946
00947 ws[1].X = RootTransform.Translation.X - Left.X - In.X;
00948 ws[1].Z = RootTransform.Translation.Z - Left.Z - In.Z;
00949
00950 ws[2].X = RootTransform.Translation.X - Left.X + In.X;
00951 ws[2].Z = RootTransform.Translation.Z - Left.Z + In.Z;
00952
00953 ws[3].X = RootTransform.Translation.X + Left.X + In.X;
00954 ws[3].Z = RootTransform.Translation.Z + Left.Z + In.Z;
00955
00956 for (i=0; i<4; i++)
00957 {
00958 geCamera_Transform(Camera,&ws[i],&ws[i]);
00959 geCamera_Project(Camera,&ws[i],&ws[i]);
00960 }
00961
00962
00963 s[0].X = ws[0].X; s[0].Y = ws[0].Y; s[0].Z = ws[0].Z;
00964 s[1].X = ws[1].X; s[1].Y = ws[1].Y; s[1].Z = ws[1].Z;
00965 s[2].X = ws[2].X; s[2].Y = ws[2].Y; s[2].Z = ws[2].Z;
00966 s[3].X = ws[3].X; s[3].Y = ws[3].Y; s[3].Z = ws[3].Z;
00967
00968 geTClip_SetTexture(P->ShadowMap);
00969
00970 geTClip_Triangle(s);
00971 s[1] = s[2];
00972 s[2] = s[3];
00973
00974 geTClip_Triangle(s);
00975 }
00976 #endif
00977
00978 #ifdef CIRCULAR_SHADOW
00979 v[0].a = v[1].a = v[2].a = 160.0f;
00980 v[0].u = v[1].u = v[2].u = 0.5f;
00981 v[0].v = v[1].v = v[2].v = 0.5f;
00982
00983 v[0].X = Impact.X;
00984 v[0].Y = v[1].Y = v[2].Y = Impact.Y;
00985 v[0].Z = Impact.Z;
00986
00987 {
00988 int steps = 30;
00989 int i;
00990 geVec3d V;
00991 geFloat Angle = 0.0f;
00992 geFloat DAngleDStep = -(2.0f * 3.14159f / (geFloat)steps);
00993 geFloat Radius = P->ShadowScale/2.0f;
00994
00995 V = Impact;
00996 geCamera_Transform(Camera,&V,&V);
00997 geCamera_Project(Camera,&V,&V);
00998 v[0].X = V.X;
00999 v[0].Y = V.Y;
01000 v[0].Z = V.Z;
01001
01002
01003 geTClip_SetTexture(P->ShadowMap);
01004
01005 V = Impact;
01006 V.Z += Radius;
01007 geCamera_Transform(Camera,&V,&V);
01008 geCamera_Project(Camera,&V,&V);
01009 v[1].X = V.X;
01010 v[1].Y = V.Y;
01011 v[1].Z = V.Z;
01012 for (i=0; i<steps+1; i++)
01013 {
01014 v[2] = v[1];
01015
01016 V = Impact;
01017 V.X += (geFloat)(sin( Angle ) * Radius);
01018 V.Z += (geFloat)(cos( Angle ) * Radius);
01019 geCamera_Transform(Camera,&V,&V);
01020 geCamera_Project(Camera,&V,&V);
01021 v[1].X = V.X;
01022 v[1].Y = V.Y;
01023 v[1].Z = V.Z;
01024
01025 Angle = Angle + DAngleDStep;
01026 geEngine_RenderPoly(Engine, (GE_TLVertex *)v, 3, P->ShadowMap, 0 );
01027
01028 }
01029 }
01030 #endif
01031
01032 #ifdef PROJECTED_SHADOW
01033 {
01034 int i,j,Count;
01035 geBodyInst_Index *List;
01036 geBodyInst_Index Command;
01037 geBody_SkinVertex *SV;
01038
01039 G = geBodyInst_GetShadowGeometry(P->BodyInstance,
01040 gePose_GetAllJointTransforms(Joints),0,Camera,&Impact);
01041
01042 if ( G == NULL )
01043 {
01044 geErrorLog_Add(ERR_PUPPET_RENDER, NULL);
01045 return GE_FALSE;
01046 }
01047
01048 geTClip_SetTexture(NULL);
01049
01050 Count = G->FaceCount;
01051 List = G->FaceList;
01052
01053 for (i=0; i<Count; i++)
01054 {
01055 Command = *List;
01056 List ++;
01057
01058 List ++;
01059
01060 assert( Command == GE_BODY_FACE_TRIANGLE );
01061
01062 {
01063 geFloat AX,AY,BXMinusAX,BYMinusAY,CYMinusAY,CXMinusAX;
01064 geBodyInst_Index *List2;
01065
01066 List2 = List;
01067 SV = &(G->SkinVertexArray[ *List2 ]);
01068 AX = SV->SVPoint.X;
01069 AY = SV->SVPoint.Y;
01070 List2++;
01071 List2++;
01072
01073 SV = &(G->SkinVertexArray[ *List2 ]);
01074 BXMinusAX = SV->SVPoint.X - AX;
01075 BYMinusAY = SV->SVPoint.Y - AY;
01076 List2++;
01077 List2++;
01078
01079 SV = &(G->SkinVertexArray[ *List2 ]);
01080 CXMinusAX = SV->SVPoint.X - AX;
01081 CYMinusAY = SV->SVPoint.Y - AY;
01082 List2++;
01083 List2++;
01084
01085
01086
01087
01088
01089 if ( ((BXMinusAX * CYMinusAY) - (BYMinusAY * CXMinusAX)) > 0.0f )
01090 {
01091 List = List2;
01092 continue;
01093 }
01094 }
01095
01096 #define SOME_SCALE ( 255.0f / 40.0f )
01097 for (j=0; j<3; j++)
01098 {
01099 SV = &(G->SkinVertexArray[ *List ]);
01100 List++;
01101
01102 v[j].X = SV->SVPoint.X;
01103 v[j].Y = SV->SVPoint.Y;
01104
01105 v[j].Z = SV->SVPoint.Z;
01106
01107 if( P->internal_env.UseEnvironmentMapping )
01108 {
01109 v[j].u = ( SV->SVU * P->internal_env.PercentPuppet );
01110 v[j].v = ( SV->SVV * P->internal_env.PercentPuppet );
01111
01112 if( P->internal_env.Supercede && PM->MaterialName[0] == 'g' )
01113 {
01114 v[j].u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentMaterial);
01115 v[j].v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentMaterial);
01116 }
01117 else
01118 {
01119 v[j].u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentEnvironment);
01120 v[j].v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentEnvironment);
01121 }
01122 }
01123 else
01124 {
01125 v[j].u = SV->SVU;
01126 v[j].v = SV->SVV;
01127
01128 if( P->internal_env.Supercede && PM->MaterialName[0] == 'g' )
01129 {
01130 v[j].u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentMaterial);
01131 v[j].v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentMaterial);
01132 }
01133 }
01134
01135 List++;
01136 v[j].a = (255.0f- (SV->SVU * SOME_SCALE));
01137 }
01138
01139 if ((v[0].a > 0) && (v[1].a > 0) && (v[2].a > 0))
01140 {
01141 geTClip_Triangle(v);
01142 }
01143 }
01144 assert( ((uint32)List) - ((uint32)G->FaceList) == (uint32)(G->FaceListSize) );
01145 }
01146 #endif
01147 }
01148
01149
01150 void GENESISCC gePuppet_SetEnvironmentOptions( gePuppet *P, geEnvironmentOptions *envop )
01151 {
01152 assert ( P );
01153 assert ( (envop->UseEnvironmentMapping == GE_TRUE) || (envop->UseEnvironmentMapping == GE_FALSE ) );
01154 assert ( (envop->Supercede == GE_TRUE) || (envop->Supercede == GE_FALSE) );
01155 assert ( (envop->PercentEnvironment >= 0.0f) && (envop->PercentEnvironment <= 1.0f) );
01156 assert ( (envop->PercentMaterial >= 0.0f) && (envop->PercentMaterial <= 1.0f) );
01157 assert ( (envop->PercentPuppet >= 0.0f) && (envop->PercentPuppet <= 1.0f) );
01158
01159 P->internal_env.UseEnvironmentMapping = envop->UseEnvironmentMapping;
01160 P->internal_env.Supercede = envop->Supercede;
01161 P->internal_env.PercentEnvironment = envop->PercentEnvironment;
01162 P->internal_env.PercentMaterial = envop->PercentEnvironment;
01163 P->internal_env.PercentPuppet = envop->PercentPuppet;
01164 }
01165
01166 geEnvironmentOptions GENESISCC gePuppet_GetEnvironmentOptions( gePuppet *P )
01167 {
01168 assert ( P );
01169 return P->internal_env;
01170 }
01171
01172 int32 NumClips;
01173
01174
01175 geFloat GENESISCC gePuppet_GetAlpha( const gePuppet *P )
01176 {
01177 assert( P ) ;
01178 return P->OverallAlpha ;
01179 }
01180
01181
01182 void GENESISCC gePuppet_SetAlpha( gePuppet *P, geFloat Alpha )
01183 {
01184 assert( P ) ;
01185 P->OverallAlpha = Alpha ;
01186 }
01187
01188
01189 geBoolean GENESISCC gePuppet_RenderThroughFrustum(const gePuppet *P,
01190 const gePose *Joints,
01191 const geExtBox *Box,
01192 geEngine *Engine,
01193 geWorld *World,
01194 const geCamera *Camera,
01195 Frustum_Info *FInfo)
01196 {
01197 int32 ClipFlags;
01198 geVec3d Scale;
01199 const geXFArray *JointTransforms;
01200
01201 const geBodyInst_Geometry *G;
01202 assert( P );
01203 assert( Engine );
01204 assert( World );
01205 assert( Camera );
01206 assert( Joints );
01207
01208 JointTransforms = gePose_GetAllJointTransforms(Joints);
01209
01210 #pragma message ("Level of detail hacked:")
01211
01212 gePose_GetScale(Joints,&Scale);
01213 G = geBodyInst_GetGeometry(P->BodyInstance, &Scale, JointTransforms, 0, NULL);
01214
01215
01216 ClipFlags = 0xffff;
01217
01218 {
01219 geExtBox MinMaxs;
01220
01221 GFX_Plane *Planes;
01222 int32 k;
01223 geVec3d Expand = {150.0f, 150.f, 150.0f};
01224 int32 OriginalClips;
01225
01226 OriginalClips = NumClips;
01227
01228 MinMaxs = *Box;
01229
01230 Planes = FInfo->Planes;
01231
01232 for (k=0; k< FInfo->NumPlanes; k++, Planes++)
01233 {
01234 int32 Side;
01235
01236 Planes->Type = PLANE_ANY;
01237
01238 Side = Trace_BoxOnPlaneSide(&MinMaxs.Min, &MinMaxs.Max, Planes);
01239
01240 if (Side == PSIDE_BACK)
01241 {
01242 NumClips = OriginalClips;
01243 return GE_TRUE;
01244 }
01245
01246 if (Side == PSIDE_FRONT)
01247 {
01248 ClipFlags &= ~(1<<k);
01249 }
01250 else
01251 NumClips++;
01252
01253 }
01254 }
01255
01256 if (G == NULL)
01257 {
01258 geErrorLog_Add(ERR_PUPPET_RENDER, NULL);
01259 return GE_FALSE;
01260 }
01261
01262 {
01263 int32 NumFaces;
01264 int32 i;
01265 geBodyInst_Index *List;
01266 geXForm3d RootTransform;
01267
01268 gePuppet_StaticLightGrp.UseFillLight = P->UseFillLight;
01269 gePuppet_StaticLightGrp.FillLightNormal = P->FillLightNormal;
01270 gePuppet_StaticLightGrp.FillLightColor.Red = P->FillLightColor.Red;
01271 gePuppet_StaticLightGrp.FillLightColor.Green = P->FillLightColor.Green;
01272 gePuppet_StaticLightGrp.FillLightColor.Blue = P->FillLightColor.Blue;
01273 gePuppet_StaticLightGrp.PerBoneLighting = P->PerBoneLighting;
01274
01275 gePose_GetJointTransform(Joints,P->LightReferenceBoneIndex,&(RootTransform));
01276
01277
01278
01279 if (P->MaxDynamicLightsToUse > 0)
01280 {
01281 if (P->PerBoneLighting)
01282 {
01283 int BoneCount;
01284 const geXForm3d *XFA = geXFArray_GetElements(JointTransforms, &BoneCount);
01285 if (BoneCount>0)
01286 {
01287 if (gePuppet_StaticBoneLightArraySize < BoneCount)
01288 {
01289 gePuppet_BoneLight *LG;
01290
01291 LG = geRam_Realloc(gePuppet_StaticBoneLightArray, sizeof(gePuppet_BoneLight) * BoneCount);
01292 if (LG==NULL)
01293 {
01294 geErrorLog_Add(ERR_PUPPET_RENDER,"Failed to allocate space for bone lighting info cache");
01295 return GE_FALSE;
01296 }
01297 gePuppet_StaticBoneLightArray = LG;
01298 gePuppet_StaticBoneLightArraySize = BoneCount;
01299 }
01300 for (i=0; i<BoneCount; i++)
01301 {
01302 gePuppet_StaticBoneLightArray[i].LightCount = gePuppet_PrepLights(P,World,
01303 gePuppet_StaticBoneLightArray[i].Lights,&(XFA[i].Translation));
01304 }
01305 }
01306 }
01307 else
01308 {
01309 gePuppet_StaticLightGrp.LightCount = gePuppet_PrepLights(P,World
01310 ,gePuppet_StaticLightGrp.Lights,&(RootTransform.Translation));
01311 }
01312 }
01313 else
01314 {
01315 gePuppet_StaticLightGrp.LightCount = 0;
01316 }
01317
01318
01319 gePuppet_StaticLightGrp.StaticLightCount = gePuppet_ComputeAmbientLight(P,
01320 World,
01321 &(gePuppet_StaticLightGrp.Ambient),
01322 gePuppet_StaticLightGrp.StaticLights,
01323 &(RootTransform.Translation));
01324 NumFaces = G->FaceCount;
01325 List = G->FaceList;
01326
01327
01328 for (i=0; i<NumFaces; i++)
01329 {
01330 #define MAX_TEMP_VERTS 30 // To be safe...
01331
01332 int32 Length1, Length2, v, p;
01333 geVec3d Dest1[MAX_TEMP_VERTS], *pDest1;
01334 geVec3d Dest2[MAX_TEMP_VERTS], *pDest2;
01335 geVec3d Verts[MAX_TEMP_VERTS], *pVerts, v1, v2, v3;
01336 Surf_TexVert TexVerts[MAX_TEMP_VERTS], Tex1[MAX_TEMP_VERTS], *pTexVerts;
01337 Surf_TexVert Tex2[MAX_TEMP_VERTS], *pTex1, *pTex2;
01338 Surf_TLVertex ScreenPts[MAX_TEMP_VERTS];
01339 GFX_Plane *FPlanes;
01340 geBodyInst_Index Command, Material;
01341 gePuppet_Material *PM;
01342 geFloat Dist;
01343
01344 Command = *List;
01345 List++;
01346 Material = *List;
01347 List ++;
01348
01349 assert( Command == GE_BODYINST_FACE_TRIANGLE );
01350 assert( Material>=0 );
01351 assert( Material<P->MaterialCount);
01352
01353 PM = &(P->MaterialArray[Material]);
01354 gePuppet_StaticLightGrp.MaterialColor = PM->Color;
01355
01356 Length1 = 3;
01357
01358 pVerts = Verts;
01359 pTexVerts = TexVerts;
01360
01361
01362 for (v=0; v< Length1; v++, pVerts++, pTexVerts++)
01363 {
01364 geBodyInst_SkinVertex *SVert;
01365 GE_LVertex lvert;
01366
01367 SVert = &G->SkinVertexArray[*List];
01368 List++;
01369
01370 *pVerts = SVert->SVPoint;
01371
01372 assert( ((geFloat)fabs(1.0-geVec3d_Length( &(G->NormalArray[ *List ] ))))< 0.001f );
01373
01374 gePuppet_StaticLightGrp.SurfaceNormal = (G->NormalArray[ *List ]);
01375
01376 List++;
01377
01378
01379 gePuppet_SetVertexColor(&lvert,SVert->ReferenceBoneIndex);
01380 pTexVerts->r = lvert.r;
01381 pTexVerts->g = lvert.g;
01382 pTexVerts->b = lvert.b;
01383
01384 if( P->internal_env.UseEnvironmentMapping )
01385 {
01386 pTexVerts->u = ( SVert->SVU * P->internal_env.PercentPuppet );
01387 pTexVerts->v = ( SVert->SVV * P->internal_env.PercentPuppet );
01388
01389 if( P->internal_env.Supercede && PM->MaterialName[0] == 'g' )
01390 {
01391 pTexVerts->u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentMaterial);
01392 pTexVerts->v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentMaterial);
01393 }
01394 else
01395 {
01396 pTexVerts->u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentEnvironment);
01397 pTexVerts->v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentEnvironment);
01398 }
01399 }
01400 else
01401 {
01402 pTexVerts->u = SVert->SVU;
01403 pTexVerts->v = SVert->SVV;
01404
01405 if( P->internal_env.Supercede && PM->MaterialName[0] == 'g' )
01406 {
01407 pTexVerts->u += ( (G->NormalArray[ *List ]).X * P->internal_env.PercentMaterial);
01408 pTexVerts->v += ( (G->NormalArray[ *List ]).Y * P->internal_env.PercentMaterial);
01409 }
01410 }
01411 }
01412
01413 geVec3d_Subtract(&Verts[2], &Verts[1], &v1);
01414 geVec3d_Subtract(&Verts[0], &Verts[1], &v2);
01415 geVec3d_CrossProduct(&v1, &v2, &v3);
01416 geVec3d_Normalize(&v3);
01417
01418 Dist = geVec3d_DotProduct(&v3, &Verts[0]);
01419
01420 Dist = geVec3d_DotProduct(&v3, geCamera_GetPov(Camera)) - Dist;
01421
01422 if (Dist <= 0)
01423 continue;
01424
01425 pDest1 = Verts;
01426 pDest2 = Dest2;
01427 pTex1 = TexVerts;
01428 pTex2 = Tex2;
01429
01430 FPlanes = FInfo->Planes;
01431
01432 for (p=0; p< FInfo->NumPlanes; p++, FPlanes++)
01433 {
01434 if (!(ClipFlags & (1<<p)))
01435 continue;
01436
01437 assert(Length1 < MAX_TEMP_VERTS);
01438
01439 if (!Frustum_ClipToPlaneUVRGBA(FPlanes, pDest1, pDest2, pTex1, pTex2, Length1, &Length2))
01440 break;
01441
01442 assert(Length2 < MAX_TEMP_VERTS);
01443
01444 if (pDest1 == Dest2)
01445 {
01446 pDest1 = Dest1;
01447 pDest2 = Dest2;
01448 pTex1 = Tex1;
01449 pTex2 = Tex2;
01450 }
01451 else
01452 {
01453 pDest1 = Dest2;
01454 pDest2 = Dest1;
01455 pTex1 = Tex2;
01456 pTex2 = Tex1;
01457 }
01458 Length1 = Length2;
01459 }
01460
01461 assert(Length1 < MAX_TEMP_VERTS);
01462
01463 if (p != FInfo->NumPlanes)
01464 continue;
01465
01466 if (Length1 < 3)
01467 continue;
01468
01469
01470 for (v=0; v<Length1; v++)
01471 geCamera_Transform(Camera, &pDest1[v], &pDest2[v]);
01472
01473
01474 Frustum_ProjectRGBA(pDest2, pTex1, (DRV_TLVertex*)ScreenPts, Length1, Camera);
01475
01476
01477 #if 1
01478 ScreenPts[0].a = P->OverallAlpha ;
01479 #else
01480 ScreenPts[0].a = 255.0f;
01481 #endif
01482
01483 geEngine_RenderPoly(Engine, (GE_TLVertex*)ScreenPts, Length1, PM->Bitmap, 0 );
01484 }
01485 }
01486
01487 #pragma message ("BUG: Shadow caused crash in mirrors (oops). Need to write a RenderShadowThroughFrustum...")
01488
01489
01490
01491
01492
01493
01494 return GE_TRUE;
01495 }
01496
01497 #ifdef PROFILE
01498 #define PUPPET_AVERAGE_ACROSS 60
01499 double Puppet_AverageCount[PUPPET_AVERAGE_ACROSS]={
01500 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
01501 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
01502 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
01503 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
01504 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,
01505 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
01506 int Puppet_AverageIndex = 0;
01507 #endif
01508
01509
01510 geBoolean GENESISCC gePuppet_Render( const gePuppet *P,
01511 const gePose *Joints,
01512 geEngine *Engine,
01513 geWorld *World,
01514 const geCamera *Camera,
01515 geExtBox *TestBox)
01516 {
01517 const geXFArray *JointTransforms;
01518 geVec3d Scale;
01519 #ifdef PROFILE
01520 rdtsc_timer_type RDTSCStart,RDTSCEnd;
01521 #endif
01522 geRect ClippingRect;
01523 geBoolean Clipping = GE_TRUE;
01524
01525 char name[128];
01526 int i, j;
01527 geBoolean flag;
01528
01529 #define BACK_EDGE (1.0f)
01530
01531 const geBodyInst_Geometry *G;
01532 assert( P );
01533 assert( Engine );
01534 assert( World );
01535 assert( Camera );
01536
01537 #ifdef PROFILE
01538 rdtsc_read(&RDTSCStart);
01539 rdtsc_zero(&RDTSCEnd);
01540 #endif
01541
01542 flag = GE_FALSE;
01543 j = Engine->DriverInfo.NumSubDrivers;
01544 for(i=0;i<j;i++)
01545 {
01546 strcpy(name, Engine->DriverInfo.SubDrivers[i].Name);
01547 if(name[0]=='G')
01548 {
01549 flag = GE_TRUE;
01550 break;
01551 }
01552 }
01553
01554
01555 geCamera_GetClippingRect(Camera,&ClippingRect);
01556
01557 if (TestBox != NULL)
01558 {
01559
01560
01561
01562 geVec3d BoxCorners[8];
01563 const geXForm3d *ObjectToCamera;
01564 geVec3d Maxs,Mins;
01565 #define BIG_NUMBER (99e9f)
01566 int i;
01567 geBoolean ZFarEnable;
01568 geFloat ZFar;
01569
01570 BoxCorners[0] = TestBox->Min;
01571 BoxCorners[1] = BoxCorners[0]; BoxCorners[1].X = TestBox->Max.X;
01572 BoxCorners[2] = BoxCorners[0]; BoxCorners[2].Y = TestBox->Max.Y;
01573 BoxCorners[3] = BoxCorners[0]; BoxCorners[3].Z = TestBox->Max.Z;
01574 BoxCorners[4] = TestBox->Max;
01575 BoxCorners[5] = BoxCorners[4]; BoxCorners[5].X = TestBox->Min.X;
01576 BoxCorners[6] = BoxCorners[4]; BoxCorners[6].Y = TestBox->Min.Y;
01577 BoxCorners[7] = BoxCorners[4]; BoxCorners[7].Z = TestBox->Min.Z;
01578
01579 ObjectToCamera = geCamera_GetCameraSpaceXForm(Camera);
01580 assert( ObjectToCamera );
01581
01582 geVec3d_Set(&Maxs,-BIG_NUMBER,-BIG_NUMBER,-BIG_NUMBER);
01583 geVec3d_Set(&Mins, BIG_NUMBER, BIG_NUMBER, BIG_NUMBER);
01584 for (i=0; i<8; i++)
01585 {
01586 geVec3d V;
01587 geXForm3d_Transform( ObjectToCamera,&(BoxCorners[i]),&(BoxCorners[i]));
01588 geCamera_Project( Camera,&(BoxCorners[i]),&V);
01589 if (V.X > Maxs.X ) Maxs.X = V.X;
01590 if (V.X < Mins.X ) Mins.X = V.X;
01591 if (V.Y > Maxs.Y ) Maxs.Y = V.Y;
01592 if (V.Y < Mins.Y ) Mins.Y = V.Y;
01593 if (V.Z > Maxs.Z ) Maxs.Z = V.Z;
01594 if (V.Z < Mins.Z ) Mins.Z = V.Z;
01595 }
01596
01597
01598 geCamera_GetFarClipPlane(Camera, &ZFarEnable, &ZFar);
01599 if (ZFarEnable)
01600 {
01601 if ( (Maxs.X < ClippingRect.Left)
01602 || (Mins.X > ClippingRect.Right)
01603 || (Maxs.Z < BACK_EDGE)
01604 || (Mins.Z > ZFar)
01605 || (Maxs.Y < ClippingRect.Top)
01606 || (Mins.Y > ClippingRect.Bottom))
01607 {
01608
01609 return GE_TRUE;
01610 }
01611
01612 } else
01613 {
01614 if ( (Maxs.X < ClippingRect.Left)
01615 || (Mins.X > ClippingRect.Right)
01616 || (Maxs.Y < ClippingRect.Top)
01617 || (Mins.Y > ClippingRect.Bottom)
01618 || (Maxs.Z < BACK_EDGE))
01619 {
01620
01621 return GE_TRUE;
01622 }
01623 }
01624
01625 }
01626
01627 Engine->DebugInfo.NumActors++;
01628
01629 geTClip_SetupEdges(Engine,
01630 (geFloat)ClippingRect.Left,
01631 (geFloat)ClippingRect.Right,
01632 (geFloat)ClippingRect.Top,
01633 (geFloat)ClippingRect.Bottom,
01634 BACK_EDGE);
01635
01636 JointTransforms = gePose_GetAllJointTransforms(Joints);
01637
01638 #pragma message ("Level of detail hacked:")
01639 gePose_GetScale(Joints,&Scale);
01640 G = geBodyInst_GetGeometry(P->BodyInstance, &Scale, JointTransforms, 0,Camera);
01641
01642 if ( G == NULL )
01643 {
01644 geErrorLog_Add(ERR_PUPPET_RENDER, NULL);
01645 return GE_FALSE;
01646 }
01647
01648 #ifdef ONE_OVER_Z_PIPELINE
01649 #define TEST_Z_OUT(zzz, edge) ((zzz) > (edge))
01650 #define TEST_Z_IN(zzz, edge) ((zzz) < (edge))
01651 #pragma message ("test this! this is untested")
01652 #else
01653 #define TEST_Z_OUT(zzz, edge) ((zzz) < (edge))
01654 #define TEST_Z_IN(zzz, edge) ((zzz) > (edge))
01655 #endif
01656
01657
01658
01659 {
01660 if ( (G->Maxs.X < ClippingRect.Left)
01661 || (G->Mins.X > ClippingRect.Right)
01662 || ( TEST_Z_OUT( G->Maxs.Z, BACK_EDGE) )
01663 || (G->Maxs.Y < ClippingRect.Top)
01664 || (G->Mins.Y > ClippingRect.Bottom) )
01665 {
01666
01667 return GE_TRUE;
01668 }
01669
01670 if ( (G->Maxs.X < ClippingRect.Right)
01671 && (G->Mins.X > ClippingRect.Left)
01672 && (G->Maxs.Y < ClippingRect.Bottom)
01673 && (G->Mins.Y > ClippingRect.Top)
01674 && ( TEST_Z_IN( G->Mins.Z, BACK_EDGE) ) )
01675 {
01676
01677 Clipping = GE_FALSE;
01678 }
01679 else
01680 {
01681 Clipping = GE_TRUE;
01682 }
01683 }
01684
01685 {
01686 GE_LVertex v[3];
01687 int i,j,Count;
01688 geBodyInst_Index *List;
01689 geBodyInst_Index Command;
01690 geBodyInst_SkinVertex *SV;
01691 geXForm3d RootTransform;
01692 gePuppet_Material *PM;
01693 geBodyInst_Index Material,LastMaterial;
01694
01695 gePuppet_StaticLightGrp.UseFillLight = P->UseFillLight;
01696 gePuppet_StaticLightGrp.FillLightNormal = P->FillLightNormal;
01697 gePuppet_StaticLightGrp.FillLightColor.Red = P->FillLightColor.Red;
01698 gePuppet_StaticLightGrp.FillLightColor.Green = P->FillLightColor.Green;
01699 gePuppet_StaticLightGrp.FillLightColor.Blue = P->FillLightColor.Blue;
01700 gePuppet_StaticLightGrp.PerBoneLighting = P->PerBoneLighting;
01701
01702 gePose_GetJointTransform(Joints,P->LightReferenceBoneIndex,&(RootTransform));
01703
01704 if (P->MaxDynamicLightsToUse > 0)
01705 {
01706 if (P->PerBoneLighting)
01707 {
01708 int BoneCount;
01709 const geXForm3d *XFA = geXFArray_GetElements(JointTransforms, &BoneCount);
01710 if (BoneCount>0)
01711 {
01712 if (gePuppet_StaticBoneLightArraySize < BoneCount)
01713 {
01714 gePuppet_BoneLight *LG;
01715
01716 LG = geRam_Realloc(gePuppet_StaticBoneLightArray, sizeof(gePuppet_BoneLight) * BoneCount);
01717 if (LG==NULL)
01718 {
01719 geErrorLog_Add(ERR_PUPPET_RENDER,"Failed to allocate space for bone lighting info cache");
01720 return GE_FALSE;
01721 }
01722 gePuppet_StaticBoneLightArray = LG;
01723 gePuppet_StaticBoneLightArraySize = BoneCount;
01724 }
01725 for (i=0; i<BoneCount; i++)
01726 {
01727 gePuppet_StaticBoneLightArray[i].LightCount = gePuppet_PrepLights(P,World,
01728 gePuppet_StaticBoneLightArray[i].Lights,&(XFA[i].Translation));
01729 }
01730 }
01731 }
01732 else
01733 {
01734 gePuppet_StaticLightGrp.LightCount = gePuppet_PrepLights(P,World
01735 ,gePuppet_StaticLightGrp.Lights,&(RootTransform.Translation));
01736 }
01737 }
01738 else
01739 {
01740 gePuppet_StaticLightGrp.LightCount = 0;
01741 }
01742
01743
01744
01745 gePuppet_StaticLightGrp.StaticLightCount = gePuppet_ComputeAmbientLight(P,
01746 World,
01747 &(gePuppet_StaticLightGrp.Ambient),
01748 gePuppet_StaticLightGrp.StaticLights ,
01749 &(RootTransform.Translation));
01750 Count = G->FaceCount;
01751 List = G->FaceList;
01752 #if 1
01753 v[0].a = v[1].a= v[2].a = P->OverallAlpha ;
01754 #else
01755 v[0].a = v[1].a= v[2].a = 255.0f;
01756 #endif
01757
01758 LastMaterial = -1;
01759
01760 for (i=0; i<Count; i++)
01761 {
01762
01763 Command = *List;
01764 List ++;
01765 Material = *List;
01766 List ++;
01767
01768 assert( Command == GE_BODYINST_FACE_TRIANGLE );
01769 assert( Material>=0 );
01770 assert( Material<P->MaterialCount);
01771
01772 {
01773 geFloat AX,AY,BXMinusAX,BYMinusAY,CYMinusAY,CXMinusAX;
01774 geBodyInst_Index *List2;
01775
01776 List2 = List;
01777 SV = &(G->SkinVertexArray[ *List2 ]);
01778 AX = SV->SVPoint.X;
01779 AY = SV->SVPoint.Y;
01780 List2++;
01781 List2++;
01782
01783 SV = &(G->SkinVertexArray[ *List2 ]);
01784 BXMinusAX = SV->SVPoint.X - AX;
01785 BYMinusAY = SV->SVPoint.Y - AY;
01786 List2++;
01787 List2++;
01788
01789 SV = &(G->SkinVertexArray[ *List2 ]);
01790 CXMinusAX = SV->SVPoint.X - AX;
01791 CYMinusAY = SV->SVPoint.Y - AY;
01792 List2++;
01793 List2++;
01794
01795
01796
01797
01798
01799 if ( ((BXMinusAX * CYMinusAY) - (BYMinusAY * CXMinusAX)) > 0.0f )
01800 {
01801 List = List2;
01802 continue;
01803 }
01804 }
01805
01806 if ( Material != LastMaterial )
01807 {
01808 PM = &(P->MaterialArray[Material]);
01809 geTClip_SetTexture(PM->Bitmap);
01810 gePuppet_StaticLightGrp.MaterialColor = PM->Color;
01811 }
01812
01813 for (j=0; j<3; j++)
01814 {
01815 SV = &(G->SkinVertexArray[ *List ]);
01816 List++;
01817
01818 v[j].X = SV->SVPoint.X;
01819 v[j].Y = SV->SVPoint.Y;
01820
01821 v[j].Z = SV->SVPoint.Z;
01822 v[j].u = SV->SVU;
01823 v[j].v = SV->SVV;
01824
01825
01826
01827 gePuppet_StaticLightGrp.SurfaceNormal = (G->NormalArray[ *List ]);
01828 List++;
01829
01830 gePuppet_SetVertexColor(&(v[j]),SV->ReferenceBoneIndex);
01831 }
01832
01833 if(flag==GE_FALSE)
01834 Clipping = GE_FALSE;
01835
01836 if (Clipping)
01837 {
01838 geTClip_Triangle(v);
01839 }
01840 else
01841 {
01842 geEngine_RenderPoly(Engine, (GE_TLVertex *)v, 3, PM->Bitmap, 0 );
01843 }
01844
01845 }
01846 assert( ((uint32)List) - ((uint32)G->FaceList) == (uint32)(G->FaceListSize) );
01847 }
01848
01849
01850 if (P->DoShadow)
01851 {
01852 gePuppet_DrawShadow(P,Joints,Engine,World,Camera);
01853 }
01854
01855
01856 #ifdef PROFILE
01857 {
01858 double Count=0.0;
01859 int i;
01860
01861 rdtsc_read(&RDTSCEnd);
01862 rdtsc_delta(&RDTSCStart,&RDTSCEnd,&RDTSCEnd);
01863 geEngine_Printf(Engine, 320,10,"Puppet Render Time=%f",(double)(rdtsc_cycles(&RDTSCEnd)/200000000.0));
01864 geEngine_Printf(Engine, 320,30,"Puppet Render Cycles=%f",(double)(rdtsc_cycles(&RDTSCEnd)));
01865 #if 1
01866 Puppet_AverageCount[(Puppet_AverageIndex++)%PUPPET_AVERAGE_ACROSS] = rdtsc_cycles(&RDTSCEnd);
01867 for (i=0; i<PUPPET_AVERAGE_ACROSS; i++)
01868 {
01869 Count+=Puppet_AverageCount[i];
01870 }
01871 Count /= (double)PUPPET_AVERAGE_ACROSS;
01872
01873 geEngine_Printf(Engine, 320,60,"Puppet AVG Render Time=%f",(double)(Count/200000000.0));
01874 geEngine_Printf(Engine, 320,90,"Puppet AVG Render Cycles=%f",(double)(Count));
01875 #endif
01876
01877 }
01878 #endif
01879
01880 return GE_TRUE;
01881 }
01882
01883 void GENESISCC gePuppet_SetShadow(gePuppet *P, geBoolean DoShadow,
01884 geFloat Scale, const geBitmap *ShadowMap,
01885 int BoneIndex)
01886 {
01887 assert( P );
01888 assert( (DoShadow==GE_FALSE) || (DoShadow==GE_TRUE));
01889
01890 if ( P->ShadowMap )
01891 geBitmap_Destroy((geBitmap **)&(P->ShadowMap));
01892
01893 P->DoShadow = DoShadow;
01894 P->ShadowScale = Scale;
01895 P->ShadowMap = ShadowMap;
01896 P->ShadowBoneIndex = BoneIndex;
01897
01898 if ( P->ShadowMap )
01899 geBitmap_CreateRef((geBitmap *)P->ShadowMap);
01900 }
01901