bvh_split.inc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. void _split_inform_references(uint32_t p_node_id) {
  2. TNode &node = _nodes[p_node_id];
  3. TLeaf &leaf = _node_get_leaf(node);
  4. for (int n = 0; n < leaf.num_items; n++) {
  5. uint32_t ref_id = leaf.get_item_ref_id(n);
  6. ItemRef &ref = _refs[ref_id];
  7. ref.tnode_id = p_node_id;
  8. ref.item_id = n;
  9. }
  10. }
  11. void _split_leaf_sort_groups_simple(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVHABB_CLASS *temp_bounds, const BVHABB_CLASS full_bound) {
  12. // special case for low leaf sizes .. should static compile out
  13. if (MAX_ITEMS < 4) {
  14. uint32_t ind = group_a[0];
  15. // add to b
  16. group_b[num_b++] = ind;
  17. // remove from a
  18. group_a[0] = group_a[num_a - 1];
  19. num_a--;
  20. return;
  21. }
  22. Point centre = full_bound.calculate_centre();
  23. Point size = full_bound.calculate_size();
  24. int order[3];
  25. order[0] = size.min_axis();
  26. order[2] = size.max_axis();
  27. order[1] = 3 - (order[0] + order[2]);
  28. // simplest case, split on the longest axis
  29. int split_axis = order[0];
  30. for (int a = 0; a < num_a; a++) {
  31. uint32_t ind = group_a[a];
  32. if (temp_bounds[ind].min.coord[split_axis] > centre.coord[split_axis]) {
  33. // add to b
  34. group_b[num_b++] = ind;
  35. // remove from a
  36. group_a[a] = group_a[num_a - 1];
  37. num_a--;
  38. // do this one again, as it has been replaced
  39. a--;
  40. }
  41. }
  42. // detect when split on longest axis failed
  43. int min_threshold = MAX_ITEMS / 4;
  44. int min_group_size[3];
  45. min_group_size[0] = MIN(num_a, num_b);
  46. if (min_group_size[0] < min_threshold) {
  47. // slow but sure .. first move everything back into a
  48. for (int b = 0; b < num_b; b++) {
  49. group_a[num_a++] = group_b[b];
  50. }
  51. num_b = 0;
  52. // now calculate the best split
  53. for (int axis = 1; axis < 3; axis++) {
  54. split_axis = order[axis];
  55. int count = 0;
  56. for (int a = 0; a < num_a; a++) {
  57. uint32_t ind = group_a[a];
  58. if (temp_bounds[ind].min.coord[split_axis] > centre.coord[split_axis]) {
  59. count++;
  60. }
  61. }
  62. min_group_size[axis] = MIN(count, num_a - count);
  63. } // for axis
  64. // best axis
  65. int best_axis = 0;
  66. int best_min = min_group_size[0];
  67. for (int axis = 1; axis < 3; axis++) {
  68. if (min_group_size[axis] > best_min) {
  69. best_min = min_group_size[axis];
  70. best_axis = axis;
  71. }
  72. }
  73. // now finally do the split
  74. if (best_min > 0) {
  75. split_axis = order[best_axis];
  76. for (int a = 0; a < num_a; a++) {
  77. uint32_t ind = group_a[a];
  78. if (temp_bounds[ind].min.coord[split_axis] > centre.coord[split_axis]) {
  79. // add to b
  80. group_b[num_b++] = ind;
  81. // remove from a
  82. group_a[a] = group_a[num_a - 1];
  83. num_a--;
  84. // do this one again, as it has been replaced
  85. a--;
  86. }
  87. }
  88. } // if there was a split!
  89. } // if the longest axis wasn't a good split
  90. // special case, none crossed threshold
  91. if (!num_b) {
  92. uint32_t ind = group_a[0];
  93. // add to b
  94. group_b[num_b++] = ind;
  95. // remove from a
  96. group_a[0] = group_a[num_a - 1];
  97. num_a--;
  98. }
  99. // opposite problem! :)
  100. if (!num_a) {
  101. uint32_t ind = group_b[0];
  102. // add to a
  103. group_a[num_a++] = ind;
  104. // remove from b
  105. group_b[0] = group_b[num_b - 1];
  106. num_b--;
  107. }
  108. }
  109. void _split_leaf_sort_groups(int &num_a, int &num_b, uint16_t *group_a, uint16_t *group_b, const BVHABB_CLASS *temp_bounds) {
  110. BVHABB_CLASS groupb_aabb;
  111. groupb_aabb.set_to_max_opposite_extents();
  112. for (int n = 0; n < num_b; n++) {
  113. int which = group_b[n];
  114. groupb_aabb.merge(temp_bounds[which]);
  115. }
  116. BVHABB_CLASS groupb_aabb_new;
  117. BVHABB_CLASS rest_aabb;
  118. float best_size = FLT_MAX;
  119. int best_candidate = -1;
  120. // find most likely from a to move into b
  121. for (int check = 0; check < num_a; check++) {
  122. rest_aabb.set_to_max_opposite_extents();
  123. groupb_aabb_new = groupb_aabb;
  124. // find aabb of all the rest
  125. for (int rest = 0; rest < num_a; rest++) {
  126. if (rest == check) {
  127. continue;
  128. }
  129. int which = group_a[rest];
  130. rest_aabb.merge(temp_bounds[which]);
  131. }
  132. groupb_aabb_new.merge(temp_bounds[group_a[check]]);
  133. // now compare the sizes
  134. float size = groupb_aabb_new.get_area() + rest_aabb.get_area();
  135. if (size < best_size) {
  136. best_size = size;
  137. best_candidate = check;
  138. }
  139. }
  140. // we should now have the best, move it from group a to group b
  141. group_b[num_b++] = group_a[best_candidate];
  142. // remove best candidate from group a
  143. num_a--;
  144. group_a[best_candidate] = group_a[num_a];
  145. }
  146. uint32_t split_leaf(uint32_t p_node_id, const BVHABB_CLASS &p_added_item_aabb) {
  147. return split_leaf_complex(p_node_id, p_added_item_aabb);
  148. }
  149. // aabb is the new inserted node
  150. uint32_t split_leaf_complex(uint32_t p_node_id, const BVHABB_CLASS &p_added_item_aabb) {
  151. VERBOSE_PRINT("split_leaf");
  152. // note the tnode before and AFTER splitting may be a different address
  153. // in memory because the vector could get relocated. So we need to reget
  154. // the tnode after the split
  155. BVH_ASSERT(_nodes[p_node_id].is_leaf());
  156. // first create child leaf nodes
  157. uint32_t *child_ids = (uint32_t *)alloca(sizeof(uint32_t) * MAX_CHILDREN);
  158. for (int n = 0; n < MAX_CHILDREN; n++) {
  159. // create node children
  160. TNode *child_node = _nodes.request(child_ids[n]);
  161. child_node->clear();
  162. // back link to parent
  163. child_node->parent_id = p_node_id;
  164. // make each child a leaf node
  165. node_make_leaf(child_ids[n]);
  166. }
  167. // don't get any leaves or nodes till AFTER the split
  168. TNode &tnode = _nodes[p_node_id];
  169. uint32_t orig_leaf_id = tnode.get_leaf_id();
  170. const TLeaf &orig_leaf = _node_get_leaf(tnode);
  171. // store the final child ids
  172. for (int n = 0; n < MAX_CHILDREN; n++) {
  173. tnode.children[n] = child_ids[n];
  174. }
  175. // mark as no longer a leaf node
  176. tnode.num_children = MAX_CHILDREN;
  177. // 2 groups, A and B, and assign children to each to split equally
  178. int max_children = orig_leaf.num_items + 1; // plus 1 for the wildcard .. the item being added
  179. //CRASH_COND(max_children > MAX_CHILDREN);
  180. uint16_t *group_a = (uint16_t *)alloca(sizeof(uint16_t) * max_children);
  181. uint16_t *group_b = (uint16_t *)alloca(sizeof(uint16_t) * max_children);
  182. // we are copying the ABBs. This is ugly, but we need one extra for the inserted item...
  183. BVHABB_CLASS *temp_bounds = (BVHABB_CLASS *)alloca(sizeof(BVHABB_CLASS) * max_children);
  184. int num_a = max_children;
  185. int num_b = 0;
  186. // setup - start with all in group a
  187. for (int n = 0; n < orig_leaf.num_items; n++) {
  188. group_a[n] = n;
  189. temp_bounds[n] = orig_leaf.get_aabb(n);
  190. }
  191. // wildcard
  192. int wildcard = orig_leaf.num_items;
  193. group_a[wildcard] = wildcard;
  194. temp_bounds[wildcard] = p_added_item_aabb;
  195. // we can choose here either an equal split, or just 1 in the new leaf
  196. _split_leaf_sort_groups_simple(num_a, num_b, group_a, group_b, temp_bounds, tnode.aabb);
  197. uint32_t wildcard_node = BVHCommon::INVALID;
  198. // now there should be equal numbers in both groups
  199. for (int n = 0; n < num_a; n++) {
  200. int which = group_a[n];
  201. if (which != wildcard) {
  202. const BVHABB_CLASS &source_item_aabb = orig_leaf.get_aabb(which);
  203. uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
  204. //const Item &source_item = orig_leaf.get_item(which);
  205. _node_add_item(tnode.children[0], source_item_ref_id, source_item_aabb);
  206. } else {
  207. wildcard_node = tnode.children[0];
  208. }
  209. }
  210. for (int n = 0; n < num_b; n++) {
  211. int which = group_b[n];
  212. if (which != wildcard) {
  213. const BVHABB_CLASS &source_item_aabb = orig_leaf.get_aabb(which);
  214. uint32_t source_item_ref_id = orig_leaf.get_item_ref_id(which);
  215. //const Item &source_item = orig_leaf.get_item(which);
  216. _node_add_item(tnode.children[1], source_item_ref_id, source_item_aabb);
  217. } else {
  218. wildcard_node = tnode.children[1];
  219. }
  220. }
  221. // now remove all items from the parent and replace with the child nodes
  222. _leaves.free(orig_leaf_id);
  223. // we should keep the references up to date!
  224. for (int n = 0; n < MAX_CHILDREN; n++) {
  225. _split_inform_references(tnode.children[n]);
  226. }
  227. refit_upward(p_node_id);
  228. BVH_ASSERT(wildcard_node != BVHCommon::INVALID);
  229. return wildcard_node;
  230. }