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_vis.cpp

887 lines
38 KiB
C++

/*
** 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_vis.cpp $*
* *
* Original Author:: Greg Hjelstrom *
* *
* $Author:: Greg_h $*
* *
* $Modtime:: 10/23/01 8:35p $*
* *
* $Revision:: 47 $*
* *
*---------------------------------------------------------------------------------------------*
* Functions: *
* PhysicsSceneClass::Release_Vis_Resources -- Releases resources used by the VIS code *
* PhysicsSceneClass::Reset_Vis -- Sets the internal vis reset flag. *
* PhysicsSceneClass::Validate_Vis -- Clears the internal vis reset flag *
* PhysicsSceneClass::Internal_Vis_Reset -- Resets the vis system if needed *
* PhysicsSceneClass::Get_Vis_Camera -- returns a pointer (ref-counted) to the vis camera *
* PhysicsSceneClass::Get_Vis_Gerd -- returns a pointer to the VIS Gerd *
* PhysicsSceneClass::Show_Vis_Window -- Makes the vis render window visible to the user *
* PhysicsSceneClass::Is_Vis_Window_Visible -- Returns status of the vis render window *
* PhysicsSceneClass::Get_Static_Light_Count -- returns the number of static lights *
* PhysicsSceneClass::Generate_Vis_For_Light -- generate a PVS for the specified light *
* PhysicsSceneClass::Update_Vis -- Performs a vis sample from the given coord system *
* PhysicsSceneClass::Vis_Render_And_Scan -- Renders the scene and scans for visible objects *
* PhysicsSceneClass::Vis_Debug_Render -- Renders the same way VIS does *
* PhysicsSceneClass::Generate_Vis_Statistics_Report -- Stats about the visibility in the le *
* PhysicsSceneClass::Optimize_Visibility_Data -- combines and removes redundant vis data *
* PhysicsSceneClass::Merge_Vis_Sector_IDs -- Merges two sector ID's *
* PhysicsSceneClass::Merge_Vis_Object_IDs -- combines two vis object ID's *
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
#include "pscene.h"
#include "staticaabtreecull.h"
#include "dynamicaabtreecull.h"
#include "staticphys.h"
#include "lightcull.h"
#include "camera.h"
#include "vertmaterial.h"
#include "shader.h"
#include "visrendercontext.h"
#include "visoptimizationcontext.h"
#include "visoptprogress.h"
#include "light.h"
#include "visrasterizer.h"
/************************************************************************************
**
** PhysicsSceneClass Visibility system
**
************************************************************************************/
void PhysicsSceneClass::Enable_Vis(bool onoff)
{
VisEnabled = onoff;
}
void PhysicsSceneClass::Invert_Vis(bool onoff)
{
VisInverted = onoff;
}
void PhysicsSceneClass::Set_Vis_Quick_And_Dirty(bool onoff)
{
VisQuickAndDirty = onoff;
}
void PhysicsSceneClass::Enable_Vis_Sector_Display(bool onoff)
{
VisSectorDisplayEnabled = onoff;
}
void PhysicsSceneClass::Enable_Vis_Sector_History_Display(bool onoff)
{
VisSectorHistoryEnabled = onoff;
}
void PhysicsSceneClass::Enable_Vis_Sector_Fallback(bool onoff)
{
VisSectorFallbackEnabled = onoff;
}
void PhysicsSceneClass::Enable_Backface_Occluder_Debug(bool onoff)
{
BackfaceDebugEnabled = onoff;
}
void PhysicsSceneClass::Set_Vis_Grid_Display_Mode(int mode)
{
VisGridDisplayMode = mode;
}
bool PhysicsSceneClass::Is_Vis_Enabled(void)
{
return VisEnabled;
}
bool PhysicsSceneClass::Is_Vis_Inverted(void)
{
return VisInverted;
}
bool PhysicsSceneClass::Is_Vis_Quick_And_Dirty(void)
{
return VisQuickAndDirty;
}
bool PhysicsSceneClass::Is_Vis_Sector_Display_Enabled(void)
{
return VisSectorDisplayEnabled;
}
bool PhysicsSceneClass::Is_Vis_Sector_History_Display_Enabled(void)
{
return VisSectorHistoryEnabled;
}
bool PhysicsSceneClass::Is_Vis_Sector_Fallback_Enabled(void)
{
return VisSectorFallbackEnabled;
}
bool PhysicsSceneClass::Is_Backface_Occluder_Debug_Enabled(void)
{
return BackfaceDebugEnabled;
}
int PhysicsSceneClass::Get_Vis_Grid_Display_Mode(void)
{
return VisGridDisplayMode;
}
void PhysicsSceneClass::Vis_Grid_Debug_Reset_Node(void)
{
DynamicObjVisSystem->Debug_Reset_Node();
}
bool PhysicsSceneClass::Vis_Grid_Debug_Enter_Parent(void)
{
return DynamicObjVisSystem->Debug_Enter_Parent();
}
bool PhysicsSceneClass::Vis_Grid_Debug_Enter_Sibling(void)
{
return DynamicObjVisSystem->Debug_Enter_Sibling();
}
bool PhysicsSceneClass::Vis_Grid_Debug_Enter_Front_Child(void)
{
return DynamicObjVisSystem->Debug_Enter_Front_Child();
}
bool PhysicsSceneClass::Vis_Grid_Debug_Enter_Back_Child(void)
{
return DynamicObjVisSystem->Debug_Enter_Back_Child();
}
bool PhysicsSceneClass::Is_Vis_Sector_Missing(void)
{
return VisSectorMissing;
}
int PhysicsSceneClass::Allocate_Vis_Object_ID(int count /* = 1*/)
{
return VisTableManager.Allocate_Vis_Object_ID(count);
}
int PhysicsSceneClass::Allocate_Vis_Sector_ID(int count /* = 1*/)
{
return VisTableManager.Allocate_Vis_Sector_ID(count);
}
int PhysicsSceneClass::Get_Vis_Table_Size(void)
{
Internal_Vis_Reset();
return VisTableManager.Get_Vis_Table_Size();
}
int PhysicsSceneClass::Get_Vis_Table_Count(void)
{
Internal_Vis_Reset();
return VisTableManager.Get_Vis_Table_Count();
}
void PhysicsSceneClass::Compute_Vis_Sample_Point(const CameraClass & camera,Vector3 * set_point)
{
WWASSERT(set_point != NULL);
if (!VisSamplePointLocked) {
float nearz,farz;
camera.Get_Clip_Planes(nearz,farz);
Matrix3D::Transform_Vector(camera.Get_Transform(),Vector3(0,0,-nearz-0.05f),set_point);
} else {
*set_point = LockedVisSamplePoint;
}
}
VisTableClass * PhysicsSceneClass::Get_Vis_Table(int vis_sector_id)
{
return VisTableManager.Get_Vis_Table(vis_sector_id);
}
VisTableClass * PhysicsSceneClass::Get_Vis_Table(const Vector3 & point)
{
int vis_id = StaticCullingSystem->Get_Vis_Sector_ID(point);
return VisTableManager.Get_Vis_Table(vis_id);
}
VisTableClass * PhysicsSceneClass::Get_Vis_Table(const CameraClass & camera)
{
Vector3 sample_point;
Compute_Vis_Sample_Point(camera,&sample_point);
return Get_Vis_Table(sample_point);
}
VisTableClass * PhysicsSceneClass::Get_Vis_Table_For_Rendering(const CameraClass & camera)
{
// Decompress the visibility table for the current camera view
// Note that if the vis system needs to be reset, we don't want to use any obsolete data
// Also, if a sample point hasn't been given, we will skip visibility.
// Also, if we don't find a vis sector, we'll try to use the last valid one that we had.
int vis_id = -1;
VisTableClass * pvs = NULL;
Vector3 vis_sample_point;
Compute_Vis_Sample_Point(camera,&vis_sample_point);
if ((!VisResetNeeded) && VisEnabled) {
vis_id = StaticCullingSystem->Get_Vis_Sector_ID(vis_sample_point);
if (vis_id == -1) {
VisSectorMissing = true;
if (VisSectorFallbackEnabled) {
vis_id = LastValidVisId;
}
} else {
if ((LastValidVisId != vis_id) && VisSectorDisplayEnabled) {
StaticPhysClass * tile = StaticCullingSystem->Find_Vis_Tile(vis_sample_point);
WWDEBUG_SAY (("Vis Sector: %s\n", tile->Peek_Model ()->Get_Name ()));
}
LastValidVisId = vis_id;
VisSectorMissing = false;
}
if (vis_id != -1) {
pvs = VisTableManager.Get_Vis_Table(LastValidVisId);
}
if ((VisInverted) && (pvs != NULL)) {
VisTableClass * new_pvs = NEW_REF(VisTableClass,(*pvs));
new_pvs->Invert();
REF_PTR_RELEASE(pvs);
pvs = new_pvs;
}
}
return pvs;
}
uint32 PhysicsSceneClass::Get_Dynamic_Object_Vis_ID
(
const AABoxClass & obj_bounds,
int * node_id
)
{
return DynamicObjVisSystem->Get_Dynamic_Object_Vis_ID(obj_bounds,node_id);
}
void PhysicsSceneClass::Debug_Display_Dynamic_Vis_Node(int node_id)
{
if (VisGridDisplayMode == VIS_GRID_DISPLAY_OCCUPIED) {
AABoxClass bounds;
DynamicObjVisSystem->Get_Node_Bounds(node_id,&bounds);
bounds.Extent -= Vector3(5,5,5);
DEBUG_RENDER_AABOX(bounds,Vector3(0,1,1),0.25f);
}
}
void PhysicsSceneClass::Lock_Vis_Sample_Point(bool onoff)
{
VisSamplePointLocked = onoff;
LockedVisSamplePoint = LastCameraPosition;
}
bool PhysicsSceneClass::Is_Vis_Sample_Point_Locked(void)
{
return VisSamplePointLocked;
}
/***********************************************************************************************
* PhysicsSceneClass::Release_Vis_Resources -- Releases resources used by the VIS code *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Release_Vis_Resources(void)
{
REF_PTR_RELEASE(VisCamera);
}
/***********************************************************************************************
* PhysicsSceneClass::Reset_Vis -- Sets the internal vis reset flag. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Reset_Vis(bool doitnow)
{
/*
** defer the actual reset until later.
** the Update_Vis call and the Save_Map methods will check
** this bit and do the real reset
*/
VisResetNeeded = true;
if (doitnow) {
Internal_Vis_Reset();
}
}
/***********************************************************************************************
* PhysicsSceneClass::Validate_Vis -- Clears the internal vis reset flag *
* *
* This should not normally be called. It is needed when the level editor loads a level. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Validate_Vis(void)
{
/*
** Clear the reset flag, this is needed after a level is loaded.
** Normally as static objects are added to the system, the reset
** flag will be set, but in the case of loading, we are also
** loading the visibility data...
*/
VisResetNeeded = false;
}
/***********************************************************************************************
* PhysicsSceneClass::Internal_Vis_Reset -- Resets the vis system if needed *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Internal_Vis_Reset(void)
{
if (VisResetNeeded) {
VisResetNeeded = false;
WWDEBUG_SAY(("Resetting the visibility system.\r\n"));
/*
** Throw away all visibility data.
*/
VisTableManager.Reset();
/*
** Re-partition the static object culling systems for the heck of it.
** We don't re-partition the dynamic object culling system since it is
** a massive preprocessing step to actually generate it.
*/
StaticCullingSystem->Re_Partition();
StaticLightingSystem->Re_Partition();
/*
** Assign Vis IDs. Each system may allocate both vis sector ID's and
** vis object IDs.
*/
StaticCullingSystem->Assign_Vis_IDs();
DynamicObjVisSystem->Assign_Vis_IDs();
StaticLightingSystem->Assign_Vis_IDs();
/*
** Force all dynamic objects to recompute their visibility id
*/
RefPhysListIterator it(&ObjList);
while (!it.Is_Done()) {
DynamicPhysClass * pobj = it.Peek_Obj()->As_DynamicPhysClass();
if (pobj!=NULL) {
pobj->Update_Visibility_Status();
}
it.Next();
}
}
}
/***********************************************************************************************
* PhysicsSceneClass::Get_Vis_Camera -- returns a pointer (ref-counted) to the vis camera *
* *
* The VIS camera is allocated the first time it is needed. Normally this is only done *
* as a pre-processing step inside the level editor. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
CameraClass * PhysicsSceneClass::Get_Vis_Camera(void)
{
if (VisCamera) {
VisCamera->Add_Ref();
return VisCamera;
}
VisCamera = new CameraClass;
VisCamera->Set_Clip_Planes(VIS_NEAR_CLIP,VIS_FAR_CLIP);
VisCamera->Set_View_Plane(DEG_TO_RAD(90.0f),DEG_TO_RAD(90.0f));
VisCamera->Set_Viewport(Vector2(0,0),Vector2(1,1));
VisCamera->Add_Ref();
return VisCamera;
}
/***********************************************************************************************
* PhysicsSceneClass::Update_Vis -- Performs a vis sample from the given coord system *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
VisSampleClass
PhysicsSceneClass::Update_Vis
(
const Matrix3D & camera_tm,
VisDirBitsType direction_bits
)
{
return Update_Vis(camera_tm.Get_Translation(),camera_tm,direction_bits);
}
/***********************************************************************************************
* PhysicsSceneClass::Update_Vis -- Performs a vis sample from the given coord system *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
VisSampleClass
PhysicsSceneClass::Update_Vis
(
const Vector3 & sample_point,
const Matrix3D & camera_tm,
VisDirBitsType direction_bits,
CameraClass * alternate_camera,
int user_vis_id
)
{
/*
** If the visibility system has been invalidated, reset it now
*/
Internal_Vis_Reset();
/*
** Look up the vis-sector-id for this vis sample
*/
int vis_id = 0;
if (user_vis_id == -1) {
vis_id = StaticCullingSystem->Get_Vis_Sector_ID(sample_point);
} else {
vis_id = user_vis_id;
}
/*
** Get the existing pvs and make a copy of it that we can
** modify with the results of our sampling
*/
VisTableClass * original_pvs = VisTableManager.Get_Vis_Table(vis_id,true);
if (original_pvs == NULL) {
VisSampleClass vis_sample(camera_tm,direction_bits);
vis_sample.Init_Error();
WWDEBUG_SAY(("Vis Sample Rejected - No Vis Sector or Vis Sector ID not assigned!\r\n"));
return vis_sample;
}
VisTableClass * pvs = new VisTableClass(*original_pvs);
/*
** Grab the camera, GERD, shader, vertex material...
*/
CameraClass * camera = NULL;
if (alternate_camera) { // if user is supplying an alternate camera, use it
camera = alternate_camera;
camera->Add_Ref();
} else { // otherwise use the vis camera
camera = Get_Vis_Camera();
}
WWASSERT (camera != NULL);
/*
** Create the render context, initialize the GERD, install the Vis shader and vertex material
*/
VisRenderContextClass context(*camera,*pvs);
context.Set_Resolution(VIS_RENDER_WIDTH,VIS_RENDER_HEIGHT);
context.Set_Vis_Quick_And_Dirty(VisQuickAndDirty);
/*
** Evaluate visiblity for the six views from this point
*/
VisSampleClass vis_sample(camera_tm,direction_bits);
WWDEBUG_SAY(("Generating Vis for sector %d... ",vis_id));
for (int i=0; i<VIS_DIRECTIONS; i++) {
if (vis_sample.Direction_Enabled((VisDirType)i)) {
if (!vis_sample.Sample_Useless() || (direction_bits & VIS_FORCE_ACCEPT)) {
vis_sample.Set_Cur_Direction((VisDirType)i);
context.Camera.Set_Transform(vis_sample.Get_Camera_Transform((VisDirType)i));
Vis_Render_And_Scan(context,vis_sample);
}
}
}
/*
** The static culling system needs to propogate the leaf visibility bits through its
** hierarchy.
*/
StaticCullingSystem->Propogate_Hierarchical_Visibility(pvs);
/*
** Record how many bits this sample actually changed
*/
vis_sample.Set_Bits_Changed(original_pvs->Count_Differences(*pvs));
/*
** Accept the sample if it was not rejected -OR- the user has set the VIS_FORCE_ACCEPT bit
*/
bool accept_sample = (!vis_sample.Sample_Rejected()) || (direction_bits & VIS_FORCE_ACCEPT);
if (accept_sample) {
VisTableManager.Update_Vis_Table(vis_id,pvs);
WWDEBUG_SAY(("Done! (%d bits changed) \r\n",vis_sample.Get_Bits_Changed()));
} else {
WWDEBUG_SAY(("Rejected!\r\n"));
}
/*
** Release assets
*/
REF_PTR_RELEASE(camera);
REF_PTR_RELEASE(original_pvs);
REF_PTR_RELEASE(pvs);
return vis_sample;
}
/***********************************************************************************************
* PhysicsSceneClass::Get_Static_Light_Count -- returns the number of static lights *
* *
* Each static light allocates a PVS. This accessor will let you loop over each light *
* and update its PVS. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/19/2000 gth : Created. *
*=============================================================================================*/
int PhysicsSceneClass::Get_Static_Light_Count(void)
{
/*
** Count the lights in the list
*/
int counter = 0;
RefPhysListIterator light_it = Get_Static_Light_Iterator();
for (light_it.First();!light_it.Is_Done(); light_it.Next()) {
counter++;
}
return counter;
}
/***********************************************************************************************
* PhysicsSceneClass::Generate_Vis_For_Light -- generate a PVS for the specified light *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/19/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Generate_Vis_For_Light(int light_index)
{
/*
** For lights, we're going to use the VIS camera but we're going to tweak the far
** clip plane to be the outer-radius of the light's falloff sphere.
*/
CameraClass * camera = Get_Vis_Camera();
/*
** Find the specified light. Array-like access into a list...
*/
RefPhysListIterator light_it = Get_Static_Light_Iterator();
for (; light_index > 0; light_index--) {
light_it.Next();
}
/*
** Update vis for the specified light.
*/
LightPhysClass * light = light_it.Peek_Obj()->As_LightPhysClass();
if ( (light != NULL) &&
(light->Get_Vis_Sector_ID() != 0xFFFFFFFF) &&
(light->Peek_Model() != NULL) &&
(light->Peek_Model()->Class_ID() == RenderObjClass::CLASSID_LIGHT))
{
/*
** Perform the vis sample
*/
LightClass * lightmodel = (LightClass *)light->Peek_Model();
camera->Set_Clip_Planes(0.01f,lightmodel->Get_Attenuation_Range());
camera->Set_Transform(light->Get_Transform());
Update_Vis( light->Get_Transform().Get_Translation(),
light->Get_Transform(),
(VisDirBitsType)(VIS_ALL | VIS_FORCE_ACCEPT),
camera,
light->Get_Vis_Sector_ID() );
}
/*
** Done, reset the camera clip planes, release resources
*/
camera->Set_Clip_Planes(VIS_NEAR_CLIP,VIS_FAR_CLIP);
REF_PTR_RELEASE(camera);
}
/***********************************************************************************************
* PhysicsSceneClass::Vis_Render_And_Scan -- Renders the scene and scans for visible objects *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Vis_Render_And_Scan(VisRenderContextClass & context,VisSampleClass & vis_sample)
{
/*
** Have the static culling system evaluate visibility for the occluders
** and build the z-buffer in the process.
*/
WWASSERT(context.VisRasterizer != NULL);
context.VisRasterizer->Set_Render_Mode(IDBufferClass::OCCLUDER_MODE);
StaticCullingSystem->Evaluate_Occluder_Visibility(context,vis_sample);
On_Vis_Occluders_Rendered(context,vis_sample);
/*
** Evaluate the visibility of the non-occluders in all systems
*/
if (!vis_sample.Sample_Rejected()) {
context.VisRasterizer->Set_Render_Mode(IDBufferClass::NON_OCCLUDER_MODE);
StaticCullingSystem->Evaluate_Non_Occluder_Visibility(context,vis_sample);
DynamicObjVisSystem->Evaluate_Non_Occluder_Visibility(context);
}
}
/***********************************************************************************************
* PhysicsSceneClass::Generate_Vis_Statistics_Report -- Stats about the visibility in the leve *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Generate_Vis_Statistics_Report(DynamicVectorClass<VisSectorStatsClass> & report)
{
/*
** Loop over each of the vis sectors in the level, adding up how many polygons and
** and how much texture memory can be seen from each one.
*/
VisSectorStatsClass stats;
RefPhysListIterator it(&StaticObjList);
for (it.First(); !it.Is_Done(); it.Next()) {
StaticPhysClass * obj = it.Peek_Obj()->As_StaticPhysClass();
if (obj && obj->Is_Vis_Sector()) {
VisTableClass * vistbl = VisTableManager.Get_Vis_Table(obj->Get_Vis_Sector_ID());
stats.Compute_Stats(obj,vistbl);
report.Add(stats);
REF_PTR_RELEASE(vistbl);
}
}
}
/***********************************************************************************************
* PhysicsSceneClass::Optimize_Visibility_Data -- combines and removes redundant vis data *
* *
* This function does three things. *
* - The dynamic object AABTree removes useless leaf nodes (nodes with visibility identical *
* to their parent) *
* - All vis "objects" are checked and combined if their visibility is nearly the same *
* - All vis "sectors" are checked and combined if their visibility is nearly the same *
* *
* INPUT: *
* progress_status - class the the physics scene will update as the process proceeds. *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Optimize_Visibility_Data(VisOptProgressClass & stats)
{
/*
** Initialize the progress_status.
** I'm goint to count one operation per each of the following
** - each node in the dynamic aabtree for the "Prune_Redundant_Leaf_Nodes" process
** - each vis object for the "Combine_Redundant_Vis_Objects" process
** - each vis sector for the "Combine_Redundant_Vis_Sectors" process
*/
stats.Reset(DynamicObjVisSystem->Partition_Node_Count() + Get_Vis_Table_Size() + Get_Vis_Table_Count());
stats.Set_Initial_Bit_Count(VisTableManager.Get_Vis_Table_Size() * VisTableManager.Get_Vis_Table_Count());
stats.Set_Initial_Sector_Count(Get_Vis_Table_Count());
stats.Set_Initial_Object_Count(Get_Vis_Table_Size());
stats.Set_Initial_Dynamic_Cell_Count(DynamicObjVisSystem->Partition_Node_Count());
/*
** Create a VisOptimizationContextClass and optimize the vis data
*/
VisOptimizationContextClass optcontext(this,stats);
optcontext.Optimize(&VisTableManager,DynamicObjVisSystem);
/*
** Reset all of dynamic objects' cached vis-ID and cull node.
*/
RefPhysListIterator it(&ObjList);
for (it.First(); !it.Is_Done(); it.Next()) {
DynamicPhysClass * obj = it.Peek_Obj()->As_DynamicPhysClass();
if (obj != NULL) {
obj->Update_Visibility_Status();
}
}
/*
** Finish the statistics
*/
stats.Set_Final_Bit_Count(VisTableManager.Get_Vis_Table_Size() * VisTableManager.Get_Vis_Table_Count());
stats.Set_Final_Sector_Count(Get_Vis_Table_Count());
stats.Set_Final_Object_Count(Get_Vis_Table_Size());
stats.Set_Final_Dynamic_Cell_Count(DynamicObjVisSystem->Partition_Node_Count());
}
/***********************************************************************************************
* PhysicsSceneClass::Merge_Vis_Sector_IDs -- Merges two sector ID's *
* *
* The greater ID will be set equal to the lesser ID. This should only be called by the *
* vis optimization process and relies on a VisOptimizationContext to track the changes *
* to the actual VIS bit vectors. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Merge_Vis_Sector_IDs(uint32 id0,uint32 id1)
{
StaticCullingSystem->Merge_Vis_Sector_IDs(id0,id1);
StaticLightingSystem->Merge_Vis_Sector_IDs(id0,id1);
}
/***********************************************************************************************
* PhysicsSceneClass::Merge_Vis_Object_IDs -- combines two vis object ID's *
* *
* The greater ID will be set equal to the lesser ID. This should only be called by the *
* vis optimization process and relies on a VisOptimizationContext to track the changes *
* to the actual VIS bit vectors. *
* *
* INPUT: *
* *
* OUTPUT: *
* *
* WARNINGS: *
* *
* HISTORY: *
* 7/5/2000 gth : Created. *
*=============================================================================================*/
void PhysicsSceneClass::Merge_Vis_Object_IDs(uint32 id0,uint32 id1)
{
StaticCullingSystem->Merge_Vis_Object_IDs(id0,id1);
DynamicObjVisSystem->Merge_Vis_Object_IDs(id0,id1);
}