mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-15 23:21:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
385
Code/wwphys/visoptimizationcontext.cpp
Normal file
385
Code/wwphys/visoptimizationcontext.cpp
Normal file
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
** 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/visoptimizationcontext.cpp $*
|
||||
* *
|
||||
* Original Author:: Greg Hjelstrom *
|
||||
* *
|
||||
* $Author:: Patrick $*
|
||||
* *
|
||||
* $Modtime:: 11/16/00 7:31p $*
|
||||
* *
|
||||
* $Revision:: 12 $*
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
#include "visoptimizationcontext.h"
|
||||
#include "visoptprogress.h"
|
||||
#include "pscene.h"
|
||||
#include "vistablemgr.h"
|
||||
#include "vistable.h"
|
||||
#include "dynamicaabtreecull.h"
|
||||
#include "wwdebug.h"
|
||||
|
||||
|
||||
const float MIN_OBJECT_MATCH_FRACTION = 0.99f;
|
||||
const float MIN_SECTOR_MATCH_FRACTION = 0.99f;
|
||||
const float MIN_PRUNE_MATCH_FRACTION = 0.90f;
|
||||
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** PVSInfoStruct Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
|
||||
VisOptimizationContextClass::PVSInfoStruct::PVSInfoStruct(void) :
|
||||
Table(NULL),
|
||||
UnUsed(false)
|
||||
{
|
||||
}
|
||||
|
||||
VisOptimizationContextClass::PVSInfoStruct::~PVSInfoStruct(void)
|
||||
{
|
||||
REF_PTR_RELEASE(Table);
|
||||
}
|
||||
|
||||
const VisOptimizationContextClass::PVSInfoStruct &
|
||||
VisOptimizationContextClass::PVSInfoStruct::operator = (const PVSInfoStruct & that)
|
||||
{
|
||||
REF_PTR_SET(Table,that.Table);
|
||||
UnUsed = that.UnUsed;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/***************************************************************************************************
|
||||
**
|
||||
** VisOptimizationContextClass Implementation
|
||||
**
|
||||
***************************************************************************************************/
|
||||
|
||||
VisOptimizationContextClass::VisOptimizationContextClass
|
||||
(
|
||||
PhysicsSceneClass * scene,
|
||||
VisOptProgressClass & stats
|
||||
) :
|
||||
MinDynCellPruneMatchFraction(MIN_PRUNE_MATCH_FRACTION),
|
||||
MinVisObjectMatchFraction(MIN_OBJECT_MATCH_FRACTION),
|
||||
MinVisSectorMatchFraction(MIN_SECTOR_MATCH_FRACTION),
|
||||
Scene(scene),
|
||||
Stats(stats)
|
||||
{
|
||||
WWASSERT(Scene != NULL);
|
||||
}
|
||||
|
||||
VisOptimizationContextClass::~VisOptimizationContextClass(void)
|
||||
{
|
||||
}
|
||||
|
||||
float VisOptimizationContextClass::Compute_Sector_Table_Match_Fraction(int sector_id_0,int sector_id_1)
|
||||
{
|
||||
if (SectorTables[sector_id_0].UnUsed || SectorTables[sector_id_1].UnUsed) {
|
||||
return 0.0f;
|
||||
}
|
||||
return SectorTables[sector_id_0].Table->Match_Fraction(*(SectorTables[sector_id_1].Table));
|
||||
}
|
||||
|
||||
float VisOptimizationContextClass::Compute_Object_Table_Match_Fraction(int object_id_0,int object_id_1)
|
||||
{
|
||||
return ObjectTables[object_id_0].Table->Match_Fraction(*(ObjectTables[object_id_1].Table));
|
||||
}
|
||||
|
||||
void VisOptimizationContextClass::Optimize
|
||||
(
|
||||
VisTableMgrClass * vis_mgr,
|
||||
DynamicAABTreeCullClass * dyn_obj_tree
|
||||
)
|
||||
{
|
||||
/*
|
||||
** Generate the object tables
|
||||
*/
|
||||
Build_Object_Tables(vis_mgr);
|
||||
|
||||
/*
|
||||
** Prune redundant leaves of the dynamic object culling tree. This operation actually
|
||||
** deletes leaf nodes from the tree.
|
||||
*/
|
||||
dyn_obj_tree->Prune_Redundant_Leaf_Nodes(*this);
|
||||
|
||||
/*
|
||||
** Combine the redundant objects. This operation combines objects by assigning the
|
||||
** same vis ID to both of them.
|
||||
*/
|
||||
Combine_Redundant_Objects();
|
||||
|
||||
/*
|
||||
** Now that we're done combining objects, build new sector tables so that we
|
||||
** can remove the redundant vis sectors. Each table will have a bitcount
|
||||
** equal to the number of object tables.
|
||||
*/
|
||||
Build_Sector_Tables_From_Object_Tables(vis_mgr);
|
||||
|
||||
/*
|
||||
** Now combine the redundant sectors
|
||||
*/
|
||||
Combine_Redundant_Sectors();
|
||||
|
||||
/*
|
||||
** All done, so install the results
|
||||
*/
|
||||
Install_Results(vis_mgr);
|
||||
}
|
||||
|
||||
void VisOptimizationContextClass::Build_Object_Tables(VisTableMgrClass * vis_mgr)
|
||||
{
|
||||
/*
|
||||
** Generate the object tables (what sectors can see each object). Consider the sector
|
||||
** tables columns and the object tables rows of the same 2D grid of visibility bits.
|
||||
*/
|
||||
int i,j;
|
||||
int sector_count = vis_mgr->Get_Vis_Table_Count();
|
||||
int object_count = vis_mgr->Get_Vis_Table_Size();
|
||||
|
||||
ObjectTables.Resize(object_count);
|
||||
for (i=0; i<object_count; i++) {
|
||||
PVSInfoStruct objinfo;
|
||||
objinfo.Table = NEW_REF(VisTableClass,(sector_count,0));
|
||||
ObjectTables.Add(objinfo);
|
||||
}
|
||||
|
||||
for (i=0; i<sector_count; i++) {
|
||||
|
||||
/*
|
||||
** Get each sector table
|
||||
*/
|
||||
VisTableClass * sector_table = vis_mgr->Get_Vis_Table(i);
|
||||
if (sector_table == NULL) {
|
||||
sector_table = NEW_REF(VisTableClass,(object_count,0));
|
||||
sector_table->Reset_All();
|
||||
}
|
||||
|
||||
/*
|
||||
** Copy its bits into the object tables
|
||||
*/
|
||||
for (j=0; j<object_count; j++) {
|
||||
ObjectTables[j].Table->Set_Bit(i,sector_table->Get_Bit(j) != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Release it
|
||||
*/
|
||||
REF_PTR_RELEASE(sector_table);
|
||||
}
|
||||
}
|
||||
|
||||
void VisOptimizationContextClass::Combine_Redundant_Objects(void)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i<ObjectTables.Count(); i++) {
|
||||
|
||||
/*
|
||||
** Take a copy of object table 'i' for comparisons
|
||||
*/
|
||||
VisTableClass *table_i = NEW_REF (VisTableClass, (*(ObjectTables[i].Table)));
|
||||
|
||||
for (j=i+1; j<ObjectTables.Count(); j++) {
|
||||
|
||||
/*
|
||||
** Compare table 'j' with the original copy of table 'i'
|
||||
*/
|
||||
float frac = table_i->Match_Fraction(*(ObjectTables[j].Table));
|
||||
if (frac > MinVisObjectMatchFraction) {
|
||||
Combine_Object_Tables(i,j);
|
||||
Stats.Increment_Objects_Merged();
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
Stats.Increment_Completed_Operations();
|
||||
REF_PTR_RELEASE (table_i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VisOptimizationContextClass::Build_Sector_Tables_From_Object_Tables(VisTableMgrClass * vis_mgr)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i<vis_mgr->Get_Vis_Table_Count(); i++) {
|
||||
|
||||
PVSInfoStruct sectorinfo;
|
||||
sectorinfo.Table = NEW_REF(VisTableClass,(ObjectTables.Count(),0));
|
||||
sectorinfo.UnUsed = (vis_mgr->Has_Vis_Table(i) == false);
|
||||
|
||||
for (j=0; j<ObjectTables.Count(); j++) {
|
||||
sectorinfo.Table->Set_Bit(j,(ObjectTables[j].Table->Get_Bit(i) != 0));
|
||||
}
|
||||
SectorTables.Add(sectorinfo);
|
||||
}
|
||||
}
|
||||
|
||||
void VisOptimizationContextClass::Combine_Redundant_Sectors(void)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0; i<SectorTables.Count(); i++) {
|
||||
|
||||
/*
|
||||
** Take a copy of object table 'i' for comparisons
|
||||
*/
|
||||
VisTableClass *table_i = NEW_REF (VisTableClass, (*(SectorTables[i].Table)));
|
||||
|
||||
for (j=i+1; j<SectorTables.Count(); j++) {
|
||||
|
||||
/*
|
||||
** Compare table 'j' with the original copy of table 'i'
|
||||
*/
|
||||
float frac = table_i->Match_Fraction(*(SectorTables[j].Table));
|
||||
if (frac > MinVisSectorMatchFraction) {
|
||||
Combine_Sector_Tables(i,j);
|
||||
Stats.Increment_Sectors_Merged();
|
||||
j--;
|
||||
}
|
||||
}
|
||||
Stats.Increment_Completed_Operations(1);
|
||||
REF_PTR_RELEASE (table_i);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VisOptimizationContextClass::Combine_Sector_Tables(int sector_id_0,int sector_id_1)
|
||||
{
|
||||
/*
|
||||
** Sort the given id's into ascending order
|
||||
*/
|
||||
int id0 = sector_id_0;
|
||||
int id1 = sector_id_1;
|
||||
if (id0 > id1) {
|
||||
int tmp = id0;
|
||||
id0 = id1;
|
||||
id1 = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Merge the second table into the first.
|
||||
*/
|
||||
SectorTables[id0].Table->Merge(*(SectorTables[id1].Table));
|
||||
SectorTables.Delete(id1);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** Remove the id1'th bit from each object_table
|
||||
*/
|
||||
for (int i=0; i<ObjectTables.Count(); i++) {
|
||||
ObjectTables[i].Table->Delete_Bit(id1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Tell the physics scene to merge any sector with id1 into id0
|
||||
*/
|
||||
Scene->Merge_Vis_Sector_IDs(id0,id1);
|
||||
}
|
||||
|
||||
void VisOptimizationContextClass::Combine_Object_Tables(int object_id_0,int object_id_1)
|
||||
{
|
||||
/*
|
||||
** Sort the given id's into ascending order
|
||||
*/
|
||||
int id0 = object_id_0;
|
||||
int id1 = object_id_1;
|
||||
if (id0 > id1) {
|
||||
int tmp = id0;
|
||||
id0 = id1;
|
||||
id1 = tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
** Merge the second table into the first
|
||||
*/
|
||||
ObjectTables[id0].Table->Merge(*(ObjectTables[id1].Table));
|
||||
ObjectTables.Delete(id1);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
** Remove the id1'th bit from each sector table
|
||||
*/
|
||||
for (int i=0; i<SectorTables.Count(); i++) {
|
||||
SectorTables[i].Table->Delete_Bit(id1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Tell the physics scene to merge any object with id1 into id0
|
||||
*/
|
||||
Scene->Merge_Vis_Object_IDs(id0,id1);
|
||||
}
|
||||
|
||||
|
||||
void VisOptimizationContextClass::Install_Results(VisTableMgrClass * vismgr)
|
||||
{
|
||||
if (vismgr == NULL) {
|
||||
WWDEBUG_SAY(("Error! NULL VisTableMgrClass passed into Install_Results\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** First, reset the contents of the vis manager
|
||||
*/
|
||||
vismgr->Reset();
|
||||
|
||||
/*
|
||||
** Allocate the ID's needed (which also sets the number of tables and the size of each table)
|
||||
*/
|
||||
vismgr->Set_Optimized_Vis_Object_Count(ObjectTables.Count());
|
||||
vismgr->Allocate_Vis_Sector_ID(SectorTables.Count());
|
||||
|
||||
/*
|
||||
** Install the Vis Tables.
|
||||
*/
|
||||
for (int i=0; i<SectorTables.Count(); i++) {
|
||||
if (SectorTables[i].UnUsed != true) {
|
||||
|
||||
vismgr->Update_Vis_Table(i,SectorTables[i].Table);
|
||||
REF_PTR_RELEASE(SectorTables[i].Table);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int VisOptimizationContextClass::Get_Vis_Sector_Count(void)
|
||||
{
|
||||
return SectorTables.Count();
|
||||
}
|
||||
|
||||
int VisOptimizationContextClass::Get_Vis_Object_Count(void)
|
||||
{
|
||||
return ObjectTables.Count();
|
||||
}
|
||||
|
||||
VisOptProgressClass & VisOptimizationContextClass::Get_Progress_Object(void)
|
||||
{
|
||||
return Stats;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user