visoptimizationcontext.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /***********************************************************************************************
  19. *** 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 ***
  20. ***********************************************************************************************
  21. * *
  22. * Project Name : WWPhys *
  23. * *
  24. * $Archive:: /Commando/Code/wwphys/visoptimizationcontext.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Patrick $*
  29. * *
  30. * $Modtime:: 11/16/00 7:31p $*
  31. * *
  32. * $Revision:: 12 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "visoptimizationcontext.h"
  38. #include "visoptprogress.h"
  39. #include "pscene.h"
  40. #include "vistablemgr.h"
  41. #include "vistable.h"
  42. #include "dynamicaabtreecull.h"
  43. #include "wwdebug.h"
  44. const float MIN_OBJECT_MATCH_FRACTION = 0.99f;
  45. const float MIN_SECTOR_MATCH_FRACTION = 0.99f;
  46. const float MIN_PRUNE_MATCH_FRACTION = 0.90f;
  47. /***************************************************************************************************
  48. **
  49. ** PVSInfoStruct Implementation
  50. **
  51. ***************************************************************************************************/
  52. VisOptimizationContextClass::PVSInfoStruct::PVSInfoStruct(void) :
  53. Table(NULL),
  54. UnUsed(false)
  55. {
  56. }
  57. VisOptimizationContextClass::PVSInfoStruct::~PVSInfoStruct(void)
  58. {
  59. REF_PTR_RELEASE(Table);
  60. }
  61. const VisOptimizationContextClass::PVSInfoStruct &
  62. VisOptimizationContextClass::PVSInfoStruct::operator = (const PVSInfoStruct & that)
  63. {
  64. REF_PTR_SET(Table,that.Table);
  65. UnUsed = that.UnUsed;
  66. return *this;
  67. }
  68. /***************************************************************************************************
  69. **
  70. ** VisOptimizationContextClass Implementation
  71. **
  72. ***************************************************************************************************/
  73. VisOptimizationContextClass::VisOptimizationContextClass
  74. (
  75. PhysicsSceneClass * scene,
  76. VisOptProgressClass & stats
  77. ) :
  78. MinDynCellPruneMatchFraction(MIN_PRUNE_MATCH_FRACTION),
  79. MinVisObjectMatchFraction(MIN_OBJECT_MATCH_FRACTION),
  80. MinVisSectorMatchFraction(MIN_SECTOR_MATCH_FRACTION),
  81. Scene(scene),
  82. Stats(stats)
  83. {
  84. WWASSERT(Scene != NULL);
  85. }
  86. VisOptimizationContextClass::~VisOptimizationContextClass(void)
  87. {
  88. }
  89. float VisOptimizationContextClass::Compute_Sector_Table_Match_Fraction(int sector_id_0,int sector_id_1)
  90. {
  91. if (SectorTables[sector_id_0].UnUsed || SectorTables[sector_id_1].UnUsed) {
  92. return 0.0f;
  93. }
  94. return SectorTables[sector_id_0].Table->Match_Fraction(*(SectorTables[sector_id_1].Table));
  95. }
  96. float VisOptimizationContextClass::Compute_Object_Table_Match_Fraction(int object_id_0,int object_id_1)
  97. {
  98. return ObjectTables[object_id_0].Table->Match_Fraction(*(ObjectTables[object_id_1].Table));
  99. }
  100. void VisOptimizationContextClass::Optimize
  101. (
  102. VisTableMgrClass * vis_mgr,
  103. DynamicAABTreeCullClass * dyn_obj_tree
  104. )
  105. {
  106. /*
  107. ** Generate the object tables
  108. */
  109. Build_Object_Tables(vis_mgr);
  110. /*
  111. ** Prune redundant leaves of the dynamic object culling tree. This operation actually
  112. ** deletes leaf nodes from the tree.
  113. */
  114. dyn_obj_tree->Prune_Redundant_Leaf_Nodes(*this);
  115. /*
  116. ** Combine the redundant objects. This operation combines objects by assigning the
  117. ** same vis ID to both of them.
  118. */
  119. Combine_Redundant_Objects();
  120. /*
  121. ** Now that we're done combining objects, build new sector tables so that we
  122. ** can remove the redundant vis sectors. Each table will have a bitcount
  123. ** equal to the number of object tables.
  124. */
  125. Build_Sector_Tables_From_Object_Tables(vis_mgr);
  126. /*
  127. ** Now combine the redundant sectors
  128. */
  129. Combine_Redundant_Sectors();
  130. /*
  131. ** All done, so install the results
  132. */
  133. Install_Results(vis_mgr);
  134. }
  135. void VisOptimizationContextClass::Build_Object_Tables(VisTableMgrClass * vis_mgr)
  136. {
  137. /*
  138. ** Generate the object tables (what sectors can see each object). Consider the sector
  139. ** tables columns and the object tables rows of the same 2D grid of visibility bits.
  140. */
  141. int i,j;
  142. int sector_count = vis_mgr->Get_Vis_Table_Count();
  143. int object_count = vis_mgr->Get_Vis_Table_Size();
  144. ObjectTables.Resize(object_count);
  145. for (i=0; i<object_count; i++) {
  146. PVSInfoStruct objinfo;
  147. objinfo.Table = NEW_REF(VisTableClass,(sector_count,0));
  148. ObjectTables.Add(objinfo);
  149. }
  150. for (i=0; i<sector_count; i++) {
  151. /*
  152. ** Get each sector table
  153. */
  154. VisTableClass * sector_table = vis_mgr->Get_Vis_Table(i);
  155. if (sector_table == NULL) {
  156. sector_table = NEW_REF(VisTableClass,(object_count,0));
  157. sector_table->Reset_All();
  158. }
  159. /*
  160. ** Copy its bits into the object tables
  161. */
  162. for (j=0; j<object_count; j++) {
  163. ObjectTables[j].Table->Set_Bit(i,sector_table->Get_Bit(j) != 0);
  164. }
  165. /*
  166. ** Release it
  167. */
  168. REF_PTR_RELEASE(sector_table);
  169. }
  170. }
  171. void VisOptimizationContextClass::Combine_Redundant_Objects(void)
  172. {
  173. int i,j;
  174. for (i=0; i<ObjectTables.Count(); i++) {
  175. /*
  176. ** Take a copy of object table 'i' for comparisons
  177. */
  178. VisTableClass *table_i = NEW_REF (VisTableClass, (*(ObjectTables[i].Table)));
  179. for (j=i+1; j<ObjectTables.Count(); j++) {
  180. /*
  181. ** Compare table 'j' with the original copy of table 'i'
  182. */
  183. float frac = table_i->Match_Fraction(*(ObjectTables[j].Table));
  184. if (frac > MinVisObjectMatchFraction) {
  185. Combine_Object_Tables(i,j);
  186. Stats.Increment_Objects_Merged();
  187. j--;
  188. }
  189. }
  190. Stats.Increment_Completed_Operations();
  191. REF_PTR_RELEASE (table_i);
  192. }
  193. }
  194. void VisOptimizationContextClass::Build_Sector_Tables_From_Object_Tables(VisTableMgrClass * vis_mgr)
  195. {
  196. int i,j;
  197. for (i=0; i<vis_mgr->Get_Vis_Table_Count(); i++) {
  198. PVSInfoStruct sectorinfo;
  199. sectorinfo.Table = NEW_REF(VisTableClass,(ObjectTables.Count(),0));
  200. sectorinfo.UnUsed = (vis_mgr->Has_Vis_Table(i) == false);
  201. for (j=0; j<ObjectTables.Count(); j++) {
  202. sectorinfo.Table->Set_Bit(j,(ObjectTables[j].Table->Get_Bit(i) != 0));
  203. }
  204. SectorTables.Add(sectorinfo);
  205. }
  206. }
  207. void VisOptimizationContextClass::Combine_Redundant_Sectors(void)
  208. {
  209. int i,j;
  210. for (i=0; i<SectorTables.Count(); i++) {
  211. /*
  212. ** Take a copy of object table 'i' for comparisons
  213. */
  214. VisTableClass *table_i = NEW_REF (VisTableClass, (*(SectorTables[i].Table)));
  215. for (j=i+1; j<SectorTables.Count(); j++) {
  216. /*
  217. ** Compare table 'j' with the original copy of table 'i'
  218. */
  219. float frac = table_i->Match_Fraction(*(SectorTables[j].Table));
  220. if (frac > MinVisSectorMatchFraction) {
  221. Combine_Sector_Tables(i,j);
  222. Stats.Increment_Sectors_Merged();
  223. j--;
  224. }
  225. }
  226. Stats.Increment_Completed_Operations(1);
  227. REF_PTR_RELEASE (table_i);
  228. }
  229. }
  230. void VisOptimizationContextClass::Combine_Sector_Tables(int sector_id_0,int sector_id_1)
  231. {
  232. /*
  233. ** Sort the given id's into ascending order
  234. */
  235. int id0 = sector_id_0;
  236. int id1 = sector_id_1;
  237. if (id0 > id1) {
  238. int tmp = id0;
  239. id0 = id1;
  240. id1 = tmp;
  241. }
  242. /*
  243. ** Merge the second table into the first.
  244. */
  245. SectorTables[id0].Table->Merge(*(SectorTables[id1].Table));
  246. SectorTables.Delete(id1);
  247. #if 0
  248. /*
  249. ** Remove the id1'th bit from each object_table
  250. */
  251. for (int i=0; i<ObjectTables.Count(); i++) {
  252. ObjectTables[i].Table->Delete_Bit(id1);
  253. }
  254. #endif
  255. /*
  256. ** Tell the physics scene to merge any sector with id1 into id0
  257. */
  258. Scene->Merge_Vis_Sector_IDs(id0,id1);
  259. }
  260. void VisOptimizationContextClass::Combine_Object_Tables(int object_id_0,int object_id_1)
  261. {
  262. /*
  263. ** Sort the given id's into ascending order
  264. */
  265. int id0 = object_id_0;
  266. int id1 = object_id_1;
  267. if (id0 > id1) {
  268. int tmp = id0;
  269. id0 = id1;
  270. id1 = tmp;
  271. }
  272. /*
  273. ** Merge the second table into the first
  274. */
  275. ObjectTables[id0].Table->Merge(*(ObjectTables[id1].Table));
  276. ObjectTables.Delete(id1);
  277. #if 0
  278. /*
  279. ** Remove the id1'th bit from each sector table
  280. */
  281. for (int i=0; i<SectorTables.Count(); i++) {
  282. SectorTables[i].Table->Delete_Bit(id1);
  283. }
  284. #endif
  285. /*
  286. ** Tell the physics scene to merge any object with id1 into id0
  287. */
  288. Scene->Merge_Vis_Object_IDs(id0,id1);
  289. }
  290. void VisOptimizationContextClass::Install_Results(VisTableMgrClass * vismgr)
  291. {
  292. if (vismgr == NULL) {
  293. WWDEBUG_SAY(("Error! NULL VisTableMgrClass passed into Install_Results\n"));
  294. return;
  295. }
  296. /*
  297. ** First, reset the contents of the vis manager
  298. */
  299. vismgr->Reset();
  300. /*
  301. ** Allocate the ID's needed (which also sets the number of tables and the size of each table)
  302. */
  303. vismgr->Set_Optimized_Vis_Object_Count(ObjectTables.Count());
  304. vismgr->Allocate_Vis_Sector_ID(SectorTables.Count());
  305. /*
  306. ** Install the Vis Tables.
  307. */
  308. for (int i=0; i<SectorTables.Count(); i++) {
  309. if (SectorTables[i].UnUsed != true) {
  310. vismgr->Update_Vis_Table(i,SectorTables[i].Table);
  311. REF_PTR_RELEASE(SectorTables[i].Table);
  312. }
  313. }
  314. }
  315. int VisOptimizationContextClass::Get_Vis_Sector_Count(void)
  316. {
  317. return SectorTables.Count();
  318. }
  319. int VisOptimizationContextClass::Get_Vis_Object_Count(void)
  320. {
  321. return ObjectTables.Count();
  322. }
  323. VisOptProgressClass & VisOptimizationContextClass::Get_Progress_Object(void)
  324. {
  325. return Stats;
  326. }