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

World.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  World.c                                                                             */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description: Code to render the world, and distribute work to other modules         */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #include <Assert.h>
00023 #include <Math.h>
00024  
00025 #include "World.h"
00026 #include "System.h"
00027 #include "Ram.h"
00028 #include "BaseType.h"
00029 #include "GBSPFile.h"
00030 #include "Camera.h"
00031 #include "Plane.h"
00032 #include "Surface.h"
00033 #include "Light.h"
00034 #include "WBitmap.h"
00035 #include "Frustum.h"
00036 #ifdef  MESHES
00037 #include "Mesh.h"
00038 #endif
00039 #include "Entities.h"
00040 #include "Vis.h"
00041 #include "User.h"
00042 #include "VFile.h"
00043 
00044 #include "Trace.h"
00045 
00046 #include "list.h"
00047 
00048 #include "Bitmap.h"
00049 #include "Bitmap._h"
00050 
00051 #include "Puppet.h"
00052 #include "Body.h"
00053 #include "Motion.h"
00054 
00055 //#define BSP_BACK_TO_FRONT
00056 
00057 //#define DO_ADDREMOVE_MESSAGES
00058 #ifndef _DEBUG
00059 #undef DO_ADDREMOVE_MESSAGES
00060 #endif
00061 
00062 //============================================================================
00063 // Dirty HACKS that need to be removed
00064 //============================================================================
00065 #pragma message ("HACK!!! remove geCamera_FillDriverInfo (uses GlobalInfo)")
00066 
00067 int32                           MirrorRecursion;                                        // GLOBAL!!!
00068 
00069 GInfo                           GlobalInfo;
00070 void                            geCamera_FillDriverInfo(geCamera *Camera);
00071 
00072 extern geVec3d          GlobalEyePos;
00073 
00074 Frustum_Info            g_HackFrustum;
00075 
00076 //============================================================================
00077 //      **END** HACK section
00078 //============================================================================
00079 geBoolean geWorld_BitmapListInit(geWorld *World);
00080 geBoolean geWorld_BitmapListShutdown(geWorld *World);
00081 geBoolean geWorld_AddBitmap(geWorld *World, geBitmap *Bitmap);
00082 geBoolean geWorld_RemoveBitmap(geWorld *World,geBitmap *Bitmap);
00083 
00084 //=====================================================================================
00085 //      Local Static Globals
00086 //=====================================================================================
00087 typedef struct
00088 {
00089         geCamera                        *Camera;
00090         Frustum_Info            *Frustum;
00091         geWorld_SkyBoxTData     *SkyTData;
00092 
00093 } geWorld_RenderInfo;
00094 
00095 static  geEngine                        *CEngine = NULL;
00096 static  geWorld                         *CWorld = NULL;
00097 static  World_BSP                       *CBSP;
00098 static  GBSP_BSPData            *BSPData = NULL;        // This is in globals, but is also kept here for speed
00099 static  geBoolean                       CanDoMirrors;
00100 static  geWorld_DebugInfo       *CDebugInfo;
00101 static  Frustum_Info            *CFrustumInfo;
00102 
00103 static  Surf_SurfInfo           *pSurfInfo;
00104 static  DRV_Driver                      *RDriver;
00105 static  geWorld_Model           *g_CurrentModel;
00106 
00107 // Temp trans poly structure
00108 #define MAX_TRANS_POLYS         256
00109 #define MAX_CACHE_VERTS         16
00110 
00111 #define TRANS_MIRROR            (1<<0)
00112 
00113 typedef struct
00114 {
00115         U32                             Flags;
00116         S32                             Face;                                           // Face this trans poly belongs too
00117         S32                             NumVerts;
00118         DRV_TLVertex    TLVerts[MAX_CACHE_VERTS];       // Screen points
00119 } World_TransPoly;
00120 
00121 World_TransPoly         TransPolys[MAX_TRANS_POLYS];
00122 S32                                     NumTransPolys[MAX_MIRROR_RECURSION+1];
00123 S32                                     FirstTransPolys[MAX_MIRROR_RECURSION+1];
00124 
00125 static void RenderTransPoly(geCamera *Camera, World_TransPoly *pPoly);
00126 
00127 // GList.c
00128 #define GLIST_MAX_OPERATIONS            1024
00129 
00130 typedef struct
00131 {
00132         uint8           Type;
00133         uint32          Data;
00134 } GList_Operation;
00135 
00136 typedef struct
00137 {
00138         GList_Operation         GListOperations[GLIST_MAX_OPERATIONS];
00139         int32                           NumGListOperations;
00140 } GList;
00141 
00142 GList_Operation         GListOperations[GLIST_MAX_OPERATIONS];
00143 int32                           FirstGListOperations[MAX_MIRROR_RECURSION+1];
00144 int32                           NumGListOperations[MAX_MIRROR_RECURSION+1];
00145 
00146 //=====================================================================================
00147 //=====================================================================================
00148 GList *GList_Create(geEngine *Engine, geWorld *World)
00149 {
00150         return NULL;
00151 }
00152 
00153 //=====================================================================================
00154 //=====================================================================================
00155 void GList_Destroy(GList *GList)
00156 {
00157         assert(GList);
00158 }
00159 
00160 //=====================================================================================
00161 //      GList_AddOperation
00162 //=====================================================================================
00163 void GList_AddOperation(uint8 Type, uint32 Data)
00164 {
00165         int32           Op;
00166 
00167         if (NumGListOperations[MirrorRecursion] >= GLIST_MAX_OPERATIONS)
00168                 return;         // Oh well...
00169 
00170         Op = FirstGListOperations[MirrorRecursion] + NumGListOperations[MirrorRecursion];
00171 
00172         GListOperations[Op].Type = Type;
00173         GListOperations[Op].Data = Data;
00174 
00175         NumGListOperations[MirrorRecursion]++;
00176 }
00177 
00178 //========================================================================================
00179 // GList_RenderOperations
00180 //========================================================================================
00181 geBoolean GList_RenderOperations(geCamera *Camera)
00182 {
00183         int32                   i;
00184 
00185         // Render the list from back to front
00186         for (i=NumGListOperations[MirrorRecursion]-1; i>= 0; i--)
00187         {
00188                 int32           Op;
00189 
00190                 Op = FirstGListOperations[MirrorRecursion] + i;
00191 
00192                 switch(GListOperations[Op].Type)
00193                 {
00194                         case 0:
00195                                 RenderTransPoly(Camera, (World_TransPoly*)GListOperations[Op].Data);
00196                                 break;
00197                         case 1:
00198                                 User_RenderPolyList((gePoly*)GListOperations[Op].Data);
00199                                 break;
00200 
00201                         default:
00202                                 assert(0);
00203                 }
00204         }
00205 
00206         NumGListOperations[MirrorRecursion] = 0;
00207 
00208         return GE_TRUE;
00209 }
00210 
00211 //=====================================================================================
00212 //      Local Static Functions
00213 //=====================================================================================
00214 static void CalcBSPModelInfo(World_BSP *BSP);
00215 static geBoolean RenderScene(geEngine *Engine, geWorld *World, geCamera *Camera, Frustum_Info *FrustumInfo);
00216 static void RenderBSPFrontBack_r(int32 Node, const geWorld_RenderInfo *RenderInfo, int32 ClipFlags);
00217 static void RenderBSPFrontBackMirror_r(int32 Node, geCamera *Camera, Frustum_Info *Fi, int32 ClipFlags);
00218 static void RenderFace(int32 Face, const geWorld_RenderInfo *RenderInfo, int32 ClipFlags);
00219 static geBoolean RenderWorldModel(geCamera *Camera, Frustum_Info *FrustumInfo, geWorld_SkyBoxTData *SkyTData);
00220 static geBoolean RenderSubModels(geCamera *Camera, Frustum_Info *FrustumInfo, geWorld_SkyBoxTData *SkyTData);
00221 static geBoolean WorldSetGBSP(geWorld *World, World_BSP *BSP);
00222 static World_BSP *CreateGBSP(geVFile *File);
00223 
00224 static geBoolean CreateStaticFogList(geWorld *World);
00225 
00226 // SkyBox functions
00227 static          geBoolean BuildSkyBox(World_SkyBox *SkyBox, const GFX_SkyData *SkyData);
00228 static void RenderSkyThroughFrustum(World_SkyBox *SkyBox, geWorld_SkyBoxTData *SkyTData, geCamera *Camera, Frustum_Info *Fi);
00229 static void SetupSkyBoxFaceForScene(World_SkyBox *SkyBox, int32 Face, const geXForm3d *XForm, Frustum_Info *Fi, geWorld_SkyBoxTData *SkyTData);
00230 static void SetupSkyForScene(World_SkyBox *SkyBox, geCamera *Camera, Frustum_Info *Fi, geWorld_SkyBoxTData *SkyTData);
00231 
00232 //=====================================================================================
00233 //      World_EngineInit
00234 //=====================================================================================
00235 geBoolean World_EngineInit(geEngine *Engine)
00236 {
00237         return GE_TRUE;
00238 }
00239 
00240 //=====================================================================================
00241 //      World_EngineShutdown
00242 //=====================================================================================
00243 void World_EngineShutdown(geEngine *Engine)
00244 {
00245         CEngine = NULL;
00246         CWorld = NULL;
00247         BSPData = NULL;
00248 }
00249 
00250 //=====================================================================================
00251 //      World_CreateFromBox
00252 //      Fill in a world with a blank bsp, with one leaf
00253 //=====================================================================================
00254 World_BSP *World_CreateBSPFromBox(const geVec3d *Mins, const geVec3d *Maxs)
00255 {
00256         World_BSP               *WorldBSP;
00257         GBSP_BSPData    *pBSP;
00258         GFX_Leaf                *pLeaf;
00259         GFX_Model               *pModel;
00260         GFX_Node                *pNode;
00261         int32                   i;
00262 
00263         WorldBSP = GE_RAM_ALLOCATE_STRUCT(World_BSP);
00264 
00265         if (!WorldBSP)
00266         {
00267                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00268                 return NULL;
00269         }
00270 
00271         memset(WorldBSP, 0, sizeof(World_BSP));
00272 
00273         pBSP = &WorldBSP->BSPData;
00274 
00275         memset(pBSP, 0, sizeof(GBSP_BSPData));
00276 
00277         pBSP->NumGFXModels = 1;
00278         pBSP->NumGFXNodes = 1;
00279         pBSP->NumGFXBNodes = 0;
00280         pBSP->NumGFXLeafs = 1;
00281         pBSP->NumGFXClusters = 1;
00282         pBSP->NumGFXAreas = 1;
00283         pBSP->NumGFXAreaPortals = 0;
00284         pBSP->NumGFXPlanes = 0;
00285         pBSP->NumGFXFaces = 0;
00286         pBSP->NumGFXLeafFaces = 0;
00287         pBSP->NumGFXLeafSides = 0;
00288         pBSP->NumGFXVerts = 0;
00289         pBSP->NumGFXVertIndexList = 0;
00290 
00291         pBSP->NumGFXEntData = 0;
00292         pBSP->NumGFXTextures = 0;
00293         pBSP->NumGFXTexInfo = 0;
00294         pBSP->NumGFXTexData = 0;
00295         pBSP->NumGFXPalettes = 0;
00296         
00297         pBSP->NumGFXLightData = 0;
00298         pBSP->NumGFXVisData = 0;
00299         pBSP->NumGFXPortals = 0;
00300 
00301         pBSP->GFXNodes = GE_RAM_ALLOCATE_ARRAY(GFX_Node, pBSP->NumGFXNodes);
00302         if (!pBSP->GFXNodes)
00303                 return NULL;
00304 
00305         pBSP->GFXModels = GE_RAM_ALLOCATE_ARRAY(GFX_Model, pBSP->NumGFXModels);
00306         if (!pBSP->GFXModels)
00307                 return NULL;
00308 
00309         pBSP->GFXLeafs = GE_RAM_ALLOCATE_ARRAY(GFX_Leaf, pBSP->NumGFXLeafs);
00310         if (!pBSP->GFXLeafs)
00311                 return NULL;
00312 
00313         pBSP->GFXClusters = GE_RAM_ALLOCATE_ARRAY(GFX_Cluster, pBSP->NumGFXClusters);
00314         if (!pBSP->GFXClusters)
00315                 return NULL;
00316 
00317         // Setup node 0 (point it to the only leaf in the level)
00318         pNode = &pBSP->GFXNodes[0];
00319         memset(pNode, 0, sizeof(*pNode));
00320         pNode->Children[0] = -1;
00321         pNode->Children[1] = -1;
00322         pNode->PlaneNum = -1;
00323 
00324         // Setup the worlds only model
00325         pModel = &pBSP->GFXModels[0];
00326 
00327         memset(pModel, 0, sizeof(GFX_Model));
00328 
00329         pModel->RootNode[0] = -1; 
00330         pModel->Mins = *Mins;
00331         pModel->Maxs = *Maxs;
00332 
00333         // Setup the leaf
00334         pLeaf = &pBSP->GFXLeafs[0];                     
00335         memset(pLeaf, 0, sizeof(GFX_Leaf));
00336 
00337         pLeaf->Contents = 0;
00338         pLeaf->Mins = *Mins;
00339         pLeaf->Maxs = *Maxs;
00340 
00341         pLeaf->Cluster = 0;
00342         pLeaf->Area = 0;
00343 
00344         // Setup the cluster that the above leaf points to
00345         pBSP->GFXClusters[pLeaf->Cluster].VisOfs = -1;                          // No visinfo for this cluster
00346 
00347         // Set up NULL sky
00348         for (i=0; i<6; i++)
00349                 pBSP->GFXSkyData.Textures[i] = -1;
00350 
00351         return WorldBSP;
00352 }
00353 
00354 //=====================================================================================
00355 //      geWorld_Create
00356 //=====================================================================================
00357 GENESISAPI geWorld *geWorld_Create(geVFile *File)
00358 {
00359         geWorld                 *NewWorld;
00360         int32                   i;
00361         geWorld_Model   *Models;
00362 
00363         NewWorld = GE_RAM_ALLOCATE_STRUCT(geWorld);
00364 
00365         if (!NewWorld)
00366         {
00367                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
00368                 return NULL;
00369         }
00370 
00371         memset(NewWorld, 0, sizeof(geWorld));
00372 
00373         // Create a ref on the world now, so if there is an error, it will free what is in the world...
00374         geWorld_CreateRef(NewWorld);
00375 
00376         if ( ! List_Start() )
00377                 goto Error;
00378 
00379         if (!File)
00380         {
00381                 geVec3d TMins = {-1000.0f, -1000.0f, -1000.0f};
00382                 geVec3d TMaxs = { 1000.0f,  1000.0f,  1000.0f};
00383 
00384                 NewWorld->CurrentBSP = World_CreateBSPFromBox(&TMins, &TMaxs);
00385         }
00386         else
00387         {
00388                 assert(File != NULL);
00389 
00390                 NewWorld->CurrentBSP = CreateGBSP(File);
00391         }
00392 
00393         // The world has changed
00394         NewWorld->Changed = GE_TRUE;
00395 
00396         if (!NewWorld->CurrentBSP)
00397                 goto Error;
00398 
00399         assert(NewWorld->CurrentBSP->BSPData.NumGFXLeafs > 0);
00400 
00401         // Create the leafdata array
00402         NewWorld->CurrentBSP->LeafData = GE_RAM_ALLOCATE_ARRAY(geWorld_Leaf, NewWorld->CurrentBSP->BSPData.NumGFXLeafs);
00403 
00404         if (!NewWorld->CurrentBSP->LeafData)
00405                 goto Error;
00406 
00407         memset(NewWorld->CurrentBSP->LeafData, 0, sizeof(geWorld_Leaf)*NewWorld->CurrentBSP->BSPData.NumGFXLeafs);
00408 
00409         if (!Light_WorldInit(NewWorld))
00410                 goto Error;
00411 
00412         if (!Ent_WorldInit(NewWorld))
00413                 goto Error;
00414 
00415         if (!Vis_WorldInit(NewWorld))
00416                 goto Error;
00417 
00418         if (!Surf_WorldInit(NewWorld))
00419                 goto Error;
00420 
00421         // Create the wbitmaps out of the GFXTexData
00422         NewWorld->CurrentBSP->WBitmapPool = geWBitmap_Pool_Create(&NewWorld->CurrentBSP->BSPData);
00423 
00424         if (!NewWorld->CurrentBSP->WBitmapPool)
00425                 goto Error;
00426 
00427         #if 1
00428                 // HACK
00429                 // We can now free the texturedata in the BSP that was loaded off disk.
00430                 // Eventually, the BSP disk format will be bitmaps, and no conversion will be needed, JP.
00431                 if (NewWorld->CurrentBSP->BSPData.GFXTexData)   // Not all worlds have tex data!!!
00432                 {
00433                         geRam_Free(NewWorld->CurrentBSP->BSPData.GFXTexData);
00434                         NewWorld->CurrentBSP->BSPData.GFXTexData = NULL;        // This is to assure that FreeGBSPFile does not touch this again
00435                         NewWorld->CurrentBSP->BSPData.NumGFXTexData = 0;
00436                 }
00437         #endif
00438 
00439         // Add all the bitmaps in the WBitmapPool to the world
00440         if (!geWorld_BitmapListInit(NewWorld))
00441         {
00442                 geErrorLog_AddString(-1, "geWorld_WorldCreate:  geWorld_BitmapListInit failed.", NULL);
00443                 return GE_FALSE;
00444         }
00445 
00446         // Init user stuff
00447         if (!User_WorldInit(NewWorld))
00448                 goto Error;
00449         
00450         Models = NewWorld->CurrentBSP->Models;
00451 
00452         //#pragma message ("Fixed number of models supported")
00453         for (i=0; i< MAX_MODELS; i++)
00454         {
00455                 memset(&Models[i], 0, sizeof(geWorld_Model));
00456 
00457                 Models[i].VisFrame = -1;
00458                 
00459                 geXForm3d_SetIdentity(&Models[i].XForm);
00460         }
00461         
00462         CalcBSPModelInfo(NewWorld->CurrentBSP);
00463 
00464         if (!BuildSkyBox(&NewWorld->SkyBox, &NewWorld->CurrentBSP->BSPData.GFXSkyData))
00465                 goto Error;
00466 
00467         NewWorld->CurrentLeaf = -1;                     // Make sure the level gets vised for the first time...
00468 
00469         NewWorld->ActorCount = 0;
00470         NewWorld->ActorArray = NULL;
00471 
00472 //MRB BEGIN
00473 //geSprite
00474         NewWorld->SpriteCount = 0;
00475         NewWorld->SpriteArray = NULL;
00476 //MRB END
00477 
00478         if (!CreateStaticFogList(NewWorld))
00479         {
00480                 geErrorLog_AddString(-1,"Failed to create static FogList", NULL);
00481                 goto Error;
00482         }
00483 
00484         return NewWorld;
00485 
00486         Error:;
00487                 geWorld_Free(NewWorld);
00488 
00489         return NULL;
00490 }
00491 
00492 //=====================================================================================
00493 //      geWorld_Free
00494 //=====================================================================================
00495 GENESISAPI void geWorld_Free(geWorld *World)
00496 {
00497         int                     i;
00498         geFog           *Fog, *Next;
00499         /*extern                geActor_Count;
00500         extern          geActor_RefCount;
00501         extern          geActor_DefCount;
00502         extern          geActor_DefRefCount;*/
00503 
00504         assert(World);
00505         assert(World->RefCount > 0);
00506 
00507         World->RefCount--;
00508 
00509         if (World->RefCount > 0)
00510                 return;                 // No need to destroy till ref count goes to zero...
00511 
00512 if (World->CurrentBSP)
00513 {
00514         // Shutdown actors
00515         if (World->ActorCount>0)
00516                 {
00517                         assert( World->ActorArray != NULL );
00518                         for (i=0; i< World->ActorCount; i++)
00519                                 {
00520                                 if(!geActor_Destroy( &( World->ActorArray[i].Actor ) ))
00521                                         geErrorLog_AddString(-1, "geWorld_Free:  geActor_Destroy failed.", NULL);
00522                                 }
00523 
00524                         /*geActor_Count       = 0;geActor_DestroyDirect
00525                         geActor_RefCount    = 0;
00526                         geActor_DefCount    = 0;
00527                         geActor_DefRefCount = 0;*/
00528                         World->ActorCount       = 0;
00529 
00530         }
00531         if (World->ActorArray != NULL)
00532                 {
00533                         geRam_Free( World->ActorArray );
00534                         World->ActorArray = NULL;
00535                 }
00536 
00537 //MRB BEGIN
00538 //geSprite
00539         // Shutdown sprites
00540         if (World->SpriteCount>0)
00541         {
00542                         assert( World->SpriteArray != NULL );
00543                         for (i=0; i< World->SpriteCount; i++)
00544                                 {
00545                                         geSprite_Destroy( &( World->SpriteArray[i].Sprite ) );
00546                                 }
00547                         World->SpriteCount = 0;
00548         }
00549         if (World->SpriteArray != NULL)
00550         {
00551                         geRam_Free( World->SpriteArray );
00552                         World->SpriteArray = NULL;
00553         }
00554 //MRB END
00555                 
00556         assert( World->ActorArray == NULL );
00557         
00558         // Call other modules to release info from the world that they created...
00559 #ifdef  MESHES
00560         Mesh_WorldShutdown(World);
00561 #endif
00562         Light_WorldShutdown(World);
00563         Ent_WorldShutdown(World);
00564         Vis_WorldShutdown(World);
00565         Surf_WorldShutdown(World);
00566 
00567         User_WorldShutdown(World);
00568 
00569         if (World->CurrentBSP->WBitmapPool)
00570         {
00571                 geWBitmap_Pool_Destroy(World->CurrentBSP->WBitmapPool);
00572                 World->CurrentBSP->WBitmapPool = NULL;
00573         }
00574 
00575         // Make sure we free all the fog
00576         for (Fog = World->FogList; Fog; Fog = Next)
00577         {
00578                 geWorld_FogData         *FogData;
00579 
00580                 Next = Fog->Next;
00581 
00582                 FogData = (geWorld_FogData*)geFog_GetUserData(Fog);
00583 
00584                 if (FogData)
00585                         geRam_Free(FogData);
00586 
00587                 geFog_SetUserData(Fog, NULL);           // Just in case...
00588 
00589                 geFog_Destroy(Fog);
00590         }
00591 
00592         // Free the leaf data array in the world
00593         if (World->CurrentBSP->LeafData)
00594         {
00595                 int32                   l;
00596                 geWorld_Leaf    *pLeafData;
00597                 
00598                 pLeafData = World->CurrentBSP->LeafData;
00599 
00600                 for (l=0; l< World->CurrentBSP->BSPData.NumGFXLeafs; l++, pLeafData++)
00601                 {
00602                         if (pLeafData->PolyList)
00603                         {
00604                                 User_DestroyPolyList(World, pLeafData->PolyList);
00605                                 pLeafData->PolyList = NULL;
00606                         }
00607                 }
00608         
00609                 geRam_Free(World->CurrentBSP->LeafData);
00610                 World->CurrentBSP->LeafData = NULL;
00611         }
00612 
00613         GBSP_FreeGBSPFile(&World->CurrentBSP->BSPData);
00614         geRam_Free(World->CurrentBSP);
00615 
00616         // Shutdown the bitmaplist      (this should be done last, to give others a chance to remove their bitmaps)
00617         geWorld_BitmapListShutdown(World);
00618 }
00619 
00620         geRam_Free(World);
00621 
00622         List_Stop();
00623 }
00624 
00625 //================================================================================
00626 //      geWorld_CreateRef
00627 //================================================================================
00628 geBoolean geWorld_CreateRef(geWorld *World)
00629 {
00630         World->RefCount++;
00631 
00632         return GE_TRUE;
00633 }
00634 
00635 //=====================================================================================
00636 //      World_SetEngine
00637 //      Lets this module and all its children know that the engine has changed
00638 //=====================================================================================
00639 geBoolean World_SetEngine(geEngine *Engine)
00640 {
00641         assert (Engine != NULL);
00642 
00643         CEngine = Engine;
00644 
00645         // Let all sub modules know what's going on...
00646         if (!Light_SetEngine(Engine))
00647                 return GE_FALSE;
00648         if (!Plane_SetEngine(Engine))
00649                 return GE_FALSE;
00650         if (!Surf_SetEngine(Engine))
00651                 return GE_FALSE;
00652 
00653         return GE_TRUE;
00654 }
00655 
00656 //=====================================================================================
00657 //      World_SetWorld
00658 //      Lets this module (and all of its children) know that the world has changed
00659 //=====================================================================================
00660 geBoolean World_SetWorld(geWorld *World)
00661 {
00662         assert(World != NULL);
00663         
00664         CWorld = World;
00665 
00666         // Let all sub modules know what's going on...
00667         if (!Light_SetWorld(World))
00668                 return GE_FALSE;
00669         if (!Plane_SetWorld(World))
00670                 return GE_FALSE;
00671         if (!Surf_SetWorld(World))
00672                 return GE_FALSE;
00673 
00674         return GE_TRUE;
00675 }
00676 
00677 //=====================================================================================
00678 //      World_SetGBSP
00679 //      Tells each module bsp data they are dealing with, and lets them update
00680 //      various pointers to the bsp, in their local statics
00681 //=====================================================================================
00682 geBoolean World_SetGBSP(World_BSP *BSP)
00683 {
00684         assert(BSP != NULL);
00685 
00686         // Make quick pointer to the world bsp data
00687         CBSP = BSP;
00688         BSPData = &BSP->BSPData;
00689 
00690         // Let all sub modules know what's going on...
00691         if (!Light_SetGBSP(BSP))
00692                 return GE_FALSE;
00693         if (!Plane_SetGBSP(BSP))
00694                 return GE_FALSE;
00695 
00696         if (!Surf_SetGBSP(BSP))
00697                 return GE_FALSE;
00698 
00699         return GE_TRUE;
00700 }
00701 
00702 //=====================================================================================
00703 //      SetupStaticData
00704 //=====================================================================================
00705 void SetupStaticData(void)
00706 {
00707         pSurfInfo = CBSP->SurfInfo;
00708         RDriver = CEngine->DriverInfo.RDriver;
00709 }
00710 
00711 //=====================================================================================
00712 //      World_RenderQ
00713 //      Render the worlds render Q using the supplied engine, world, and camera
00714 //=====================================================================================
00715 geBoolean World_WorldRenderQ(geEngine *Engine, geWorld *World, geCamera *Camera)
00716 {
00717         Frustum_Info            FrustumInfo;
00718         geFloat                         Rpm;
00719         World_SkyBox            *pSkyBox;
00720 
00721         assert(Engine != NULL);
00722         assert(World != NULL);
00723         assert(Camera!= NULL);
00724 
00725         World->CurFrameDynamic++;
00726 
00727         MirrorRecursion = 0;
00728         NumTransPolys[MirrorRecursion] = 0;
00729         NumGListOperations[MirrorRecursion] = 0;
00730         
00731         // Clear the debug info for this world
00732         //memset(&World->DebugInfo, 0, sizeof(geWorld_DebugInfo));
00733         CDebugInfo = &World->DebugInfo;
00734 
00735         // Setup modules that need info that we don't want to lug around with us...
00736         // NOTE - This might screw up multi-threading, so it might need to be changed
00737         // around a little to work with multi-threading
00738         World_SetEngine(Engine);
00739         World_SetWorld(World);
00740         World_SetGBSP(World->CurrentBSP);
00741         
00742         // FIXME:  REMOVE!!!!!
00743         GlobalEyePos = *geCamera_GetPov(Camera);
00744 
00745         // Setup some globals for this pass (this must be done before anyone uses them, or KABOOM)
00746         SetupStaticData();
00747 
00748         CFrustumInfo = &FrustumInfo;
00749 
00750         // Se if we can do mirrors with this driver
00751         CanDoMirrors = (RDriver->EngineSettings->PreferenceFlags & DRV_PREFERENCE_NO_MIRRORS)==0;
00752 
00753         // Setup the View Frustum to default window from the camera
00754         Frustum_SetFromCamera(&FrustumInfo, Camera);
00755 
00756         // Have the Vis module setup all vising info
00757         Vis_VisWorld(Engine, World, Camera, &FrustumInfo);
00758 
00759         // Setup the dynamic lights, etc...
00760         if (!Light_SetupLights(World))
00761                 return GE_FALSE;
00762 
00763         g_HackFrustum = FrustumInfo;
00764 
00765         // Render the entire scene through the DEFAULT FRUSTUM
00766         if (!RenderScene(Engine, World, Camera, &FrustumInfo))
00767                 return GE_FALSE;
00768 
00769         // Adjust current sky angle 
00770         pSkyBox = &World->SkyBox;
00771         Rpm = (pSkyBox->Dpm/180.0f)*3.14159f;           // Get radiuns per minute
00772         pSkyBox->Angle += Rpm*(1/30.0f);                        // Assume 30 fps for now :)
00773 
00774         // Little hack to flush the scene
00775         RDriver->BeginModels();
00776         RDriver->EndModels();
00777 
00778         if (!User_DestroyOncePolys(World))
00779                 return GE_FALSE;
00780 
00781 #if 1
00782         // <> CB remember the last camera we rendered with,
00783         //      so we can avoiding redoing view-dependent calculation
00784         World->LastCameraXForm = * geCamera_GetCameraSpaceXForm(Camera);
00785 #endif
00786 
00787         return GE_TRUE;
00788 }
00789 
00790 
00791 GENESISAPI geBoolean GENESISCC geWorld_IsActorPotentiallyVisible(const geWorld *World, const geActor *Actor, const geCamera *Camera)
00792                 // if the actor doesn't have a render hint box, we assume it's potentially visible
00793 {
00794         #pragma message ("This is a fairly poor test: ")
00795                 // mirrors aren't checked.
00796                 // this doesn't check the extents of the actor, just the center point.
00797                 // if the render hint box isn't set, should this return true, or find the DynamicExtBox?
00798         geExtBox                Box;
00799         geBoolean               Enabled;
00800         geVec3d                 Center;
00801         const geXForm3d *CameraTransform;
00802         int32                   Leaf,CameraLeaf;
00803                 
00804         assert( World != NULL );
00805         assert( geActor_IsValid(Actor)!= GE_FALSE );
00806         assert( Camera != NULL );
00807 
00808         geActor_GetRenderHintExtBox(Actor,&Box,&Enabled);
00809         if (Enabled == GE_FALSE)
00810                 return GE_TRUE;
00811         geExtBox_GetTranslation ( &Box, &Center );
00812         // NOTE - We are not taking into acount that a actor may live in more than one leaf...
00813         geWorld_GetLeaf(World, &Center, &Leaf);
00814 
00815         CameraTransform = geCamera_GetWorldSpaceVisXForm( Camera );
00816         geWorld_GetLeaf(World, &(CameraTransform->Translation), &CameraLeaf);
00817 
00818         #pragma message ("geWorld_MightSeeLeaf would be WAY FASTER here, but would be a frame behind...")
00819         if (geWorld_LeafMightSeeLeaf(World, Leaf, CameraLeaf, 0 )==GE_FALSE)
00820                 return GE_FALSE;
00821 
00822         {
00823                   // perhaps this should be a 'geCamera_IsExtBoxOnScreen(Camera,Box)' function?
00824                 // see if the hint box is visible on the screen.  
00825                 // (transform and project it to the screen, then check extents of that projection
00826                 //  against the clipping rect)
00827                 #pragma message ("This should use frustum in world space, and use Trace_BoxOnPlaneSides with frustum planes...")
00828                 geRect ClippingRect;
00829                 geVec3d BoxCorners[8];
00830                 const geXForm3d *ObjectToCamera;
00831                 geVec3d Maxs,Mins;
00832                 #define BIG_NUMBER (99e9f)  
00833                 int i;
00834 
00835                 geCamera_GetClippingRect(Camera,&ClippingRect);
00836                 BoxCorners[0] = Box.Min;
00837                 BoxCorners[1] = BoxCorners[0];  BoxCorners[1].X = Box.Max.X;
00838                 BoxCorners[2] = BoxCorners[0];  BoxCorners[2].Y = Box.Max.Y;
00839                 BoxCorners[3] = BoxCorners[0];  BoxCorners[3].Z = Box.Max.Z;
00840                 BoxCorners[4] = Box.Max;
00841                 BoxCorners[5] = BoxCorners[4];  BoxCorners[5].X = Box.Min.X;
00842                 BoxCorners[6] = BoxCorners[4];  BoxCorners[6].Y = Box.Min.Y;
00843                 BoxCorners[7] = BoxCorners[4];  BoxCorners[7].Z = Box.Min.Z;
00844 
00845                 ObjectToCamera = geCamera_GetCameraSpaceXForm(Camera);
00846                 assert( ObjectToCamera );
00847 
00848                 geVec3d_Set(&Maxs,-BIG_NUMBER,-BIG_NUMBER,-BIG_NUMBER);
00849                 geVec3d_Set(&Mins, BIG_NUMBER, BIG_NUMBER, BIG_NUMBER);
00850                 for (i=0; i<8; i++)
00851                         {
00852                                 geVec3d V;
00853                                 geXForm3d_Transform(  ObjectToCamera,&(BoxCorners[i]),&(BoxCorners[i]));
00854                                 geCamera_Project(  Camera,&(BoxCorners[i]),&V);
00855                                 if (V.X > Maxs.X ) Maxs.X = V.X;
00856                                 if (V.X < Mins.X ) Mins.X = V.X;
00857                                 if (V.Y > Maxs.Y ) Maxs.Y = V.Y;
00858                                 if (V.Y < Mins.Y ) Mins.Y = V.Y;
00859                                 if (V.Z > Maxs.Z ) Maxs.Z = V.Z;
00860                                 if (V.Z < Mins.Z ) Mins.Z = V.Z;
00861                         }
00862 
00863                 if (   (Maxs.X < ClippingRect.Left) 
00864                         || (Mins.X > ClippingRect.Right)
00865                         || (Maxs.Y < ClippingRect.Top) 
00866                         || (Mins.Y > ClippingRect.Bottom)
00867                         || (Maxs.Z < 0.0f) )
00868                         {
00869                                 return GE_FALSE;
00870                         }
00871         }
00872 
00873         return GE_TRUE;
00874 
00875 }
00876 
00877 //MRB BEGIN
00878 //geSprite
00879 GENESISAPI geBoolean GENESISCC geWorld_IsSpritePotentiallyVisible(const geWorld *World, const geSprite *Sprite, const geCamera *Camera)
00880 {
00881         #pragma message ("This is a fairly poor test: ")
00882                 // mirrors aren't checked.
00883                 // this doesn't check the extents of the sprite, just the center point.
00884         geVec3d                 Center;
00885         const geXForm3d *CameraTransform;
00886         int32                   Leaf,CameraLeaf;
00887                 
00888         assert( World != NULL );
00889         assert( geSprite_IsValid(Sprite)!= GE_FALSE );
00890         assert( Camera != NULL );
00891 
00892         geSprite_GetPosition ( Sprite, &Center );
00893 
00894         // NOTE - We are not taking into acount that a sprite may live in more than one leaf...
00895         geWorld_GetLeaf(World, &Center, &Leaf);
00896 
00897         CameraTransform = geCamera_GetWorldSpaceVisXForm( Camera );
00898         geWorld_GetLeaf(World, &(CameraTransform->Translation), &CameraLeaf);
00899 
00900         #pragma message ("geWorld_MightSeeLeaf would be WAY FASTER here, but would be a frame behind...")
00901         if (geWorld_LeafMightSeeLeaf(World, Leaf, CameraLeaf, 0 )==GE_FALSE)
00902                 return GE_FALSE;
00903 
00904         return GE_TRUE;
00905 }
00906 //MRB END
00907 
00908 
00909 //=====================================================================================
00910 //      RenderScene
00911 //      This can be recursivly re-entered
00912 //=====================================================================================
00913 static geBoolean RenderScene(geEngine *Engine, geWorld *World, geCamera *Camera, Frustum_Info *FrustumInfo)
00914 {
00915         geWorld_SkyBoxTData             SkyTData;
00916 
00917         if (MirrorRecursion > 0)
00918         {
00919                 FirstTransPolys[MirrorRecursion] = NumTransPolys[MirrorRecursion-1];
00920                 FirstGListOperations[MirrorRecursion] = NumGListOperations[MirrorRecursion-1];
00921         }
00922         else
00923         {
00924                 FirstTransPolys[MirrorRecursion] = 0;
00925                 FirstGListOperations[MirrorRecursion] = 0;
00926         }
00927 
00928         NumTransPolys[MirrorRecursion] = 0;
00929         NumGListOperations[MirrorRecursion] = 0;
00930 
00931         memset(&SkyTData, 0, sizeof(SkyTData));
00932 
00933         //
00934         // Setup the sky for this scene
00935         //
00936         SetupSkyForScene(&World->SkyBox, Camera, FrustumInfo, &SkyTData);
00937 
00938         //
00939         // Render the world...
00940         //
00941         if (!RenderWorldModel(Camera, FrustumInfo, &SkyTData))
00942                 return GE_FALSE;
00943 
00944         //
00945         // Then render the Sub models of the world
00946         //
00947         if (!RenderSubModels(Camera, FrustumInfo, &SkyTData))
00948                 return GE_FALSE;
00949 
00950         //
00951         //      Render the actors
00952         //
00953         {       
00954                 int i;
00955                 World_Actor             *WActor;
00956 
00957 //MRB BEGIN
00958 //geSprite
00959                 World_Sprite *WSprite;
00960 //MRB END
00961 
00962                 //geXForm3d             XForm;
00963                 geVec3d                 Center;
00964                 int32                   Leaf;
00965                 Frustum_Info    ActorFrustum;
00966 
00967                 // Make the frustum go to world space for actors
00968                 Frustum_TransformToWorldSpace(FrustumInfo, Camera, &ActorFrustum);
00969 
00970                 // Tell the driver we want to render meshes
00971                 if (!Engine->DriverInfo.RDriver->BeginMeshes())
00972                 {
00973                         geErrorLog_Add(GE_ERR_BEGIN_MESHES_FAILED, NULL);
00974                         return GE_FALSE;
00975                 }
00976 
00977                 // We were using the actor array alot, so I though I'd move it out...
00978                 // There were also going to be a lot of nested if's, so they are continues now...
00979                 WActor = World->ActorArray;
00980 
00981                 for (i=0; i< World->ActorCount; i++, WActor++)
00982                         {
00983                                 if (MirrorRecursion == 0 && !(WActor->Flags & (GE_ACTOR_RENDER_NORMAL | GE_ACTOR_RENDER_ALWAYS)))
00984                                         continue;               // Not visible in normal views, skip it
00985                                 if (MirrorRecursion > 0 && !(WActor->Flags & (GE_ACTOR_RENDER_MIRRORS | GE_ACTOR_RENDER_ALWAYS)))
00986                                         continue;               // Not visible in mirros, skip it
00987 
00988                                 {
00989                                         geExtBox Box;
00990                                         geBoolean Enabled;
00991                                         geActor_GetRenderHintExtBox(WActor->Actor,&Box,&Enabled);
00992                                         if (Enabled == GE_TRUE)
00993                                                 {
00994                                                         geExtBox_GetTranslation ( &Box, &Center );
00995                                                         if      (!(WActor->Flags & GE_ACTOR_RENDER_ALWAYS))
00996                                                                 {
00997                                                                         // NOTE - We are not taking into acount that a actor may live in more than one leaf...
00998                                                                         geWorld_GetLeaf(World, &Center, &Leaf);
00999                                         
01000                                                                         if (World->CurrentBSP->LeafData[Leaf].VisFrame != World->CurFrameStatic)
01001                                                                                 continue;               // Not in PVS, skip it
01002                                                                 }
01003                                                 }
01004                                 }
01005 
01006                                 if (MirrorRecursion == 0)
01007                                 {
01008                                         geActor_Render( WActor->Actor, Engine, World, Camera);
01009                                         // For debugging...
01010                                         //  This is set inside Actor/Puppet.  Engine->DebugInfo.NumActors++;
01011                                 }
01012                                 else
01013                                 {
01014                                         geActor_RenderThroughFrustum( WActor->Actor, Engine, World, Camera, &ActorFrustum);
01015                                         // For debugging...
01016                                         Engine->DebugInfo.NumActors++;
01017                                 }
01018 
01019                         }
01020 
01021 //MRB BEGIN
01022 //geSprite
01023                 WSprite = World->SpriteArray;
01024 
01025                 for (i = 0; i < World->SpriteCount; i++, WSprite++)
01026                 {
01027                         // Not visible in normal views, skip it
01028                         if ( (MirrorRecursion == 0) && !(WSprite->Flags & (GE_SPRITE_RENDER_NORMAL | GE_SPRITE_RENDER_ALWAYS)) )
01029                                 continue;
01030 
01031                         // Not visible in mirros, skip it
01032                         if ( (MirrorRecursion > 0) && !(WSprite->Flags & (GE_SPRITE_RENDER_MIRRORS | GE_SPRITE_RENDER_ALWAYS)) )
01033                                 continue;
01034 
01035                         // if it is not always rendered, then make sure it is in a visible leaf
01036                         if (!(WSprite->Flags & GE_SPRITE_RENDER_ALWAYS))
01037                         {
01038                                 // get the position of the sprite
01039                                 geSprite_GetPosition( WSprite->Sprite, &Center );
01040 
01041                                 // NOTE - We are not taking into acount that a sprite may live in more than one leaf...
01042                                 geWorld_GetLeaf(World, &Center, &Leaf);
01043 
01044                                 // Not in PVS, skip it
01045                                 if (World->CurrentBSP->LeafData[Leaf].VisFrame != World->CurFrameStatic)
01046                                         continue;               
01047                         }
01048 
01049                         // render the sprite through the frustum
01050                         geSprite_RenderThroughFrustum(WSprite->Sprite, Engine, World, Camera, &ActorFrustum);
01051                 }
01052 //MRB END
01053 
01054                 if (!Engine->DriverInfo.RDriver->EndMeshes())
01055                 {
01056                         geErrorLog_Add(GE_ERR_END_MESHES_FAILED, NULL);
01057                         return GE_FALSE;
01058                 }
01059         }
01060 
01061         // Hack...  Must restore the camera hack for trans world polys
01062         geCamera_FillDriverInfo(Camera);
01063         
01064         // Setup the user stuff with the world for this scene
01065         if (!User_SetCameraInfo(Engine, World, Camera, FrustumInfo))
01066                 return GE_FALSE;
01067 
01068         // Render all the translucent polys last (on top of everything)....
01069         if (!GList_RenderOperations(Camera))
01070                 return GE_FALSE;
01071 
01072         return GE_TRUE;
01073 }
01074 
01075 //=====================================================================================
01076 //      RenderBSPFrontBack_r2
01077 //      Fast traverser, that only traverses to visible leafs, nothing else.
01078 //=====================================================================================
01079 static void RenderBSPFrontBack_r2(int32 Node, geCamera *Camera)
01080 {
01081         geFloat                 Dist1;
01082         GFX_Node                *pNode;
01083         int32                   Side;
01084 
01085         if (Node < 0)           // At leaf, no more recursing
01086         {
01087                 int32           Leaf;
01088                 gePoly          *PolyList;
01089 
01090                 Leaf = -(Node+1);
01091 
01092                 assert(Leaf >= 0 && Leaf < CWorld->CurrentBSP->BSPData.NumGFXLeafs);
01093 
01094                 PolyList = CWorld->CurrentBSP->LeafData[Leaf].PolyList;
01095 
01096                 if (PolyList)
01097                 {
01098                         CDebugInfo->NumLeafsWithUserPolys++;
01099                         GList_AddOperation(1, (uint32)PolyList);
01100                 }
01101 
01102                 CDebugInfo->NumLeafsHit2++;
01103                 
01104                 return;
01105         }
01106 
01107         if (CBSP->NodeVisFrame[Node] != CWorld->CurFrameStatic)         
01108         {
01109                 if (CWorld->VisInfo)
01110                         return;
01111         }
01112         
01113         CDebugInfo->NumNodesTraversed2++;
01114 
01115         pNode = &BSPData->GFXNodes[Node];
01116         
01117         // Get the distance that the eye is from this plane
01118         Dist1 = Plane_PlaneDistanceFast(&BSPData->GFXPlanes[pNode->PlaneNum], geCamera_GetPov(Camera));
01119 
01120         if (Dist1 < 0)
01121                 Side = 1;
01122         else
01123                 Side = 0;
01124         
01125         // Go down the side we are on first, then the other side
01126         RenderBSPFrontBack_r2(pNode->Children[Side], Camera);
01127         RenderBSPFrontBack_r2(pNode->Children[!Side], Camera);
01128 }
01129 
01130 //=====================================================================================
01131 //      RenderBSPFrontBack_r
01132 //=====================================================================================
01133 static void RenderBSPFrontBack_r(int32 Node, const geWorld_RenderInfo *RenderInfo, int32 ClipFlags)
01134 {
01135         geFloat                 Dist1;
01136         int32                   i;
01137         int32                   k, f, Side;
01138         GFX_Node                *pNode;
01139         GFX_Face                *pFace;
01140         Surf_SurfInfo   *pSurfInfo2;
01141 
01142         if (Node < 0)           // At leaf, no more recursing
01143         {
01144                 int32           Leaf;
01145                 gePoly          *PolyList;
01146 
01147                 Leaf = -(Node+1);
01148 
01149                 assert(Leaf >= 0 && Leaf < CWorld->CurrentBSP->BSPData.NumGFXLeafs);
01150 
01151                 PolyList = CWorld->CurrentBSP->LeafData[Leaf].PolyList;
01152 
01153                 if (PolyList)
01154                 {
01155                         CDebugInfo->NumLeafsWithUserPolys++;
01156                         GList_AddOperation(1, (uint32)PolyList);
01157                 }
01158 
01159                 CDebugInfo->NumLeafsHit1++;
01160 
01161                 return;
01162         }
01163 
01164         if (CBSP->NodeVisFrame[Node] != CWorld->CurFrameStatic)         
01165         {
01166                 if (CWorld->VisInfo)
01167                         return;
01168         }
01169         
01170         CDebugInfo->NumNodesTraversed1++;
01171 
01172         pNode = &BSPData->GFXNodes[Node];
01173         
01174         if (ClipFlags)  
01175         {
01176                 geFloat                 *MinMaxs;
01177                 int32                   *Index;
01178                 geFloat                 Dist;
01179                 geVec3d                 Pnt;
01180                 GFX_Plane               *Planes;
01181                 Frustum_Info    *Fi;
01182 
01183                 Fi = RenderInfo->Frustum;
01184 
01185                 MinMaxs = (geFloat*)&pNode->Mins;
01186                 Planes = Fi->Planes;
01187 
01188                 for (k=0; k< Fi->NumPlanes; k++)
01189                 {
01190                         if (!(ClipFlags & (1<<k)) )
01191                                 continue;
01192                         
01193                         Index = Fi->pFrustumBBoxIndexes[k];
01194 
01195                         Pnt.X = MinMaxs[Index[0]];
01196                         Pnt.Y = MinMaxs[Index[1]];
01197                         Pnt.Z = MinMaxs[Index[2]];
01198                         
01199                         Dist = geVec3d_DotProduct(&Pnt, &Planes[k].Normal);
01200                         Dist -= Fi->Planes[k].Dist;
01201 
01202                         if (Dist <= 0)
01203                         {
01204                                 // We have no more visible nodes from this POV, so just traverse to leafs from here
01205                                 RenderBSPFrontBack_r2(Node, RenderInfo->Camera);
01206                                 return;
01207                         }
01208 
01209                         Pnt.X = MinMaxs[Index[3+0]];
01210                         Pnt.Y = MinMaxs[Index[3+1]];
01211                         Pnt.Z = MinMaxs[Index[3+2]];
01212 
01213                         Dist = geVec3d_DotProduct(&Pnt, &Planes[k].Normal);
01214                         Dist -= Planes[k].Dist;
01215 
01216                         if (Dist >= 0)          
01217                                 ClipFlags &= ~(1<<k);           // Don't need to clip to this plane anymore
01218                 }
01219         }
01220         
01221         // Get the distance that the eye is from this plane
01222         Dist1 = Plane_PlaneDistanceFast(&BSPData->GFXPlanes[pNode->PlaneNum], geCamera_GetPov(RenderInfo->Camera));
01223 
01224         pSurfInfo2 = &pSurfInfo[pNode->FirstFace];
01225         pFace = &BSPData->GFXFaces[pNode->FirstFace];
01226 
01227         if (Dist1 < 0)
01228                 Side = 1;               // Back side first
01229         else
01230                 Side = 0;               // Front side first
01231 
01232         // Render the side of the node we are on first
01233         RenderBSPFrontBack_r(pNode->Children[Side], RenderInfo, ClipFlags);
01234                 
01235         // Setup the global driver info about this plane (all the faces share it for this run)
01236         // FIXME:  Software driver needs to calculate gradients from uv's, so we can QUIT doing this here...
01237         GlobalInfo.PlaneNormal = BSPData->GFXPlanes[pNode->PlaneNum].Normal;
01238         GlobalInfo.PlaneDist = BSPData->GFXPlanes[pNode->PlaneNum].Dist;
01239         geXForm3d_Rotate(geCamera_GetCameraSpaceXForm(RenderInfo->Camera), &GlobalInfo.PlaneNormal, &GlobalInfo.RPlaneNormal);
01240 
01241         // Render faces on this node
01242         for (i = 0; i < pNode->NumFaces; i++, pSurfInfo2++, pFace++)
01243         {
01244                 f = i + pNode->FirstFace;
01245                         
01246                 if (pSurfInfo2->VisFrame != CWorld->CurFrameStatic && CWorld->VisInfo)
01247                         continue;
01248                 
01249                 if (pFace->PlaneSide != Side)
01250                         continue;
01251                 
01252                 CEngine->DebugInfo.TraversedPolys++;
01253                 RenderFace(f, RenderInfo, ClipFlags);
01254         }
01255 
01256         // Render faces on the other side of the node
01257         RenderBSPFrontBack_r(pNode->Children[!Side], RenderInfo, ClipFlags);
01258 }
01259 
01260 void GENESISCC geXForm3d_SetLeft(geXForm3d *M, const geVec3d *Left)
01261         // Gets a vector that is 'left' in the frame of reference of M (facing -Z)
01262 {
01263         assert( M     != NULL );
01264         assert( Left != NULL );
01265         
01266         M->AX = -Left->X;
01267         M->BX = -Left->Y;
01268         M->CX = -Left->Z;
01269 }
01270 
01271 void GENESISCC geXForm3d_SetUp(geXForm3d *M, const geVec3d *Up)
01272         // Gets a vector that is 'up' in the frame of reference of M (facing -Z)
01273 {
01274         assert( M  != NULL );
01275         assert( Up != NULL );
01276         
01277         M->AY = Up->X;
01278         M->BY = Up->Y;
01279         M->CY = Up->Z;
01280 }
01281 
01282 void GENESISCC geXForm3d_SetIn(geXForm3d *M,const geVec3d *In)
01283         // Gets a vector that is 'in' in the frame of reference of M (facing -Z)
01284 {
01285         assert( M    != NULL );
01286         assert( In != NULL );
01287 
01288         M->AZ = -In->X;
01289         M->BZ = -In->Y;
01290         M->CZ = -In->Z;
01291 }
01292 
01293 //================================================================================
01294 //      BackRotateVector
01295 //      Rotate a vector from viewspace to worldspace.
01296 //================================================================================
01297 static void BackRotateVector(const geVec3d *In, geVec3d *Out, const geXForm3d *XForm)
01298 {
01299     geVec3d     VRight, VUp, VIn;
01300         
01301         //      Get the 3 vectors that make up the Xform axis 
01302         VRight.X = XForm->AX; VRight.Y = XForm->AY; VRight.Z = XForm->AZ;
01303         VUp.X    = XForm->BX; VUp.Y    = XForm->BY; VUp.Z    = XForm->BZ;
01304         VIn.X    = XForm->CX; VIn.Y    = XForm->CY; VIn.Z    = XForm->CZ;
01305 
01306     Out->X = (In->X * VRight.X) + (In->Y * VUp.X) + (In->Z * VIn.X);
01307     Out->Y = (In->X * VRight.Y) + (In->Y * VUp.Y) + (In->Z * VIn.Y);
01308     Out->Z = (In->X * VRight.Z) + (In->Y * VUp.Z) + (In->Z * VIn.Z);
01309 }
01310 
01311 #define GOURAUD_SHADING
01312 
01313 //=====================================================================================
01314 //      RenderFace
01315 //=====================================================================================
01316 static void RenderFace(int32 Face, const geWorld_RenderInfo *RenderInfo, int32 ClipFlags)
01317 {
01318         geVec3d                         Dest1[MAX_RENDERFACE_VERTS], Dest2[MAX_RENDERFACE_VERTS];
01319         geVec3d                         *pDest1, *pDest2;
01320         Surf_TexVert            Tex1[MAX_RENDERFACE_VERTS], Tex2[MAX_RENDERFACE_VERTS];
01321         Surf_TexVert            *pTex1, *pTex2;
01322         DRV_TLVertex            Clipped1[MAX_RENDERFACE_VERTS];
01323         geVec3d                         *pGFXVerts;
01324         int32                           Length1, Length2;
01325         int32                           i, p;
01326         int32                           *pIndex;
01327         int32                           TexFlags;
01328         int32                           NumVerts;
01329         geBitmap                        *pBitmap;
01330         GFX_Face                        *pFace;
01331         GFX_TexInfo                     *pTexInfo;
01332         const geXForm3d         *CXForm;
01333         GFX_Plane                       *FPlanes;
01334         uint32                          RenderFlags;
01335         DRV_TexInfo                     DrvTexInfo;
01336         geWBitmap                       *pWBitmap;
01337         geRDriver_THandle       *THandle;
01338         Frustum_Info            *Fi;
01339         geCamera                        *Camera;
01340 
01341         Fi = RenderInfo->Frustum;
01342         Camera = RenderInfo->Camera;
01343 
01344         if (pSurfInfo[Face].LInfo.Face == -1)
01345                 return;
01346 
01347         pFace = &BSPData->GFXFaces[Face];
01348         pGFXVerts = BSPData->GFXVerts;
01349 
01350         NumVerts = pFace->NumVerts;
01351 
01352         assert(NumVerts < MAX_RENDERFACE_VERTS);
01353 
01354         pTexInfo = &BSPData->GFXTexInfo[pFace->TexInfo];
01355         TexFlags = pTexInfo->Flags;
01356         
01357         pDest1 = Dest1;
01358         pIndex = &BSPData->GFXVertIndexList[pFace->FirstVert];
01359 
01360         if (pSurfInfo[Face].Flags & SURFINFO_WAVY)
01361         {
01362                 for (i = 0; i < NumVerts; i++)
01363                 {
01364                         int32 Offs1, Offs2;
01365 
01366                         // HACK 
01367                         Offs1 = (CEngine->WaveTable[*pIndex & 15]-75) / 25;
01368                         Offs2 = (CEngine->WaveTable[*pIndex & 15]-75) / 20;
01369 
01370                         pDest1->X = pGFXVerts[*pIndex].X + Offs1;
01371                         pDest1->Y = pGFXVerts[*pIndex].Y;
01372                         pDest1->Z = pGFXVerts[*pIndex].Z + Offs2;
01373                         pDest1++;
01374                         pIndex++;
01375                 }
01376         }
01377         else 
01378         {
01379                 for (i = 0; i < NumVerts; i++)
01380                 {
01381                         pDest1->X = pGFXVerts[*pIndex].X;
01382                         pDest1->Y = pGFXVerts[*pIndex].Y;
01383                         pDest1->Z = pGFXVerts[*pIndex].Z;
01384                         pDest1++;
01385                         pIndex++;
01386 
01387                 }
01388         }
01389 
01390         pDest1 = Dest1;
01391         pDest2 = Dest2;
01392         pTex1 = &CBSP->TexVerts[pFace->FirstVert];
01393         pTex2 = Tex2;
01394         Length1 = NumVerts;
01395 
01396 
01397         FPlanes = Fi->Planes;
01398 
01399 #if 0           // Test
01400         //
01401         //      Apply any fog to the faces verts
01402         //
01403         TexFlags |= TEXINFO_GOURAUD;
01404         pTexInfo->Flags |= TEXINFO_NO_LIGHTMAP;
01405 
01406         for (i=0; i< Length1; i++)
01407         {
01408                 pTex1[i].r = 20.0f;
01409                 pTex1[i].g = 20.0f;
01410                 pTex1[i].b = 20.0f;
01411         }
01412         for (i=0; i<CWorld->NumVisibleFog; i++)
01413         {
01414                 Light_FogVerts(CWorld->VisibleFog[i], geCamera_GetPov(Camera), pDest1, pTex1, Length1);
01415         }
01416         for (i=0; i< Length1; i++)
01417         {
01418                 if (pTex1[i].r > 255.0f)
01419                         pTex1[i].r = 255.0f;
01420                 if (pTex1[i].g > 255.0f)
01421                         pTex1[i].g = 255.0f;
01422                 if (pTex1[i].b > 255.0f)
01423                         pTex1[i].b = 255.0f;
01424         }
01425 #endif
01426 
01427         if (ClipFlags)
01428         {
01429                 for (p=0; p< Fi->NumPlanes; p++)
01430                 {
01431                         // Only do clipping if we have to
01432                         if (!(ClipFlags & (1<<p)) )
01433                                 continue;
01434 
01435                         if (TexFlags & TEXINFO_GOURAUD)
01436                         {
01437                                 if (!Frustum_ClipToPlaneUVRGB(&FPlanes[p], pDest1, pDest2, pTex1, pTex2, Length1, &Length2))
01438                                         return;
01439                         }
01440                         else
01441                         {
01442                                 if (!Frustum_ClipToPlaneUV(&FPlanes[p], pDest1, pDest2, pTex1, pTex2, Length1, &Length2))
01443                                         return;
01444                         }
01445 
01446                         if (pDest1 == Dest2)
01447                         {
01448                                 pDest1 = Dest1;
01449                                 pDest2 = Dest2;
01450                                 pTex1 = Tex1;
01451                                 pTex2 = Tex2;
01452                         }
01453                         else
01454                         {
01455                                 pDest1 = Dest2;
01456                                 pDest2 = Dest1;
01457                                 pTex1 = Tex2;
01458                                 pTex2 = Tex1;
01459                         }
01460                         Length1 = Length2;
01461                 }
01462         }
01463           
01464         if (Length1 < 3)
01465                 return;                 // Poly was clipped away
01466 
01467         // This bitmap is being used, so set its vis frame to the worlds...
01468         pWBitmap = geWBitmap_Pool_GetWBitmapByIndex(CBSP->WBitmapPool, pTexInfo->Texture);
01469         assert(pWBitmap);
01470         geWBitmap_SetVisFrame(pWBitmap, CWorld->CurFrameDynamic);
01471 
01472         //
01473         // Get the camera XForm
01474         //
01475         CXForm = geCamera_GetCameraSpaceXForm(Camera);
01476         
01477         //
01478         // Transform the array of verts
01479         //
01480         geXForm3d_TransformArray(CXForm, pDest1, pDest2, Length1);
01481         
01482         if (TexFlags & TEXINFO_SKY)             // If this is a sky face, then render the sky through it, and return
01483         {
01484                 Frustum_Info    SkyFrustum;
01485 
01486                 // Create a frustum from the poly
01487                 Frustum_SetFromPoly(&SkyFrustum, pDest2, Length1, MirrorRecursion&1);
01488 
01489                 // Render the sky through the poly's frustum
01490                 RenderSkyThroughFrustum(&CWorld->SkyBox, RenderInfo->SkyTData, Camera, &SkyFrustum);
01491                 return;         // Once the sky was rendered through the face, return
01492         }
01493         else if (TexFlags & TEXINFO_GOURAUD)
01494         {
01495                 Frustum_ProjectRGB(pDest2, pTex1, Clipped1, Length1, Camera);
01496         }
01497         else
01498         {
01499                 Frustum_Project(pDest2, pTex1, Clipped1, Length1, Camera);
01500 
01501                 for (i=0; i< Length1; i++)
01502                 {
01503                         Clipped1[i].r = 255.0f;
01504                         Clipped1[i].g = 255.0f;
01505                         Clipped1[i].b = 255.0f;
01506                 }
01507         }
01508 
01509         // If we hit a mirror face, render the world through the mirror's POV, then draw the mirror poly on top of the 
01510         //      hole made by the mirror  (NOTE - we only do this if the Driver wants to do recursive scenes)
01511         if ((TexFlags & TEXINFO_MIRROR) && CanDoMirrors && MirrorRecursion < MAX_MIRROR_RECURSION)
01512         {
01513                 Frustum_Info    MirrorFrustum;
01514                 geXForm3d               MirrorXForm, OldXForm;
01515                 GFX_Plane               *pPlane;
01516                 geVec3d                 FaceNormal;
01517                 geFloat                 FaceDist;
01518                 
01519                 //
01520                 // Create the mirror frustum, for the mirrored scene.
01521                 // Use the transformed data, since the Frustum is expected to start out in camera space
01522                 //
01523                 if (!Frustum_SetFromPoly(&MirrorFrustum, pDest2, Length1, MirrorRecursion&1))
01524                         return;
01525 
01526                 if (MirrorFrustum.NumPlanes+1 >= MAX_FCP)
01527                         return;         // Oh well...
01528 
01529                 // Add the transformed face plane to the frustum, so we only draw what is on the front
01530                 // side of the mirror
01531                 pPlane = &MirrorFrustum.Planes[MirrorFrustum.NumPlanes++];
01532 
01533                 if (MirrorRecursion&1)
01534                         gePlane_SetFromVerts(pPlane, &pDest2[0], &pDest2[1], &pDest2[2]);
01535                 else
01536                         gePlane_SetFromVerts(pPlane, &pDest2[2], &pDest2[1], &pDest2[0]);
01537 
01538                 //
01539                 //      Mirror the camera
01540                 //      Use the world space face for this
01541                 //
01542                 #pragma message ("Rotated models are broken in mirrors.  Quick fix:  Rotate the plane against the models xform")
01543 
01544                 FaceNormal = BSPData->GFXPlanes[pFace->PlaneNum].Normal;
01545                 FaceDist = BSPData->GFXPlanes[pFace->PlaneNum].Dist;
01546 
01547                 if (pFace->PlaneSide)
01548                 {
01549                         geVec3d_Inverse(&FaceNormal);
01550                         FaceDist = -FaceDist;
01551                 }
01552 
01553                 // Save old camera xform
01554                 OldXForm = *geCamera_GetWorldSpaceXForm(Camera);
01555 
01556                 // Create the xform that will mirror the camera, by taking the surfaca plane of this face
01557                 geXForm3d_Mirror(&OldXForm, &FaceNormal, FaceDist, &MirrorXForm);
01558 
01559                 // Mirror the camera using this xform
01560                 geCamera_SetWorldSpaceXForm(Camera, &MirrorXForm);
01561 
01562                 MirrorRecursion++;
01563                 CEngine->DebugInfo.NumMirrors++;
01564                 
01565                 // Render the world through the poly, from the mirrored camera 
01566                 RenderScene(CEngine, CWorld, Camera, &MirrorFrustum);
01567 
01568                 MirrorRecursion--;
01569 
01570                 // Restore the camera
01571                 geCamera_SetWorldSpaceXForm(Camera, &OldXForm);
01572         }
01573 
01574         // Get a pointer to the bitmap (texture)
01575         pBitmap = geWBitmap_GetBitmap(pWBitmap);
01576         assert(geWorld_HasBitmap(CWorld, pBitmap));
01577 
01578         RenderFlags = 0;
01579 
01580         CEngine->DebugInfo.SentPolys++;
01581 
01582         // All transparent polys (either some alpha translucency, or color key) will be drawn last, and sorted.
01583         //      They are then added to the TransPoly list (front to back), then when all is done, the Trans polys are drawn
01584         //  in reverse order (back to front) last.  
01585         //      NOTE - Mirrors are not put in this list.  They are drawn below, to cover up the "hole" made by the mirror...
01586         if ((pSurfInfo[Face].Flags & SURFINFO_TRANS) && !(pTexInfo->Flags & TEXINFO_MIRROR))
01587         {
01588                 DRV_TLVertex    *pVerts;
01589                 World_TransPoly *pPoly;
01590                 int32                   Start;
01591 
01592                 Start = FirstTransPolys[MirrorRecursion]+NumTransPolys[MirrorRecursion];
01593 
01594                 if (Start+1 >= MAX_TRANS_POLYS || Length1 > MAX_CACHE_VERTS) 
01595                         return;         // Oh well...
01596 
01597                 pPoly = &TransPolys[Start];
01598 
01599                 pVerts = pPoly->TLVerts;
01600 
01601                 for (i = 0; i < Length1; i++, pVerts++)
01602                         *pVerts = Clipped1[i];
01603 
01604                 pPoly->Flags = 0;
01605                 pPoly->Face = Face;
01606                 pPoly->NumVerts = Length1;
01607 
01608                 // Add this TransPoly to the GList (Geometry List) that is rendered after the current subscene is done
01609                 GList_AddOperation(0, (uint32)pPoly);
01610 
01611                 NumTransPolys[MirrorRecursion]++;
01612 
01613                 // Just return, the Trans poly will get rendered at the end of the scene in GList_RenderOperations...
01614                 return;
01615         }
01616 
01617         // If this surface is a mirror, and we can do mirrors, then render it with some alpha
01618         if ((pTexInfo->Flags & TEXINFO_MIRROR) && CanDoMirrors)
01619         {
01620                 RenderFlags |= DRV_RENDER_ALPHA | DRV_RENDER_FLUSH;
01621                 Clipped1[0].a = pTexInfo->Alpha;
01622         }
01623         else
01624         {
01625                 // Else, don't render with any alpha
01626                 Clipped1[0].a = 255.0f;
01627         }
01628 
01629         DrvTexInfo.ShiftU = pSurfInfo[Face].ShiftU;
01630         DrvTexInfo.ShiftV = pSurfInfo[Face].ShiftV;
01631         //DrvTexInfo.ShiftU = pTexInfo->Shift[0];
01632         //DrvTexInfo.ShiftV = pTexInfo->Shift[1];
01633         DrvTexInfo.DrawScaleU = pTexInfo->DrawScale[0];
01634         DrvTexInfo.DrawScaleV = pTexInfo->DrawScale[1];
01635 
01636         GlobalInfo.VecU = pTexInfo->Vecs[0];
01637         GlobalInfo.VecV = pTexInfo->Vecs[1];
01638         GlobalInfo.TexShiftX = pTexInfo->Shift[0];
01639         GlobalInfo.TexShiftY = pTexInfo->Shift[1];
01640 
01641         // Get the THandle from the bitmap
01642         THandle = geBitmap_GetTHandle(pBitmap);
01643         assert(THandle);
01644 
01645         if (pTexInfo->Flags & TEXINFO_NO_LIGHTMAP)
01646         {
01647                 RDriver->RenderWorldPoly(Clipped1, Length1, THandle, &DrvTexInfo, NULL, RenderFlags);
01648         }
01649         else
01650         {
01651                 DRV_LInfo                       *pLInfo = &pSurfInfo[Face].LInfo;
01652 
01653                 // The camera is set up at the beginning of the world...
01654                 GlobalInfo.TexMinsX = pLInfo->MinU;
01655                 GlobalInfo.TexMinsY = pLInfo->MinV;
01656                 GlobalInfo.TexWidth = pLInfo->Width<<4;
01657                 GlobalInfo.TexHeight = pLInfo->Height<<4;
01658 
01659                 RDriver->RenderWorldPoly(Clipped1, Length1, THandle, &DrvTexInfo, &pSurfInfo[Face].LInfo, RenderFlags);
01660         }
01661 }
01662 
01663 //=====================================================================================
01664 //      RenderWorldModel
01665 //      Renders model 0 (the world model)
01666 //=====================================================================================
01667 static geBoolean RenderWorldModel(geCamera *Camera, Frustum_Info *FrustumInfo, geWorld_SkyBoxTData *SkyTData)
01668 {
01669         geXForm3d                       OldXForm,NewXForm, CXForm;
01670         geWorld_Model           *Models;
01671         Frustum_Info            WorldSpaceFrustum;
01672         uint32                          StartClipFlags;
01673         geWorld_RenderInfo      RenderInfo;
01674         
01675         assert(CWorld != NULL);                 // Asser that some globals are true (hopefully)...
01676         assert(CBSP != NULL);
01677 
01678         Models = CBSP->Models;          
01679 
01680         g_CurrentModel = Models;
01681 
01682         if (!RDriver->BeginWorld())
01683         {
01684                 geErrorLog_Add(GE_ERR_BEGIN_WORLD_FAILED, NULL);
01685                 return GE_FALSE;
01686         }
01687 
01688         OldXForm = *geCamera_GetWorldSpaceXForm(Camera); //Camera->MXForm;      // Save old camera for this model
01689 
01690         NewXForm = OldXForm;
01691 
01692         // Put the camera model about models origin
01693         geVec3d_Subtract(&NewXForm.Translation, &Models[0].Pivot, &NewXForm.Translation);
01694 
01695         // Transform the cameras xform against the models xform
01696 
01697         // treat the model as a camera, and apply it to the camera model
01698         geCamera_ConvertWorldSpaceToCameraSpace(&Models[0].XForm, &CXForm);
01699 
01700         geXForm3d_Multiply(&CXForm, &NewXForm, &NewXForm);
01701 
01702         // Put back into camera space
01703         geVec3d_Add(&NewXForm.Translation, &Models[0].Pivot, &NewXForm.Translation);
01704 
01705         // Convert the NewXForm back into a real camera
01706         geCamera_SetWorldSpaceXForm(Camera, &NewXForm);
01707 
01708         // Make the frustum go to world space
01709         Frustum_TransformToWorldSpace(FrustumInfo, Camera, &WorldSpaceFrustum);
01710 
01711         geCamera_FillDriverInfo(Camera);
01712         
01713         // Make a ClipFlags bits for for each side of the frustum...
01714         assert(WorldSpaceFrustum.NumPlanes < 32);
01715 
01716         StartClipFlags = (1<<WorldSpaceFrustum.NumPlanes)-1;
01717 
01718         RenderInfo.Camera = Camera;
01719         RenderInfo.Frustum = &WorldSpaceFrustum;
01720         RenderInfo.SkyTData = SkyTData;
01721 
01722         // Render the tree through the frustum
01723         RenderBSPFrontBack_r(   BSPData->GFXModels[0].RootNode[0], 
01724                                                         &RenderInfo,
01725                                                         StartClipFlags);
01726 
01727         // Restore the camera
01728         geCamera_SetWorldSpaceXForm(Camera, &OldXForm);
01729         
01730         if (!RDriver->EndWorld())
01731         {
01732                 geErrorLog_Add(GE_ERR_END_WORLD_FAILED, NULL);
01733                 return GE_FALSE;
01734         }
01735         return GE_TRUE;
01736 }
01737 
01738 //=====================================================================================
01739 //      RenderSubModels
01740 //      Renders all other models besides world model
01741 //=====================================================================================
01742 static geBoolean RenderSubModels(geCamera *Camera, Frustum_Info *FrustumInfo, geWorld_SkyBoxTData *SkyTData)
01743 {
01744         int32                           i;
01745         BOOL                            OldVis;
01746         geWorld_Model           *Model;
01747         geXForm3d                       OldXForm, NewXForm, CXForm;
01748         Frustum_Info            ModelSpaceFrustum;
01749         uint32                          StartClipFlags;
01750         geWorld_RenderInfo      RenderInfo;
01751 
01752 
01753         if (!RDriver->BeginModels())
01754         {
01755                 geErrorLog_Add(GE_ERR_BEGIN_MODELS_FAILED, NULL);
01756                 return GE_FALSE;
01757         }
01758 
01759         assert(CWorld != NULL);                 // Assert that some globals are true (hopefully)...
01760         assert(CBSP != NULL);
01761         
01762         OldVis = CWorld->VisInfo;               // Save old vis info flag
01763 
01764         CWorld->VisInfo = FALSE;                // Fake no vis info so ALL model faces/modes will draw
01765         
01766         Model = &CBSP->Models[1];               // Start with the model (skip the world, Models[0])
01767         
01768         // Render all sub models
01769         for (i=1; i< BSPData->NumGFXModels; i++, Model++)
01770         {
01771                 g_CurrentModel = Model;
01772 
01773                 if (Model->VisFrame != CWorld->CurFrameDynamic)
01774                         continue;
01775                 if (MirrorRecursion == 0 && !(Model->Flags & (GE_MODEL_RENDER_NORMAL | GE_MODEL_RENDER_ALWAYS)))
01776                         continue;
01777                 if (MirrorRecursion > 0 && !(Model->Flags & (GE_MODEL_RENDER_MIRRORS | GE_MODEL_RENDER_ALWAYS)))
01778                         continue;
01779 
01780                 CEngine->DebugInfo.NumModels++;
01781 
01782                 OldXForm = *geCamera_GetWorldSpaceXForm(Camera);//Camera->MXForm;       // Save old camera for this model
01783 
01784                 NewXForm = OldXForm;
01785 
01786                 // Put the camera model about models origin
01787                 geVec3d_Subtract(&NewXForm.Translation, &Model->Pivot, &NewXForm.Translation);
01788 
01789                 // Transform the cameras xform against the models xform
01790 
01791                 // treat the model as a camera, and apply it to the camera model
01792                 geCamera_ConvertWorldSpaceToCameraSpace(&Model->XForm, &CXForm);
01793 
01794                 geXForm3d_Multiply(&CXForm, &NewXForm, &NewXForm);
01795 
01796                 // Put back into camera space
01797                 geVec3d_Add(&NewXForm.Translation, &Model->Pivot, &NewXForm.Translation);
01798 
01799                 // Convert the NewXForm back into a real camera
01800                 geCamera_SetWorldSpaceXForm(Camera, &NewXForm);
01801 
01802                 // Make the frustum go to World/Model space
01803                 Frustum_TransformToWorldSpace(FrustumInfo, Camera, &ModelSpaceFrustum);
01804 
01805                 geCamera_FillDriverInfo(Camera);
01806         
01807                 // Make a ClipFlags bits for for each side of the frustum...
01808                 StartClipFlags = (1<<ModelSpaceFrustum.NumPlanes)-1;
01809 
01810                 RenderInfo.Camera = Camera;
01811                 RenderInfo.Frustum = &ModelSpaceFrustum;
01812                 RenderInfo.SkyTData = SkyTData;
01813 
01814                 // Render the tree through the frustum
01815                 RenderBSPFrontBack_r(   BSPData->GFXModels[i].RootNode[0], 
01816                                                                 &RenderInfo,
01817                                                                 StartClipFlags);
01818 
01819                 // Restore the camera
01820                 geCamera_SetWorldSpaceXForm(Camera, &OldXForm);
01821         }
01822 
01823         CWorld->VisInfo = OldVis;               // Restore original vis info
01824         
01825         if (!RDriver->EndModels())
01826         {
01827                 geErrorLog_Add(GE_ERR_END_MODELS_FAILED, NULL);
01828                 return GE_FALSE;
01829         }
01830         return GE_TRUE;
01831 }
01832 
01833 //========================================================================================
01834 //      CreateGBSP
01835 //========================================================================================
01836 static World_BSP *CreateGBSP(geVFile *File)     
01837 {
01838         World_BSP       *NewBSP;
01839 
01840         assert(File != NULL);
01841 
01842         // Create a new bsp World
01843         NewBSP = GE_RAM_ALLOCATE_STRUCT(World_BSP);
01844 
01845         if (!NewBSP)
01846         {
01847                 geErrorLog_Add(GE_ERR_OUT_OF_MEMORY, NULL);
01848                 return NULL;
01849         }
01850         
01851         memset(NewBSP, 0, sizeof(World_BSP));
01852         
01853         if (!GBSP_LoadGBSPFile(File, &NewBSP->BSPData))
01854         {
01855                 geErrorLog_Add(GE_ERR_GBSP_LOAD_FAILURE, NULL);
01856                 return NULL;
01857         }
01858 
01859         return NewBSP;
01860 }
01861 
01862 //========================================================================================
01863 //      RenderTransPoly
01864 //========================================================================================
01865 static void RenderTransPoly(geCamera *Camera, World_TransPoly *pPoly)
01866 {
01867         int32                   Face;
01868         DRV_TLVertex    *pTLVerts;
01869         GFX_Face                *pFace;
01870         GFX_TexInfo             *pTexInfo;
01871         geBitmap                *pBitmap;
01872         int32                   NumVerts;
01873         Surf_SurfInfo   *pSurfInfo2;
01874         DRV_LInfo               *pLInfo;
01875         DRV_TexInfo             DrvTexInfo;
01876         
01877         Face = pPoly->Face;
01878                 
01879         pFace = &BSPData->GFXFaces[Face];
01880 
01881         pTLVerts = pPoly->TLVerts;
01882         NumVerts = pPoly->NumVerts;
01883                 
01884         pTexInfo = &BSPData->GFXTexInfo[pFace->TexInfo];
01885         pSurfInfo2 = &pSurfInfo[Face];
01886         pLInfo = &pSurfInfo2->LInfo;
01887 
01888         // Get a pointer to the bitmap (texture)
01889         pBitmap = geWBitmap_Pool_GetBitmapByIndex(CBSP->WBitmapPool, pTexInfo->Texture);
01890 
01891         assert(geWorld_HasBitmap(CWorld, pBitmap));
01892 
01893         pTLVerts->a = pTexInfo->Alpha;
01894 
01895         DrvTexInfo.ShiftU = pSurfInfo2->ShiftU;
01896         DrvTexInfo.ShiftV = pSurfInfo2->ShiftV;
01897         //DrvTexInfo.ShiftU = pTexInfo->Shift[0];
01898         //DrvTexInfo.ShiftV = pTexInfo->Shift[1];
01899         DrvTexInfo.DrawScaleU = pTexInfo->DrawScale[0];
01900         DrvTexInfo.DrawScaleV = pTexInfo->DrawScale[1];
01901 
01902         // Setup the global info (pass this in the driver the right way!!!)
01903         GlobalInfo.VecU = pTexInfo->Vecs[0];
01904         GlobalInfo.VecV = pTexInfo->Vecs[1];
01905         GlobalInfo.TexShiftX = pTexInfo->Shift[0];
01906         GlobalInfo.TexShiftY = pTexInfo->Shift[1];
01907 
01908         GlobalInfo.PlaneNormal = BSPData->GFXPlanes[pFace->PlaneNum].Normal;
01909         GlobalInfo.PlaneDist = BSPData->GFXPlanes[pFace->PlaneNum].Dist;
01910         geXForm3d_Rotate(geCamera_GetCameraSpaceXForm(Camera), &GlobalInfo.PlaneNormal, &GlobalInfo.RPlaneNormal);
01911 
01912         if (pTexInfo->Flags & TEXINFO_NO_LIGHTMAP)
01913         {
01914                 geRDriver_THandle       *THandle;
01915 
01916                 THandle = geBitmap_GetTHandle(pBitmap);
01917 
01918                 assert(THandle);
01919 
01920                 RDriver->RenderWorldPoly(pTLVerts, NumVerts, THandle, &DrvTexInfo, NULL, DRV_RENDER_ALPHA | DRV_RENDER_FLUSH);
01921         }
01922         else
01923         {
01924                 geRDriver_THandle       *THandle;
01925 
01926                 // This global info only needs to be set up for faces that have lightmaps...
01927                 GlobalInfo.TexMinsX = pLInfo->MinU;
01928                 GlobalInfo.TexMinsY = pLInfo->MinV;
01929                 GlobalInfo.TexWidth = pLInfo->Width<<4;
01930                 GlobalInfo.TexHeight = pLInfo->Height<<4;
01931 
01932                 THandle = geBitmap_GetTHandle(pBitmap);
01933 
01934                 assert(THandle);
01935 
01936                 RDriver->RenderWorldPoly(pTLVerts, NumVerts, THandle, &DrvTexInfo, pLInfo, DRV_RENDER_ALPHA | DRV_RENDER_FLUSH);
01937         }
01938 }
01939 
01940 //========================================================================================
01941 //      CalcBSPModelInfo
01942 //      Calculates the center of each BModel by taking the center of their bounding boxs...
01943 //      Calcs other info as well...
01944 //========================================================================================
01945 static void CalcBSPModelInfo(World_BSP *BSP)
01946 {
01947         int32                   m, Node;
01948         geWorld_Model   *Models;
01949         GBSP_BSPData    *BData;
01950         geVec3d                 Mins, Maxs;
01951         
01952         assert(BSP != NULL);
01953 
01954         Models = BSP->Models;
01955         BData = &BSP->BSPData;
01956 
01957         for (m=0; m< BData->NumGFXModels; m++)
01958         {
01959                 int32           i;
01960 
01961                 Node = BData->GFXModels[m].RootNode[0];
01962 
01963                 if (Node < 0 )
01964                         continue;
01965 
01966                 Mins = BData->GFXNodes[Node].Mins;
01967                 Maxs = BData->GFXNodes[Node].Maxs;
01968 
01969                 // Need this so that we can get the motions later.  Horrible.
01970                 Models[m].BSPModel = &BData->GFXModels[m];
01971 
01972                 // Get the models REAL center
01973                 for (i=0; i<3; i++)
01974                         VectorToSUB(Models[m].RealCenter, i) = 
01975                                 (VectorToSUB(Mins, i) + VectorToSUB(Maxs, i)) * 0.5f;
01976 
01977                 // Get the models rotational pivot point
01978                 Models[m].Pivot = BData->GFXModels[m].Origin;
01979                 
01980                 Models[m].GFXModelNum = m;
01981 
01982                 Models[m].Mins = Mins;
01983                 Models[m].Maxs = Maxs;
01984 
01985                 // Set the translated mins/maxs to some default value...
01986                 Models[m].TMins = Mins;
01987                 Models[m].TMaxs = Maxs;
01988 
01989                 Models[m].Flags = GE_MODEL_RENDER_NORMAL | GE_MODEL_RENDER_MIRRORS;
01990                 Models[m].ChangedFlags = MODEL_CHANGED_XFORM;
01991         }
01992 }
01993 
01994 // FIXME:  Put all this model stuff into Model.c
01995 #pragma message ("Fix naming convention in models i.e: geWorld_SetModelXForm ---> geWorld_ModelSetXForm...")
01996 //========================================================================================
01997 //      World_SetModelXForm
01998 //========================================================================================
01999 GENESISAPI geBoolean geWorld_SetModelXForm(geWorld *World, geWorld_Model *Model, const geXForm3d *XForm)
02000 {
02001         geVec3d AxisVecs[3], Center;
02002         int             i, j;
02003 
02004         assert(World != NULL);
02005         assert(Model != NULL);
02006 
02007         Model->XForm = *XForm;
02008         memset(AxisVecs, 0, sizeof(geVec3d)*3);
02009 
02010         //grab the box center
02011         geVec3d_Add(&Model->Mins, &Model->Maxs, &Center);
02012         geVec3d_Scale(&Center, 0.5f, &Center);
02013 
02014         //build a local rotated axis based on extent vectors
02015         //(this could be simplified to less fmuls)
02016         for(i=0;i < 3;i++)
02017         {
02018                 VectorToSUB(AxisVecs[i], i)     =VectorToSUB(Model->Maxs, i) - VectorToSUB(Center, i);
02019                 geXForm3d_Rotate(XForm, &AxisVecs[i], &AxisVecs[i]);
02020         }
02021 
02022         //mask off the sign bits
02023         for(i=0;i < 3;i++)
02024         {
02025                 for(j=0;j < 3;j++)
02026                 {
02027                         *((int *)(&AxisVecs[i])+j)      =*((int *)(&AxisVecs[i])+j) & 0x7fffffff;
02028                 }
02029         }
02030 
02031         //add up vecs to get max
02032         for(i=0;i < 3;i++)
02033         {
02034                 VectorToSUB(Model->TMaxs, i)
02035                         =VectorToSUB(AxisVecs[0], i)
02036                         + VectorToSUB(AxisVecs[1], i)
02037                         + VectorToSUB(AxisVecs[2], i);
02038         }
02039 
02040         //local min is opposite of max
02041         Model->TMins    =Model->TMaxs;
02042         geVec3d_Inverse(&Model->TMins);
02043 
02044         //move back to world
02045         geVec3d_Add(&XForm->Translation, &Center, &Center);
02046         geVec3d_Add(&Model->TMins, &Center, &Model->TMins);
02047         geVec3d_Add(&Model->TMaxs, &Center, &Model->TMaxs);
02048 
02049         //add a small epsilon
02050         for(i=0;i < 3;i++)
02051         {
02052                 VectorToSUB(Model->TMaxs, i)    +=1.0f;
02053                 VectorToSUB(Model->TMins, i)    -=1.0f;
02054         }
02055 
02056         Model->ChangedFlags |= MODEL_CHANGED_XFORM;
02057 
02058         return GE_TRUE;
02059 }
02060 
02061 //========================================================================================
02062 //      World_GetModelXForm
02063 //========================================================================================
02064 GENESISAPI geBoolean geWorld_GetModelXForm(const geWorld *World, const geWorld_Model *Model, geXForm3d *XForm)
02065 {
02066         assert(World != NULL);
02067         assert(Model != NULL);
02068         assert(XForm != NULL);
02069 
02070         *XForm = Model->XForm;
02071 
02072         return GE_TRUE;
02073 }
02074 
02075 //=====================================================================================
02076 //      FillAreas_r
02077 //=====================================================================================
02078 void FillAreas_r(geWorld *World, uint32 Area, uint8 *List, uint32 *Count)
02079 {
02080         GBSP_BSPData    *BSP;
02081         GFX_Area                *a;
02082         GFX_AreaPortal  *p;
02083         int32                   i;
02084 
02085         List[*Count] = (uint8)Area;
02086         *Count++;
02087         
02088         BSP = &World->CurrentBSP->BSPData;
02089 
02090         a = &BSP->GFXAreas[Area];
02091 
02092         p = &BSP->GFXAreaPortals[a->FirstAreaPortal];
02093 
02094         for (i=0; i< a->NumAreaPortals; i++, p++)
02095         {
02096                 geWorld_Model   *Model;
02097 
02098                 Model = &World->CurrentBSP->Models[p->ModelNum];
02099 
02100                 if (Model->Open)
02101                         FillAreas_r(World, p->Area, List, Count);
02102         }
02103 }
02104 
02105 //========================================================================================
02106 //      geWorld_OpenModel
02107 //========================================================================================
02108 GENESISAPI geBoolean geWorld_OpenModel(geWorld *World, geWorld_Model *Model, geBoolean Open)
02109 {
02110         World_BSP       *WBSP;
02111         int32           a0, a1;
02112         GFX_Model       *GFXModel;
02113 #if 0
02114         int32           i0, i1;
02115         int32           NumWorkAreas0;
02116         uint8           WorkAreas0[256];
02117         int32           NumWorkAreas1;
02118         uint8           WorkAreas1[256];
02119 #endif
02120 
02121         assert(World);
02122         assert(Model);
02123 
02124         if (Model->Open == Open)
02125                 return GE_TRUE;                 // Nothing changed
02126 
02127         Model->Open = Open;
02128         World->ForceVis = GE_TRUE;                      // Force an update
02129 
02130         WBSP = World->CurrentBSP;
02131 
02132         GFXModel = &WBSP->BSPData.GFXModels[Model->GFXModelNum];
02133 
02134         a0 = GFXModel->Areas[0];
02135         a1 = GFXModel->Areas[1];
02136 
02137         // We know these 2 can see each other
02138         WBSP->AreaConnections[a0][a1] = Open;
02139         WBSP->AreaConnections[a1][a0] = Open;
02140 
02141 #if 0
02142         NumWorkAreas0 = NumWorkAreas1 = 0;
02143         
02144         if (Open)
02145         {
02146                 // Combine list into one, and combine vis sets
02147                 FillAreas_r(World, a0, WorkAreas0, &NumWorkAreas0);
02148                 FillAreas_r(World, a1, WorkAreas0, &NumWorkAreas0);
02149 
02150                 // Connect all areas that were flooded into on each side
02151                 for (i0=0; i0<NumWorkAreas0; i0++)
02152                 {
02153                         uint8           *pWork0, *pWork1;
02154 
02155                         pWork0 = &WorkAreas0[i0];
02156                         pWork1 = WorkAreas0;
02157 
02158                         for (i1=0; i1<NumWorkAreas0; i1++, pWork1++)
02159                         {
02160                                 WBSP->AreaConnections[*pWork0][*pWork1] = 1;
02161                                 WBSP->AreaConnections[*pWork1][*pWork0] = 1;
02162                         }
02163                 }
02164         }
02165         else
02166         {
02167                 // Seperate list into two list, and seperate vis list
02168                 FillAreas_r(World, a0, WorkAreas0, &NumWorkAreas0);
02169                 FillAreas_r(World, a1, WorkAreas1, &NumWorkAreas1);
02170 
02171                 // Seperate visiblity from one side to the other
02172                 for (i0=0; i0<NumWorkAreas0; i0++)
02173                 {
02174                         uint8           *pWork0, *pWork1;
02175 
02176                         pWork0 = &WorkAreas0[i0];
02177                         pWork1 = WorkAreas1;
02178 
02179                         for (i1=0; i1<NumWorkAreas1; i1++, pWork1++)
02180                         {
02181                                 WBSP->AreaConnections[*pWork0][*pWork1] = 0;
02182                                 WBSP->AreaConnections[*pWork1][*pWork0] = 0;
02183                         }
02184                 }
02185         }
02186  #endif
02187 
02188         return GE_TRUE;
02189 }
02190 
02191 //========================================================================================
02192 //========================================================================================
02193 GENESISAPI geBoolean geWorld_GetModelRotationalCenter(
02194         const geWorld *                 World,
02195         const geWorld_Model *   Model,
02196         geVec3d *                               Center)
02197 {
02198         assert(World != NULL);
02199         assert(Model != NULL);
02200         assert(Center != NULL);
02201 
02202         *Center = Model->Pivot;
02203 
02204         return GE_TRUE;
02205 }
02206 
02207 //========================================================================================
02208 //      World_ModelGetBBox
02209 //========================================================================================
02210 GENESISAPI geBoolean geWorld_ModelGetBBox(const geWorld *World, const geWorld_Model *Model, geVec3d *Mins, geVec3d *Maxs)
02211 {
02212         int32           i;
02213 
02214         assert(World != NULL);
02215         assert(Model != NULL);
02216         assert(Mins);
02217         assert(Maxs);
02218 
02219         *Mins = Model->Mins;
02220         *Maxs = Model->Maxs;
02221 
02222         // Translate the BBox to object space 
02223         for (i=0; i<3; i++)
02224         {
02225                 VectorToSUB(*Mins, i) -= VectorToSUB(Model->Pivot, i);
02226                 VectorToSUB(*Maxs, i) -= VectorToSUB(Model->Pivot, i);
02227         } 
02228 
02229         return GE_TRUE;
02230 }
02231 
02232 //========================================================================================
02233 //      World_ModelGetMotion
02234 //========================================================================================
02235 GENESISAPI geMotion * geWorld_ModelGetMotion(geWorld_Model *Model)
02236 {
02237         assert(Model);
02238         return Model->BSPModel->Motion;
02239 }
02240 
02241 //========================================================================================
02242 //========================================================================================
02243 GENESISAPI void * geWorld_ModelGetUserData(const geWorld_Model *Model)
02244 {
02245         assert(Model);
02246         return Model->UserData;
02247 }
02248 
02249 //========================================================================================
02250 //========================================================================================
02251 GENESISAPI void geWorld_ModelSetUserData(geWorld_Model *Model, void *UserData)
02252 {
02253         assert(Model);
02254         Model->UserData = UserData;
02255 }
02256 
02257 //========================================================================================
02258 //========================================================================================
02259 GENESISAPI void geWorld_ModelSetFlags(geWorld_Model *Model, uint32 ModelFlags)
02260 {
02261         assert(Model);
02262         Model->Flags = ModelFlags;
02263 }
02264 
02265 //========================================================================================
02266 //========================================================================================
02267 GENESISAPI uint32 geWorld_ModelGetFlags(geWorld_Model *Model)
02268 {
02269         assert(Model);
02270 
02271         return Model->Flags;
02272 }
02273 
02274 //      eaa3 07/28/2000 Gods, you'd think when you asked for the rotational
02275 //      ..center you'd get the REAL center of the model.  Fine, this will
02276 //      ..return the Actual True Center (feh).
02277 
02278 GENESISAPI void geWorld_ModelGetCenter(geWorld_Model *Model, geVec3d *Center)
02279 {
02280   *Center = Model->RealCenter;
02281 
02282   return;
02283 }
02284 
02285 //========================================================================================
02286 //========================================================================================
02287 GENESISAPI geBoolean geWorld_AddActor( geWorld *World, geActor *Actor, uint32 Flags, uint32 UserFlags)
02288 {
02289         World_Actor *NewArray;
02290         assert( World != NULL );
02291         assert( geActor_IsValid(Actor) != GE_FALSE );
02292         assert( World->ActorCount >= 0 );
02293 
02294         NewArray = GE_RAM_REALLOC_ARRAY( World->ActorArray, World_Actor , World->ActorCount+1);
02295         if (NewArray == NULL)   
02296                 {
02297                         geErrorLog_AddString(-1,"Failed to grow world actor array", NULL);
02298                         return GE_FALSE;
02299                 }
02300         World->ActorArray = NewArray;
02301         World->ActorArray[World->ActorCount].Actor              = Actor;
02302         World->ActorArray[World->ActorCount].Flags              = Flags;
02303         World->ActorArray[World->ActorCount].UserFlags  = UserFlags;
02304         if (geActor_RenderPrep( Actor,World )==GE_FALSE)
02305                 {
02306                         geErrorLog_AddString(-1,"Failed to prepare the actor for rendering", NULL);
02307                         return GE_FALSE;
02308                 }
02309         World->ActorCount++;
02310         geActor_CreateRef(Actor);
02311 
02312         #ifdef DO_ADDREMOVE_MESSAGES    
02313         {
02314         char str[100];
02315                 sprintf(str,"World_AddActor : %08X\n",Actor);
02316                 OutputDebugString(str);
02317         }
02318         #endif
02319         
02320         return GE_TRUE;
02321 }
02322 
02323 
02324 //========================================================================================
02325 //========================================================================================
02326 GENESISAPI geBoolean geWorld_RemoveActor(geWorld *World, geActor *Actor)
02327 {
02328         int i,Count;
02329         assert( World != NULL );
02330         assert( geActor_IsValid(Actor) != GE_FALSE );
02331         assert( World->ActorCount >= 0 );
02332 
02333         Count = World->ActorCount;
02334 
02335         #ifdef DO_ADDREMOVE_MESSAGES    
02336         {
02337         char str[100];
02338                 sprintf(str,"World_RemoveActor : %08X\n",Actor);
02339                 OutputDebugString(str);
02340         }
02341         #endif
02342 
02343         for (i=0; i<Count; i++)
02344                 {
02345                         if (World->ActorArray[i].Actor == Actor)
02346                                 {
02347                                         geActor_Destroy( &Actor );
02348                                         World->ActorArray[i] = World->ActorArray[Count-1];
02349                                         World->ActorArray[Count-1].Actor = NULL;
02350                                         World->ActorArray[Count-1].Flags = 0;
02351                                         World->ActorCount--;
02352                                         return GE_TRUE;
02353                                 }
02354                 }
02355         geErrorLog_AddString(-1,"Failed to find actor in actor list", NULL);
02356         
02357         return GE_FALSE;
02358 }
02359 
02360 //========================================================================================
02361 //========================================================================================
02362 GENESISAPI geBoolean geWorld_SetActorFlags(geWorld *World, geActor *Actor, uint32 Flags)
02363 {
02364         int i,Count;
02365         assert( World != NULL );
02366         assert( geActor_IsValid(Actor) != GE_FALSE );
02367 
02368         Count = World->ActorCount;
02369 
02370         for (i=0; i<Count; i++)
02371                 {
02372                         if (World->ActorArray[i].Actor == Actor)
02373                                 {
02374                                         World->ActorArray[i].Flags = Flags;
02375                                         return GE_TRUE;
02376                                 }
02377                 }
02378         geErrorLog_AddString(-1,"Failed to find actor in actor list", NULL);
02379         return GE_FALSE;
02380 }
02381 
02382 //MRB BEGIN
02383 //geSprite
02384 //========================================================================================
02385 //========================================================================================
02386 GENESISAPI geBoolean geWorld_AddSprite(geWorld *World, geSprite *Sprite, uint32 Flags, uint32 UserFlags)
02387 {
02388         World_Sprite *NewArray;
02389 
02390         assert( World );
02391         assert( geSprite_IsValid(Sprite) );
02392         assert( World->SpriteCount >= 0 );
02393 
02394         NewArray = GE_RAM_REALLOC_ARRAY( World->SpriteArray, World_Sprite, (World->SpriteCount + 1) );
02395 
02396         if (NewArray == NULL)   
02397         {
02398                 geErrorLog_AddString(-1, "Failed to grow world sprite array", NULL);
02399                 return GE_FALSE;
02400         }
02401 
02402         World->SpriteArray = NewArray;
02403         World->SpriteArray[World->SpriteCount].Sprite                   = Sprite;
02404         World->SpriteArray[World->SpriteCount].Flags                    = Flags;
02405         World->SpriteArray[World->SpriteCount].UserFlags        = UserFlags;
02406 
02407         if ( geSprite_RenderPrep(Sprite, World) == GE_FALSE )
02408         {
02409                 geErrorLog_AddString(-1, "Failed to prepare the sprite for rendering", NULL);
02410                 return GE_FALSE;
02411         }
02412 
02413         World->SpriteCount++;
02414         geSprite_CreateRef(Sprite);
02415 
02416 #ifdef DO_ADDREMOVE_MESSAGES    
02417         {
02418                 char str[100];
02419 
02420                 sprintf(str, "World_AddSprite : %08X\n", Sprite);
02421                 OutputDebugString(str);
02422         }
02423 #endif
02424         
02425         return GE_TRUE;
02426 }
02427 
02428 
02429 //========================================================================================
02430 //========================================================================================
02431 GENESISAPI geBoolean geWorld_RemoveSprite(geWorld *World, geSprite *Sprite)
02432 {
02433         int i, Count;
02434 
02435         assert( World );
02436         assert( geSprite_IsValid(Sprite) );
02437         assert( World->SpriteCount >= 0 );
02438 
02439         Count = World->SpriteCount;
02440 
02441 #ifdef DO_ADDREMOVE_MESSAGES    
02442         {
02443                 char str[100];
02444 
02445                 sprintf(str,"World_RemoveSprite : %08X\n",Sprite);
02446                 OutputDebugString(str);
02447         }
02448 #endif
02449 
02450         for (i=0; i < Count; i++)
02451         {
02452                 if (World->SpriteArray[i].Sprite == Sprite)
02453                 {
02454                         geSprite_Destroy( &Sprite );
02455 
02456                         World->SpriteArray[i] = World->SpriteArray[Count-1];
02457 
02458                         World->SpriteArray[Count-1].Sprite = NULL;
02459                         World->SpriteArray[Count-1].Flags = 0;
02460                         
02461                         World->SpriteCount--;
02462 
02463                         return GE_TRUE;
02464                 }
02465         }
02466 
02467         geErrorLog_AddString(-1,"Failed to find actor in actor list", NULL);
02468         
02469         return GE_FALSE;
02470 }
02471 
02472 //========================================================================================
02473 //========================================================================================
02474 GENESISAPI geBoolean geWorld_SetSpriteFlags(geWorld *World, geSprite *Sprite, uint32 Flags)
02475 {
02476         int i, Count;
02477 
02478         assert( World );
02479         assert( geSprite_IsValid(Sprite) );
02480 
02481         Count = World->SpriteCount;
02482 
02483         for (i = 0; i < Count; i++)
02484         {
02485                 if (World->SpriteArray[i].Sprite == Sprite)
02486                 {
02487                         World->SpriteArray[i].Flags = Flags;
02488                         return GE_TRUE;
02489                 }
02490         }
02491 
02492         geErrorLog_AddString(-1,"Failed to find actor in actor list", NULL);
02493 
02494         return GE_FALSE;
02495 }
02496 //MRB END
02497 
02498 //========================================================================================
02499 //      geWorld_GetLeaf
02500 //========================================================================================
02501 GENESISAPI geBoolean geWorld_GetLeaf(const geWorld *World, const geVec3d *Pos, int32 *Leaf)
02502 {
02503         assert(World);
02504         assert(Leaf);
02505 
02506         // Return the leaf that is model 0 (the main world model)
02507         *Leaf = Plane_FindLeaf(World, World->CurrentBSP->BSPData.GFXModels[0].RootNode[0], Pos);
02508 
02509         return GE_TRUE;
02510 }
02511 
02512 //========================================================================================
02513 //      geWorld_MightSeeLeaf
02514 //========================================================================================
02515 GENESISAPI geBoolean geWorld_MightSeeLeaf(const geWorld *World, int32 Leaf)
02516 {
02517         assert(World);
02518 
02519         assert(Leaf >= 0 && Leaf < World->CurrentBSP->BSPData.NumGFXLeafs);
02520 
02521         if (World->CurrentBSP->LeafData[Leaf].VisFrame == World->CurFrameStatic)
02522                 return GE_TRUE;
02523 
02524         return GE_FALSE;
02525 }
02526 
02527 //========================================================================================
02528 //      geWorld_LeafMightSeeLeaf
02529 //========================================================================================
02530 GENESISAPI geBoolean geWorld_LeafMightSeeLeaf(const geWorld *World, int32 Leaf1, int32 Leaf2, uint32 VisFlags)
02531 {
02532         GBSP_BSPData    *BSPData;
02533         int32                   Cluster1, Cluster2, VisOfs;
02534         uint8                   *VisData;
02535 
02536         assert(World);
02537         assert(World->CurrentBSP);
02538         assert(VisFlags == 0);          // VisFlags are not used, and must be set to 0 for future use...
02539 
02540         BSPData = &World->CurrentBSP->BSPData;
02541 
02542         assert(Leaf1 >= 0 && Leaf1 < BSPData->NumGFXLeafs);
02543         assert(Leaf2 >= 0 && Leaf2 < BSPData->NumGFXLeafs);
02544 
02545         // Get the clusters that the leafs are in...
02546         Cluster1 = BSPData->GFXLeafs[Leaf1].Cluster;
02547         Cluster2 = BSPData->GFXLeafs[Leaf2].Cluster;
02548 
02549         if (Cluster1 == -1 || Cluster2 == -1)
02550                 return GE_FALSE;                // If either on is in solid space, thern assume they can't see each other...
02551 
02552         assert(Cluster1 >= 0 && Cluster1 < BSPData->NumGFXClusters);
02553         assert(Cluster2 >= 0 && Cluster2 < BSPData->NumGFXClusters);
02554 
02555         VisOfs = BSPData->GFXClusters[Cluster1].VisOfs;
02556 
02557         // If no vis data for cluster 1, then assume no vis data in entire map, and just return TRUE...
02558         // This lets them run the map with no vis info, they will just suffer...
02559         if (VisOfs == -1)
02560                 return GE_TRUE;
02561 
02562         assert(VisOfs >=0 && VisOfs < BSPData->NumGFXVisData);
02563 
02564         VisData = &BSPData->GFXVisData[VisOfs];
02565 
02566         // See if Cluster2's bit is set in Cluster1's vis data set
02567         if (VisData[Cluster2>>3] & (1<<(Cluster2&7)) )          
02568         {
02569                 int32   Area1, Area2;
02570 
02571                 Area1 = BSPData->GFXLeafs[Leaf1].Area;
02572                 Area2 = BSPData->GFXLeafs[Leaf2].Area;
02573 
02574                 assert(Area1 > 0 && Area2 > 0);
02575 
02576                 if (World->CurrentBSP->AreaConnections[Area1][Area2])
02577                         return GE_TRUE;                         // They can see each other...
02578         }
02579 
02580         return GE_FALSE;                                // They cannot see each other...
02581 }
02582 
02583 //========================================================================================
02584 //      geWorld_GetSetByClass
02585 //========================================================================================
02586 GENESISAPI geEntity_EntitySet *geWorld_GetEntitySet(geWorld *World, const char *ClassName)
02587 {
02588         geWorld_EntClassSet             *WSets;
02589         int32                                   i;
02590 
02591         assert(World);
02592 
02593         // No classname, just return the main set of all entities
02594         if (!ClassName)
02595         {
02596                 assert(World->EntClassSets[0].Set);
02597 
02598                 return World->EntClassSets[0].Set;
02599         }
02600 
02601         WSets = World->EntClassSets;
02602         
02603         for (i=1; i< World->NumEntClassSets; i++)
02604         {
02605                 assert(WSets[i].Set);
02606 
02607                 if (!stricmp(WSets[i].ClassName, ClassName))
02608                         return WSets[i].Set;
02609         }
02610 
02611         return NULL;
02612 }
02613 
02614 //====================================================================================
02615 //      geWorld_GetNextModel
02616 //====================================================================================
02617 GENESISAPI geWorld_Model *geWorld_GetNextModel(geWorld *World, geWorld_Model *Start)
02618 {
02619         int32                   MNum;
02620         GBSP_BSPData    *BSPData;
02621         World_BSP               *WorldBSP;
02622 
02623         assert(World != NULL);
02624 
02625         WorldBSP = World->CurrentBSP;
02626 
02627         assert(WorldBSP != NULL);
02628 
02629         BSPData = &WorldBSP->BSPData;
02630 
02631         if (Start)
02632         {
02633                 MNum = (Start - WorldBSP->Models);
02634 
02635                 assert(MNum >= 0);
02636                 assert(MNum < BSPData->NumGFXModels);
02637 
02638                 MNum++;
02639         }
02640         else
02641                 MNum = 0;
02642 
02643         if (MNum >= BSPData->NumGFXModels)
02644                 return NULL;            // No more models
02645 
02646         return &WorldBSP->Models[MNum];
02647 }
02648 
02649 //====================================================================================
02650 //      *********** FOG stuff *************
02651 //====================================================================================
02652 
02653 //====================================================================================
02654 //      FogSetAttributesCB
02655 //      CB to be called whenever geFog_SetAttributes is called
02656 //====================================================================================
02657 static geBoolean geFog_SetAttributesCB(geFog *Fog)
02658 {
02659         geWorld_FogData         *FogData;
02660         geVec3d                         *Mins, *Maxs;
02661 
02662         //Fog->VolumeRadius = 1000.0f;          // Test
02663 
02664         FogData = geFog_GetUserData(Fog);
02665 
02666         // Record the leaf the fog is in...
02667         geWorld_GetLeaf(FogData->World, &Fog->Pos, &FogData->Leaf);
02668 
02669         // Set Mins/Maxs to fog radius
02670         Mins = &FogData->Mins;
02671         Maxs = &FogData->Maxs;
02672 
02673         Mins->X = -Fog->VolumeRadius;
02674         Mins->Y = -Fog->VolumeRadius;
02675         Mins->Z = -Fog->VolumeRadius;
02676 
02677         Maxs->X =  Fog->VolumeRadius;
02678         Maxs->Y =  Fog->VolumeRadius;
02679         Maxs->Z =  Fog->VolumeRadius;
02680 
02681         return GE_TRUE;
02682 }
02683 
02684 //====================================================================================
02685 //      geWorld_AddFog
02686 //====================================================================================
02687 GENESISAPI geFog *geWorld_AddFog(geWorld *World)
02688 {
02689         geFog                           *Fog;
02690         geWorld_FogData         *FogData;
02691 
02692         assert(World);
02693 
02694         Fog = NULL;
02695         FogData = NULL;
02696 
02697         Fog = geFog_Create(geFog_SetAttributesCB);              // Create the fog
02698 
02699         if (!Fog)
02700                 goto ExitWithError;
02701 
02702         // Insert at begining of list
02703         if (World->FogList)
02704                 World->FogList->Prev = Fog;
02705 
02706         Fog->Next = World->FogList;
02707         World->FogList = Fog;
02708 
02709         // Set up fog user data for the engine to use ONLY
02710         FogData = GE_RAM_ALLOCATE_STRUCT(geWorld_FogData);
02711 
02712         if (!FogData)
02713                 goto ExitWithError;
02714 
02715         FogData->World = World;                         // Remember what world created the fog
02716 
02717         geFog_SetUserData(Fog, FogData);
02718 
02719         return Fog;
02720 
02721         ExitWithError:
02722         {
02723                 if (FogData)
02724                         geRam_Free(FogData);
02725 
02726                 if (Fog)
02727                         geWorld_RemoveFog(World, Fog);
02728         }
02729 
02730         return NULL;
02731 }
02732 
02733 //====================================================================================
02734 //      geWorld_RemoveFog
02735 //====================================================================================
02736 GENESISAPI geBoolean geWorld_RemoveFog(geWorld *World, geFog *Fog)
02737 {
02738         geWorld_FogData         *FogData;
02739 
02740         assert(World);
02741         assert(Fog);
02742 
02743         FogData = geFog_GetUserData(Fog);
02744 
02745         if (FogData)
02746                 geRam_Free(FogData);
02747 
02748         geFog_SetUserData(Fog, NULL);           // Just in case
02749         
02750         if (Fog->Prev)
02751                 Fog->Prev->Next = Fog->Next;
02752 
02753         if (Fog->Next)
02754                 Fog->Next->Prev = Fog->Prev;
02755 
02756         if (Fog == World->FogList)
02757         {
02758                 assert(Fog->Prev == NULL);
02759                 World->FogList = Fog->Next;
02760         }
02761 
02762         geFog_Destroy(Fog);
02763 
02764         return GE_TRUE;
02765 }
02766 
02767 typedef struct
02768 {
02769         geVec3d         Origin;
02770         GE_RGBA         Color;
02771         geFloat         Brightness;
02772         geFloat         Radius;
02773 
02774 } MapFogData;
02775 
02776 //====================================================================================
02777 //      CreateStaticFogList
02778 //====================================================================================
02779 static geBoolean CreateStaticFogList(geWorld *World)
02780 {
02781         geEntity                        *Entity;
02782         geEntity_EntitySet      *EntitySet;
02783         geFog                           *Fog;
02784 
02785         // ONly interested in "FogLight"'s
02786 
02787         if ( World->NumEntClassSets == 0 )
02788                 return GE_TRUE;
02789 
02790         EntitySet = geWorld_GetEntitySet(World, "FogLight");
02791 
02792         if (!EntitySet)
02793                 return GE_TRUE;
02794 
02795         Entity = NULL;
02796 
02797         while (1)
02798         {
02799                 MapFogData      *Fd;
02800 
02801                 Entity = geEntity_EntitySetGetNextEntity(EntitySet, Entity);
02802 
02803                 if (!Entity)
02804                         break;
02805 
02806                 Fd = geEntity_GetUserData(Entity);
02807 
02808                 // Must have user data set
02809                 if (!Fd)
02810                         goto ExitWithError;
02811                 
02812                 // Add the fog to the world
02813                 Fog = geWorld_AddFog(World);
02814 
02815                 if (!Fog)
02816                         goto ExitWithError;
02817 
02818                 if (!geFog_SetAttributes(Fog, &Fd->Origin, &Fd->Color, 1.0f, Fd->Brightness, Fd->Radius))
02819                         goto ExitWithError;
02820 
02821         }
02822 
02823         return GE_TRUE;
02824         
02825         //=== ERROR
02826         ExitWithError:
02827         {
02828                 if (Fog)
02829                         geWorld_RemoveFog(World, Fog);
02830 
02831                 return GE_FALSE;
02832         }
02833 }
02834 
02835 //================================================================================
02836 //      ***** SkyBox stuff ******
02837 //================================================================================
02838 
02839 #define SKYBOX_WIDTH    10000.0f
02840 #define SKYBOX_HEIGHT   10000.0f
02841 #define SKYBOX_DEPTH    10000.0f
02842 
02843 //========================================================================================
02844 //      BuildSkyBox
02845 //========================================================================================
02846 static geBoolean BuildSkyBox(World_SkyBox *SkyBox, const GFX_SkyData *SkyData)
02847 {
02848         geVec3d                 *Verts;
02849         int32                   i;
02850         geFloat                 TexWidth, TexHeight;
02851         geVec3d                 Zero;
02852 
02853         // Copy data over so it is more convenient
02854         SkyBox->Axis = SkyData->Axis;
02855         SkyBox->Dpm = SkyData->Dpm;
02856         SkyBox->DrawScale = SkyData->DrawScale;
02857 
02858         for (i=0; i<6; i++)
02859                 SkyBox->Textures[i] = SkyData->Textures[i];
02860 
02861         geVec3d_Set(&Zero, 0.0f, 0.0f, 0.0f);
02862         if (geVec3d_Compare(&SkyBox->Axis, &Zero, 0.05f))
02863                 geVec3d_Set(&SkyBox->Axis, 1.0f, 0.0f, 0.0f);
02864 
02865         // Build top
02866         Verts = SkyBox->Verts[0];
02867         
02868         Verts[0].X = -(SKYBOX_WIDTH/2); 
02869         Verts[0].Y =  (SKYBOX_HEIGHT/2); 
02870         Verts[0].Z =  (SKYBOX_DEPTH/2);
02871 
02872         Verts[1].X =  (SKYBOX_WIDTH/2); 
02873         Verts[1].Y =  (SKYBOX_HEIGHT/2);
02874         Verts[1].Z =  (SKYBOX_DEPTH/2);
02875 
02876         Verts[2].X =  (SKYBOX_WIDTH/2);
02877         Verts[2].Y =  (SKYBOX_HEIGHT/2);
02878         Verts[2].Z = -(SKYBOX_DEPTH/2);
02879 
02880         Verts[3].X = -(SKYBOX_WIDTH/2); 
02881         Verts[3].Y =  (SKYBOX_HEIGHT/2); 
02882         Verts[3].Z = -(SKYBOX_DEPTH/2);
02883 
02884         // Build Bottom
02885         Verts = SkyBox->Verts[1]; 
02886         Verts[0].X = -(SKYBOX_WIDTH/2); 
02887         Verts[0].Y = -(SKYBOX_HEIGHT/2); 
02888         Verts[0].Z = -(SKYBOX_DEPTH/2);
02889 
02890         Verts[1].X =  (SKYBOX_WIDTH/2);
02891         Verts[1].Y = -(SKYBOX_HEIGHT/2);
02892         Verts[1].Z = -(SKYBOX_DEPTH/2);
02893 
02894         Verts[2].X =  (SKYBOX_WIDTH/2);
02895         Verts[2].Y = -(SKYBOX_HEIGHT/2);
02896         Verts[2].Z =  (SKYBOX_DEPTH/2);
02897 
02898         Verts[3].X = -(SKYBOX_WIDTH/2);
02899         Verts[3].Y = -(SKYBOX_HEIGHT/2);
02900         Verts[3].Z =  (SKYBOX_DEPTH/2);
02901 
02902         // Build Left
02903         Verts = SkyBox->Verts[2];
02904         Verts[0].X = -(SKYBOX_WIDTH/2);
02905         Verts[0].Y =  (SKYBOX_HEIGHT/2);
02906         Verts[0].Z =  (SKYBOX_DEPTH/2);
02907 
02908         Verts[1].X = -(SKYBOX_WIDTH/2);
02909         Verts[1].Y =  (SKYBOX_HEIGHT/2);
02910         Verts[1].Z = -(SKYBOX_DEPTH/2);
02911 
02912         Verts[2].X = -(SKYBOX_WIDTH/2);
02913         Verts[2].Y = -(SKYBOX_HEIGHT/2);
02914         Verts[2].Z = -(SKYBOX_DEPTH/2);
02915 
02916         Verts[3].X = -(SKYBOX_WIDTH/2);
02917         Verts[3].Y = -(SKYBOX_HEIGHT/2);
02918         Verts[3].Z =  (SKYBOX_DEPTH/2);
02919 
02920         // Build Right
02921         Verts = SkyBox->Verts[3];
02922         Verts[0].X =  (SKYBOX_WIDTH/2);
02923         Verts[0].Y =  (SKYBOX_HEIGHT/2);
02924         Verts[0].Z = -(SKYBOX_DEPTH/2);
02925 
02926         Verts[1].X =  (SKYBOX_WIDTH/2);
02927         Verts[1].Y =  (SKYBOX_HEIGHT/2);
02928         Verts[1].Z =  (SKYBOX_DEPTH/2);
02929 
02930         Verts[2].X =  (SKYBOX_WIDTH/2);
02931         Verts[2].Y = -(SKYBOX_HEIGHT/2);
02932         Verts[2].Z =  (SKYBOX_DEPTH/2);
02933 
02934         Verts[3].X =  (SKYBOX_WIDTH/2);
02935         Verts[3].Y = -(SKYBOX_HEIGHT/2);
02936         Verts[3].Z = -(SKYBOX_DEPTH/2);
02937 
02938         // Build Front
02939         Verts = SkyBox->Verts[4];
02940         Verts[0].X = -(SKYBOX_WIDTH/2);
02941         Verts[0].Y =  (SKYBOX_HEIGHT/2);
02942         Verts[0].Z = -(SKYBOX_DEPTH/2);
02943 
02944         Verts[1].X =  (SKYBOX_WIDTH/2);
02945         Verts[1].Y =  (SKYBOX_HEIGHT/2);
02946         Verts[1].Z = -(SKYBOX_DEPTH/2);
02947 
02948         Verts[2].X =  (SKYBOX_WIDTH/2);
02949         Verts[2].Y = -(SKYBOX_HEIGHT/2);
02950         Verts[2].Z = -(SKYBOX_DEPTH/2);
02951 
02952         Verts[3].X = -(SKYBOX_WIDTH/2);
02953         Verts[3].Y = -(SKYBOX_HEIGHT/2);
02954         Verts[3].Z = -(SKYBOX_DEPTH/2);
02955 
02956         // Build back
02957         Verts = SkyBox->Verts[5];
02958         Verts[0].X =  (SKYBOX_WIDTH/2);
02959         Verts[0].Y =  (SKYBOX_HEIGHT/2);
02960         Verts[0].Z =  (SKYBOX_DEPTH/2);
02961 
02962         Verts[1].X = -(SKYBOX_WIDTH/2);
02963         Verts[1].Y =  (SKYBOX_HEIGHT/2);
02964         Verts[1].Z =  (SKYBOX_DEPTH/2);
02965 
02966         Verts[2].X = -(SKYBOX_WIDTH/2);
02967         Verts[2].Y = -(SKYBOX_HEIGHT/2);
02968         Verts[2].Z =  (SKYBOX_DEPTH/2);
02969 
02970         Verts[3].X =  (SKYBOX_WIDTH/2);
02971         Verts[3].Y = -(SKYBOX_HEIGHT/2);
02972         Verts[3].Z =  (SKYBOX_DEPTH/2);
02973 
02974         TexWidth = SkyBox->DrawScale;
02975         TexHeight = SkyBox->DrawScale;
02976 
02977         for (i=0; i<6; i++)
02978         {
02979                 Surf_TexVert    *TexVerts;
02980 
02981                 TexVerts = SkyBox->TexVerts[i];
02982 
02983                 TexVerts[0].u = 0.0f;
02984                 TexVerts[0].v = 0.0f;
02985 
02986                 TexVerts[1].u = TexWidth;
02987                 TexVerts[1].v = 0.0f;
02988 
02989                 TexVerts[2].u = TexWidth;
02990                 TexVerts[2].v = TexHeight;
02991 
02992                 TexVerts[3].u = 0.0f;
02993                 TexVerts[3].v = TexHeight;
02994         }
02995 
02996         return GE_TRUE;
02997 }
02998 
02999 //========================================================================================
03000 //      RenderSkyThroughFrustum
03001 //========================================================================================
03002 static void RenderSkyThroughFrustum(World_SkyBox *SkyBox, geWorld_SkyBoxTData *SkyTData, geCamera *Camera, Frustum_Info *Fi)
03003 {
03004         int32                   i, p;
03005         DRV_TLVertex    Clipped1[30];
03006         geVec3d                 *pDest1, *pDest2, Dest1[30], Dest2[30];
03007         Surf_TexVert    *pTex1, *pTex2, Tex1[30], Tex2[30];
03008         int32                   Length1, Length2;
03009         geBitmap                *pBitmap;
03010         geVec3d                 CameraPos = {0.0f, 0.0f, 0.0f};
03011         int32                   TexNum;
03012         GFX_Plane               *Planes;
03013         uint32                  SkyFlags;
03014         int nFoo;
03015 
03016         assert(SkyTData->NumTransformed >= 0);          // Now that we have a far clip plane, it is possible to have no sky...
03017 
03018         if (!SkyTData->NumTransformed)
03019                 return;
03020 
03021         SkyFlags = DRV_RENDER_FLUSH | DRV_RENDER_POLY_NO_FOG; // skybox fog
03022 
03023         if (SkyBox->DrawScale <= 1.0f)
03024                 SkyFlags |= DRV_RENDER_CLAMP_UV;
03025 
03026         Planes = Fi->Planes;
03027 
03028         for (i=0; i< SkyTData->NumTransformed; i++)
03029         {
03030                 geRDriver_THandle       *THandle;
03031 
03032                 // Get a pointer to the bitmap (texture)
03033                 // NOTE - The sky box uses textures from the bsp file, but node that they were
03034                 // created with RegisterMiscTexture with the driver.   The engine knew how to do this
03035                 // by looking at the texture flags when it uploaded them...
03036                 TexNum = SkyBox->Textures[SkyTData->OriginalFaces[i]];
03037 
03038                 if (TexNum < 0)
03039                         continue;
03040 
03041                 pBitmap = geWBitmap_Pool_GetBitmapByIndex(CBSP->WBitmapPool, TexNum);
03042 
03043                 assert(geWorld_HasBitmap(CWorld, pBitmap));
03044 
03045                 pDest1 = SkyTData->TransformedVerts[i];
03046                 pDest2 = Dest2;
03047                 pTex1 = SkyTData->TransformedTexVerts[i];
03048                 pTex2 = Tex2;
03049                 Length1 = SkyTData->NumTransformedVerts[i];
03050                                                 
03051 
03052                 // NumVerts is the number of clip planes from the sky poly...
03053 
03054 //      eaa3 01/30/2001 EVIL HACK
03055 //      ..for some reason, it is possible to get your skybox culled even if you
03056 //      ..don't want it to be.  Since I like my skybox to draw no matter what my
03057 //      ..far clip plane is, this little EVIL HACK makes sure the skybox doesn't
03058 //      ..fall prey to the far clip plane, if active.
03059 
03060     nFoo = Fi->NumPlanes;                       // EVIL HACK
03061 
03062           if(nFoo > 4)                                                  // EVIL HACK - 5 planes means far clip enabled
03063             nFoo = Fi->NumPlanes-1;                                                             // EVIL HACK - leave my skybox alone!
03064 
03065                 for (p=0; p< nFoo; p++)
03066                 {
03067                         if (!Frustum_ClipToPlaneUV(&Planes[p], pDest1, pDest2, pTex1, pTex2, Length1, &Length2))
03068                                 break;
03069 
03070                         if (pDest1 == Dest2)
03071                         {
03072                                 pDest1 = Dest1;
03073                                 pDest2 = Dest2;
03074                                 pTex1 = Tex1;
03075                                 pTex2 = Tex2;
03076                         }
03077                         else
03078                         {
03079                                 pDest1 = Dest2;
03080                                 pDest2 = Dest1;
03081                                 pTex1 = Tex2;
03082                                 pTex2 = Tex1;
03083                         }
03084                         Length1 = Length2;
03085                 }
03086 
03087                 if (p != nFoo)
03088                         continue;                                               // eaa3 01/30/2001 more EVIL HACK work
03089 
03090                 if (Length1 < 3)
03091                         continue;
03092 
03093                 // Project them to screen space
03094                 Frustum_Project(pDest1, pTex1, Clipped1, Length1, Camera);
03095 
03096                 for (p=0; p<Length1; p++)
03097                 {
03098                         Clipped1[p].r = 255.0f;
03099                         Clipped1[p].g = 255.0f;
03100                         Clipped1[p].b = 255.0f;
03101                 }
03102 
03103                 Clipped1[0].a = 255.0f;
03104 
03105                 THandle = geBitmap_GetTHandle(pBitmap);
03106                 assert(THandle);
03107 
03108         #ifdef SKY_BOX_USE_WORLD_POLY
03109                 {
03110                         DRV_TexInfo     TexInfo;
03111 
03112                         TexInfo.ShiftU = 0.0f;
03113                         TexInfo.ShiftV = 0.0f;
03114                         TexInfo.DrawScaleU = 1.0f;
03115                         TexInfo.DrawScaleV = 1.0f;
03116 
03117                         RDriver->RenderWorldPoly(Clipped1, Length1, THandle, &TexInfo, NULL, SkyFlags);
03118                 }
03119         #else
03120                 RDriver->RenderMiscTexturePoly(Clipped1, Length1, THandle, SkyFlags);
03121         #endif
03122 
03123         }
03124 
03125 }
03126 
03127 //=====================================================================================
03128 //      SetupSkyBoxFaceForScene
03129 //=====================================================================================
03130 static void SetupSkyBoxFaceForScene(World_SkyBox *SkyBox, int32 Face, const geXForm3d *XForm, Frustum_Info *Fi, geWorld_SkyBoxTData *SkyTData)
03131 {
03132         geVec3d                 Dest1[MAX_RENDERFACE_VERTS], Dest2[MAX_RENDERFACE_VERTS], *pDest1, *pDest2;
03133         Surf_TexVert    Tex1[MAX_RENDERFACE_VERTS], Tex2[MAX_RENDERFACE_VERTS];
03134         Surf_TexVert    *pTex1, *pTex2;
03135         int32                   Length1, Length2;
03136         int32                   p;
03137         GFX_Plane               *pFPlane;
03138         geFloat                 Width, Height;
03139         int32                   TexNum;
03140         GFX_Texture             *pTexture;
03141   int nFoo;
03142 
03143         TexNum = CWorld->CurrentBSP->BSPData.GFXSkyData.Textures[Face];
03144 
03145         if (TexNum < 0)         // No texture on sky face
03146                 return;
03147 
03148         pDest1 = SkyBox->Verts[Face];
03149         pDest2 = Dest2;
03150         pTex1 = SkyBox->TexVerts[Face];
03151         pTex2 = Tex2;
03152         Length1 = 4;
03153 
03154         pFPlane = Fi->Planes;
03155 
03156 //      eaa3 01/30/2001 EVIL HACK
03157 //      ..for some reason, it is possible to get your skybox culled even if you
03158 //      ..don't want it to be.  Since I like my skybox to draw no matter what my
03159 //      ..far clip plane is, this little EVIL HACK makes sure the skybox doesn't
03160 //      ..fall prey to the far clip plane, if active.
03161 
03162   nFoo = Fi->NumPlanes;                 // EVIL HACK
03163 
03164         if(nFoo > 4)                                                    // EVIL HACK - 5 planes means far clip enabled
03165           nFoo = Fi->NumPlanes-1;                                                               // EVIL HACK - leave my skybox alone!
03166 
03167         for (p=0; p< nFoo; p++, pFPlane++)
03168         {
03169                 if (!Frustum_ClipToPlaneUV(pFPlane, pDest1, pDest2, pTex1, pTex2, Length1, &Length2))
03170                         return;
03171 
03172                 if (pDest1 == Dest2)
03173                 {
03174                         pDest1 = Dest1;
03175                         pDest2 = Dest2;
03176                         pTex1 = Tex1;
03177                         pTex2 = Tex2;
03178                 }
03179                 else
03180                 {
03181                         pDest1 = Dest2;
03182                         pDest2 = Dest1;
03183                         pTex1 = Tex2;
03184                         pTex2 = Tex1;
03185                 }
03186                 Length1 = Length2;
03187         }
03188           
03189         if (Length1 < 3)
03190                 return;
03191 
03192         pDest2 = SkyTData->TransformedVerts[SkyTData->NumTransformed];
03193         pTex2 = SkyTData->TransformedTexVerts[SkyTData->NumTransformed];
03194         SkyTData->NumTransformedVerts[SkyTData->NumTransformed] = Length1;
03195         SkyTData->OriginalFaces[SkyTData->NumTransformed] = Face;
03196 
03197         pTexture = &CWorld->CurrentBSP->BSPData.GFXTextures[TexNum];
03198 
03199         Width = (geFloat)pTexture->Width;
03200         Height = (geFloat)pTexture->Height;
03201         
03202         //geXForm3d_RotateArray(CXForm, pDest1, pDest2, Length1);
03203         for (p=0; p<Length1; p++)
03204         {
03205                 geXForm3d_Rotate(XForm, pDest1, pDest2);
03206                 pDest1++;
03207                 pDest2++;
03208 
03209                 *pTex2 = *pTex1;
03210 
03211                 #ifdef SKY_BOX_USE_WORLD_POLY
03212                         pTex2->u *= Width;
03213                         pTex2->v *= Height;
03214                 #endif
03215 
03216                 pTex1++;
03217                 pTex2++;
03218         }
03219 
03220         SkyTData->NumTransformed++;             // Increase the number of sky polys transformed...
03221 }
03222 
03223 //=====================================================================================
03224 //      SetupSkyForScene
03225 //      Sets up sky for rendering through sky portals
03226 //=====================================================================================
03227 static void SetupSkyForScene(World_SkyBox *SkyBox, geCamera *Camera, Frustum_Info *Fi, geWorld_SkyBoxTData *SkyTData)
03228 {
03229         int32                   i;
03230         geXForm3d               XForm, OldXForm, QXForm;
03231         Frustum_Info    WorldSpaceFrustum;
03232         geQuaternion    Quat;
03233         
03234         // Reset the number of skypolys transformed...
03235         SkyTData->NumTransformed = 0;
03236 
03237         // Get the camera matrix
03238         XForm = *geCamera_GetWorldSpaceXForm(Camera);
03239 
03240         // Save it, so we can restore is when we are done
03241         OldXForm = XForm;
03242 
03243         // Rotate the camera's xform about the selected axis
03244         // First, build a quat that will do this
03245         geQuaternion_SetFromAxisAngle(&Quat, &SkyBox->Axis, -SkyBox->Angle);
03246 
03247         // Then convert the quat to a xform
03248         geQuaternion_ToMatrix(&Quat, &QXForm);
03249         
03250         geXForm3d_Multiply(&QXForm, &XForm, &XForm);
03251 
03252         // Put the XForm back into the camera
03253         geCamera_SetWorldSpaceXForm(Camera, &XForm);
03254 
03255         // Setup the View Frustum to look into the world
03256         Frustum_RotateToWorldSpace(Fi, Camera, &WorldSpaceFrustum);
03257 
03258         // NOTE - SetupSkyBoxFaceForScene only rotates the box, and does not translate...
03259         for (i=0; i<6; i++)
03260                 SetupSkyBoxFaceForScene(SkyBox, i, geCamera_GetCameraSpaceXForm(Camera), &WorldSpaceFrustum, SkyTData);
03261 
03262         // Restore the camera
03263         geCamera_SetWorldSpaceXForm(Camera, &OldXForm);
03264 }
03265 
03266 //================================================================================
03267 //      *** BitmapList stuff ***
03268 //================================================================================
03269 
03270 //================================================================================
03271 //      geWorld_BitmapListInit
03272 //      Initializes the world bitmaplist
03273 //================================================================================
03274 geBoolean geWorld_BitmapListInit(geWorld *World)
03275 {
03276         assert(World);
03277         assert(World->AttachedBitmaps == NULL);
03278 
03279         if (World->AttachedBitmaps == NULL )
03280         {
03281                 World->AttachedBitmaps = BitmapList_Create();
03282 
03283                 if (!World->AttachedBitmaps )
03284                 {
03285                         geErrorLog_AddString(-1, "geWorld_BitmapListInit:  BitmapList_Create failed.", NULL);
03286                         return GE_FALSE;
03287                 }
03288         }
03289 
03290         // Only add bitmaps if the list is not NULL (could be an empty world with no textures yet)
03291         if (World->CurrentBSP->WBitmapPool)
03292         {
03293                 int32           i, Count;
03294                 Count = geWBitmap_Pool_GetWBitmapCount(World->CurrentBSP->WBitmapPool);
03295 
03296                 for (i=0; i<Count; i++)
03297                 {
03298                         geBitmap                *pBitmap;
03299                         geWBitmap               *pWBitmap;
03300                         geBitmap_Info   Info;
03301                         uint32                  Flags;
03302 
03303                         pWBitmap = geWBitmap_Pool_GetWBitmapByIndex(World->CurrentBSP->WBitmapPool, i);
03304                         assert(pWBitmap);
03305 
03306                         pBitmap = geWBitmap_GetBitmap(pWBitmap);
03307                         assert(pBitmap);
03308 
03309                         Flags = geWBitmap_GetFlags(pWBitmap);
03310 
03311                         if (!geBitmap_GetInfo(pBitmap, &Info, NULL))
03312                         {
03313                                 geErrorLog_AddString(-1, "geWorld_BitmapListInit:  geBitmap_GetInfo failed.", NULL);
03314                                 return GE_FALSE;
03315                         }
03316                         
03317                         if (!geWorld_AddBitmap(World, pBitmap))
03318                         {
03319                                 geErrorLog_AddString(-1, "geWorld_BitmapListInit:  geWorld_AddBitmap failed.", NULL);
03320                                 return GE_FALSE;
03321                         }
03322 
03323                         World->Changed = GE_TRUE;
03324                 }
03325         }
03326 
03327         return GE_TRUE;
03328 }
03329 
03330 //================================================================================
03331 //      geWorld_BitmapListShutdown
03332 //================================================================================
03333 geBoolean geWorld_BitmapListShutdown(geWorld *World)
03334 {
03335         assert(World);
03336 
03337         if (World->AttachedBitmaps )
03338         {
03339                 //BitmapList_DetachAll(World->AttachedBitmaps);
03340                 BitmapList_Destroy(World->AttachedBitmaps);
03341                 World->AttachedBitmaps = NULL;
03342         }
03343 
03344         return GE_TRUE;
03345 }
03346 
03347 //================================================================================
03348 //      geWorld_AddBitmap
03349 //================================================================================
03350 GENESISAPI geBoolean geWorld_AddBitmap(geWorld *World, geBitmap *Bitmap)
03351 {
03352         assert(World);
03353         assert(Bitmap);
03354         assert(World->AttachedBitmaps);
03355 
03356         if (!World->AttachedBitmaps)
03357         {
03358                 geErrorLog_AddString(-1, "geWorld_AddBitmap:  AttachedBitmapList is NULL.", NULL);
03359                 return GE_FALSE;
03360         }
03361 
03362         geBitmap_SetDriverFlags(Bitmap, RDRIVER_PF_3D | RDRIVER_PF_COMBINE_LIGHTMAP);
03363 
03364         // Add bitmap to the list of bitmaps attached to the engine
03365         if ( BitmapList_Add(World->AttachedBitmaps, (void*)Bitmap) )
03366         {
03367                 World->Changed = GE_TRUE;
03368                 
03369                 #ifdef DO_ADDREMOVE_MESSAGES    
03370                 {
03371                 char str[100];
03372                         sprintf(str,"World_AddBitmap : %08X : new\n",Bitmap);
03373                         OutputDebugString(str);
03374                 }
03375                 #endif
03376         }
03377         else
03378         {
03379                 #ifdef DO_ADDREMOVE_MESSAGES    
03380                 {
03381                 char str[100];
03382                         sprintf(str,"World_AddBitmap : %08X : old\n",Bitmap);
03383                         OutputDebugString(str);
03384                 }
03385                 #endif
03386         }
03387 
03388         return GE_TRUE;
03389 }
03390 
03391 //================================================================================
03392 //      geWorld_RemoveBitmap
03393 //================================================================================
03394 GENESISAPI geBoolean geWorld_RemoveBitmap(geWorld *World,geBitmap *Bitmap)
03395 {
03396 
03397         assert(World);
03398         assert(Bitmap);
03399         assert(World->AttachedBitmaps);
03400 
03401         if (!World->AttachedBitmaps)
03402                 return GE_FALSE;
03403 
03404         if ( BitmapList_Remove(World->AttachedBitmaps, Bitmap) )
03405         {
03406                 World->Changed = GE_TRUE;
03407                 
03408                 #ifdef DO_ADDREMOVE_MESSAGES    
03409                 {
03410                 char str[100];
03411                         sprintf(str,"World_RemoveBitmap : %08X : removed\n",Bitmap);
03412                         OutputDebugString(str);
03413                 }
03414                 #endif
03415         }
03416         else
03417         {
03418                 #ifdef DO_ADDREMOVE_MESSAGES    
03419                 {
03420                 char str[100];
03421                         sprintf(str,"World_RemoveBitmap : %08X : left\n",Bitmap);
03422                         OutputDebugString(str);
03423                 }
03424                 #endif
03425         }
03426                 
03427 
03428         return GE_TRUE;
03429 }
03430 
03431 //================================================================================
03432 //      geWorld_GetBitmapByName
03433 //================================================================================
03434 GENESISAPI geBitmap *geWorld_GetBitmapByName(geWorld *World, const char *BitmapName)
03435 {
03436         if (!World->CurrentBSP)
03437                 return NULL;
03438 
03439         assert(World->CurrentBSP->WBitmapPool);
03440 
03441         return geWBitmap_Pool_GetBitmapByName(World->CurrentBSP->WBitmapPool, BitmapName);
03442 }
03443 
03444 //================================================================================
03445 //      geWorld_AttachAll
03446 //================================================================================
03447 geBoolean geWorld_AttachAll(geWorld *World, DRV_Driver *Driver, geFloat Gamma)
03448 {
03449         assert(World);
03450         assert(World->AttachedBitmaps);
03451         assert(Driver);
03452 
03453         if (!BitmapList_AttachAll(World->AttachedBitmaps, Driver, Gamma))
03454         {
03455                 geErrorLog_AddString(-1, "geWorld_AttachAll:  BitmapList_AttachAll failed.", NULL);
03456                 return GE_FALSE;
03457         }
03458         
03459         return GE_TRUE;
03460 }
03461 
03462 //================================================================================
03463 //      geWorld_DetachAll
03464 //================================================================================
03465 geBoolean geWorld_DetachAll(geWorld *World)
03466 {
03467         assert(World);
03468         assert(World->AttachedBitmaps);
03469 
03470         if (!BitmapList_DetachAll(World->AttachedBitmaps))
03471         {
03472                 geErrorLog_AddString(-1, "geWorld_DetachAll:  BitmapList_DetachAll failed.", NULL);
03473                 return GE_FALSE;
03474         }
03475         return GE_TRUE;
03476 }
03477 
03478 //================================================================================
03479 //      geWorld_HasBitmap
03480 //================================================================================
03481 GENESISAPI geBoolean geWorld_HasBitmap(const geWorld *World, const geBitmap *Bitmap)
03482 {
03483         assert(World);
03484         assert(World->AttachedBitmaps);
03485 
03486         return BitmapList_Has((BitmapList*)World->AttachedBitmaps, (geBitmap*)Bitmap);
03487 }
03488 //================================================================================
03489 //================================================================================
03490 GENESISAPI geBoolean geWorld_BitmapIsVisible(geWorld *World, const geBitmap *Bitmap)
03491 {
03492         geWBitmap       *pWBitmap;
03493 
03494         pWBitmap = geWBitmap_Pool_GetWBitmapByBitmap(World->CurrentBSP->WBitmapPool, Bitmap);
03495 
03496         if (!pWBitmap)                  // Not in the list!  Should this be an error?????
03497                 return GE_FALSE;
03498 
03499         if (geWBitmap_GetVisFrame(pWBitmap) == World->CurFrameDynamic)
03500                 return GE_TRUE;
03501 
03502         return GE_FALSE;
03503 }
03504 
03505 

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