bvh_structs.inc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. public:
  2. struct ItemRef {
  3. uint32_t tnode_id; // -1 is invalid
  4. uint32_t item_id; // in the leaf
  5. bool is_active() const { return tnode_id != BVHCommon::INACTIVE; }
  6. void set_inactive() {
  7. tnode_id = BVHCommon::INACTIVE;
  8. item_id = BVHCommon::INACTIVE;
  9. }
  10. };
  11. // extra info kept in separate parallel list to the references,
  12. // as this is less used as keeps cache better
  13. struct ItemExtra {
  14. uint32_t last_updated_tick;
  15. uint32_t pairable;
  16. uint32_t pairable_mask;
  17. uint32_t pairable_type;
  18. int32_t subindex;
  19. // the active reference is a separate list of which references
  20. // are active so that we can slowly iterate through it over many frames for
  21. // slow optimize.
  22. uint32_t active_ref_id;
  23. T *userdata;
  24. };
  25. // this is an item OR a child node depending on whether a leaf node
  26. struct Item {
  27. BVHABB_CLASS aabb;
  28. uint32_t item_ref_id;
  29. };
  30. // tree leaf
  31. struct TLeaf {
  32. uint16_t num_items;
  33. private:
  34. uint16_t dirty;
  35. // separate data orientated lists for faster SIMD traversal
  36. uint32_t item_ref_ids[MAX_ITEMS];
  37. BVHABB_CLASS aabbs[MAX_ITEMS];
  38. public:
  39. // accessors
  40. BVHABB_CLASS &get_aabb(uint32_t p_id) { return aabbs[p_id]; }
  41. const BVHABB_CLASS &get_aabb(uint32_t p_id) const { return aabbs[p_id]; }
  42. uint32_t &get_item_ref_id(uint32_t p_id) { return item_ref_ids[p_id]; }
  43. const uint32_t &get_item_ref_id(uint32_t p_id) const { return item_ref_ids[p_id]; }
  44. bool is_dirty() const { return dirty; }
  45. void set_dirty(bool p) { dirty = p; }
  46. void clear() {
  47. num_items = 0;
  48. set_dirty(true);
  49. }
  50. bool is_full() const { return num_items >= MAX_ITEMS; }
  51. void remove_item_unordered(uint32_t p_id) {
  52. BVH_ASSERT(p_id < num_items);
  53. num_items--;
  54. aabbs[p_id] = aabbs[num_items];
  55. item_ref_ids[p_id] = item_ref_ids[num_items];
  56. }
  57. uint32_t request_item() {
  58. if (num_items < MAX_ITEMS) {
  59. uint32_t id = num_items;
  60. num_items++;
  61. return id;
  62. }
  63. return -1;
  64. }
  65. };
  66. // tree node
  67. struct TNode {
  68. BVHABB_CLASS aabb;
  69. // either number of children if positive
  70. // or leaf id if negative (leaf id 0 is disallowed)
  71. union {
  72. int32_t num_children;
  73. int32_t neg_leaf_id;
  74. };
  75. uint32_t parent_id; // or -1
  76. uint16_t children[MAX_CHILDREN];
  77. // height in the tree, where leaves are 0, and all above are 1+
  78. // (or the highest where there is a tie off)
  79. int32_t height;
  80. bool is_leaf() const { return num_children < 0; }
  81. void set_leaf_id(int id) { neg_leaf_id = -id; }
  82. int get_leaf_id() const { return -neg_leaf_id; }
  83. void clear() {
  84. num_children = 0;
  85. parent_id = BVHCommon::INVALID;
  86. height = 0; // or -1 for testing
  87. // for safety set to improbable value
  88. aabb.set_to_max_opposite_extents();
  89. // other members are not blanked for speed .. they may be uninitialized
  90. }
  91. bool is_full_of_children() const { return num_children >= MAX_CHILDREN; }
  92. void remove_child_internal(uint32_t child_num) {
  93. children[child_num] = children[num_children - 1];
  94. num_children--;
  95. }
  96. int find_child(uint32_t p_child_node_id) {
  97. BVH_ASSERT(!is_leaf());
  98. for (int n = 0; n < num_children; n++) {
  99. if (children[n] == p_child_node_id) {
  100. return n;
  101. }
  102. }
  103. // not found
  104. return -1;
  105. }
  106. };
  107. // instead of using linked list we maintain
  108. // item references (for quick lookup)
  109. PooledList<ItemRef, true> _refs;
  110. PooledList<ItemExtra, true> _extra;
  111. PooledList<ItemPairs> _pairs;
  112. // these 2 are not in sync .. nodes != leaves!
  113. PooledList<TNode, true> _nodes;
  114. PooledList<TLeaf, true> _leaves;
  115. // we can maintain an un-ordered list of which references are active,
  116. // in order to do a slow incremental optimize of the tree over each frame.
  117. // This will work best if dynamic objects and static objects are in a different tree.
  118. LocalVector<uint32_t, uint32_t, true> _active_refs;
  119. uint32_t _current_active_ref = 0;
  120. // instead of translating directly to the userdata output,
  121. // we keep an intermediate list of hits as reference IDs, which can be used
  122. // for pairing collision detection
  123. LocalVector<uint32_t, uint32_t, true> _cull_hits;
  124. // we now have multiple root nodes, allowing us to store
  125. // more than 1 tree. This can be more efficient, while sharing the same
  126. // common lists
  127. enum { NUM_TREES = 2,
  128. };
  129. // Tree 0 - Non pairable
  130. // Tree 1 - Pairable
  131. // This is more efficient because in physics we only need check non pairable against the pairable tree.
  132. uint32_t _root_node_id[NUM_TREES];
  133. // these values may need tweaking according to the project
  134. // the bound of the world, and the average velocities of the objects
  135. // node expansion is important in the rendering tree
  136. // larger values give less re-insertion as items move...
  137. // but on the other hand over estimates the bounding box of nodes.
  138. // we can either use auto mode, where the expansion is based on the root node size, or specify manually
  139. real_t _node_expansion = 0.5;
  140. bool _auto_node_expansion = true;
  141. // pairing expansion important for physics pairing
  142. // larger values gives more 'sticky' pairing, and is less likely to exhibit tunneling
  143. // we can either use auto mode, where the expansion is based on the root node size, or specify manually
  144. real_t _pairing_expansion = 0.1;
  145. bool _auto_pairing_expansion = true;