| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- /*
- ** 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;
- }
|