BVH can now have multiple objects per leaf.

This commit is contained in:
Nathan Vegdahl 2016-01-02 12:35:00 -08:00
parent cb8db6a0b6
commit 5278675fb7
2 changed files with 37 additions and 18 deletions

View File

@ -23,12 +23,12 @@ enum BVHNode {
Leaf { Leaf {
bounds: BBox, bounds: BBox,
object_index: usize, object_range: (usize, usize),
}, },
} }
impl<'a, T> BVH<'a, T> { impl<'a, T> BVH<'a, T> {
pub fn from_objects<F>(objects: &'a mut [T], bounder: F) -> BVH<'a, T> pub fn from_objects<F>(objects: &'a mut [T], objects_per_leaf: usize, bounder: F) -> BVH<'a, T>
where F: Fn(&T) -> BBox where F: Fn(&T) -> BBox
{ {
let mut bvh = BVH { let mut bvh = BVH {
@ -37,7 +37,7 @@ impl<'a, T> BVH<'a, T> {
depth: 0, depth: 0,
}; };
bvh.recursive_build(0, 0, objects, &bounder); bvh.recursive_build(0, 0, objects_per_leaf, objects, &bounder);
bvh.objects = objects; bvh.objects = objects;
println!("BVH Depth: {}", bvh.depth); println!("BVH Depth: {}", bvh.depth);
@ -49,6 +49,7 @@ impl<'a, T> BVH<'a, T> {
fn recursive_build<F>(&mut self, fn recursive_build<F>(&mut self,
offset: usize, offset: usize,
depth: usize, depth: usize,
objects_per_leaf: usize,
objects: &mut [T], objects: &mut [T],
bounder: &F) bounder: &F)
-> usize -> usize
@ -58,11 +59,17 @@ impl<'a, T> BVH<'a, T> {
if objects.len() == 0 { if objects.len() == 0 {
return 0; return 0;
} else if objects.len() == 1 { } else if objects.len() <= objects_per_leaf {
// Leaf node // Leaf node
self.nodes.push(BVHNode::Leaf { self.nodes.push(BVHNode::Leaf {
bounds: bounder(&objects[0]), bounds: {
object_index: offset, let mut bounds = bounder(&objects[0]);
for obj in &objects[1..] {
bounds = bounds | bounder(obj);
}
bounds
},
object_range: (offset, offset + objects.len()),
}); });
if self.depth < depth { if self.depth < depth {
@ -112,9 +119,14 @@ impl<'a, T> BVH<'a, T> {
}; };
// Create child nodes // Create child nodes
self.recursive_build(offset, depth + 1, &mut objects[..split_index], bounder); self.recursive_build(offset,
depth + 1,
objects_per_leaf,
&mut objects[..split_index],
bounder);
let child2_index = self.recursive_build(offset + split_index, let child2_index = self.recursive_build(offset + split_index,
depth + 1, depth + 1,
objects_per_leaf,
&mut objects[split_index..], &mut objects[split_index..],
bounder); bounder);
@ -153,8 +165,8 @@ impl<'a, T> BVHTraverser<'a, T> {
} }
impl<'a, T> Iterator for BVHTraverser<'a, T> { impl<'a, T> Iterator for BVHTraverser<'a, T> {
type Item = (&'a T, &'a mut [Ray]); type Item = (&'a [T], &'a mut [Ray]);
fn next(&mut self) -> Option<(&'a T, &'a mut [Ray])> { fn next(&mut self) -> Option<(&'a [T], &'a mut [Ray])> {
let rays = unsafe { slice::from_raw_parts_mut(self.rays.0, self.rays.1) }; let rays = unsafe { slice::from_raw_parts_mut(self.rays.0, self.rays.1) };
while self.stack_ptr > 0 { while self.stack_ptr > 0 {
match self.bvh.nodes[self.i_stack[self.stack_ptr]] { match self.bvh.nodes[self.i_stack[self.stack_ptr]] {
@ -172,10 +184,15 @@ impl<'a, T> Iterator for BVHTraverser<'a, T> {
} }
} }
BVHNode::Leaf { bounds: _, object_index } => { BVHNode::Leaf { bounds, object_range } => {
// let part = self.ray_i_stack[self.stack_ptr];
let part = partition(&mut rays[..self.ray_i_stack[self.stack_ptr]],
|r| bounds.intersect_ray(r));
self.stack_ptr -= 1; self.stack_ptr -= 1;
return Some((&self.bvh.objects[object_index], if part > 0 {
&mut rays[..self.ray_i_stack[self.stack_ptr + 1]])); return Some((&self.bvh.objects[object_range.0..object_range.1],
&mut rays[..part]));
}
} }
} }
} }

View File

@ -105,7 +105,7 @@ fn main() {
} }
triangles triangles
}; };
let scene = bvh::BVH::from_objects(&mut triangles[..], |tri| { let scene = bvh::BVH::from_objects(&mut triangles[..], 3, |tri| {
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));
BBox { BBox {
@ -144,8 +144,9 @@ fn main() {
} }
// Test ray against scene // Test ray against scene
for (tri, rs) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut rays[..]) { for (tris, rs) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut rays[..]) {
for r in rs.iter_mut() { for r in rs.iter_mut() {
for tri in tris.iter() {
if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) {
if t < r.max_t { if t < r.max_t {
isects[r.id as usize] = (true, tri_u, tri_v); isects[r.id as usize] = (true, tri_u, tri_v);
@ -154,6 +155,7 @@ fn main() {
} }
} }
} }
}
// Calculate color based on ray hits // Calculate color based on ray hits
let mut r = 0.0; let mut r = 0.0;