gridcull.cpp 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024
  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 : WWMath *
  23. * *
  24. * $Archive:: /Commando/Code/wwmath/gridcull.cpp $*
  25. * *
  26. * Author:: Greg Hjelstrom *
  27. * *
  28. * $Modtime:: 4/27/00 7:00p $*
  29. * *
  30. * $Revision:: 18 $*
  31. * *
  32. *---------------------------------------------------------------------------------------------*
  33. * Functions: *
  34. * GridCullSystemClass::GridCullSystemClass -- Constructor *
  35. * GridCullSystemClass::~GridCullSystemClass -- Destructor *
  36. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given point *
  37. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given AABox *
  38. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given OBBox *
  39. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given Frustum *
  40. * GridCullSystemClass::Re_Partition -- re-compute grid parameters for the given volume *
  41. * GridCullSystemClass::Collect_And_Unlink_All -- collects all objects and removes them from *
  42. * GridCullSystemClass::Update_Culling -- updates an objects position in the grid *
  43. * GridCullSystemClass::Load -- load function *
  44. * GridCullSystemClass::Save -- Save function *
  45. * GridCullSystemClass::Reset_Statistics -- reset debugging stats *
  46. * GridCullSystemClass::Get_Statistics -- returns reference to the statistics structure *
  47. * GridCullSystemClass::Add_Object_Internal -- links an object into the system *
  48. * GridCullSystemClass::Remove_Object_Internal -- unlinks an object from the system *
  49. * GridCullSystemClass::link_object -- figures out which cell the object is in and links it *
  50. * GridCullSystemClass::unlink_object -- unlinks the object from the cell it is in *
  51. * GridCullSystemClass::link_object_to_list -- grid list link function *
  52. * GridCullSystemClass::unlink_object_from_list -- grid list unlink function *
  53. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  54. #include "gridcull.h"
  55. #include "chunkio.h"
  56. #include "iostruct.h"
  57. #include "colmath.h"
  58. #include "colmathinlines.h"
  59. /*
  60. ** Declare the pool for GridLinks
  61. */
  62. DEFINE_AUTO_POOL(GridLinkClass,256);
  63. /*
  64. ** Current version of the file format
  65. */
  66. const uint32 GRID_CURRENT_VERSION = 0x00010000;
  67. /*
  68. ** Chunk Id's used by the aabtree code to save itself into a file
  69. */
  70. enum
  71. {
  72. GRID_CHUNK_VERSION = 0x00000001, // version wrapper, contains 32bit version #
  73. GRID_CHUNK_PARAMETERS = 0x00000100, // parameters for the grid cull system
  74. };
  75. /*
  76. ** IOGridParametersStruct
  77. ** Data structure for the contents of a node in the AAB-Tree
  78. */
  79. struct IOGridParametersStruct
  80. {
  81. IOVector3Struct MinCellSize;
  82. IOVector3Struct Origin;
  83. IOVector3Struct CellDim;
  84. uint32 CellCount[3];
  85. float32 MaxObjExtent;
  86. };
  87. /*************************************************************************
  88. **
  89. ** Utility functions for walking the object list in an AABTree Node
  90. **
  91. *************************************************************************/
  92. static inline CullableClass * get_next_object(CullableClass * obj)
  93. {
  94. return ((GridLinkClass *)obj->Get_Cull_Link())->Next;
  95. }
  96. /*************************************************************************
  97. **
  98. ** GridLinkClass Implementation
  99. **
  100. *************************************************************************/
  101. GridLinkClass::GridLinkClass(GridCullSystemClass * system) :
  102. CullLinkClass(system),
  103. GridAddress(-1),
  104. Prev(NULL),
  105. Next(NULL)
  106. {
  107. }
  108. GridLinkClass::~GridLinkClass(void)
  109. {
  110. }
  111. /*************************************************************************
  112. **
  113. ** GridCullSystemClass Implementation
  114. **
  115. *************************************************************************/
  116. /***********************************************************************************************
  117. * GridCullSystemClass::GridCullSystemClass -- Constructor *
  118. * *
  119. * INPUT: *
  120. * *
  121. * OUTPUT: *
  122. * *
  123. * WARNINGS: *
  124. * *
  125. * HISTORY: *
  126. * 4/27/2000 gth : Created. *
  127. *=============================================================================================*/
  128. GridCullSystemClass::GridCullSystemClass(void) :
  129. MinCellSize(10,10,10),
  130. MaxObjExtent(15),
  131. Origin(-100,-100,-100),
  132. CellDim(10,10,10),
  133. Cells(NULL),
  134. NoGridList(NULL),
  135. ObjCount(0),
  136. TerminationCellCount(TERMINATION_CELL_COUNT)
  137. {
  138. CellCount[0] = CellCount[1] = CellCount[2] = 0;
  139. Re_Partition(Vector3(-100,-100,-100),Vector3(100,100,100),15);
  140. Reset_Statistics();
  141. }
  142. /***********************************************************************************************
  143. * GridCullSystemClass::~GridCullSystemClass -- Destructor *
  144. * *
  145. * INPUT: *
  146. * *
  147. * OUTPUT: *
  148. * *
  149. * WARNINGS: *
  150. * *
  151. * HISTORY: *
  152. * 4/27/2000 gth : Created. *
  153. *=============================================================================================*/
  154. GridCullSystemClass::~GridCullSystemClass(void)
  155. {
  156. if (Cells != NULL) {
  157. delete Cells;
  158. Cells = NULL;
  159. }
  160. }
  161. /***********************************************************************************************
  162. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given point *
  163. * *
  164. * INPUT: *
  165. * *
  166. * OUTPUT: *
  167. * *
  168. * WARNINGS: *
  169. * *
  170. * HISTORY: *
  171. * 4/27/2000 gth : Created. *
  172. *=============================================================================================*/
  173. void GridCullSystemClass::Collect_Objects(const Vector3 & point)
  174. {
  175. /*
  176. ** Collect the objects in the grid
  177. */
  178. VolumeStruct vol;
  179. init_volume(point,point,&vol);
  180. if (!vol.Is_Empty()) {
  181. int delta_x = vol.Max[0] - vol.Min[0];
  182. int i,j,k;
  183. int address = map_indices_to_address(vol.Min[0],vol.Min[1],vol.Min[2]);
  184. for (k=vol.Min[2]; k<vol.Max[2]; k++) {
  185. for (j=vol.Min[1]; j<vol.Max[1]; j++) {
  186. for (i=vol.Min[0]; i<vol.Max[0]; i++) {
  187. GRIDCULL_NODE_TRIVIALLY_ACCEPTED;
  188. collect_objects_in_leaf(point,Cells[address]);
  189. address++;
  190. }
  191. address -= delta_x;
  192. address += CellCount[0];
  193. }
  194. address = map_indices_to_address(vol.Min[0],vol.Min[1],k+1);
  195. }
  196. }
  197. /*
  198. ** Collect the objects in the no-grid-list
  199. */
  200. collect_objects_in_leaf(point,NoGridList);
  201. }
  202. /***********************************************************************************************
  203. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given AABox *
  204. * *
  205. * INPUT: *
  206. * *
  207. * OUTPUT: *
  208. * *
  209. * WARNINGS: *
  210. * *
  211. * HISTORY: *
  212. * 4/27/2000 gth : Created. *
  213. *=============================================================================================*/
  214. void GridCullSystemClass::Collect_Objects(const AABoxClass & box)
  215. {
  216. /*
  217. ** Collect the objects in the grid
  218. */
  219. VolumeStruct vol;
  220. init_volume(box,&vol);
  221. if (!vol.Is_Empty()) {
  222. int delta_x = vol.Max[0] - vol.Min[0];
  223. int i,j,k;
  224. int address = map_indices_to_address(vol.Min[0],vol.Min[1],vol.Min[2]);
  225. for (k=vol.Min[2]; k<vol.Max[2]; k++) {
  226. for (j=vol.Min[1]; j<vol.Max[1]; j++) {
  227. for (i=vol.Min[0]; i<vol.Max[0]; i++) {
  228. GRIDCULL_NODE_TRIVIALLY_ACCEPTED;
  229. collect_objects_in_leaf(box,Cells[address]);
  230. address++;
  231. }
  232. address -= delta_x;
  233. address += CellCount[0];
  234. }
  235. address = map_indices_to_address(vol.Min[0],vol.Min[1],k+1);
  236. }
  237. }
  238. /*
  239. ** Collect the objects in the no-grid-list
  240. */
  241. collect_objects_in_leaf(box,NoGridList);
  242. }
  243. /***********************************************************************************************
  244. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given OBBox *
  245. * *
  246. * INPUT: *
  247. * *
  248. * OUTPUT: *
  249. * *
  250. * WARNINGS: *
  251. * *
  252. * HISTORY: *
  253. * 4/27/2000 gth : Created. *
  254. *=============================================================================================*/
  255. void GridCullSystemClass::Collect_Objects(const OBBoxClass & box)
  256. {
  257. /*
  258. ** Collect the objects in the grid
  259. */
  260. VolumeStruct vol;
  261. init_volume(box,&vol);
  262. if (!vol.Is_Empty()) {
  263. int delta_x = vol.Max[0] - vol.Min[0];
  264. int i,j,k;
  265. int address = map_indices_to_address(vol.Min[0],vol.Min[1],vol.Min[2]);
  266. for (k=vol.Min[2]; k<vol.Max[2]; k++) {
  267. for (j=vol.Min[1]; j<vol.Max[1]; j++) {
  268. for (i=vol.Min[0]; i<vol.Max[0]; i++) {
  269. GRIDCULL_NODE_TRIVIALLY_ACCEPTED;
  270. collect_objects_in_leaf(box,Cells[address]);
  271. address++;
  272. }
  273. address -= delta_x;
  274. address += CellCount[0];
  275. }
  276. address = map_indices_to_address(vol.Min[0],vol.Min[1],k+1);
  277. }
  278. }
  279. /*
  280. ** Collect the objects in the no-grid-list
  281. */
  282. collect_objects_in_leaf(box,NoGridList);
  283. }
  284. /***********************************************************************************************
  285. * GridCullSystemClass::Collect_Objects -- Collect all objects touching the given Frustum *
  286. * *
  287. * INPUT: *
  288. * *
  289. * OUTPUT: *
  290. * *
  291. * WARNINGS: *
  292. * *
  293. * HISTORY: *
  294. * 4/27/2000 gth : Created. *
  295. *=============================================================================================*/
  296. void GridCullSystemClass::Collect_Objects(const FrustumClass & frustum)
  297. {
  298. /*
  299. ** Collect the objects in the grid
  300. */
  301. VolumeStruct vol;
  302. init_volume(frustum,&vol);
  303. if (!vol.Is_Empty()) {
  304. int delta_x = vol.Max[0] - vol.Min[0];
  305. int i,j,k;
  306. int address = map_indices_to_address(vol.Min[0],vol.Min[1],vol.Min[2]);
  307. for (k=vol.Min[2]; k<vol.Max[2]; k++) {
  308. for (j=vol.Min[1]; j<vol.Max[1]; j++) {
  309. for (i=vol.Min[0]; i<vol.Max[0]; i++) {
  310. GRIDCULL_NODE_TRIVIALLY_ACCEPTED;
  311. collect_objects_in_leaf(frustum,Cells[address]);
  312. address++;
  313. }
  314. address -= delta_x;
  315. address += CellCount[0];
  316. }
  317. address = map_indices_to_address(vol.Min[0],vol.Min[1],k+1);
  318. }
  319. }
  320. /*
  321. ** Collect the objects in the no-grid-list
  322. */
  323. collect_objects_in_leaf(frustum,NoGridList);
  324. }
  325. /***********************************************************************************************
  326. * GridCullSystemClass::Re_Partition -- re-compute grid parameters for the given volume *
  327. * *
  328. * *
  329. * *
  330. * *
  331. * INPUT: *
  332. * input_min - 'min' corner of the world *
  333. * input_max - 'max' corner of the world *
  334. * objdim - largest object dimesion that will be allowed in the grid *
  335. * *
  336. * OUTPUT: *
  337. * *
  338. * WARNINGS: *
  339. * *
  340. * HISTORY: *
  341. * 4/27/2000 gth : Created. *
  342. *=============================================================================================*/
  343. void GridCullSystemClass::Re_Partition(const Vector3 & input_min,const Vector3 & input_max,float objdim)
  344. {
  345. /*
  346. ** grab all objects into the collection list and unlink them from the grid
  347. */
  348. Reset_Collection();
  349. Collect_And_Unlink_All();
  350. /*
  351. ** Do a sanity check on the input parameters
  352. */
  353. Vector3 min = input_min;
  354. Vector3 max = input_max;
  355. if (max.X - min.X < 1.0f) {
  356. max.X += MinCellSize.X;
  357. min.X -= MinCellSize.X;
  358. }
  359. if (max.Y - min.Y < 1.0f) {
  360. max.Y += MinCellSize.Y;
  361. min.Y -= MinCellSize.Y;
  362. }
  363. if (max.Z - min.Z < 1.0f) {
  364. max.Z += MinCellSize.Z;
  365. min.Z -= MinCellSize.Z;
  366. }
  367. /*
  368. ** Compute the grid parameters
  369. */
  370. Origin = min;
  371. Vector3 world_dim = max - min;
  372. MaxObjExtent = objdim;
  373. WWASSERT(world_dim.X > 0.0f);
  374. WWASSERT(world_dim.Y > 0.0f);
  375. WWASSERT(world_dim.Z > 0.0f);
  376. /*
  377. ** how many cells should we use on each dimension?
  378. */
  379. CellCount[0] = CellCount[1] = CellCount[2] = 1;
  380. CellDim = world_dim;
  381. bool done = false;
  382. while (!done) {
  383. /*
  384. ** find biggest dimension
  385. */
  386. int bigdim = 0;
  387. if (CellDim[1]/MinCellSize[1] > CellDim[bigdim]/MinCellSize[bigdim]) bigdim = 1;
  388. if (CellDim[2]/MinCellSize[2] > CellDim[bigdim]/MinCellSize[bigdim]) bigdim = 2;
  389. /*
  390. ** split dimension in two if possible
  391. */
  392. if (CellDim[bigdim] >= 2.0f * MinCellSize[bigdim]) {
  393. CellDim[bigdim] /= 2.0f;
  394. CellCount[bigdim] *= 2;
  395. }
  396. /*
  397. ** check termination conditions
  398. */
  399. if (total_cell_count() >= TerminationCellCount) {
  400. done = true;
  401. }
  402. if ( (CellDim[0] < 2.0*MinCellSize[0]) &&
  403. (CellDim[1] < 2.0*MinCellSize[1]) &&
  404. (CellDim[2] < 2.0*MinCellSize[2]) ) {
  405. done = true;
  406. }
  407. }
  408. OOCellDim.X = 1.0f / CellDim.X;
  409. OOCellDim.Y = 1.0f / CellDim.Y;
  410. OOCellDim.Z = 1.0f / CellDim.Z;
  411. if (Cells != NULL) {
  412. delete[] Cells;
  413. }
  414. Cells = new CullableClass * [total_cell_count()];
  415. memset(&(Cells[0]),0,total_cell_count() * sizeof(CullableClass *));
  416. /*
  417. ** iterate the collection list and re-insert all objects into the grid
  418. */
  419. CullableClass * obj;
  420. for ( obj = Get_First_Collected_Object_Internal();
  421. obj != NULL;
  422. obj = Get_Next_Collected_Object_Internal(obj))
  423. {
  424. link_object(obj);
  425. }
  426. }
  427. /***********************************************************************************************
  428. * GridCullSystemClass::Collect_And_Unlink_All -- collects all objects and removes them from t *
  429. * *
  430. * This is used when re-partitioning the grid. All objects are pulled out and linked into *
  431. * the collection list. When the grid has been re-initialized, the objects are put back in. *
  432. * *
  433. * INPUT: *
  434. * *
  435. * OUTPUT: *
  436. * *
  437. * WARNINGS: *
  438. * *
  439. * HISTORY: *
  440. * 4/27/2000 gth : Created. *
  441. *=============================================================================================*/
  442. void GridCullSystemClass::Collect_And_Unlink_All(void)
  443. {
  444. Reset_Collection();
  445. /*
  446. ** pull all objects out of the grid
  447. */
  448. for (int k=0; k<CellCount[2]; k++) {
  449. for (int j=0; j<CellCount[1]; j++) {
  450. for (int i=0; i<CellCount[0]; i++) {
  451. /*
  452. ** collect and unlink all objects in cell(i,j,k)
  453. */
  454. CullableClass * obj = Cells[map_indices_to_address(i,j,k)];
  455. while (obj) {
  456. CullableClass * nextobj = get_next_object(obj);
  457. unlink_object(obj);
  458. Add_To_Collection(obj);
  459. obj = nextobj;
  460. }
  461. }
  462. }
  463. }
  464. /*
  465. ** pull all objects out of the "no-grid" list
  466. */
  467. CullableClass * obj = NoGridList;
  468. while (obj) {
  469. CullableClass * nextobj = get_next_object(obj);
  470. unlink_object(obj);
  471. Add_To_Collection(obj);
  472. obj = nextobj;
  473. }
  474. }
  475. /***********************************************************************************************
  476. * GridCullSystemClass::Update_Culling -- updates an objects position in the grid *
  477. * *
  478. * INPUT: *
  479. * *
  480. * OUTPUT: *
  481. * *
  482. * WARNINGS: *
  483. * *
  484. * HISTORY: *
  485. * 4/27/2000 gth : Created. *
  486. *=============================================================================================*/
  487. void GridCullSystemClass::Update_Culling(CullableClass * obj)
  488. {
  489. WWASSERT(obj);
  490. WWASSERT(obj->Get_Culling_System() == this);
  491. int address;
  492. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  493. map_point_to_address(obj->Get_Cull_Box().Center,address);
  494. if (address != link->GridAddress) {
  495. unlink_object(obj);
  496. link_object(obj,address);
  497. }
  498. }
  499. /***********************************************************************************************
  500. * GridCullSystemClass::Load -- load function *
  501. * *
  502. * INPUT: *
  503. * *
  504. * OUTPUT: *
  505. * *
  506. * WARNINGS: *
  507. * *
  508. * HISTORY: *
  509. * 4/27/2000 gth : Created. *
  510. *=============================================================================================*/
  511. void GridCullSystemClass::Load(ChunkLoadClass & cload)
  512. {
  513. /*
  514. ** read the version chunk
  515. */
  516. uint32 version;
  517. cload.Open_Chunk();
  518. WWASSERT(cload.Cur_Chunk_ID() == GRID_CHUNK_VERSION);
  519. cload.Read(&version,sizeof(version));
  520. cload.Close_Chunk();
  521. /*
  522. ** read the parameters chunk
  523. */
  524. IOGridParametersStruct params;
  525. memset(&params,0,sizeof(params));
  526. cload.Open_Chunk();
  527. WWASSERT(cload.Cur_Chunk_ID() == GRID_CHUNK_PARAMETERS);
  528. cload.Read(&params,sizeof(params));
  529. cload.Close_Chunk();
  530. /*
  531. ** unlink all objects
  532. */
  533. Collect_And_Unlink_All();
  534. /*
  535. ** partition the grid according to the loaded parameters
  536. */
  537. CellCount[0] = params.CellCount[0];
  538. CellCount[1] = params.CellCount[1];
  539. CellCount[2] = params.CellCount[2];
  540. CellDim.X = params.CellDim.X;
  541. CellDim.Y = params.CellDim.Y;
  542. CellDim.Z = params.CellDim.Z;
  543. MaxObjExtent = params.MaxObjExtent;
  544. MinCellSize.X = params.MinCellSize.X;
  545. MinCellSize.Y = params.MinCellSize.Y;
  546. MinCellSize.Z = params.MinCellSize.Z;
  547. Origin.X = params.Origin.X;
  548. Origin.Y = params.Origin.Y;
  549. Origin.Z = params.Origin.Z;
  550. OOCellDim.X = 1.0f / CellDim.X;
  551. OOCellDim.Y = 1.0f / CellDim.Y;
  552. OOCellDim.Z = 1.0f / CellDim.Z;
  553. if (Cells != NULL) {
  554. delete [] Cells;
  555. Cells = NULL;
  556. }
  557. Cells = new CullableClass * [total_cell_count()];
  558. memset(&(Cells[0]),0,total_cell_count() * sizeof(CullableClass *));
  559. /*
  560. ** re-link the objects in
  561. */
  562. CullableClass * obj;
  563. for ( obj = Get_First_Collected_Object_Internal();
  564. obj != NULL;
  565. obj = Get_Next_Collected_Object_Internal(obj))
  566. {
  567. link_object(obj);
  568. }
  569. }
  570. /***********************************************************************************************
  571. * GridCullSystemClass::Save -- Save function *
  572. * *
  573. * INPUT: *
  574. * *
  575. * OUTPUT: *
  576. * *
  577. * WARNINGS: *
  578. * *
  579. * HISTORY: *
  580. * 4/27/2000 gth : Created. *
  581. *=============================================================================================*/
  582. void GridCullSystemClass::Save(ChunkSaveClass & csave)
  583. {
  584. /*
  585. ** write the version chunk
  586. */
  587. uint32 version = GRID_CURRENT_VERSION;
  588. csave.Begin_Chunk(GRID_CHUNK_VERSION);
  589. csave.Write(&version,sizeof(version));
  590. csave.End_Chunk();
  591. /*
  592. ** write the grid parameters
  593. */
  594. IOGridParametersStruct params;
  595. memset(&params,0,sizeof(params));
  596. params.CellCount[0] = CellCount[0];
  597. params.CellCount[1] = CellCount[1];
  598. params.CellCount[2] = CellCount[2];
  599. params.CellDim.X = CellDim.X;
  600. params.CellDim.Y = CellDim.Y;
  601. params.CellDim.Z = CellDim.Z;
  602. params.MaxObjExtent = MaxObjExtent;
  603. params.MinCellSize.X = MinCellSize.X;
  604. params.MinCellSize.Y = MinCellSize.Y;
  605. params.MinCellSize.Z = MinCellSize.Z;
  606. params.Origin.X = Origin.X;
  607. params.Origin.Y = Origin.Y;
  608. params.Origin.Z = Origin.Z;
  609. csave.Begin_Chunk(GRID_CHUNK_PARAMETERS);
  610. csave.Write(&params,sizeof(params));
  611. csave.End_Chunk();
  612. }
  613. /***********************************************************************************************
  614. * GridCullSystemClass::Reset_Statistics -- reset debugging stats *
  615. * *
  616. * INPUT: *
  617. * *
  618. * OUTPUT: *
  619. * *
  620. * WARNINGS: *
  621. * *
  622. * HISTORY: *
  623. * 4/27/2000 gth : Created. *
  624. *=============================================================================================*/
  625. void GridCullSystemClass::Reset_Statistics(void)
  626. {
  627. // number of (virtual) nodes = 2n-1
  628. Stats.NodeCount = 2 * (CellCount[0] * CellCount[1] * CellCount[2]) - 1;
  629. Stats.NodesAccepted = 0;
  630. Stats.NodesTriviallyAccepted = 0;
  631. Stats.NodesRejected = 0;
  632. }
  633. /***********************************************************************************************
  634. * GridCullSystemClass::Get_Statistics -- returns reference to the statistics structure *
  635. * *
  636. * INPUT: *
  637. * *
  638. * OUTPUT: *
  639. * *
  640. * WARNINGS: *
  641. * *
  642. * HISTORY: *
  643. * 4/27/2000 gth : Created. *
  644. *=============================================================================================*/
  645. const GridCullSystemClass::StatsStruct & GridCullSystemClass::Get_Statistics(void)
  646. {
  647. return Stats;
  648. }
  649. /***********************************************************************************************
  650. * GridCullSystemClass::Add_Object_Internal -- links an object into the system *
  651. * *
  652. * INPUT: *
  653. * *
  654. * OUTPUT: *
  655. * *
  656. * WARNINGS: *
  657. * *
  658. * HISTORY: *
  659. * 4/27/2000 gth : Created. *
  660. *=============================================================================================*/
  661. void GridCullSystemClass::Add_Object_Internal(CullableClass * obj)
  662. {
  663. WWASSERT(obj);
  664. WWASSERT(obj->Get_Culling_System() == NULL);
  665. GridLinkClass * link = new GridLinkClass(this);
  666. obj->Set_Cull_Link(link);
  667. link_object(obj);
  668. ObjCount++;
  669. obj->Add_Ref();
  670. }
  671. /***********************************************************************************************
  672. * GridCullSystemClass::Remove_Object_Internal -- unlinks an object from the system *
  673. * *
  674. * INPUT: *
  675. * *
  676. * OUTPUT: *
  677. * *
  678. * WARNINGS: *
  679. * *
  680. * HISTORY: *
  681. * 4/27/2000 gth : Created. *
  682. *=============================================================================================*/
  683. void GridCullSystemClass::Remove_Object_Internal(CullableClass * obj)
  684. {
  685. WWASSERT(obj);
  686. WWASSERT(obj->Get_Culling_System() == this);
  687. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  688. unlink_object(obj);
  689. link->Set_Culling_System(NULL);
  690. delete link;
  691. obj->Set_Cull_Link(NULL);
  692. ObjCount--;
  693. obj->Release_Ref();
  694. }
  695. /***********************************************************************************************
  696. * GridCullSystemClass::link_object -- figures out which cell the object is in and links it *
  697. * *
  698. * INPUT: *
  699. * *
  700. * OUTPUT: *
  701. * *
  702. * WARNINGS: *
  703. * *
  704. * HISTORY: *
  705. * 4/27/2000 gth : Created. *
  706. *=============================================================================================*/
  707. void GridCullSystemClass::link_object(CullableClass * obj)
  708. {
  709. WWASSERT(obj);
  710. WWASSERT(obj->Get_Culling_System() == this);
  711. int address;
  712. map_point_to_address(obj->Get_Cull_Box().Center,address);
  713. link_object(obj,address);
  714. }
  715. void GridCullSystemClass::link_object(CullableClass * obj,int address)
  716. {
  717. WWASSERT(obj);
  718. WWASSERT(obj->Get_Culling_System() == this);
  719. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  720. WWASSERT(link != NULL);
  721. /*
  722. ** if obj cannot be inserted into the grid, add it to the NoGridList
  723. ** otherwise, insert it into the cell
  724. */
  725. const AABoxClass & box = obj->Get_Cull_Box();
  726. if (
  727. (box.Extent.X > MaxObjExtent) ||
  728. (box.Extent.Y > MaxObjExtent) ||
  729. (box.Extent.Z > MaxObjExtent) ||
  730. (address == UNGRIDDED_ADDRESS)
  731. )
  732. {
  733. link->GridAddress = UNGRIDDED_ADDRESS;
  734. link_object_to_list(&NoGridList,obj);
  735. } else {
  736. link->GridAddress = address;
  737. link_object_to_list(&(Cells[address]),obj);
  738. }
  739. }
  740. /***********************************************************************************************
  741. * GridCullSystemClass::unlink_object -- unlinks the object from the cell it is in *
  742. * *
  743. * INPUT: *
  744. * *
  745. * OUTPUT: *
  746. * *
  747. * WARNINGS: *
  748. * *
  749. * HISTORY: *
  750. * 4/27/2000 gth : Created. *
  751. *=============================================================================================*/
  752. void GridCullSystemClass::unlink_object(CullableClass * obj)
  753. {
  754. WWASSERT(obj);
  755. WWASSERT(obj->Get_Culling_System() == this);
  756. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  757. if (link->GridAddress == UNGRIDDED_ADDRESS) {
  758. unlink_object_from_list(&NoGridList,obj);
  759. } else {
  760. unlink_object_from_list(&(Cells[link->GridAddress]),obj);
  761. }
  762. }
  763. /***********************************************************************************************
  764. * GridCullSystemClass::link_object_to_list -- grid list link function *
  765. * *
  766. * INPUT: *
  767. * *
  768. * OUTPUT: *
  769. * *
  770. * WARNINGS: *
  771. * *
  772. * HISTORY: *
  773. * 4/27/2000 gth : Created. *
  774. *=============================================================================================*/
  775. void GridCullSystemClass::link_object_to_list(CullableClass ** head,CullableClass * obj)
  776. {
  777. WWASSERT(obj);
  778. WWASSERT(obj->Get_Culling_System() == this);
  779. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  780. /*
  781. ** Insert this object as the new head of the list.
  782. */
  783. link->Next = *head;
  784. link->Prev = NULL;
  785. if (link->Next != NULL) {
  786. GridLinkClass * next_link = (GridLinkClass *)link->Next->Get_Cull_Link();
  787. WWASSERT(next_link != NULL);
  788. next_link->Prev = obj;
  789. }
  790. *head = obj;
  791. }
  792. /***********************************************************************************************
  793. * GridCullSystemClass::unlink_object_from_list -- grid list unlink function *
  794. * *
  795. * INPUT: *
  796. * *
  797. * OUTPUT: *
  798. * *
  799. * WARNINGS: *
  800. * *
  801. * HISTORY: *
  802. * 4/27/2000 gth : Created. *
  803. *=============================================================================================*/
  804. void GridCullSystemClass::unlink_object_from_list(CullableClass ** head,CullableClass * obj)
  805. {
  806. WWASSERT(obj);
  807. WWASSERT(obj->Get_Culling_System() == this);
  808. GridLinkClass * link = (GridLinkClass *)obj->Get_Cull_Link();
  809. /*
  810. ** check to see that the object is actually in this list
  811. */
  812. #ifdef WWDEBUG
  813. CullableClass * tmp = *head;
  814. bool found = false;
  815. while (tmp && !found) {
  816. if (tmp == obj) found = true;
  817. tmp = ((GridLinkClass *)(tmp->Get_Cull_Link()))->Next;
  818. }
  819. WWASSERT(found);
  820. #endif
  821. /*
  822. ** If we were the head of the list, make the head point to the next object
  823. */
  824. if (obj == *head) {
  825. *head = link->Next;
  826. }
  827. /*
  828. ** Link the object previous to us to our next...
  829. */
  830. if (link->Prev) {
  831. GridLinkClass * prev_link = (GridLinkClass *)link->Prev->Get_Cull_Link();
  832. prev_link->Next = link->Next;
  833. }
  834. /*
  835. ** Link the objects after us to our previous...
  836. */
  837. if (link->Next) {
  838. GridLinkClass * next_link = (GridLinkClass *)link->Next->Get_Cull_Link();
  839. next_link->Prev = link->Prev;
  840. }
  841. link->Prev = NULL;
  842. link->Next = NULL;
  843. }
  844. /*************************************************************************
  845. **
  846. ** GridCullSystem Internal Leaf-iterating collection functions
  847. **
  848. *************************************************************************/
  849. void GridCullSystemClass::collect_objects_in_leaf(const Vector3 & point,CullableClass * head)
  850. {
  851. if (head != NULL) {
  852. GridListIterator it(head);
  853. for (;!it.Is_Done(); it.Next()) {
  854. CullableClass * obj = it.Peek_Obj();
  855. if (obj->Get_Cull_Box ().Contains (point) == true) {
  856. Add_To_Collection(obj);
  857. }
  858. }
  859. }
  860. }
  861. void GridCullSystemClass::collect_objects_in_leaf(const AABoxClass & box,CullableClass * head)
  862. {
  863. if (head != NULL) {
  864. GridListIterator it(head);
  865. for (;!it.Is_Done(); it.Next()) {
  866. CullableClass * obj = it.Peek_Obj();
  867. if (CollisionMath::Overlap_Test(box,obj->Get_Cull_Box()) != CollisionMath::OUTSIDE) {
  868. Add_To_Collection(obj);
  869. }
  870. }
  871. }
  872. }
  873. void GridCullSystemClass::collect_objects_in_leaf(const OBBoxClass & obbox,CullableClass * head)
  874. {
  875. if (head != NULL) {
  876. GridListIterator it(head);
  877. for (;!it.Is_Done(); it.Next()) {
  878. CullableClass * obj = it.Peek_Obj();
  879. if (CollisionMath::Overlap_Test(obbox,obj->Get_Cull_Box()) != CollisionMath::OUTSIDE) {
  880. Add_To_Collection(obj);
  881. }
  882. }
  883. }
  884. }
  885. void GridCullSystemClass::collect_objects_in_leaf(const FrustumClass & frustum,CullableClass * head)
  886. {
  887. if (head != NULL) {
  888. GridListIterator it(head);
  889. for (;!it.Is_Done(); it.Next()) {
  890. CullableClass * obj = it.Peek_Obj();
  891. if (CollisionMath::Overlap_Test(frustum,obj->Get_Cull_Box()) != CollisionMath::OUTSIDE) {
  892. Add_To_Collection(obj);
  893. }
  894. }
  895. }
  896. }