mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 22:41:30 +11:00
Fix stack overflow during BVH construction
The epsilon for float equality was too small which prevented the function from terminating. Additionally, it has been rewritten in terms of a loop because tail-call optimization was not happening.
This commit is contained in:
parent
b604dafe73
commit
044a735729
38
src/bvh.rs
38
src/bvh.rs
|
@ -6,7 +6,7 @@
|
|||
use std::iter::FusedIterator;
|
||||
use std::mem;
|
||||
|
||||
use approx::relative_eq;
|
||||
use approx::abs_diff_eq;
|
||||
use rayon::iter::{
|
||||
IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator,
|
||||
};
|
||||
|
@ -180,7 +180,7 @@ impl<'a, T> Internal<'a, T> {
|
|||
|
||||
fn build_rec<T: Send>(
|
||||
idx: NodeIdx,
|
||||
bounds: Aabb<f64>,
|
||||
mut bounds: Aabb<f64>,
|
||||
internal_nodes: &mut [InternalNode],
|
||||
leaf_nodes: &mut [LeafNode<T>],
|
||||
total_leaf_count: NodeIdx,
|
||||
|
@ -192,6 +192,7 @@ fn build_rec<T: Send>(
|
|||
return (total_leaf_count - 1 + idx, leaf_nodes[0].bb);
|
||||
}
|
||||
|
||||
loop {
|
||||
debug_assert!(bounds.is_valid());
|
||||
let dims = bounds.max - bounds.min;
|
||||
|
||||
|
@ -221,28 +222,26 @@ fn build_rec<T: Send>(
|
|||
// Check if one of the halves is empty. (We can't have empty nodes)
|
||||
// Also take care to handle the edge case of overlapping points.
|
||||
if split == 0 {
|
||||
if relative_eq!(bounds_right.min, bounds_right.max) {
|
||||
if abs_diff_eq!(
|
||||
bounds_right.min,
|
||||
bounds_right.max,
|
||||
epsilon = f64::EPSILON * 100.0
|
||||
) {
|
||||
split += 1;
|
||||
} else {
|
||||
return build_rec(
|
||||
idx,
|
||||
bounds_right,
|
||||
internal_nodes,
|
||||
leaf_nodes,
|
||||
total_leaf_count,
|
||||
);
|
||||
bounds = bounds_right;
|
||||
continue;
|
||||
}
|
||||
} else if split == leaf_nodes.len() {
|
||||
if relative_eq!(bounds_left.min, bounds_left.max) {
|
||||
if abs_diff_eq!(
|
||||
bounds_left.min,
|
||||
bounds_left.max,
|
||||
epsilon = f64::EPSILON * 100.0
|
||||
) {
|
||||
split -= 1;
|
||||
} else {
|
||||
return build_rec(
|
||||
idx,
|
||||
bounds_left,
|
||||
internal_nodes,
|
||||
leaf_nodes,
|
||||
total_leaf_count,
|
||||
);
|
||||
bounds = bounds_left;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -276,7 +275,8 @@ fn build_rec<T: Send>(
|
|||
internal.left = left;
|
||||
internal.right = right;
|
||||
|
||||
(idx + split as NodeIdx - 1, internal.bb)
|
||||
break (idx + split as NodeIdx - 1, internal.bb);
|
||||
}
|
||||
}
|
||||
|
||||
fn partition<T>(s: &mut [T], mut pred: impl FnMut(&T) -> bool) -> usize {
|
||||
|
|
Loading…
Reference in a new issue