bvh.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  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>
  46. template <class T, bool USE_PAIRS = false, int MAX_ITEMS = 32>
  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 AABB &p_aabb = AABB(), 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. AABB &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 AABB &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 AABB &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) {
  135. BVHHandle h;
  136. h.set(p_handle);
  137. set_pairable(h, p_pairable, p_pairable_type, p_pairable_mask);
  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 AABB &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. AABB 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 AABB &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) {
  239. tree.item_set_pairable(p_handle, p_pairable, p_pairable_type, p_pairable_mask);
  240. if (USE_PAIRS) {
  241. // not sure if absolutely necessary to flush collisions here. It will cost performance to, instead
  242. // of waiting for update, so only uncomment this if there are bugs.
  243. //_check_for_collisions();
  244. if (get_active(p_handle)) {
  245. // when the pairable state changes, we need to force a collision check because newly pairable
  246. // items may be in collision, and unpairable items might move out of collision.
  247. // We cannot depend on waiting for the next update, because that may come much later.
  248. AABB aabb;
  249. item_get_AABB(p_handle, aabb);
  250. // passing false disables the optimization which prevents collision checks if
  251. // the aabb hasn't changed
  252. _add_changed_item(p_handle, aabb, false);
  253. // force an immediate collision check (probably just for this one item)
  254. // but it must be a FULL collision check, also checking pairable state and masks.
  255. // This is because AABB intersecting objects may have changed pairable state / mask
  256. // such that they should no longer be paired. E.g. lights.
  257. _check_for_collisions(true);
  258. } // only if active
  259. }
  260. }
  261. // cull tests
  262. int cull_aabb(const AABB &p_aabb, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  263. typename BVHTREE_CLASS::CullParams params;
  264. params.result_count_overall = 0;
  265. params.result_max = p_result_max;
  266. params.result_array = p_result_array;
  267. params.subindex_array = p_subindex_array;
  268. params.mask = p_mask;
  269. params.pairable_type = 0;
  270. params.test_pairable_only = false;
  271. params.abb.from(p_aabb);
  272. tree.cull_aabb(params);
  273. return params.result_count_overall;
  274. }
  275. int cull_segment(const Vector3 &p_from, const Vector3 &p_to, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  276. typename BVHTREE_CLASS::CullParams params;
  277. params.result_count_overall = 0;
  278. params.result_max = p_result_max;
  279. params.result_array = p_result_array;
  280. params.subindex_array = p_subindex_array;
  281. params.mask = p_mask;
  282. params.pairable_type = 0;
  283. params.segment.from = p_from;
  284. params.segment.to = p_to;
  285. tree.cull_segment(params);
  286. return params.result_count_overall;
  287. }
  288. int cull_point(const Vector3 &p_point, T **p_result_array, int p_result_max, int *p_subindex_array = nullptr, uint32_t p_mask = 0xFFFFFFFF) {
  289. typename BVHTREE_CLASS::CullParams params;
  290. params.result_count_overall = 0;
  291. params.result_max = p_result_max;
  292. params.result_array = p_result_array;
  293. params.subindex_array = p_subindex_array;
  294. params.mask = p_mask;
  295. params.pairable_type = 0;
  296. params.point = p_point;
  297. tree.cull_point(params);
  298. return params.result_count_overall;
  299. }
  300. int cull_convex(const Vector<Plane> &p_convex, T **p_result_array, int p_result_max, uint32_t p_mask = 0xFFFFFFFF) {
  301. if (!p_convex.size())
  302. return 0;
  303. Vector<Vector3> convex_points = Geometry::compute_convex_mesh_points(&p_convex[0], p_convex.size());
  304. if (convex_points.size() == 0)
  305. return 0;
  306. typename BVHTREE_CLASS::CullParams params;
  307. params.result_count_overall = 0;
  308. params.result_max = p_result_max;
  309. params.result_array = p_result_array;
  310. params.subindex_array = nullptr;
  311. params.mask = p_mask;
  312. params.pairable_type = 0;
  313. params.hull.planes = &p_convex[0];
  314. params.hull.num_planes = p_convex.size();
  315. params.hull.points = &convex_points[0];
  316. params.hull.num_points = convex_points.size();
  317. tree.cull_convex(params);
  318. return params.result_count_overall;
  319. }
  320. private:
  321. // do this after moving etc.
  322. void _check_for_collisions(bool p_full_check = false) {
  323. if (!changed_items.size()) {
  324. // noop
  325. return;
  326. }
  327. AABB bb;
  328. typename BVHTREE_CLASS::CullParams params;
  329. params.result_count_overall = 0;
  330. params.result_max = INT_MAX;
  331. params.result_array = nullptr;
  332. params.subindex_array = nullptr;
  333. params.mask = 0xFFFFFFFF;
  334. params.pairable_type = 0;
  335. for (unsigned int n = 0; n < changed_items.size(); n++) {
  336. const BVHHandle &h = changed_items[n];
  337. // use the expanded aabb for pairing
  338. const AABB &expanded_aabb = tree._pairs[h.id()].expanded_aabb;
  339. BVH_ABB abb;
  340. abb.from(expanded_aabb);
  341. // find all the existing paired aabbs that are no longer
  342. // paired, and send callbacks
  343. _find_leavers(h, abb, p_full_check);
  344. uint32_t changed_item_ref_id = h.id();
  345. // set up the test from this item.
  346. // this includes whether to test the non pairable tree,
  347. // and the item mask.
  348. tree.item_fill_cullparams(h, params);
  349. params.abb = abb;
  350. params.result_count_overall = 0; // might not be needed
  351. tree.cull_aabb(params, false);
  352. for (unsigned int i = 0; i < tree._cull_hits.size(); i++) {
  353. uint32_t ref_id = tree._cull_hits[i];
  354. // don't collide against ourself
  355. if (ref_id == changed_item_ref_id)
  356. continue;
  357. #ifdef BVH_CHECKS
  358. // if neither are pairable, they should ignore each other
  359. // THIS SHOULD NEVER HAPPEN .. now we only test the pairable tree
  360. // if the changed item is not pairable
  361. CRASH_COND(params.test_pairable_only && !tree._extra[ref_id].pairable);
  362. #endif
  363. // checkmasks is already done in the cull routine.
  364. BVHHandle h_collidee;
  365. h_collidee.set_id(ref_id);
  366. // find NEW enterers, and send callbacks for them only
  367. _collide(h, h_collidee);
  368. }
  369. }
  370. _reset();
  371. }
  372. public:
  373. void item_get_AABB(BVHHandle p_handle, AABB &r_aabb) {
  374. BVH_ABB abb;
  375. tree.item_get_ABB(p_handle, abb);
  376. abb.to(r_aabb);
  377. }
  378. private:
  379. // supplemental funcs
  380. bool item_is_pairable(BVHHandle p_handle) const { return _get_extra(p_handle).pairable; }
  381. T *item_get_userdata(BVHHandle p_handle) const { return _get_extra(p_handle).userdata; }
  382. int item_get_subindex(BVHHandle p_handle) const { return _get_extra(p_handle).subindex; }
  383. void _unpair(BVHHandle p_from, BVHHandle p_to) {
  384. tree._handle_sort(p_from, p_to);
  385. typename BVHTREE_CLASS::ItemExtra &exa = tree._extra[p_from.id()];
  386. typename BVHTREE_CLASS::ItemExtra &exb = tree._extra[p_to.id()];
  387. // if the userdata is the same, no collisions should occur
  388. if ((exa.userdata == exb.userdata) && exa.userdata) {
  389. return;
  390. }
  391. typename BVHTREE_CLASS::ItemPairs &pairs_from = tree._pairs[p_from.id()];
  392. typename BVHTREE_CLASS::ItemPairs &pairs_to = tree._pairs[p_to.id()];
  393. void *ud_from = pairs_from.remove_pair_to(p_to);
  394. pairs_to.remove_pair_to(p_from);
  395. // callback
  396. if (unpair_callback) {
  397. unpair_callback(pair_callback_userdata, p_from, exa.userdata, exa.subindex, p_to, exb.userdata, exb.subindex, ud_from);
  398. }
  399. }
  400. // returns true if unpair
  401. bool _find_leavers_process_pair(typename BVHTREE_CLASS::ItemPairs &p_pairs_from, const BVH_ABB &p_abb_from, BVHHandle p_from, BVHHandle p_to, bool p_full_check) {
  402. BVH_ABB abb_to;
  403. tree.item_get_ABB(p_to, abb_to);
  404. // do they overlap?
  405. if (p_abb_from.intersects(abb_to)) {
  406. // the full check for pairable / non pairable and mask changes is extra expense
  407. // this need not be done in most cases (for speed) except in the case where set_pairable is called
  408. // where the masks etc of the objects in question may have changed
  409. if (!p_full_check) {
  410. return false;
  411. }
  412. const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_from);
  413. const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_to);
  414. // one of the two must be pairable to still pair
  415. // if neither are pairable, we always unpair
  416. if (exa.pairable || exb.pairable) {
  417. // the masks must still be compatible to pair
  418. // i.e. if there is a hit between the two, then they should stay paired
  419. if (tree._cull_pairing_mask_test_hit(exa.pairable_mask, exa.pairable_type, exb.pairable_mask, exb.pairable_type)) {
  420. return false;
  421. }
  422. }
  423. }
  424. _unpair(p_from, p_to);
  425. return true;
  426. }
  427. // find all the existing paired aabbs that are no longer
  428. // paired, and send callbacks
  429. void _find_leavers(BVHHandle p_handle, const BVH_ABB &expanded_abb_from, bool p_full_check) {
  430. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
  431. BVH_ABB abb_from = expanded_abb_from;
  432. // remove from pairing list for every partner
  433. for (unsigned int n = 0; n < p_from.extended_pairs.size(); n++) {
  434. BVHHandle h_to = p_from.extended_pairs[n].handle;
  435. if (_find_leavers_process_pair(p_from, abb_from, p_handle, h_to, p_full_check)) {
  436. // we need to keep the counter n up to date if we deleted a pair
  437. // as the number of items in p_from.extended_pairs will have decreased by 1
  438. // and we don't want to miss an item
  439. n--;
  440. }
  441. }
  442. }
  443. // find NEW enterers, and send callbacks for them only
  444. // handle a and b
  445. void _collide(BVHHandle p_ha, BVHHandle p_hb) {
  446. // only have to do this oneway, lower ID then higher ID
  447. tree._handle_sort(p_ha, p_hb);
  448. const typename BVHTREE_CLASS::ItemExtra &exa = _get_extra(p_ha);
  449. const typename BVHTREE_CLASS::ItemExtra &exb = _get_extra(p_hb);
  450. // if the userdata is the same, no collisions should occur
  451. if ((exa.userdata == exb.userdata) && exa.userdata) {
  452. return;
  453. }
  454. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_ha.id()];
  455. typename BVHTREE_CLASS::ItemPairs &p_to = tree._pairs[p_hb.id()];
  456. // does this pair exist already?
  457. // or only check the one with lower number of pairs for greater speed
  458. if (p_from.num_pairs <= p_to.num_pairs) {
  459. if (p_from.contains_pair_to(p_hb))
  460. return;
  461. } else {
  462. if (p_to.contains_pair_to(p_ha))
  463. return;
  464. }
  465. // callback
  466. void *callback_userdata = nullptr;
  467. if (pair_callback) {
  468. callback_userdata = pair_callback(pair_callback_userdata, p_ha, exa.userdata, exa.subindex, p_hb, exb.userdata, exb.subindex);
  469. }
  470. // new pair! .. only really need to store the userdata on the lower handle, but both have storage so...
  471. p_from.add_pair_to(p_hb, callback_userdata);
  472. p_to.add_pair_to(p_ha, callback_userdata);
  473. }
  474. // if we remove an item, we need to immediately remove the pairs, to prevent reading the pair after deletion
  475. void _remove_pairs_containing(BVHHandle p_handle) {
  476. typename BVHTREE_CLASS::ItemPairs &p_from = tree._pairs[p_handle.id()];
  477. // remove from pairing list for every partner.
  478. // can't easily use a for loop here, because removing changes the size of the list
  479. while (p_from.extended_pairs.size()) {
  480. BVHHandle h_to = p_from.extended_pairs[0].handle;
  481. _unpair(p_handle, h_to);
  482. }
  483. }
  484. private:
  485. const typename BVHTREE_CLASS::ItemExtra &_get_extra(BVHHandle p_handle) const {
  486. return tree._extra[p_handle.id()];
  487. }
  488. const typename BVHTREE_CLASS::ItemRef &_get_ref(BVHHandle p_handle) const {
  489. return tree._refs[p_handle.id()];
  490. }
  491. void _reset() {
  492. changed_items.clear();
  493. _tick++;
  494. }
  495. void _add_changed_item(BVHHandle p_handle, const AABB &aabb, bool p_check_aabb = true) {
  496. // Note that non pairable items can pair with pairable,
  497. // so all types must be added to the list
  498. // aabb check with expanded aabb. This greatly decreases processing
  499. // at the cost of slightly less accurate pairing checks
  500. // Note this pairing AABB is separate from the AABB in the actual tree
  501. AABB &expanded_aabb = tree._pairs[p_handle.id()].expanded_aabb;
  502. // passing p_check_aabb false disables the optimization which prevents collision checks if
  503. // the aabb hasn't changed. This is needed where set_pairable has been called, but the position
  504. // has not changed.
  505. if (p_check_aabb && expanded_aabb.encloses(aabb))
  506. return;
  507. // ALWAYS update the new expanded aabb, even if already changed once
  508. // this tick, because it is vital that the AABB is kept up to date
  509. expanded_aabb = aabb;
  510. expanded_aabb.grow_by(tree._pairing_expansion);
  511. // this code is to ensure that changed items only appear once on the updated list
  512. // collision checking them multiple times is not needed, and repeats the same thing
  513. uint32_t &last_updated_tick = tree._extra[p_handle.id()].last_updated_tick;
  514. if (last_updated_tick == _tick)
  515. return; // already on changed list
  516. // mark as on list
  517. last_updated_tick = _tick;
  518. // add to the list
  519. changed_items.push_back(p_handle);
  520. }
  521. void _remove_changed_item(BVHHandle p_handle) {
  522. // Care has to be taken here for items that are deleted. The ref ID
  523. // could be reused on the same tick for new items. This is probably
  524. // rare but should be taken into consideration
  525. // callbacks
  526. _remove_pairs_containing(p_handle);
  527. // remove from changed items (not very efficient yet)
  528. for (int n = 0; n < (int)changed_items.size(); n++) {
  529. if (changed_items[n] == p_handle) {
  530. changed_items.remove_unordered(n);
  531. // because we are using an unordered remove,
  532. // the last changed item will now be at spot 'n',
  533. // and we need to redo it, so we prevent moving on to
  534. // the next n at the next for iteration.
  535. n--;
  536. }
  537. }
  538. // reset the last updated tick (may not be necessary but just in case)
  539. tree._extra[p_handle.id()].last_updated_tick = 0;
  540. }
  541. PairCallback pair_callback;
  542. UnpairCallback unpair_callback;
  543. void *pair_callback_userdata;
  544. void *unpair_callback_userdata;
  545. BVHTREE_CLASS tree;
  546. // for collision pairing,
  547. // maintain a list of all items moved etc on each frame / tick
  548. LocalVector<BVHHandle, uint32_t, true> changed_items;
  549. uint32_t _tick;
  550. public:
  551. BVH_Manager() {
  552. _tick = 1; // start from 1 so items with 0 indicate never updated
  553. pair_callback = nullptr;
  554. unpair_callback = nullptr;
  555. pair_callback_userdata = nullptr;
  556. unpair_callback_userdata = nullptr;
  557. }
  558. };
  559. #undef BVHTREE_CLASS
  560. #endif // BVH_H