staticaabtreecull.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  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/staticaabtreecull.cpp $*
  25. * *
  26. * Original Author:: Greg Hjelstrom *
  27. * *
  28. * $Author:: Greg_h $*
  29. * *
  30. * $Modtime:: 1/19/02 5:38p $*
  31. * *
  32. * $Revision:: 26 $*
  33. * *
  34. *---------------------------------------------------------------------------------------------*
  35. * Functions: *
  36. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  37. #include "staticaabtreecull.h"
  38. #include "staticphys.h"
  39. #include "wwphystrig.h"
  40. #include "ww3d.h"
  41. #include "wwphysids.h"
  42. #include "camera.h"
  43. #include "shader.h"
  44. #include "vertmaterial.h"
  45. #include "vistable.h"
  46. #include "visrasterizer.h"
  47. #include "chunkio.h"
  48. #include "visrendercontext.h"
  49. #include "colmathfrustum.h"
  50. #include "colmathplane.h"
  51. #include "colmathaabox.h"
  52. #include "wwmemlog.h"
  53. #define LOG_HIERARCHICAL_CULLING 0
  54. #define VIS_SAMPLE_DISTANCE 20.0f
  55. /*
  56. ** Static variables
  57. */
  58. static int _HierarchicalCellsRejected = 0;
  59. /*
  60. ** Chunk Id's used by the static-aabtree code to save itself into a file
  61. */
  62. enum
  63. {
  64. STATICAABTREE_CHUNK_VERSION = 0x00000001, // OBSOLETE version wrapper, contains 32bit version #
  65. STATICAABTREE_CHUNK_AABTREE_CLASS_DATA = 0x00000104, // wraps the AABTreeCullSystemClass's save data
  66. };
  67. /*
  68. ** StaticAABTreeCullClass is a derived AABTree which assumes it contains StaticPhysClasses
  69. ** these two functions encapsulate some typecasting which happens in a lot
  70. ** of places...
  71. */
  72. inline StaticPhysClass * get_first_object(AABTreeNodeClass * node)
  73. {
  74. return (StaticPhysClass *)(node->Object);
  75. }
  76. inline StaticPhysClass * get_next_object(StaticPhysClass * tile)
  77. {
  78. return (StaticPhysClass *)(((AABTreeLinkClass *)tile->Get_Cull_Link())->NextObject);
  79. }
  80. /*
  81. ** Implementation of StaticAABTreeCullClass
  82. */
  83. StaticAABTreeCullClass::StaticAABTreeCullClass(PhysicsSceneClass * pscene) :
  84. PhysAABTreeCullClass(pscene)
  85. {
  86. }
  87. StaticAABTreeCullClass::~StaticAABTreeCullClass(void)
  88. {
  89. }
  90. void StaticAABTreeCullClass::Add_Object(PhysClass * obj, int cull_node_id /*= -1*/)
  91. {
  92. WWASSERT(Scene != NULL);
  93. WWASSERT(obj->As_StaticPhysClass() != NULL);
  94. PhysAABTreeCullClass::Add_Object(obj, cull_node_id);
  95. // (gth) not resetting vis when adding a static object
  96. // Scene->Reset_Vis();
  97. }
  98. void StaticAABTreeCullClass::Remove_Object(PhysClass * obj)
  99. {
  100. WWASSERT(Scene != NULL);
  101. WWASSERT(obj->As_StaticPhysClass() != NULL);
  102. PhysAABTreeCullClass::Remove_Object(obj);
  103. // (gth) not resetting vis when removing a static object
  104. // Scene->Reset_Vis();
  105. }
  106. void StaticAABTreeCullClass::Update_Culling(CullableClass * obj)
  107. {
  108. WWASSERT(Scene != NULL);
  109. PhysAABTreeCullClass::Update_Culling(obj);
  110. // (gth) not resetting vis when moving a static object
  111. // Scene->Reset_Vis();
  112. }
  113. void StaticAABTreeCullClass::Collect_Visible_Objects
  114. (
  115. const FrustumClass & frustum,
  116. VisTableClass * pvs,
  117. RefPhysListClass & visobjlist,
  118. RefPhysListClass & wsmeshlist
  119. )
  120. {
  121. WWASSERT(RootNode != NULL);
  122. if (pvs != NULL) {
  123. /*
  124. ** If we got a pvs then we call the custom hierarchical visible object
  125. ** collection function.
  126. */
  127. VisObjCollectContextClass context(frustum,*pvs,visobjlist,wsmeshlist);
  128. if (Scene->Is_Vis_Inverted() || !Is_Hierarchical_Vis_Culling_Enabled()) {
  129. Collect_Visible_Objects_No_HVis_Recursive(RootNode,context);
  130. } else {
  131. _HierarchicalCellsRejected = 0;
  132. Collect_Visible_Objects_Recursive(RootNode,context);
  133. #if LOG_HIERARCHICAL_CULLING
  134. if (_HierarchicalCellsRejected > 0) {
  135. WWDEBUG_SAY(("HCells Rejected: %d\n",_HierarchicalCellsRejected));
  136. }
  137. #endif
  138. }
  139. } else {
  140. /*
  141. ** Otherwise, just call the built-in frustum collection function and
  142. ** link the objects into the given lists
  143. */
  144. Reset_Collection();
  145. Collect_Objects(frustum);
  146. /*
  147. ** Loop over each object, adding it into the list
  148. */
  149. StaticPhysClass * obj;
  150. for ( obj = (StaticPhysClass *)Get_First_Collected_Object();
  151. obj != NULL;
  152. obj = (StaticPhysClass *)Get_Next_Collected_Object(obj))
  153. {
  154. if (obj->Is_World_Space_Mesh()) {
  155. wsmeshlist.Add(obj);
  156. } else {
  157. visobjlist.Add(obj);
  158. }
  159. }
  160. }
  161. }
  162. void StaticAABTreeCullClass::Collect_Visible_Objects_Recursive
  163. (
  164. AABTreeNodeClass * node,
  165. VisObjCollectContextClass & context
  166. )
  167. {
  168. /*
  169. ** If this node is not visible, stop.
  170. */
  171. if (context.PVS.Get_Bit(node->UserData) == 0) {
  172. #if LOG_HIERARCHICAL_CULLING
  173. _HierarchicalCellsRejected++;
  174. #endif
  175. NODE_REJECTED();
  176. return;
  177. }
  178. /*
  179. ** Cull the bounding volume of this node against the frustum.
  180. ** If it is culled, stop descending the tree.
  181. */
  182. CollisionMath::OverlapType overlap;
  183. overlap = CollisionMath::Overlap_Test(context.Frustum,node->Box,context.PlanesPassed);
  184. if (overlap == CollisionMath::OUTSIDE) {
  185. NODE_REJECTED();
  186. return;
  187. }
  188. NODE_ACCEPTED();
  189. /*
  190. ** Test any objects in this node
  191. */
  192. if (node->Object) {
  193. StaticPhysClass * obj = get_first_object(node);
  194. while (obj) {
  195. if ( (context.PVS.Get_Bit(obj->Get_Vis_Object_ID()) != 0) &&
  196. (CollisionMath::Overlap_Test(context.Frustum,obj->Get_Cull_Box(),context.PlanesPassed) != CollisionMath::OUTSIDE) )
  197. {
  198. if (obj->Is_World_Space_Mesh()) {
  199. context.WSMeshList.Add(obj);
  200. } else {
  201. context.VisObjList.Add(obj);
  202. }
  203. }
  204. obj = get_next_object(obj);
  205. }
  206. }
  207. /*
  208. ** Recurse into the children
  209. */
  210. if (node->Back) {
  211. Collect_Visible_Objects_Recursive(node->Back,context);
  212. }
  213. if (node->Front) {
  214. Collect_Visible_Objects_Recursive(node->Front,context);
  215. }
  216. }
  217. void StaticAABTreeCullClass::Collect_Visible_Objects_No_HVis_Recursive
  218. (
  219. AABTreeNodeClass * node,
  220. VisObjCollectContextClass & context
  221. )
  222. {
  223. /*
  224. ** Cull the bounding volume of this node against the frustum.
  225. ** If it is culled, stop descending the tree.
  226. */
  227. CollisionMath::OverlapType overlap;
  228. overlap = CollisionMath::Overlap_Test(context.Frustum,node->Box,context.PlanesPassed);
  229. if (overlap == CollisionMath::OUTSIDE) {
  230. NODE_REJECTED();
  231. return;
  232. }
  233. NODE_ACCEPTED();
  234. /*
  235. ** Test any objects in this node
  236. */
  237. if (node->Object) {
  238. StaticPhysClass * obj = get_first_object(node);
  239. while (obj) {
  240. if ( (context.PVS.Get_Bit(obj->Get_Vis_Object_ID()) != 0) &&
  241. (CollisionMath::Overlap_Test(context.Frustum,obj->Get_Cull_Box(),context.PlanesPassed) != CollisionMath::OUTSIDE) )
  242. {
  243. if (obj->Is_World_Space_Mesh()) {
  244. context.WSMeshList.Add(obj);
  245. } else {
  246. context.VisObjList.Add(obj);
  247. }
  248. }
  249. obj = get_next_object(obj);
  250. }
  251. }
  252. /*
  253. ** Recurse into the children
  254. */
  255. if (node->Back) {
  256. Collect_Visible_Objects_No_HVis_Recursive(node->Back,context);
  257. }
  258. if (node->Front) {
  259. Collect_Visible_Objects_No_HVis_Recursive(node->Front,context);
  260. }
  261. }
  262. void StaticAABTreeCullClass::Assign_Vis_IDs(void)
  263. {
  264. /*
  265. ** Allocate sector and object ID's for the objects in the leaf nodes.
  266. */
  267. int nodecount = Partition_Node_Count();
  268. for (int i=0; i<nodecount; i++) {
  269. AABTreeNodeClass * node = IndexedNodes[i];
  270. /*
  271. ** assign a vis-object-id to each node in the tree (for hierarchical visibility!)
  272. */
  273. node->UserData = Scene->Allocate_Vis_Object_ID();
  274. /*
  275. ** assign vis-object-id's to all objects in this node.
  276. ** assign vis-sector-id's to any object that contains vis meshes.
  277. */
  278. StaticPhysClass * obj = get_first_object(node);
  279. while(obj) {
  280. obj->Set_Vis_Object_ID(Scene->Allocate_Vis_Object_ID());
  281. if (obj->Is_Vis_Sector()) {
  282. obj->Set_Vis_Sector_ID(Scene->Allocate_Vis_Sector_ID());
  283. }
  284. obj = get_next_object(obj);
  285. }
  286. }
  287. }
  288. void StaticAABTreeCullClass::Evaluate_Occluder_Visibility
  289. (
  290. VisRenderContextClass & context,
  291. VisSampleClass & sample
  292. )
  293. {
  294. context.VisRasterizer->Set_Render_Mode(IDBufferClass::OCCLUDER_MODE);
  295. context.VisRasterizer->Clear();
  296. Render_Occluders(RootNode,context);
  297. context.Scan_Frame_Buffer(&sample);
  298. }
  299. void StaticAABTreeCullClass::Evaluate_Non_Occluder_Visibility
  300. (
  301. VisRenderContextClass & context,
  302. VisSampleClass & sample
  303. )
  304. {
  305. /*
  306. ** Tell the rasterizer to not write into its Z-buffer and to always exit early
  307. */
  308. context.VisRasterizer->Set_Render_Mode(IDBufferClass::NON_OCCLUDER_MODE);
  309. /*
  310. ** Collect the non-occluder render objects
  311. */
  312. RefPhysListClass non_occluders;
  313. Collect_Non_Occluders(RootNode,context,non_occluders);
  314. if (context.Is_Vis_Quick_And_Dirty()) {
  315. RefPhysListIterator it(&non_occluders);
  316. for (it.First(); !it.Is_Done(); it.Next()) {
  317. StaticPhysClass * obj = (StaticPhysClass *)it.Peek_Obj();
  318. WWASSERT(obj != NULL);
  319. context.VisTable.Set_Bit(obj->Get_Vis_Object_ID(),true);
  320. }
  321. } else {
  322. RefPhysListIterator it(&non_occluders);
  323. for (it.First(); !it.Is_Done(); it.Next()) {
  324. StaticPhysClass * obj = (StaticPhysClass *)it.Peek_Obj();
  325. WWASSERT(obj != NULL);
  326. /*
  327. ** If the camera is inside the bounding box of this non-occluder; mark it visible
  328. */
  329. if (obj->Get_Bounding_Box().Contains(context.Camera.Get_Position())) {
  330. context.VisTable.Set_Bit(obj->Get_Vis_Object_ID(),true);
  331. }
  332. /*
  333. ** Check this object if its bounding box is in view and we don't already
  334. ** think it can be seen.
  335. */
  336. if ( !context.Camera.Cull_Box(obj->Get_Bounding_Box()) &&
  337. (context.VisTable.Get_Bit(obj->Get_Vis_Object_ID()) == 0) )
  338. {
  339. context.VisRasterizer->Reset_Pixel_Counter();
  340. context.Set_Vis_ID(obj->Get_Vis_Object_ID()); // set up the vis id
  341. obj->Vis_Render(context); // render the model
  342. if (context.VisRasterizer->Get_Pixel_Counter() > 0) { // if any pixels passed, the obj is visible!
  343. context.VisTable.Set_Bit(obj->Get_Vis_Object_ID(),true);
  344. #if 0
  345. /*
  346. ** DEBUGGING!!! If _test_vis_id is visible, display the vis buffer!
  347. ** If you want to use this, disable the early exit above:
  348. ** (context.VisTable.Get_Bit(obj->Get_Vis_Object_ID() == 0)
  349. */
  350. static int _test_vis_id = -1;
  351. if ((_test_vis_id != -1) && (obj->Get_Vis_Object_ID() == _test_vis_id)) {
  352. context.Set_Vis_ID(0x00FFFFFF); // set up a highly visible vis id
  353. context.VisRasterizer->Set_Render_Mode(IDBufferClass::OCCLUDER_MODE);
  354. obj->Vis_Render(context);
  355. PhysicsSceneClass::Get_Instance()->On_Vis_Occluders_Rendered(context,sample);
  356. context.VisRasterizer->Set_Render_Mode(IDBufferClass::NON_OCCLUDER_MODE);
  357. }
  358. #endif
  359. }
  360. }
  361. }
  362. }
  363. }
  364. void StaticAABTreeCullClass::Render_Occluders(AABTreeNodeClass * node,VisRenderContextClass & context)
  365. {
  366. if (context.Camera.Cull_Box(node->Box)) {
  367. return;
  368. }
  369. if (node->Object) {
  370. StaticPhysClass * obj = get_first_object(node);
  371. while(obj) {
  372. if (obj->Is_Occluder()) {
  373. context.Set_Vis_ID(obj->Get_Vis_Object_ID());
  374. obj->Vis_Render(context);
  375. }
  376. obj = get_next_object(obj);
  377. }
  378. }
  379. if (node->Back) {
  380. Render_Occluders(node->Back,context);
  381. }
  382. if (node->Front) {
  383. Render_Occluders(node->Front,context);
  384. }
  385. }
  386. void StaticAABTreeCullClass::Collect_Non_Occluders
  387. (
  388. AABTreeNodeClass * node,
  389. VisRenderContextClass & context,
  390. RefPhysListClass & non_occluder_list
  391. )
  392. {
  393. if (context.Camera.Cull_Box(node->Box)) {
  394. return;
  395. }
  396. if (node->Object) {
  397. StaticPhysClass * obj = get_first_object(node);
  398. while(obj) {
  399. if (!obj->Is_Occluder()) {
  400. non_occluder_list.Add(obj);
  401. }
  402. obj = get_next_object(obj);
  403. }
  404. }
  405. if (node->Back) {
  406. Collect_Non_Occluders(node->Back,context,non_occluder_list);
  407. }
  408. if (node->Front) {
  409. Collect_Non_Occluders(node->Front,context,non_occluder_list);
  410. }
  411. }
  412. StaticPhysClass * StaticAABTreeCullClass::Find_Vis_Tile(const Vector3 & sample_point)
  413. {
  414. Vector3 p0 = sample_point;
  415. Vector3 p1 = p0;
  416. p1.Z -= VIS_SAMPLE_DISTANCE;
  417. //
  418. // Cast a fat box down
  419. //
  420. CastResultStruct box_result;
  421. AABoxClass box(p0,Vector3(0.05f,0.05f,0.0f));
  422. PhysAABoxCollisionTestClass boxtest(box,p1-p0,&box_result,0,COLLISION_TYPE_VIS);
  423. boxtest.CheckDynamicObjs = false;
  424. Cast_AABox(boxtest);
  425. //
  426. // Cast a ray down
  427. //
  428. CastResultStruct ray_result;
  429. LineSegClass ray(p0,p1);
  430. PhysRayCollisionTestClass raytest(ray,&ray_result,0,COLLISION_TYPE_VIS);
  431. raytest.CheckDynamicObjs = false;
  432. Cast_Ray(raytest);
  433. //
  434. // Use the ray result, unless the fat box result was a lot closer to
  435. // the camera point (this is the case where the ray went through a crack or something. (ug)
  436. //
  437. float box_dist = -(box_result.Fraction * (p1.Z - p0.Z));
  438. float ray_dist = -(ray_result.Fraction * (p1.Z - p0.Z));
  439. if ((ray_dist > 3.5f) && (box_dist < ray_dist - 1.0f) && (box_result.Fraction < 1.0f)) {
  440. // return pointer to the tile that the box hit
  441. WWASSERT(boxtest.CollidedPhysObj);
  442. WWASSERT(boxtest.CollidedPhysObj->As_StaticPhysClass() != NULL);
  443. return (StaticPhysClass *)boxtest.CollidedPhysObj;
  444. } else if (ray_result.Fraction < 1.0f) {
  445. // return pointer to the tile that the ray hit
  446. WWASSERT(raytest.CollidedPhysObj);
  447. WWASSERT(raytest.CollidedPhysObj->As_StaticPhysClass() != NULL);
  448. return (StaticPhysClass *)raytest.CollidedPhysObj;
  449. } else {
  450. return NULL;
  451. }
  452. }
  453. int StaticAABTreeCullClass::Get_Vis_Sector_ID(const Vector3 & sample_point)
  454. {
  455. StaticPhysClass * tile = Find_Vis_Tile(sample_point);
  456. if (tile == NULL) {
  457. return -1;
  458. }
  459. return tile->Get_Vis_Sector_ID();
  460. }
  461. void StaticAABTreeCullClass::Propogate_Hierarchical_Visibility(VisTableClass * pvs)
  462. {
  463. Propogate_Hierarchical_Visibility_Recursive(RootNode,pvs);
  464. }
  465. void StaticAABTreeCullClass::Propogate_Hierarchical_Visibility_Recursive
  466. (
  467. AABTreeNodeClass * node,
  468. VisTableClass * pvs
  469. )
  470. {
  471. /*
  472. ** Recurse to the bottom of the tree first
  473. */
  474. if (node->Front != NULL) {
  475. Propogate_Hierarchical_Visibility_Recursive(node->Front,pvs);
  476. }
  477. if (node->Back != NULL) {
  478. Propogate_Hierarchical_Visibility_Recursive(node->Back,pvs);
  479. }
  480. /*
  481. ** We can only turn on the visibility of this node if any of its children
  482. ** are visible. Turning off the visibility is not allowed because we may
  483. ** be sharing our vis-object-id with another node due to vis-compression.
  484. */
  485. bool child_visible = Is_Child_Visible(node,pvs);
  486. if (child_visible) {
  487. pvs->Set_Bit(node->UserData,true);
  488. }
  489. }
  490. bool StaticAABTreeCullClass::Is_Child_Visible
  491. (
  492. AABTreeNodeClass * node,
  493. VisTableClass * pvs
  494. )
  495. {
  496. /*
  497. ** If this is a leaf node, we check for visibility of any contained objects
  498. ** Otherwise we check if either of the child nodes are visible
  499. */
  500. if ((node->Front != NULL) && (pvs->Get_Bit(node->Front->UserData) != 0)) {
  501. return true;
  502. }
  503. if ((node->Back != NULL) && (pvs->Get_Bit(node->Back->UserData) != 0)) {
  504. return true;
  505. }
  506. StaticPhysClass * obj = get_first_object(node);
  507. while(obj) {
  508. if (pvs->Get_Bit(obj->Get_Vis_Object_ID()) != 0) {
  509. return true;
  510. }
  511. obj = get_next_object(obj);
  512. }
  513. return false;
  514. }
  515. void StaticAABTreeCullClass::Merge_Vis_Object_IDs(uint32 id0,uint32 id1)
  516. {
  517. /*
  518. ** Each node and each staticphys object has a vis object id.
  519. ** Whenever we encounter one of these with id1, set it to id0.
  520. ** Whenever we encounter one with id > id1, subtract one from it.
  521. */
  522. for (int i=0; i<NodeCount; i++) {
  523. AABTreeNodeClass * node = IndexedNodes[i];
  524. if (node->UserData == id1) {
  525. node->UserData = id0;
  526. } else if (node->UserData > id1) {
  527. node->UserData--;
  528. }
  529. StaticPhysClass * obj = get_first_object(node);
  530. while (obj) {
  531. uint32 obj_id = obj->Get_Vis_Object_ID();
  532. if (obj_id != 0xFFFFFFFF) {
  533. if (obj_id == id1) {
  534. obj_id = id0;
  535. } else if (obj_id > id1) {
  536. obj_id--;
  537. }
  538. obj->Set_Vis_Object_ID(obj_id);
  539. }
  540. obj = get_next_object(obj);
  541. }
  542. }
  543. }
  544. void StaticAABTreeCullClass::Merge_Vis_Sector_IDs(uint32 id0,uint32 id1)
  545. {
  546. /*
  547. ** Each staticphys object may have a vis sector id.
  548. ** Whenever we encounter one of these with id1, set it to id0.
  549. ** Whenever we encounter one with id > id1, subtract one from it.
  550. */
  551. for (int i=0; i<NodeCount; i++) {
  552. AABTreeNodeClass * node = IndexedNodes[i];
  553. StaticPhysClass * obj = get_first_object(node);
  554. while (obj) {
  555. uint32 sector_id = obj->Get_Vis_Sector_ID();
  556. if (sector_id != 0xFFFFFFFF) {
  557. if (sector_id == id1) {
  558. sector_id = id0;
  559. } else if (sector_id > id1) {
  560. sector_id--;
  561. }
  562. obj->Set_Vis_Sector_ID(sector_id);
  563. }
  564. obj = get_next_object(obj);
  565. }
  566. }
  567. }
  568. void StaticAABTreeCullClass::Load_Static_Data(ChunkLoadClass & cload)
  569. {
  570. WWMEMLOG(MEM_CULLINGDATA);
  571. while(cload.Open_Chunk())
  572. {
  573. switch(cload.Cur_Chunk_ID())
  574. {
  575. case STATICAABTREE_CHUNK_AABTREE_CLASS_DATA:
  576. {
  577. TypedAABTreeCullSystemClass<PhysClass>::Load(cload);
  578. }
  579. break;
  580. default:
  581. WWDEBUG_SAY(("Unhandled chunk type: %d in StaticAABTreeCullClass::Load\r\n",cload.Cur_Chunk_ID()));
  582. break;
  583. }
  584. cload.Close_Chunk();
  585. }
  586. }
  587. void StaticAABTreeCullClass::Save_Static_Data(ChunkSaveClass & csave)
  588. {
  589. csave.Begin_Chunk(STATICAABTREE_CHUNK_AABTREE_CLASS_DATA);
  590. TypedAABTreeCullSystemClass<PhysClass>::Save(csave);
  591. csave.End_Chunk();
  592. }