diff --git a/src/partitioning/qbvh/update.rs b/src/partitioning/qbvh/update.rs index 7c948432..e7fa8ac1 100644 --- a/src/partitioning/qbvh/update.rs +++ b/src/partitioning/qbvh/update.rs @@ -339,6 +339,11 @@ impl<LeafData: IndexedData> Qbvh<LeafData> { const MIN_CHANGED_DEPTH: u8 = 5; // TODO: find a good value + // PERF: if we have modifications past this depth, the QBVH has become very + // unbalanced and a full rebuild is warranted. + // TODO: work on a way to reduce the risks of imbalance. + const FULL_REBUILD_DEPTH: u8 = 15; + for root_child in self.nodes[0].children { if root_child < self.nodes.len() as u32 { workspace.stack.push((root_child, 1)); @@ -346,7 +351,13 @@ impl<LeafData: IndexedData> Qbvh<LeafData> { } // Collect empty slots and pseudo-leaves to sort. + let mut force_full_rebuild = false; while let Some((id, depth)) = workspace.stack.pop() { + if depth > FULL_REBUILD_DEPTH { + force_full_rebuild = true; + break; + } + let node = &mut self.nodes[id as usize]; if node.is_leaf() { @@ -374,6 +385,18 @@ impl<LeafData: IndexedData> Qbvh<LeafData> { } } + if force_full_rebuild { + workspace.clear(); + let all_leaves: Vec<_> = self + .proxies + .iter() + .filter_map(|proxy| self.node_aabb(proxy.node).map(|aabb| (proxy.data, aabb))) + .collect(); + + self.clear_and_rebuild(all_leaves.into_iter(), 0.0); + return; + } + workspace.to_sort.extend(0..workspace.orig_ids.len()); let root_id = NodeIndex::new(0, 0);