Adjusted the API of the BVH builder.

The bounder closure now returns slices of BBoxes instead of
filling in a given Vec.
This commit is contained in:
Nathan Vegdahl 2016-01-06 23:47:32 -08:00
parent 655c16542d
commit a569586455
2 changed files with 30 additions and 43 deletions

View File

@ -11,7 +11,6 @@ pub struct BVH {
bounds: Vec<BBox>, bounds: Vec<BBox>,
depth: usize, depth: usize,
bounds_cache: Vec<BBox>, bounds_cache: Vec<BBox>,
bounds_temp: Vec<BBox>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -30,65 +29,50 @@ enum BVHNode {
impl BVH { impl BVH {
pub fn from_objects<'a, T, F>(objects: &mut [T], objects_per_leaf: usize, bounder: F) -> BVH pub fn from_objects<'a, T, F>(objects: &mut [T], objects_per_leaf: usize, bounder: F) -> BVH
where F: Fn(&T, &mut Vec<BBox>) where F: 'a + Fn(&T) -> &'a [BBox]
{ {
let mut bvh = BVH { let mut bvh = BVH {
nodes: Vec::new(), nodes: Vec::new(),
bounds: Vec::new(), bounds: Vec::new(),
depth: 0, depth: 0,
bounds_cache: Vec::new(), bounds_cache: Vec::new(),
bounds_temp: Vec::new(),
}; };
bvh.recursive_build(0, 0, objects_per_leaf, objects, &bounder); bvh.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
bvh.bounds_cache.clear(); bvh.bounds_cache.clear();
bvh.bounds_temp.clear();
bvh.bounds_cache.shrink_to_fit(); bvh.bounds_cache.shrink_to_fit();
bvh.bounds_temp.shrink_to_fit();
println!("BVH Depth: {}", bvh.depth); println!("BVH Depth: {}", bvh.depth);
bvh bvh
} }
fn acc_bounds<T, F>(&mut self, objects1: &mut [T], bounder: F) fn acc_bounds<'a, T, F>(&mut self, objects1: &mut [T], bounder: &F)
where F: Fn(&T, &mut Vec<BBox>) where F: 'a + Fn(&T) -> &'a [BBox]
{ {
// TODO: merging of different length bounds // TODO: merging of different length bounds
self.bounds_cache.clear(); self.bounds_cache.clear();
bounder(&objects1[0], &mut self.bounds_cache); for bb in bounder(&objects1[0]).iter() {
self.bounds_cache.push(*bb);
}
for obj in &objects1[1..] { for obj in &objects1[1..] {
self.bounds_temp.clear(); let bounds = bounder(obj);
bounder(obj, &mut self.bounds_temp); debug_assert!(self.bounds_cache.len() == bounds.len());
debug_assert!(self.bounds_cache.len() == self.bounds_temp.len()); for i in 0..bounds.len() {
for i in 0..self.bounds_cache.len() { self.bounds_cache[i] = self.bounds_cache[i] | bounds[i];
self.bounds_cache[i] = self.bounds_cache[i] | self.bounds_temp[i];
} }
} }
} }
fn recursive_build<T, F>(&mut self, fn recursive_build<'a, T, F>(&mut self,
offset: usize, offset: usize,
depth: usize, depth: usize,
objects_per_leaf: usize, objects_per_leaf: usize,
objects: &mut [T], objects: &mut [T],
bounder: &F) bounder: &F)
-> (usize, (usize, usize)) -> (usize, (usize, usize))
where F: Fn(&T, &mut Vec<BBox>) where F: 'a + Fn(&T) -> &'a [BBox]
{ {
// fn acc_bounds2(objects2: &mut [T]) {
// self.bounds_cache2.clear();
// bounder(&objects2[0], &mut self.bounds_cache2);
// for obj in &objects2[1..] {
// self.bounds_temp.clear();
// bounder(obj, &mut self.bounds_temp);
// debug_assert!(self.bounds_cache2.len() == self.bounds_temp.len());
// for i in 0..self.bounds_cache2.len() {
// self.bounds_cache2[i] = self.bounds_cache2[i] | self.bounds_temp[i];
// }
// }
// }
let me = self.nodes.len(); let me = self.nodes.len();
if objects.len() == 0 { if objects.len() == 0 {
@ -122,9 +106,7 @@ impl BVH {
let bounds = { let bounds = {
let mut bb = BBox::new(); let mut bb = BBox::new();
for obj in &objects[..] { for obj in &objects[..] {
self.bounds_cache.clear(); bb = bb | lerp_slice(bounder(obj), 0.5);
bounder(obj, &mut self.bounds_cache);
bb = bb | lerp_slice(&self.bounds_cache[..], 0.5);
} }
bb bb
}; };
@ -145,9 +127,7 @@ impl BVH {
// Partition objects based on split // Partition objects based on split
let split_index = { let split_index = {
let mut split_i = partition(&mut objects[..], |obj| { let mut split_i = partition(&mut objects[..], |obj| {
self.bounds_cache.clear(); let tb = lerp_slice(bounder(obj), 0.5);
bounder(obj, &mut self.bounds_cache);
let tb = lerp_slice(&self.bounds_cache[..], 0.5);
let centroid = (tb.min[split_axis] + tb.max[split_axis]) * 0.5; let centroid = (tb.min[split_axis] + tb.max[split_axis]) * 0.5;
centroid < split_pos centroid < split_pos
}); });

View File

@ -21,17 +21,24 @@ impl TriangleMesh {
triangles: Vec<(Point, Point, Point)>) triangles: Vec<(Point, Point, Point)>)
-> TriangleMesh { -> TriangleMesh {
assert!(triangles.len() % time_samples == 0); assert!(triangles.len() % time_samples == 0);
let mut indices: Vec<usize> = (0..(triangles.len() / time_samples)) let mut indices: Vec<usize> = (0..(triangles.len() / time_samples))
.map(|n| n * time_samples) .map(|n| n * time_samples)
.collect(); .collect();
let accel = BVH::from_objects(&mut indices[..], 3, |tri_i, bounds| { let bounds = {
for tri in &triangles[*tri_i..(*tri_i + time_samples)] { let mut bounds = Vec::new();
for tri in triangles.iter() {
let minimum = tri.0.min(tri.1.min(tri.2)); let minimum = tri.0.min(tri.1.min(tri.2));
let maximum = tri.0.max(tri.1.max(tri.2)); let maximum = tri.0.max(tri.1.max(tri.2));
bounds.push(BBox::from_points(minimum, maximum)); bounds.push(BBox::from_points(minimum, maximum));
} }
}); bounds
};
let accel = BVH::from_objects(&mut indices[..],
3,
|tri_i| &bounds[*tri_i..(*tri_i + time_samples)]);
TriangleMesh { TriangleMesh {
time_samples: time_samples, time_samples: time_samples,