| 1 | void _debug_node_verify_bound(uint32_t p_node_id) { |
|---|---|
| 2 | TNode &node = _nodes[p_node_id]; |
| 3 | BVHABB_CLASS abb_before = node.aabb; |
| 4 | |
| 5 | node_update_aabb(node); |
| 6 | |
| 7 | BVHABB_CLASS abb_after = node.aabb; |
| 8 | CRASH_COND(abb_before != abb_after); |
| 9 | } |
| 10 | |
| 11 | void node_update_aabb(TNode &tnode) { |
| 12 | tnode.aabb.set_to_max_opposite_extents(); |
| 13 | tnode.height = 0; |
| 14 | |
| 15 | if (!tnode.is_leaf()) { |
| 16 | for (int n = 0; n < tnode.num_children; n++) { |
| 17 | uint32_t child_node_id = tnode.children[n]; |
| 18 | |
| 19 | // merge with child aabb |
| 20 | const TNode &tchild = _nodes[child_node_id]; |
| 21 | tnode.aabb.merge(tchild.aabb); |
| 22 | |
| 23 | // do heights at the same time |
| 24 | if (tchild.height > tnode.height) { |
| 25 | tnode.height = tchild.height; |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | // the height of a non leaf is always 1 bigger than the biggest child |
| 30 | tnode.height++; |
| 31 | |
| 32 | #ifdef BVH_CHECKS |
| 33 | if (!tnode.num_children) { |
| 34 | // the 'blank' aabb will screw up parent aabbs |
| 35 | WARN_PRINT("BVH_Tree::TNode no children, AABB is undefined"); |
| 36 | } |
| 37 | #endif |
| 38 | } else { |
| 39 | // leaf |
| 40 | const TLeaf &leaf = _node_get_leaf(tnode); |
| 41 | |
| 42 | for (int n = 0; n < leaf.num_items; n++) { |
| 43 | tnode.aabb.merge(leaf.get_aabb(n)); |
| 44 | } |
| 45 | |
| 46 | // now the leaf items are unexpanded, we expand only in the node AABB |
| 47 | tnode.aabb.expand(_node_expansion); |
| 48 | #ifdef BVH_CHECKS |
| 49 | if (!leaf.num_items) { |
| 50 | // the 'blank' aabb will screw up parent aabbs |
| 51 | WARN_PRINT("BVH_Tree::TLeaf no items, AABB is undefined"); |
| 52 | } |
| 53 | #endif |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | void refit_all(int p_tree_id) { |
| 58 | refit_downward(_root_node_id[p_tree_id]); |
| 59 | } |
| 60 | |
| 61 | void refit_upward(uint32_t p_node_id) { |
| 62 | while (p_node_id != BVHCommon::INVALID) { |
| 63 | TNode &tnode = _nodes[p_node_id]; |
| 64 | node_update_aabb(tnode); |
| 65 | p_node_id = tnode.parent_id; |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | void refit_upward_and_balance(uint32_t p_node_id, uint32_t p_tree_id) { |
| 70 | while (p_node_id != BVHCommon::INVALID) { |
| 71 | uint32_t before = p_node_id; |
| 72 | p_node_id = _logic_balance(p_node_id, p_tree_id); |
| 73 | |
| 74 | if (before != p_node_id) { |
| 75 | VERBOSE_PRINT("REBALANCED!"); |
| 76 | } |
| 77 | |
| 78 | TNode &tnode = _nodes[p_node_id]; |
| 79 | |
| 80 | // update overall aabb from the children |
| 81 | node_update_aabb(tnode); |
| 82 | |
| 83 | p_node_id = tnode.parent_id; |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | void refit_downward(uint32_t p_node_id) { |
| 88 | TNode &tnode = _nodes[p_node_id]; |
| 89 | |
| 90 | // do children first |
| 91 | if (!tnode.is_leaf()) { |
| 92 | for (int n = 0; n < tnode.num_children; n++) { |
| 93 | refit_downward(tnode.children[n]); |
| 94 | } |
| 95 | } |
| 96 | |
| 97 | node_update_aabb(tnode); |
| 98 | } |
| 99 | |
| 100 | // go down to the leaves, then refit upward |
| 101 | void refit_branch(uint32_t p_node_id) { |
| 102 | // our function parameters to keep on a stack |
| 103 | struct RefitParams { |
| 104 | uint32_t node_id; |
| 105 | }; |
| 106 | |
| 107 | // most of the iterative functionality is contained in this helper class |
| 108 | BVH_IterativeInfo<RefitParams> ii; |
| 109 | |
| 110 | // alloca must allocate the stack from this function, it cannot be allocated in the |
| 111 | // helper class |
| 112 | ii.stack = (RefitParams *)alloca(ii.get_alloca_stacksize()); |
| 113 | |
| 114 | // seed the stack |
| 115 | ii.get_first()->node_id = p_node_id; |
| 116 | |
| 117 | RefitParams rp; |
| 118 | |
| 119 | // while there are still more nodes on the stack |
| 120 | while (ii.pop(rp)) { |
| 121 | TNode &tnode = _nodes[rp.node_id]; |
| 122 | |
| 123 | // do children first |
| 124 | if (!tnode.is_leaf()) { |
| 125 | for (int n = 0; n < tnode.num_children; n++) { |
| 126 | uint32_t child_id = tnode.children[n]; |
| 127 | |
| 128 | // add to the stack |
| 129 | RefitParams *child = ii.request(); |
| 130 | child->node_id = child_id; |
| 131 | } |
| 132 | } else { |
| 133 | // leaf .. only refit upward if dirty |
| 134 | TLeaf &leaf = _node_get_leaf(tnode); |
| 135 | if (leaf.is_dirty()) { |
| 136 | leaf.set_dirty(false); |
| 137 | refit_upward(p_node_id); |
| 138 | } |
| 139 | } |
| 140 | } // while more nodes to pop |
| 141 | } |
| 142 |