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

Vis.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  Vis.c                                                                               */
00003 /*                                                                                      */
00004 /*  Author: John Pollard                                                                */
00005 /*  Description: Code to vis the world from a given pov                                 */
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 
00024 #include "BaseType.h"
00025 #include "World.h"
00026 #include "Plane.h"
00027 #include "Vec3d.h"
00028 #include "Ram.h"
00029 #include "Surface.h"
00030 #include "Trace.h"
00031 #include "Camera.h"
00032 #include "Frustum.h"
00033 #include "System.h"
00034 
00035 #include "Fog.h"
00036 
00037 #ifdef _TSC
00038 #include "tsc.h"
00039 #endif
00040 
00041 //#define SUPER_VIS1
00042 
00043 static void MarkVisibleParents(geWorld *World, int32 Leaf);
00044 static void FindParents(World_BSP *Bsp);
00045 static void VisFog(geEngine *Engine, geWorld *World, const geCamera *Camera, Frustum_Info *Fi, int32 Area);
00046 
00047 //=====================================================================================
00048 //      Vis_WorldInit
00049 //=====================================================================================
00050 geBoolean Vis_WorldInit(geWorld *World)
00051 {
00052         World_BSP       *BSP;
00053         int32           i;
00054         static int32 StartupParams[]={0x696C6345,0x21657370};
00055         
00056         assert(World  != NULL);
00057 
00058         BSP = World->CurrentBSP;
00059 
00060         assert(BSP != NULL);
00061 
00062         if (!BSP)
00063                 return GE_FALSE;
00064 
00065         BSP->NodeVisFrame = GE_RAM_ALLOCATE_ARRAY(int32, BSP->BSPData.NumGFXNodes);
00066 
00067         if (!BSP->NodeVisFrame)
00068                 goto Error;
00069 
00070         BSP->ClusterVisFrame = GE_RAM_ALLOCATE_ARRAY(int32, BSP->BSPData.NumGFXClusters);
00071 
00072         if (!BSP->ClusterVisFrame)
00073                 goto Error;
00074 
00075         BSP->AreaVisFrame = GE_RAM_ALLOCATE_ARRAY(int32, BSP->BSPData.NumGFXAreas);
00076 
00077         if (!BSP->AreaVisFrame)
00078                 goto Error;
00079 
00080         BSP->NodeParents = GE_RAM_ALLOCATE_ARRAY(int32, BSP->BSPData.NumGFXNodes);
00081 
00082         if (!BSP->NodeParents)
00083                 goto Error;
00084 
00085         memset(BSP->NodeVisFrame, 0, sizeof(int32)*BSP->BSPData.NumGFXNodes);
00086         memset(BSP->ClusterVisFrame, 0, sizeof(int32)*BSP->BSPData.NumGFXClusters);
00087         memset(BSP->AreaVisFrame, 0, sizeof(int32)*BSP->BSPData.NumGFXAreas);
00088 
00089         memset(BSP->NodeParents, 0, sizeof(int32)*BSP->BSPData.NumGFXNodes);
00090         
00091         FindParents(World->CurrentBSP);
00092 
00093         // Set the identity on the AreaMatrix
00094         for (i=0; i<256; i++)
00095                 World->CurrentBSP->AreaConnections[i][i] = 1;
00096 
00097         return GE_TRUE;
00098 
00099         Error:
00100                 if (BSP->NodeVisFrame)
00101                         geRam_Free(BSP->NodeVisFrame);
00102                 if (BSP->ClusterVisFrame)
00103                         geRam_Free(BSP->ClusterVisFrame);
00104                 if (BSP->AreaVisFrame)
00105                         geRam_Free(BSP->AreaVisFrame);
00106                 if (BSP->NodeParents)
00107                         geRam_Free(BSP->NodeParents);
00108 
00109                 BSP->NodeVisFrame = NULL;
00110                 BSP->ClusterVisFrame = NULL;
00111                 BSP->AreaVisFrame = NULL;
00112                 BSP->NodeParents = NULL;
00113                 return GE_FALSE;
00114 }
00115 
00116 //=====================================================================================
00117 //      Vis_WorldShutdown
00118 //=====================================================================================
00119 void Vis_WorldShutdown(geWorld *World)
00120 {
00121         World_BSP       *BSP;
00122         
00123         assert(World  != NULL);
00124 
00125         if (!World->CurrentBSP)
00126                 return;
00127 
00128         BSP = World->CurrentBSP;
00129         
00130         if (BSP->NodeVisFrame)
00131                 geRam_Free(BSP->NodeVisFrame);
00132         if (BSP->ClusterVisFrame)
00133                 geRam_Free(BSP->ClusterVisFrame);
00134         if (BSP->AreaVisFrame)
00135                 geRam_Free(BSP->AreaVisFrame);
00136         if (BSP->NodeParents)
00137                 geRam_Free(BSP->NodeParents);
00138 
00139         BSP->NodeVisFrame = NULL;
00140         BSP->ClusterVisFrame = NULL;
00141         BSP->AreaVisFrame = NULL;
00142         BSP->NodeParents = NULL;
00143 }
00144 
00145 //=====================================================================================
00146 //      ModelVisible
00147 //=====================================================================================
00148 geBoolean ModelVisible(geWorld *World, geWorld_Model *Model)
00149 {
00150         return Trace_BBoxInVisibleLeaf(World, &Model->TMins, &Model->TMaxs);
00151 }
00152 
00153 //=====================================================================================
00154 //      Vis_FloodAreas_r
00155 //=====================================================================================
00156 void Vis_FloodAreas_r(geWorld *World, int32 Area)
00157 {
00158         GBSP_BSPData    *BSP;
00159         GFX_Area                *a;
00160         GFX_AreaPortal  *p;
00161         int32                   i;
00162 
00163         if (World->CurrentBSP->AreaVisFrame[Area] == World->CurFrameStatic)
00164                 return;         // Area already set
00165         
00166         World->CurrentBSP->AreaVisFrame[Area] = World->CurFrameStatic;          // Mark this area visible
00167         
00168         BSP = &World->CurrentBSP->BSPData;
00169 
00170         a = &BSP->GFXAreas[Area];
00171 
00172         p = &BSP->GFXAreaPortals[a->FirstAreaPortal];
00173 
00174         for (i=0; i< a->NumAreaPortals; i++, p++)
00175         {
00176                 geWorld_Model   *Model;
00177 
00178                 Model = &World->CurrentBSP->Models[p->ModelNum];
00179 
00180                 if (Model->Open)
00181                         Vis_FloodAreas_r(World, p->Area);
00182         }
00183 }
00184 
00185 //=====================================================================================
00186 //      Vis_VisWorld
00187 //=====================================================================================
00188 geBoolean Vis_VisWorld(geEngine *Engine, geWorld *World, const geCamera *Camera, Frustum_Info *Fi)
00189 {
00190         uint8                   *VisData;
00191         int32                   k, i, Area;
00192         GFX_Node                *GFXNodes;
00193         GFX_Leaf                *GFXLeafs;
00194         Surf_SurfInfo   *SurfInfo;
00195         uint8                   *GFXVisData;
00196         int32                   Leaf, Cluster;
00197         GFX_Model               *GFXModels;
00198         int32                   *GFXLeafFaces;
00199         GFX_Cluster             *GFXClusters;
00200         GBSP_BSPData    *BSPData;
00201         geWorld_Model   *Models;
00202         const geVec3d   *Pos;
00203         GFX_Leaf                *pLeaf;
00204 
00205 #ifdef _TSC
00206         pushTSC();
00207 #endif
00208 
00209         Pos = geCamera_GetVisPov(Camera);
00210 
00211         BSPData = &World->CurrentBSP->BSPData;
00212 
00213         GFXNodes = BSPData->GFXNodes;
00214         GFXLeafs = BSPData->GFXLeafs;
00215         GFXClusters = BSPData->GFXClusters;
00216         GFXVisData = BSPData->GFXVisData;
00217         GFXModels = BSPData->GFXModels;
00218         GFXLeafFaces = BSPData->GFXLeafFaces;
00219 
00220         SurfInfo = World->CurrentBSP->SurfInfo;
00221 
00222         Leaf = Plane_FindLeaf(World, GFXModels[0].RootNode[0], Pos);
00223         Area = GFXLeafs[Leaf].Area;
00224 
00225         // Check to see if we cen get rid of most of the work load by seeing if the leaf has not changed...
00226         if (World->CurrentLeaf == Leaf && !World->ForceVis)
00227                 goto LeafDidNotChange;
00228 
00229         World->ForceVis = GE_FALSE;                     // Reset force vis flag
00230         
00231         World->CurrentLeaf = Leaf;
00232 
00233         World->CurFrameStatic++;                        // Make all old vis info obsolete
00234 
00235         Cluster = GFXLeafs[Leaf].Cluster;
00236 
00237         if (Cluster == -1 || GFXClusters[Cluster].VisOfs == -1)
00238         {
00239                 World->VisInfo = GE_FALSE;
00240                 return GE_TRUE;
00241         }
00242 
00243         if (Area)
00244                 Vis_FloodAreas_r(World, Area);
00245 
00246         World->VisInfo = GE_TRUE;
00247 
00248         VisData = &GFXVisData[GFXClusters[Cluster].VisOfs];
00249 
00250         // Mark all visible clusters
00251         for (i=0; i<GFXModels[0].NumClusters; i++)
00252         {
00253                 if (VisData[i>>3] & (1<<(i&7)) )
00254                         World->CurrentBSP->ClusterVisFrame[i] = World->CurFrameStatic;
00255         }
00256 
00257         pLeaf = &GFXLeafs[GFXModels[0].FirstLeaf];
00258 
00259         // Go through and find all visible leafs based on the visible clusters the leafs are in
00260         for (i=0; i< GFXModels[0].NumLeafs; i++, pLeaf++)
00261         {
00262                 int32   *pFace;
00263 
00264                 Cluster = pLeaf->Cluster;
00265 
00266                 if (Cluster == -1)              // No cluster info for this leaf (must be solid)
00267                         continue;
00268 
00269                 // If the cluster is not visible, then the leaf is not visible
00270                 if (World->CurrentBSP->ClusterVisFrame[Cluster] != World->CurFrameStatic)
00271                         continue;
00272                 
00273                 // If the area is not visible, then the leaf is not visible
00274                 if (World->CurrentBSP->AreaVisFrame[pLeaf->Area] != World->CurFrameStatic)
00275                         continue;
00276 
00277                 // Mark all visible nodes by bubbling up the tree from the leaf
00278                 MarkVisibleParents(World, i);
00279 
00280                 // Mark the leafs vis frame to worlds current frame
00281                 World->CurrentBSP->LeafData[i].VisFrame = World->CurFrameStatic;
00282                         
00283                 pFace = &GFXLeafFaces[pLeaf->FirstFace];
00284 
00285                 // Go ahead and vis surfaces here...
00286                 for (k=0; k< pLeaf->NumFaces; k++)
00287                 {
00288                         // Update each surface infos visframe thats touches each visible leaf
00289                         SurfInfo[*pFace++].VisFrame = World->CurFrameStatic;
00290                 }
00291         }
00292 
00293         LeafDidNotChange:
00294 
00295         // The world is always visible as a model
00296         World->CurrentBSP->Models[0].VisFrame = World->CurFrameDynamic;
00297 
00298         Models = &World->CurrentBSP->Models[1];
00299         // Do models, skipping world models (it's always visible)
00300         for (i=1; i< BSPData->NumGFXModels; i++, Models++)
00301         {
00302         #if 0
00303                 int32           Cluster;
00304 
00305                 // First, lets cheat, and see if the center is in a valid location to test for vis
00306                 Leaf = Plane_FindLeaf(World, GFXModels[0].RootNode[0], &Models->Pivot);
00307 
00308                 Cluster = GFXLeafs[Leaf].Cluster;
00309 
00310                 if (Cluster >= 0 && GFXClusters[Cluster].VisOfs >= 0)           // If there is vis data for this leaf
00311                 {
00312                         if (World->CurrentBSP->LeafData[Leaf].VisFrame == World->CurFrameStatic)
00313                                 Models->VisFrame = World->CurFrameDynamic;
00314                         else
00315                         {
00316                                 GFX_Model       *pModel;
00317 
00318                                 pModel = &BSPData->GFXModels[i];
00319 
00320                                 if (pModel->Areas[0] == Area || pModel->Areas[1] == Area && 
00321                                         World->CurrentBSP->ClusterVisFrame[Cluster] == World->CurFrameStatic)
00322                                         Models->VisFrame = World->CurFrameDynamic;
00323                         }
00324                 }
00325                 else if (ModelVisible(World, Models))
00326                         Models->VisFrame = World->CurFrameDynamic;
00327         #else
00328                 
00329                 if (ModelVisible(World, Models))
00330                         Models->VisFrame = World->CurFrameDynamic;
00331                 
00332         #endif
00333                 
00334                 Models->ChangedFlags &= ~MODEL_CHANGED_XFORM;
00335         }
00336         
00337         VisFog(Engine, World, Camera, Fi, Area);
00338 
00339 #ifdef _TSC
00340         showPopTSC("Vis_VisWorld");
00341 #endif
00342         
00343         return GE_TRUE;
00344 }
00345 
00346 //=====================================================================================
00347 //      Vis_MarkWaterFaces
00348 //=====================================================================================
00349 geBoolean Vis_MarkWaterFaces(World_BSP *WBSP)
00350 {
00351         GFX_Leaf                *GFXLeafs;
00352         int32                   i, f, FNum;
00353         int32                   NumLeafs, Contents;
00354         Surf_SurfInfo   *SurfInfo;
00355         S32                             *GFXLeafFaces;
00356 
00357         assert(WBSP != NULL);
00358         
00359         GFXLeafs = WBSP->BSPData.GFXLeafs;
00360         GFXLeafFaces = WBSP->BSPData.GFXLeafFaces;
00361 
00362         NumLeafs = WBSP->BSPData.GFXModels[0].NumLeafs;
00363         
00364         SurfInfo = WBSP->SurfInfo;
00365 
00366         assert(SurfInfo != NULL);
00367 
00368         for (i = 0; i< NumLeafs; i++)
00369         {
00370                 Contents = GFXLeafs[i].Contents;
00371 
00372                 if (!(Contents & GE_CONTENTS_WAVY))
00373                         continue;
00374 
00375                 for (f=0; f< GFXLeafs[i].NumFaces; f++)
00376                 {
00377                         FNum = GFXLeafFaces[GFXLeafs[i].FirstFace + f];
00378 
00379                         // Disable for now, not working quite right...
00380                         // There is a problem with the leafs...
00381                         SurfInfo[FNum].Flags |= SURFINFO_WAVY;
00382                 }
00383         }
00384 
00385         return GE_TRUE;
00386 }
00387 
00388 static GFX_Node         *GFXNodes;
00389 static int32            *NodeParents;
00390 static geWorld_Leaf     *LeafData;
00391 
00392 //=====================================================================================
00393 // FindParents_r
00394 //=====================================================================================
00395 static void FindParents_r(int32 Node, int32 Parent)
00396 {
00397         if (Node < 0)           // At a leaf, mark leaf parent and return
00398         {
00399                 LeafData[-(Node+1)].Parent = Parent;
00400                 return;
00401         }
00402 
00403         // At a node, mark node parent, and keep going till hitting a leaf
00404         NodeParents[Node] = Parent;
00405 
00406         // Go down front and back markinf parents on the way down...
00407         FindParents_r(GFXNodes[Node].Children[0], Node);
00408         FindParents_r(GFXNodes[Node].Children[1], Node);
00409 }
00410 
00411 //=====================================================================================
00412 //      Vis_FindParents
00413 //=====================================================================================
00414 static void FindParents(World_BSP *Bsp)
00415 {
00416         assert(Bsp != NULL);
00417         
00418         // Assign some static globals so they don't flood the stack...
00419         GFXNodes = Bsp->BSPData.GFXNodes;
00420         LeafData = Bsp->LeafData;
00421         NodeParents = Bsp->NodeParents;
00422 
00423         FindParents_r(Bsp->BSPData.GFXModels[0].RootNode[0], -1);
00424 }
00425 
00426 //=====================================================================================
00427 //      MarkVisibleParents
00428 //=====================================================================================
00429 static void MarkVisibleParents(geWorld *World, int32 Leaf)
00430 {
00431         int32           Node;
00432         World_BSP       *Bsp;
00433 
00434         assert(Leaf >= 0);
00435         assert(Leaf < World->CurrentBSP->BSPData.NumGFXLeafs);
00436 
00437         Bsp = World->CurrentBSP;
00438 
00439         // Find the leafs parent
00440         Node = Bsp->LeafData[Leaf].Parent;
00441 
00442         // Bubble up the tree from the current node, marking them as visible
00443         while (Node >= 0)
00444         {
00445                 Bsp->NodeVisFrame[Node] = World->CurFrameStatic;
00446                 Node = Bsp->NodeParents[Node];
00447         }
00448 }
00449 
00450 // FIXME:  Put the fog in Fog.c
00451 //=====================================================================================
00452 //      VisFog
00453 //=====================================================================================
00454 static void VisFog(geEngine *Engine, geWorld *World, const geCamera *Camera, Frustum_Info *Fi, int32 Area)
00455 {
00456         GBSP_BSPData    *BSPData;
00457         GFX_Leaf                *GFXLeafs;
00458         geFog                   *Fog;
00459         World_BSP               *CBSP;
00460         Frustum_Info    WorldSpaceFrustum;
00461         //geVec3d                       *Pos;
00462 
00463         assert(World);
00464         assert(Camera);
00465         assert(Fi);
00466 
00467         World->NumVisibleFog = 0;
00468 
00469         if (!World->FogList)
00470                 return;                         // Don't waste time
00471 
00472         //return;
00473 
00474         // Make the frustum go to world space
00475         Frustum_TransformToWorldSpace(Fi, Camera, &WorldSpaceFrustum);
00476 
00477         CBSP = World->CurrentBSP;
00478         
00479         BSPData = &CBSP->BSPData;
00480 
00481         GFXLeafs = BSPData->GFXLeafs;
00482         
00483         for (Fog = World->FogList; Fog; Fog = Fog->Next)
00484         {
00485                 geWorld_FogData *FogData;
00486 
00487                 if (World->NumVisibleFog >= MAX_VISIBLE_FOG)
00488                         return;         // Oh well...
00489                 
00490                 FogData = (geWorld_FogData*)geFog_GetUserData(Fog);
00491 
00492                 if (CBSP->LeafData[FogData->Leaf].VisFrame != World->CurFrameStatic)
00493                         continue;               // might not be visible
00494 
00495                 if (Area != GFXLeafs[FogData->Leaf].Area)
00496                         continue;               // Fog only effects it's own area
00497 
00498                 // If not in the view frustum, then tottaly ignore...
00499                 if (!Frustum_PointInFrustum(&WorldSpaceFrustum, &Fog->Pos, Fog->VolumeRadius-1.0f))
00500                         continue;
00501                 
00502                 FogData->VisFrame = World->CurFrameDynamic;
00503 
00504                 // Add it to the list
00505                 World->VisibleFog[World->NumVisibleFog++] = Fog;
00506                 
00507                 // For debugging...
00508                 Engine->DebugInfo.NumFog++;
00509         }
00510 }

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