This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/wwphys/pscene_saveload.cpp

729 lines
20 KiB
C++
Raw Permalink Normal View History

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/***********************************************************************************************
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
***********************************************************************************************
* *
* Project Name : WWPhys *
* *
* $Archive:: /Commando/Code/wwphys/pscene_saveload.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Bhayes $*
* *
* $Modtime:: 1/07/03 2:22p $*
* *
* $Revision:: 22 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "pscene.h"
#include "chunkio.h"
#include "staticaabtreecull.h"
#include "dynamicaabtreecull.h"
#include "physgridcull.h"
#include "staticphys.h"
#include "staticanimphys.h"
#include "lightcull.h"
#include "light.h"
#include "persistfactory.h"
#include "wwmemlog.h"
/*
** This module contains the save-load related methods of PhysicsSceneClass.
*/
/*
** Chunk-ID's for PhysicsSceneClass
**
** LOAD-SAVE NOTES:
** The data in the physics scene will be broken into two different files, the LSD (Level Static Data)
** file and the LDD (Level Dynamic Data) file. The primary reason for this is simply so that
** save-games can simply be a new export of the LDD file and not contain the data which is completely
** static throughout the run of the level.
**
*/
enum
{
// Chunk ID's used by the physics scene when saving the 'Static Data' (PhysStaticDataSaveSystem)
PSCENE_SD_CHUNK_STATIC_OBJECT_AABTREE = 0x00004500,
PSCENE_SD_CHUNK_STATIC_LIGHT_AABTREE = 0x00004501,
PSCENE_SD_CHUNK_DYNAMIC_OBJECT_GRID = 0x00004600, // OBSOLETE!!!
PSCENE_SD_CHUNK_DYNAMIC_OBJECT_VIS_AABTREE = 0x00004601,
PSCENE_SD_CHUNK_VISIBILITY_DATA = 0x00004700,
PSCENE_SD_CHUNK_SUNLIGHT = 0x00004800,
PSCENE_SD_CHUNK_SCENECLASS = 0x00004810,
PSCENE_SD_CHUNK_VARIABLES = 0x00004820,
PSCENE_SD_VARIABLE_AMBIENT = 0x00,
// Chunk ID's used by the physics scene when saving the 'Static Objects' (PhysStaticObjectsSaveSystem)
PSCENE_SO_CHUNK_STATIC_OBJECTS = 0x00770100,
PSCENE_SO_CHUNK_STATIC_OBJECT,
PSCENE_SO_CHUNK_STATIC_OBJECT_AABLINK,
PSCENE_SO_CHUNK_STATIC_LIGHTS = 0x00770200,
PSCENE_SO_CHUNK_STATIC_LIGHT,
PSCENE_SO_CHUNK_STATIC_LIGHT_AABLINK,
// Chunk ID's used by the physics scene when saving the dynamic data and objects (PhysDynamicDataSaveSystem)
XXX_PSCENE_DD_CHUNK_SCENECLASS = 0x00890000,
PSCENE_DD_CHUNK_VARIABLES = 0x00890001,
PSCENE_DD_CHUNK_COLLISION_FLAGS = 0x00890002, // OBSOLETE!!!
PSCENE_DD_CHUNK_DYNAMIC_OBJECTS = 0x00890100,
PSCENE_DD_CHUNK_DYNAMIC_OBJECT,
PSCENE_DD_CHUNK_DYNAMIC_OBJECT_GRIDLINK,
// Chunk ID's used to save the states of static objects
PSCENE_DD_CHUNK_STATIC_OBJECT_STATES = 0x00890200,
PSCENE_DD_CHUNK_STATIC_OBJECT_STATE,
PSCENE_DD_CHUNK_STATIC_OBJECT_ID,
PSCENE_DD_CHUNK_STATIC_OLD_PTR,
// Micro Chunk ID's used by dynamic data variables
PSCENE_DD_VARIABLE_DYNAMICPOLYBUDGET = 0x00,
PSCENE_DD_VARIABLE_STATICPOLYBUDGET = 0x01,
};
/*
** Structure for saving the sun settings
*/
struct IOSunLightStruct
{
uint32 Enabled;
float32 Yaw;
float32 Pitch;
float32 Intensity;
IOVector3Struct Color;
};
void PhysicsSceneClass::Export_Vis_Data(ChunkSaveClass & csave)
{
VisTableManager.Save(csave);
}
void PhysicsSceneClass::Import_Vis_Data(ChunkLoadClass & cload)
{
Internal_Vis_Reset();
VisTableManager.Load(cload);
}
void PhysicsSceneClass::Save_Level_Static_Data(ChunkSaveClass & csave)
{
/*
** If the visibility system has been invalidated, reset it so that
** we dont save garbage data!
*/
Internal_Vis_Reset();
/*
** Things to save here:
** - Parent class settings (SceneClass -> fog color, depth ranges, polyrender mode, etc)
** - StaticCullingSystem structure (but not the objects in it)
** - DynamicCullingSystem structure (not objects)
** - LightCullingSystem structure (not objects)
** - Visibility Tables
** - Sunlight settings
*/
csave.Begin_Chunk(PSCENE_SD_CHUNK_SCENECLASS);
SceneClass::Save(csave);
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_STATIC_OBJECT_AABTREE);
StaticCullingSystem->Save_Static_Data(csave);
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_STATIC_LIGHT_AABTREE);
StaticLightingSystem->Save_Static_Data(csave);
csave.End_Chunk();
// csave.Begin_Chunk(PSCENE_SD_CHUNK_DYNAMIC_OBJECT_GRID);
// DynamicCullingSystem->Save_Static_Data(csave);
// csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_DYNAMIC_OBJECT_VIS_AABTREE);
DynamicObjVisSystem->Save_Static_Data(csave);
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_VISIBILITY_DATA);
VisTableManager.Save(csave);
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_SUNLIGHT);
Save_Sun_Light(csave);
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SD_CHUNK_VARIABLES);
WRITE_MICRO_CHUNK(csave,PSCENE_SD_VARIABLE_AMBIENT,SceneAmbientLight);
csave.End_Chunk();
}
void PhysicsSceneClass::Load_Level_Static_Data(ChunkLoadClass & cload)
{
WWMEMLOG(MEM_PHYSICSDATA);
VisResetNeeded = false;
LastValidVisId = -1;
/*
** Things to load here:
** - StaticCullingSystem structure (but not the objects in it)
** - LightCullingSystem structure (not objects)
** - DynamicCullingSystem structure (not objects)
** - Visibility Tables
*/
VisTableManager.Reset();
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID()) {
case PSCENE_SD_CHUNK_SCENECLASS:
SceneClass::Load(cload);
break;
case PSCENE_SD_CHUNK_STATIC_OBJECT_AABTREE:
StaticCullingSystem->Load_Static_Data(cload);
break;
case PSCENE_SD_CHUNK_STATIC_LIGHT_AABTREE:
StaticLightingSystem->Load_Static_Data(cload);
break;
// case PSCENE_SD_CHUNK_DYNAMIC_OBJECT_GRID:
// DynamicCullingSystem->Load(cload);
// break;
case PSCENE_SD_CHUNK_DYNAMIC_OBJECT_VIS_AABTREE:
DynamicObjVisSystem->Load_Static_Data(cload);
break;
case PSCENE_SD_CHUNK_VISIBILITY_DATA:
VisTableManager.Load(cload);
break;
case PSCENE_SD_CHUNK_SUNLIGHT:
Load_Sun_Light(cload);
break;
case PSCENE_SD_CHUNK_VARIABLES:
while (cload.Open_Micro_Chunk()) {
switch(cload.Cur_Micro_Chunk_ID()) {
READ_MICRO_CHUNK(cload,PSCENE_SD_VARIABLE_AMBIENT,SceneAmbientLight);
}
cload.Close_Micro_Chunk();
}
break;
}
cload.Close_Chunk();
}
}
void PhysicsSceneClass::Post_Load_Level_Static_Data(void)
{
Vector3 wmin,wmax;
Get_Level_Extents(wmin,wmax);
DynamicCullingSystem->Re_Partition(wmin,wmax,10.0f);
Compute_Vis_Mesh_Ram();
}
void PhysicsSceneClass::Save_Level_Static_Objects(ChunkSaveClass & csave)
{
/*
** Things to save here:
** - Objects which have absolutely no dynamic state and cannot be created or destroyed during a level.
** - Lights which also follow the same rules...
*/
if (!StaticObjList.Is_Empty()) {
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_OBJECTS);
Save_Static_Objects(csave);
csave.End_Chunk();
}
if (!StaticLightList.Is_Empty()) {
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_LIGHTS);
Save_Static_Lights(csave);
csave.End_Chunk();
}
}
void PhysicsSceneClass::Load_Level_Static_Objects(ChunkLoadClass & cload)
{
/*
** Things to load here:
** - Static objects and lights
*/
WWASSERT(StaticObjList.Is_Empty());
WWASSERT(StaticLightList.Is_Empty());
while (cload.Open_Chunk()) {
switch (cload.Cur_Chunk_ID())
{
case PSCENE_SO_CHUNK_STATIC_OBJECTS:
Load_Static_Objects(cload);
break;
case PSCENE_SO_CHUNK_STATIC_LIGHTS:
Load_Static_Lights(cload);
break;
}
cload.Close_Chunk();
}
}
void PhysicsSceneClass::Post_Load_Level_Static_Objects(void)
{
}
void PhysicsSceneClass::Save_Level_Dynamic_Data(ChunkSaveClass & csave)
{
/*
** Things to save here
** - CollisionFlags
** - DynamicPolyBudget
** - StaticPolyBudget
** - List of dynamic objects (embed each in a chunk, embed cull linkage, build the list again at load time)
** - List of static objects (embed each in a chunk, ... )
** - List of static lights (embed each in a chunk, ... )
** - DirtyCullList - this will have to be a "de-swizzle" list.
** NOTES:
** - each phys obj should tell their render object that they were added in post-load
*/
csave.Begin_Chunk(PSCENE_DD_CHUNK_VARIABLES);
Save_LDD_Variables(csave);
csave.End_Chunk();
if (!ObjList.Is_Empty()) {
csave.Begin_Chunk(PSCENE_DD_CHUNK_DYNAMIC_OBJECTS);
Save_Dynamic_Objects(csave);
csave.End_Chunk();
}
if (!StaticAnimList.Is_Empty()) {
csave.Begin_Chunk(PSCENE_DD_CHUNK_STATIC_OBJECT_STATES);
Save_Static_Object_States(csave);
csave.End_Chunk();
}
#if 0 // Do I need to do this?
if (!DirtyCullList.Is_Empty()) {
csave.Begin_Chunk(PSCENE_LDD_CHUNK_DIRTY_CULL_LIST);
Save_LDD_Dirty_Cull_List();
csave.End_Chunk();
}
#endif
}
void PhysicsSceneClass::Load_Level_Dynamic_Data(ChunkLoadClass & cload)
{
WWMEMLOG(MEM_PHYSICSDATA);
while (cload.Open_Chunk()) {
switch(cload.Cur_Chunk_ID()) {
case PSCENE_DD_CHUNK_VARIABLES:
Load_LDD_Variables(cload);
break;
case PSCENE_DD_CHUNK_DYNAMIC_OBJECTS:
Load_Dynamic_Objects(cload);
break;
case PSCENE_DD_CHUNK_STATIC_OBJECT_STATES:
Load_Static_Object_States(cload);
break;
#if 0 // Do I need to do this?
case PSCENE_LDD_CHUNK_DIRTY_CULL_LIST:
Load_LDD_Dirty_Cull_List(cload);
break;
#endif
default:
WWDEBUG_SAY(("Unhandled Chunk: 0x%X in file: %s, line %d\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
break;
}
cload.Close_Chunk();
}
}
void PhysicsSceneClass::Save_LDD_Variables(ChunkSaveClass & csave)
{
}
void PhysicsSceneClass::Load_LDD_Variables(ChunkLoadClass & cload)
{
while (cload.Open_Micro_Chunk()) {
switch (cload.Cur_Micro_Chunk_ID()) {
OBSOLETE_MICRO_CHUNK(PSCENE_DD_VARIABLE_DYNAMICPOLYBUDGET);
OBSOLETE_MICRO_CHUNK(PSCENE_DD_VARIABLE_STATICPOLYBUDGET);
default:
WWDEBUG_SAY(("Unhandled Micro Chunk: 0x%x in file &s, line %d\n",cload.Cur_Micro_Chunk_ID(),__FILE__,__LINE__));
}
cload.Close_Micro_Chunk();
}
}
void PhysicsSceneClass::Save_Static_Objects(ChunkSaveClass & csave)
{
/*
** Save each object and save each object's culling linkage
*/
RefPhysListIterator it(&StaticObjList);
for (it.First(); !it.Is_Done(); it.Next()) {
PhysClass * obj = it.Peek_Obj();
WWASSERT(obj != NULL);
if ((obj) && (obj->Is_Dont_Save_Enabled() == false)) {
StaticPhysClass * staticobj = obj->As_StaticPhysClass();
WWASSERT(staticobj != NULL);
if (staticobj) {
/*
** Wrap the factory defined chunk with our own so that it's in its own
** "chunk-space"
*/
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_OBJECT);
csave.Begin_Chunk(staticobj->Get_Factory().Chunk_ID());
staticobj->Get_Factory().Save(csave,staticobj);
csave.End_Chunk();
csave.End_Chunk();
/*
** Follow the object data with its linkage data
*/
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_OBJECT_AABLINK);
StaticCullingSystem->Save_Object_Linkage(csave,staticobj);
csave.End_Chunk();
}
}
}
}
void PhysicsSceneClass::Load_Static_Objects(ChunkLoadClass & cload)
{
while (cload.Open_Chunk()) {
if (cload.Cur_Chunk_ID() == PSCENE_SO_CHUNK_STATIC_OBJECT) {
/*
** Load the object
*/
cload.Open_Chunk();
StaticPhysClass * obj = NULL;
PersistFactoryClass * fact = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
WWASSERT(fact != NULL);
if (fact) {
obj = (StaticPhysClass *)fact->Load(cload);
}
cload.Close_Chunk();
cload.Close_Chunk();
/*
** Load the object's linkage into the Static Culling System
*/
cload.Open_Chunk();
if ((cload.Cur_Chunk_ID() == PSCENE_SO_CHUNK_STATIC_OBJECT_AABLINK) && (obj)) {
StaticCullingSystem->Load_Object_Linkage(cload,obj);
}
cload.Close_Chunk();
/*
** Finish installing the object into the physics scene
** - Add it to the static objects list
** - If it requires time-stepping, add to the timestep list
** - Let the base SceneClass notify the render object that it has been added.
*/
Internal_Add_Static_Object(obj);
obj->Release_Ref();
} else {
WWDEBUG_SAY(("Unhandled Chunk: 0x%x in file %s, line %d\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
cload.Close_Chunk();
}
}
}
void PhysicsSceneClass::Save_Static_Lights(ChunkSaveClass & csave)
{
/*
** Save each object and save each object's culling linkage
*/
RefPhysListIterator it(&StaticLightList);
for (it.First(); !it.Is_Done(); it.Next()) {
PhysClass * obj = it.Peek_Obj();
WWASSERT(obj != NULL);
if (obj) {
LightPhysClass * lightobj = obj->As_LightPhysClass();
WWASSERT(lightobj != NULL);
if (lightobj) {
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_LIGHT);
csave.Begin_Chunk(lightobj->Get_Factory().Chunk_ID());
lightobj->Get_Factory().Save(csave,lightobj);
csave.End_Chunk();
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_SO_CHUNK_STATIC_LIGHT_AABLINK);
StaticLightingSystem->Save_Object_Linkage(csave,lightobj);
csave.End_Chunk();
}
}
}
}
void PhysicsSceneClass::Load_Static_Lights(ChunkLoadClass & cload)
{
while (cload.Open_Chunk()) {
if (cload.Cur_Chunk_ID() == PSCENE_SO_CHUNK_STATIC_LIGHT) {
/*
** Load the object
*/
cload.Open_Chunk();
LightPhysClass * obj = NULL;
PersistFactoryClass * fact = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
WWASSERT(fact != NULL);
if (fact) {
obj = (LightPhysClass *)fact->Load(cload);
}
cload.Close_Chunk();
cload.Close_Chunk();
/*
** Load the object's linkage into the static light culling system
*/
WWASSERT(obj);
cload.Open_Chunk();
if ((cload.Cur_Chunk_ID() == PSCENE_SO_CHUNK_STATIC_LIGHT_AABLINK) && (obj)) {
StaticLightingSystem->Load_Object_Linkage(cload,obj);
}
cload.Close_Chunk();
/*
** Finish installing the object into the physics scene
*/
Internal_Add_Static_Light(obj);
obj->Release_Ref();
} else {
WWDEBUG_SAY(("Unhandled Chunk: 0x%x in file &s, line %d\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
cload.Close_Chunk();
}
}
}
void PhysicsSceneClass::Load_Sun_Light(ChunkLoadClass & cload)
{
WWASSERT(SunLight != NULL);
IOSunLightStruct sun;
cload.Read(&sun,sizeof(sun));
UseSun = (sun.Enabled == 1);
Vector3 color;
color.X = sun.Color.X;
color.Y = sun.Color.Y;
color.Z = sun.Color.Z;
SunLight->Set_Diffuse(color);
SunLight->Set_Intensity(sun.Intensity);
Set_Sun_Light_Orientation(sun.Yaw,sun.Pitch);
}
void PhysicsSceneClass::Save_Sun_Light(ChunkSaveClass & csave)
{
WWASSERT(SunLight != NULL);
IOSunLightStruct sun;
memset(&sun,0,sizeof(sun));
sun.Enabled = (UseSun ? 1 : 0);
sun.Yaw = SunYaw;
sun.Pitch = SunPitch;
sun.Intensity = SunLight->Get_Intensity();
Vector3 c;
SunLight->Get_Diffuse(&c);
sun.Color.X = c.X;
sun.Color.Y = c.Y;
sun.Color.Z = c.Z;
csave.Write(&sun,sizeof(sun));
}
void PhysicsSceneClass::Save_Dynamic_Objects(ChunkSaveClass & csave)
{
/*
** Save each object and save each object's culling linkage
*/
RefPhysListIterator it(&ObjList);
for (it.First(); !it.Is_Done(); it.Next()) {
PhysClass * obj = it.Peek_Obj();
WWASSERT(obj != NULL);
if ((obj) && (obj->Is_Dont_Save_Enabled() == false)) {
csave.Begin_Chunk(PSCENE_DD_CHUNK_DYNAMIC_OBJECT);
csave.Begin_Chunk(obj->Get_Factory().Chunk_ID());
obj->Get_Factory().Save(csave,obj);
csave.End_Chunk();
csave.End_Chunk();
}
}
}
void PhysicsSceneClass::Load_Dynamic_Objects(ChunkLoadClass & cload)
{
while (cload.Open_Chunk()) {
if (cload.Cur_Chunk_ID() == PSCENE_DD_CHUNK_DYNAMIC_OBJECT) {
/*
** Load the object
*/
cload.Open_Chunk();
PhysClass * obj = NULL;
PersistFactoryClass * fact = SaveLoadSystemClass::Find_Persist_Factory(cload.Cur_Chunk_ID());
WWASSERT(fact != NULL);
if (fact) {
obj = (PhysClass *)fact->Load(cload);
}
cload.Close_Chunk();
cload.Close_Chunk();
WWASSERT(obj);
/*
** Add the object to the dynamic culling system
*/
DynamicCullingSystem->Add_Object(obj);
/*
** Finish installing the object into the physics scene
** - Add it to the culling system
** - Add it to the appropriate list
** - Notify the render object that it was added to the scene
*/
Internal_Add_Dynamic_Object(obj);
obj->Release_Ref();
} else {
WWDEBUG_SAY(("Unhandled Chunk: 0x%x in file &s, line %d\n",cload.Cur_Chunk_ID(),__FILE__,__LINE__));
cload.Close_Chunk();
}
}
}
void PhysicsSceneClass::Save_Static_Object_States(ChunkSaveClass & csave)
{
RefPhysListIterator it(&StaticObjList);
while (!it.Is_Done()) {
if (((StaticPhysClass*)it.Peek_Obj())->Has_Dynamic_State()) {
csave.Begin_Chunk(PSCENE_DD_CHUNK_STATIC_OBJECT_ID);
uint32 id = it.Peek_Obj()->Get_ID();
csave.Write(&id,sizeof(uint32));
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_DD_CHUNK_STATIC_OLD_PTR);
void * old_ptr = it.Peek_Obj();
csave.Write(&old_ptr,sizeof(void *));
csave.End_Chunk();
csave.Begin_Chunk(PSCENE_DD_CHUNK_STATIC_OBJECT_STATE);
((StaticPhysClass *)it.Peek_Obj())->Save_State(csave);
csave.End_Chunk();
}
it.Next();
}
}
void PhysicsSceneClass::Load_Static_Object_States(ChunkLoadClass & cload)
{
while (cload.Open_Chunk()) {
WWASSERT(cload.Cur_Chunk_ID()==PSCENE_DD_CHUNK_STATIC_OBJECT_ID);
uint32 id;
cload.Read(&id,sizeof(uint32));
cload.Close_Chunk();
StaticPhysClass * sphys = Get_Static_Object_By_ID(id);
cload.Open_Chunk();
WWASSERT(cload.Cur_Chunk_ID()==PSCENE_DD_CHUNK_STATIC_OLD_PTR);
void * old_ptr;
cload.Read(&old_ptr,sizeof(void *));
SaveLoadSystemClass::Register_Pointer(old_ptr, sphys);
cload.Close_Chunk();
cload.Open_Chunk();
WWASSERT(cload.Cur_Chunk_ID()==PSCENE_DD_CHUNK_STATIC_OBJECT_STATE);
if (sphys != NULL) {
sphys->Load_State(cload);
sphys->Release_Ref();
} else {
WWDEBUG_SAY(("Unable to find static object! id = %d\r\n",id));
}
cload.Close_Chunk();
}
}
void PhysicsSceneClass::Post_Load_Level_Dynamic_Data(void)
{
/*
** Possible TODO List:
** - Rebuild the dirty cull list?
** - Rebuild the lists of vertex processors? (tell each model that its been added?)
*/
/*
** Re-generate the static shadows
*/
// Generate_Static_Shadow_Projectors();
// We don't necessarily have active device at this point so we can't render the shadows yet.
// The shadows will be generated as soon as the device is available at the start of the game.
Invalidate_Static_Shadow_Projectors();
}
StaticPhysClass * PhysicsSceneClass::Get_Static_Object_By_ID(uint32 id)
{
RefPhysListIterator it(&StaticObjList);
while (!it.Is_Done()) {
if (it.Peek_Obj()->Get_ID() == id) {
return (StaticPhysClass *)it.Get_Obj();
}
it.Next();
}
return NULL;
}