Special case BVH building when we get too close to max depth.
This avoids exceeding max BVH depth even in pathological cases. Still need improve non-worst case building, but this at least prevents crashes in worst case.
This commit is contained in:
parent
c372d485e2
commit
35ef58b09c
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -7,6 +7,7 @@ dependencies = [
|
|||
"lodepng 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nom 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quickersort 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scoped_threadpool 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -76,6 +77,11 @@ name = "nom"
|
|||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.1.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "0.2.12"
|
||||
|
@ -84,6 +90,15 @@ dependencies = [
|
|||
"libc 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quickersort"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"num-traits 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "0.1.71"
|
||||
|
@ -138,11 +153,24 @@ dependencies = [
|
|||
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unreachable"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8-ranges"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.7"
|
||||
|
|
|
@ -10,4 +10,5 @@ nom = "1.2"
|
|||
scoped_threadpool = "0.1"
|
||||
crossbeam = "0.2"
|
||||
num_cpus = "0.2"
|
||||
quickersort = "2.0"
|
||||
lodepng = "0.8"
|
39
src/bvh.rs
39
src/bvh.rs
|
@ -1,10 +1,15 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::cmp::Ordering;
|
||||
use quickersort::sort_by;
|
||||
use lerp::lerp_slice;
|
||||
use bbox::BBox;
|
||||
use boundable::Boundable;
|
||||
use ray::AccelRay;
|
||||
use algorithm::{partition, merge_slices_append};
|
||||
use math::log2_64;
|
||||
|
||||
const BVH_MAX_DEPTH: usize = 64;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BVH {
|
||||
|
@ -129,10 +134,15 @@ impl BVH {
|
|||
2
|
||||
}
|
||||
};
|
||||
let split_pos = (bounds.min[split_axis] + bounds.max[split_axis]) * 0.5;
|
||||
|
||||
// Partition objects based on split
|
||||
let split_index = {
|
||||
// Partition objects based on split.
|
||||
// If we're too near the max depth, we do balanced building to
|
||||
// avoid exceeding max depth.
|
||||
// Otherwise we do cooler clever stuff to build better trees.
|
||||
let split_index = if (log2_64(objects.len() as u64) as usize) <
|
||||
(BVH_MAX_DEPTH - depth) {
|
||||
// Clever splitting, when we have room to play
|
||||
let split_pos = (bounds.min[split_axis] + bounds.max[split_axis]) * 0.5;
|
||||
let mut split_i = partition(&mut objects[..], |obj| {
|
||||
let tb = lerp_slice(bounder(obj), 0.5);
|
||||
let centroid = (tb.min[split_axis] + tb.max[split_axis]) * 0.5;
|
||||
|
@ -143,6 +153,25 @@ impl BVH {
|
|||
}
|
||||
|
||||
split_i
|
||||
} else {
|
||||
// Balanced splitting, when we don't have room to play
|
||||
sort_by(objects,
|
||||
&|a, b| {
|
||||
let tb_a = lerp_slice(bounder(a), 0.5);
|
||||
let tb_b = lerp_slice(bounder(b), 0.5);
|
||||
let centroid_a = (tb_a.min[split_axis] + tb_a.max[split_axis]) * 0.5;
|
||||
let centroid_b = (tb_b.min[split_axis] + tb_b.max[split_axis]) * 0.5;
|
||||
|
||||
if centroid_a < centroid_b {
|
||||
Ordering::Less
|
||||
} else if centroid_a == centroid_b {
|
||||
Ordering::Equal
|
||||
} else {
|
||||
Ordering::Greater
|
||||
}
|
||||
});
|
||||
|
||||
objects.len() / 2
|
||||
};
|
||||
|
||||
// Create child nodes
|
||||
|
@ -186,8 +215,8 @@ impl BVH {
|
|||
return;
|
||||
}
|
||||
|
||||
let mut i_stack = [0; 256];
|
||||
let mut ray_i_stack = [rays.len(); 256];
|
||||
let mut i_stack = [0; BVH_MAX_DEPTH + 1];
|
||||
let mut ray_i_stack = [rays.len(); BVH_MAX_DEPTH + 1];
|
||||
let mut stack_ptr = 1;
|
||||
|
||||
while stack_ptr > 0 {
|
||||
|
|
|
@ -3,6 +3,7 @@ extern crate docopt;
|
|||
extern crate scoped_threadpool;
|
||||
extern crate crossbeam;
|
||||
extern crate num_cpus;
|
||||
extern crate quickersort;
|
||||
extern crate lodepng;
|
||||
#[macro_use]
|
||||
extern crate nom;
|
||||
|
|
|
@ -40,6 +40,24 @@ pub fn fast_ln(x: f32) -> f32 {
|
|||
|
||||
|
||||
|
||||
pub fn log2_64(value: u64) -> u64 {
|
||||
const TAB64: [u64; 64] = [63, 0, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54, 33, 42, 3, 61, 51,
|
||||
37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62, 57, 46,
|
||||
52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31,
|
||||
35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5];
|
||||
|
||||
let value = value | (value >> 1);
|
||||
let value = value | (value >> 2);
|
||||
let value = value | (value >> 4);
|
||||
let value = value | (value >> 8);
|
||||
let value = value | (value >> 16);
|
||||
let value = value | (value >> 32);
|
||||
|
||||
TAB64[((((value - (value >> 1)) * 0x07EDD5E59A4E28C2)) >> 58) as usize]
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Creates a coordinate system from a single vector.
|
||||
pub fn coordinate_system_from_vector(v: Vector) -> (Vector, Vector, Vector) {
|
||||
let v2 = if v[0].abs() > v[1].abs() {
|
||||
|
|
Loading…
Reference in New Issue
Block a user