bvh.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  1. /*************************************************************************/
  2. /* bvh.h */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2021 Godot Engine contributors (cf. AUTHORS.md). */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #ifndef BVH_H
  31. #define BVH_H
  32. // BVH
  33. // This class provides a wrapper around BVH tree, which contains most of the functionality
  34. // for a dynamic BVH with templated leaf size.
  35. // However BVH also adds facilities for pairing, to maintain compatibility with Godot 3.2.
  36. // Pairing is a collision pairing system, on top of the basic BVH.
  37. // Some notes on the use of BVH / Octree from Godot 3.2.
  38. // This is not well explained elsewhere.
  39. // The rendering tree mask and types that are sent to the BVH are NOT layer masks.
  40. // They are INSTANCE_TYPES (defined in visual_server.h), e.g. MESH, MULTIMESH, PARTICLES etc.
  41. // Thus the lights do no cull by layer mask in the BVH.
  42. // Layer masks are implemented in the renderers as a later step, and light_cull_mask appears to be
  43. // implemented in GLES3 but not GLES2. Layer masks are not yet implemented for directional lights.
  44. #include "bvh_tree.h"
  45. #define BVHTREE_CLASS BVH_Tree<T, 2, MAX_ITEMS, USE_PAIRS, Bounds, Point>
  46. template <class T, bool USE_PAIRS = false, int MAX_ITEMS = 32, class Bounds = AABB, class Point = Vector3>
  47. class BVH_Manager {
  48. public:
  49. // note we are using uint32_t instead of BVHHandle, losing type safety, but this
  50. // is for compatibility with octree
  51. typedef void *(*PairCallback)(void *, uint32_t, T *, int, uint32_t, T *, int);
  52. typedef void (*UnpairCallback)(void *, uint32_t, T *, int, uint32_t, T *, int, void *);
  53. // these 2 are crucial for fine tuning, and can be applied manually
  54. // see the variable declarations for more info.
  55. void params_set_node_expansion(real_t p_value) {
  56. if (p_value >= 0.0) {
  57. tree._node_expansion = p_value;
  58. tree._auto_node_expansion = false;
  59. } else {
  60. tree._auto_node_expansion = true;
  61. }
  62. }
  63. void params_set_pairing_expansion(real_t p_value) {
  64. if (p_value >= 0.0) {
  65. tree._pairing_expansion = p_value;
  66. tree._auto_pairing_expansion = false;
  67. } else {
  68. tree._auto_pairing_expansion = true;
  69. }
  70. }
  71. void set_pair_callback(PairCallback p_callback, void *p_userdata) {
  72. pair_callback = p_callback;
  73. pair_callback_userdata = p_userdata;
  74. }
  75. void set_unpair_callback(UnpairCallback p_callback, void *p_userdata) {
  76. unpair_callback = p_callback;
  77. unpair_callback_userdata = p_userdata;
  78. }
  79. BVHHandle create(T *p_userdata, bool p_active, const Bounds &p_aabb = Bounds(), int p_subindex = 0, bool p_pairable = false, uint32_t p_pairable_type = 0, uint32_t p_pairable_mask = 1) {
  80. // not sure if absolutely necessary to flush collisions here. It will cost performance to, instead
  81. // of waiting for update, so only uncomment this if there are bugs.
  82. if (USE_PAIRS) {
  83. //_check_for_collisions();
  84. }
  85. #ifdef TOOLS_ENABLED
  86. if (!USE_PAIRS) {
  87. if (p_pairable) {
  88. WARN_PRINT_ONCE("creating pairable item in BVH with USE_PAIRS set to false");
  89. }
  90. }
  91. #endif
  92. BVHHandle h = tree.item_add(p_userdata, p_active, p_aabb, p_subindex, p_pairable, p_pairable_type, p_pairable_mask);
  93. if (USE_PAIRS) {
  94. // for safety initialize the expanded AABB
  95. Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
  96. expanded_aabb = p_aabb;
  97. expanded_aabb.grow_by(tree._pairing_expansion);
  98. // force a collision check no matter the AABB
  99. if (p_active) {
  100. _add_changed_item(h, p_aabb, false);
  101. _check_for_collisions(true);
  102. }
  103. }
  104. return h;
  105. }
  106. ////////////////////////////////////////////////////
  107. // wrapper versions that use uint32_t instead of handle
  108. // for backward compatibility. Less type safe
  109. void move(uint32_t p_handle, const Bounds &p_aabb) {
  110. BVHHandle h;
  111. h.set(p_handle);
  112. move(h, p_aabb);
  113. }
  114. void erase(uint32_t p_handle) {
  115. BVHHandle h;
  116. h.set(p_handle);
  117. erase(h);
  118. }
  119. void force_collision_check(uint32_t p_handle) {
  120. BVHHandle h;
  121. h.set(p_handle);
  122. force_collision_check(h);
  123. }
  124. bool activate(uint32_t p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) {
  125. BVHHandle h;
  126. h.set(p_handle);
  127. return activate(h, p_aabb, p_delay_collision_check);
  128. }
  129. bool deactivate(uint32_t p_handle) {
  130. BVHHandle h;
  131. h.set(p_handle);
  132. return deactivate(h);
  133. }
  134. void set_pairable(uint32_t p_handle, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_force_collision_check = true) {
  135. BVHHandle h;
  136. h.set(p_handle);
  137. set_pairable(h, p_pairable, p_pairable_type, p_pairable_mask, p_force_collision_check);
  138. }
  139. bool is_pairable(uint32_t p_handle) const {
  140. BVHHandle h;
  141. h.set(p_handle);
  142. return item_is_pairable(h);
  143. }
  144. int get_subindex(uint32_t p_handle) const {
  145. BVHHandle h;
  146. h.set(p_handle);
  147. return item_get_subindex(h);
  148. }
  149. T *get(uint32_t p_handle) const {
  150. BVHHandle h;
  151. h.set(p_handle);
  152. return item_get_userdata(h);
  153. }
  154. ////////////////////////////////////////////////////
  155. void move(BVHHandle p_handle, const Bounds &p_aabb) {
  156. if (tree.item_move(p_handle, p_aabb)) {
  157. if (USE_PAIRS) {
  158. _add_changed_item(p_handle, p_aabb);
  159. }
  160. }
  161. }
  162. void erase(BVHHandle p_handle) {
  163. // call unpair and remove all references to the item
  164. // before deleting from the tree
  165. if (USE_PAIRS) {
  166. _remove_changed_item(p_handle);
  167. }
  168. tree.item_remove(p_handle);
  169. _check_for_collisions(true);
  170. }
  171. // use in conjunction with activate if you have deferred the collision check, and
  172. // set pairable has never been called.
  173. // (deferred collision checks are a workaround for visual server for historical reasons)
  174. void force_collision_check(BVHHandle p_handle) {
  175. if (USE_PAIRS) {
  176. // the aabb should already be up to date in the BVH
  177. Bounds aabb;
  178. item_get_AABB(p_handle, aabb);
  179. // add it as changed even if aabb not different
  180. _add_changed_item(p_handle, aabb, false);
  181. // force an immediate full collision check, much like calls to set_pairable
  182. _check_for_collisions(true);
  183. }
  184. }
  185. // these should be read as set_visible for render trees,
  186. // but generically this makes items add or remove from the
  187. // tree internally, to speed things up by ignoring inactive items
  188. bool activate(BVHHandle p_handle, const Bounds &p_aabb, bool p_delay_collision_check = false) {
  189. // sending the aabb here prevents the need for the BVH to maintain
  190. // a redundant copy of the aabb.
  191. // returns success
  192. if (tree.item_activate(p_handle, p_aabb)) {
  193. if (USE_PAIRS) {
  194. // in the special case of the render tree, when setting visibility we are using the combination of
  195. // activate then set_pairable. This would case 2 sets of collision checks. For efficiency here we allow
  196. // deferring to have a single collision check at the set_pairable call.
  197. // Watch for bugs! This may cause bugs if set_pairable is not called.
  198. if (!p_delay_collision_check) {
  199. _add_changed_item(p_handle, p_aabb, false);
  200. // force an immediate collision check, much like calls to set_pairable
  201. _check_for_collisions(true);
  202. }
  203. }
  204. return true;
  205. }
  206. return false;
  207. }
  208. bool deactivate(BVHHandle p_handle) {
  209. // returns success
  210. if (tree.item_deactivate(p_handle)) {
  211. // call unpair and remove all references to the item
  212. // before deleting from the tree
  213. if (USE_PAIRS) {
  214. _remove_changed_item(p_handle);
  215. // force check for collisions, much like an erase was called
  216. _check_for_collisions(true);
  217. }
  218. return true;
  219. }
  220. return false;
  221. }
  222. bool get_active(BVHHandle p_handle) const {
  223. return tree.item_get_active(p_handle);
  224. }
  225. // call e.g. once per frame (this does a trickle optimize)
  226. void update() {
  227. tree.update();
  228. _check_for_collisions();
  229. #ifdef BVH_INTEGRITY_CHECKS
  230. tree.integrity_check_all();
  231. #endif
  232. }
  233. // this can be called more frequently than per frame if necessary
  234. void update_collisions() {
  235. _check_for_collisions();
  236. }
  237. // prefer calling this directly as type safe
  238. void set_pairable(const BVHHandle &p_handle, bool p_pairable, uint32_t p_pairable_type, uint32_t p_pairable_mask, bool p_force_collision_check = true) {
  239. // Returns true if the pairing state has changed.
  240. bool state_changed = tree.item_set_pairable(p_handle, p_pairable, p_pairable_type, p_pairable_mask);
  241. if (USE_PAIRS) {
  242. // not sure if absolutely necessary to flush collisions here. It will cost performance to, instead
  243. // of waiting for update, so only uncomment this if there are bugs.
  244. //_check_for_collisions();
  245. if ((p_force_collision_check || state_changed) && get_active(p_handle)) {
  246. // when the pairable state changes, we need to force a collision check because newly pairable
  247. // items may be in collision, and unpairable items might move out of collision.
  248. // We cannot depend on waiting for the next update, because that may come much later.
  249. Bounds aabb;
  250. item_get_AABB(p_handle, aabb);
  251. // passing false disables the optimization which prevents collision checks if
  252. // the aabb hasn't changed
  253. _add_changed_item(p_handle, aabb, false);
  254. // force an immediate collision check (probably just for this one item)
  255. // but it must be a FULL collision check, also checking pairable state and masks.
  256. // This is because AABB intersecting objects may have changed pairable state / mask
  257. // such that they should no longer be paired. E.g. lights.
  258. _check_for_collisions(true);
  259. } // only if active
  260. }
  261. }
  262. // cull tests
  263. int cull_aabb(const Bounds &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  264. typename BVHTREE_CLASS::CullParams params;
  265. params.result_count_overall = 0;
  266. params.result_max = p_result_max;
  267. params.result_array = p_result_array;
  268. params.subindex_array = p_subindex_array;
  269. params.mask = p_mask;
  270. params.pairable_type = 0;
  271. params.test_pairable_only = false;
  272. params.abb.from(p_aabb);
  273. tree.cull_aabb(params);
  274. return params.result_count_overall;
  275. }
  276. int cull_segment(const Point &p_from, const Point &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  277. typename BVHTREE_CLASS::CullParams params;
  278. params.result_count_overall = 0;
  279. params.result_max = p_result_max;
  280. params.result_array = p_result_array;
  281. params.subindex_array = p_subindex_array;
  282. params.mask = p_mask;
  283. params.pairable_type = 0;
  284. params.segment.from = p_from;
  285. params.segment.to = p_to;
  286. tree.cull_segment(params);
  287. return params.result_count_overall;
  288. }
  289. int cull_point(const Point &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  290. typename BVHTREE_CLASS::CullParams params;
  291. params.result_count_overall = 0;
  292. params.result_max = p_result_max;
  293. params.result_array = p_result_array;
  294. params.subindex_array = p_subindex_array;
  295. params.mask = p_mask;
  296. params.pairable_type = 0;
  297. params.point = p_point;
  298. tree.cull_point(params);
  299. return params.result_count_overall;
  300. }
  301. int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask = 0xFFFFFFFF) {
  302. if (!p_convex.size()) {
  303. return 0;
  304. }
  305. Vector<Vector3> convex_points = Geometry::compute_convex_mesh_points(&p_convex[0], p_convex.size());
  306. if (convex_points.size() == 0) {
  307. return 0;
  308. }
  309. typename BVHTREE_CLASS::CullParams params;
  310. params.result_count_overall = 0;
  311. params.result_max = p_result_max;
  312. params.result_array = p_result_array;
  313. params.subindex_array = nullptr;
  314. params.mask = p_mask;
  315. params.pairable_type = 0;
  316. params.hull.planes = &p_convex[0];
  317. params.hull.num_planes = p_convex.size();
  318. params.hull.points = &convex_points[0];
  319. params.hull.num_points = convex_points.size();
  320. tree.cull_convex(params);
  321. return params.result_count_overall;
  322. }
  323. private:
  324. // do this after moving etc.
  325. void _check_for_collisions(bool p_full_check = false) {
  326. if (!changed_items.size()) {
  327. // noop
  328. return;
  329. }
  330. Bounds bb;
  331. typename BVHTREE_CLASS::CullParams params;
  332. params.result_count_overall = 0;
  333. params.result_max = INT_MAX;
  334. params.result_array = nullptr;
  335. params.subindex_array = nullptr;
  336. params.mask = 0xFFFFFFFF;
  337. params.pairable_type = 0;
  338. for (unsigned int n = 0; n < changed_items.size(); n++) {
  339. const BVHHandle &h = changed_items[n];
  340. // use the expanded aabb for pairing
  341. const Bounds &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
  342. BVHABB_CLASS abb;
  343. abb.from(expanded_aabb);
  344. // find all the existing paired aabbs that are no longer
  345. // paired, and send callbacks
  346. _find_leavers(h, abb, p_full_check);
  347. uint32_t changed_item_ref_id = h.id();
  348. // set up the test from this item.
  349. // this includes whether to test the non pairable tree,
  350. // and the item mask.
  351. tree.item_fill_cullparams(h, params);
  352. params.abb = abb;
  353. params.result_count_overall = 0; // might not be needed
  354. tree.cull_aabb(params, false);
  355. for (unsigned int i = 0; i < tree._cull_hits.size(); i++) {
  356. uint32_t ref_id = tree._cull_hits[i];
  357. // don't collide against ourself
  358. if (ref_id == changed_item_ref_id) {
  359. continue;
  360. }
  361. #ifdef BVH_CHECKS
  362. // if neither are pairable, they should ignore each other
  363. // THIS SHOULD NEVER HAPPEN .. now we only test the pairable tree
  364. // if the changed item is not pairable
  365. CRASH_COND(params.test_pairable_only && !tree._extra[ref_id].pairable);
  366. #endif
  367. // checkmasks is already done in the cull routine.
  368. BVHHandle h_collidee;
  369. h_collidee.set_id(ref_id);
  370. // find NEW enterers, and send callbacks for them only
  371. _collide(h, h_collidee);
  372. }
  373. }
  374. _reset();
  375. }
  376. public:
  377. void item_get_AABB(BVHHandle p_handle, Bounds &r_aabb) {
  378. BVHABB_CLASS abb;
  379. tree.item_get_ABB(p_handle, abb);
  380. abb.to(r_aabb);
  381. }
  382. private:
  383. // supplemental funcs
  384. bool item_is_pairable(BVHHandle p_handle) const { return _get_extra(p_handle).pairable; }
  385. T *item_get_userdata(BVHHandle p_handle) const { return _get_extra(p_handle).userdata; }
  386. int item_get_subindex(BVHHandle p_handle) const { return _get_extra(p_handle).subindex; }
  387. void _unpair(BVHHandle p_from, BVHHandle p_to) {
  388. tree._handle_sort(p_from, p_to);
  389. typename BVHTREE_CLASS::ItemExtra &exa = tree._extra[p_from.id()];
  390. typename BVHTREE_CLASS::ItemExtra &exb = tree._extra[p_to.id()];
  391. // if the userdata is the same, no collisions should occur
  392. if ((exa.userdata == exb.userdata) && exa.userdata) {
  393. return;
  394. }
  395. typename BVHTREE_CLASS::ItemPairs &pairs_from = tree._pairs[p_from.id()];
  396. typename BVHTREE_CLASS::ItemPairs &pairs_to = tree._pairs[p_to.id()];
  397. void *ud_from = pairs_from.remove_pair_to(p_to);
  398. pairs_to.remove_pair_to(p_from);
  399. // callback
  400. if (unpair_callback) {
  401. unpair_callback(pair_callback_userdata, p_from, exa.userdata, exa.subindex, p_to, exb.userdata, exb.subindex, ud_from);
  402. }
  403. }
  404. // returns true if unpair
  405. bool _find_leavers_process_pair(typename BVHTREE_CLASS::ItemPairs &p_pairs_from, const BVHABB_CLASS &p_abb_from, BVHHandle p_from, BVHHandle p_to, bool p_full_check) {
  406. BVHABB_CLASS abb_to;
  407. tree.item_get_ABB(p_to, abb_to);
  408. // do they overlap?
  409. if (p_abb_from.intersects(abb_to)) {
  410. // the full check for pairable / non pairable and mask changes is extra expense
  411. // this need not be done in most cases (for speed) except in the case where set_pairable is called
  412. // where the masks etc of the objects in question may have changed
  413. if (!p_full_check) {
  414. return false;
  415. }
  416. const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_from);
  417. const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_to);
  418. // one of the two must be pairable to still pair
  419. // if neither are pairable, we always unpair
  420. if (exa.pairable || exb.pairable) {
  421. // the masks must still be compatible to pair
  422. // i.e. if there is a hit between the two, then they should stay paired
  423. if (tree._cull_pairing_mask_test_hit(exa.pairable_mask, exa.pairable_type, exb.pairable_mask, exb.pairable_type)) {
  424. return false;
  425. }
  426. }
  427. }
  428. _unpair(p_from, p_to);
  429. return true;
  430. }
  431. // find all the existing paired aabbs that are no longer
  432. // paired, and send callbacks
  433. void _find_leavers(BVHHandle p_handle, const BVHABB_CLASS &expanded_abb_from, bool p_full_check) {
  434. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
  435. BVHABB_CLASS abb_from = expanded_abb_from;
  436. // remove from pairing list for every partner
  437. for (unsigned int n = 0; n < p_from.extended_pairs.size(); n++) {
  438. BVHHandle h_to = p_from.extended_pairs[n].handle;
  439. if (_find_leavers_process_pair(p_from, abb_from, p_handle, h_to, p_full_check)) {
  440. // we need to keep the counter n up to date if we deleted a pair
  441. // as the number of items in p_from.extended_pairs will have decreased by 1
  442. // and we don't want to miss an item
  443. n--;
  444. }
  445. }
  446. }
  447. // find NEW enterers, and send callbacks for them only
  448. // handle a and b
  449. void _collide(BVHHandle p_ha, BVHHandle p_hb) {
  450. // only have to do this oneway, lower ID then higher ID
  451. tree._handle_sort(p_ha, p_hb);
  452. const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_ha);
  453. const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_hb);
  454. // if the userdata is the same, no collisions should occur
  455. if ((exa.userdata == exb.userdata) && exa.userdata) {
  456. return;
  457. }
  458. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_ha.id()];
  459. typename BVHTREE_CLASS::ItemPairs &p_to = tree._pairs[p_hb.id()];
  460. // does this pair exist already?
  461. // or only check the one with lower number of pairs for greater speed
  462. if (p_from.num_pairs <= p_to.num_pairs) {
  463. if (p_from.contains_pair_to(p_hb)) {
  464. return;
  465. }
  466. } else {
  467. if (p_to.contains_pair_to(p_ha)) {
  468. return;
  469. }
  470. }
  471. // callback
  472. void *callback_userdata = nullptr;
  473. if (pair_callback) {
  474. callback_userdata = pair_callback(pair_callback_userdata, p_ha, exa.userdata, exa.subindex, p_hb, exb.userdata, exb.subindex);
  475. }
  476. // new pair! .. only really need to store the userdata on the lower handle, but both have storage so...
  477. p_from.add_pair_to(p_hb, callback_userdata);
  478. p_to.add_pair_to(p_ha, callback_userdata);
  479. }
  480. // if we remove an item, we need to immediately remove the pairs, to prevent reading the pair after deletion
  481. void _remove_pairs_containing(BVHHandle p_handle) {
  482. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
  483. // remove from pairing list for every partner.
  484. // can't easily use a for loop here, because removing changes the size of the list
  485. while (p_from.extended_pairs.size()) {
  486. BVHHandle h_to = p_from.extended_pairs[0].handle;
  487. _unpair(p_handle, h_to);
  488. }
  489. }
  490. private:
  491. const typename BVHTREE_CLASS::ItemExtra &_get_extra(BVHHandle p_handle) const {
  492. return tree._extra[p_handle.id()];
  493. }
  494. const typename BVHTREE_CLASS::ItemRef &_get_ref(BVHHandle p_handle) const {
  495. return tree._refs[p_handle.id()];
  496. }
  497. void _reset() {
  498. changed_items.clear();
  499. _tick++;
  500. }
  501. void _add_changed_item(BVHHandle p_handle, const Bounds &aabb, bool p_check_aabb = true) {
  502. // Note that non pairable items can pair with pairable,
  503. // so all types must be added to the list
  504. // aabb check with expanded aabb. This greatly decreases processing
  505. // at the cost of slightly less accurate pairing checks
  506. // Note this pairing AABB is separate from the AABB in the actual tree
  507. Bounds &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb;
  508. // passing p_check_aabb false disables the optimization which prevents collision checks if
  509. // the aabb hasn't changed. This is needed where set_pairable has been called, but the position
  510. // has not changed.
  511. if (p_check_aabb && expanded_aabb.encloses(aabb)) {
  512. return;
  513. }
  514. // ALWAYS update the new expanded aabb, even if already changed once
  515. // this tick, because it is vital that the AABB is kept up to date
  516. expanded_aabb = aabb;
  517. expanded_aabb.grow_by(tree._pairing_expansion);
  518. // this code is to ensure that changed items only appear once on the updated list
  519. // collision checking them multiple times is not needed, and repeats the same thing
  520. uint32_t &last_updated_tick = tree._extra[p_handle.id()].last_updated_tick;
  521. if (last_updated_tick == _tick) {
  522. return; // already on changed list
  523. }
  524. // mark as on list
  525. last_updated_tick = _tick;
  526. // add to the list
  527. changed_items.push_back(p_handle);
  528. }
  529. void _remove_changed_item(BVHHandle p_handle) {
  530. // Care has to be taken here for items that are deleted. The ref ID
  531. // could be reused on the same tick for new items. This is probably
  532. // rare but should be taken into consideration
  533. // callbacks
  534. _remove_pairs_containing(p_handle);
  535. // remove from changed items (not very efficient yet)
  536. for (int n = 0; n < (int)changed_items.size(); n++) {
  537. if (changed_items[n] == p_handle) {
  538. changed_items.remove_unordered(n);
  539. // because we are using an unordered remove,
  540. // the last changed item will now be at spot 'n',
  541. // and we need to redo it, so we prevent moving on to
  542. // the next n at the next for iteration.
  543. n--;
  544. }
  545. }
  546. // reset the last updated tick (may not be necessary but just in case)
  547. tree._extra[p_handle.id()].last_updated_tick = 0;
  548. }
  549. PairCallback pair_callback;
  550. UnpairCallback unpair_callback;
  551. void *pair_callback_userdata;
  552. void *unpair_callback_userdata;
  553. BVHTREE_CLASS tree;
  554. // for collision pairing,
  555. // maintain a list of all items moved etc on each frame / tick
  556. LocalVector<BVHHandle, uint32_t, true> changed_items;
  557. uint32_t _tick;
  558. public:
  559. BVH_Manager() {
  560. _tick = 1; // start from 1 so items with 0 indicate never updated
  561. pair_callback = nullptr;
  562. unpair_callback = nullptr;
  563. pair_callback_userdata = nullptr;
  564. unpair_callback_userdata = nullptr;
  565. }
  566. };
  567. #undef BVHTREE_CLASS
  568. #endif // BVH_H