From 9b5e6ad23d6bf8a82f516fb5e6f9186f16887c74 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sat, 2 Jan 2016 13:10:06 -0800 Subject: [PATCH] Replaced BVHTraverser with a method that takes a closure. This is not only simpler conceptually, but also turns out to have better performance. --- src/bvh.rs | 66 +++++++++++++++++------------------------------------ src/main.rs | 18 +++++++-------- 2 files changed, 29 insertions(+), 55 deletions(-) diff --git a/src/bvh.rs b/src/bvh.rs index deed211..d0e3225 100644 --- a/src/bvh.rs +++ b/src/bvh.rs @@ -1,8 +1,5 @@ #![allow(dead_code)] -use std::marker; -use std::slice; - use bbox::BBox; use ray::Ray; use algorithm::partition; @@ -139,64 +136,43 @@ impl<'a, T> BVH<'a, T> { return me; } -} -pub struct BVHTraverser<'a, T: 'a> { - bvh: &'a BVH<'a, T>, - rays: (*mut Ray, usize), - _ray_marker: marker::PhantomData<&'a mut [Ray]>, - i_stack: [usize; 65], - ray_i_stack: [usize; 65], - stack_ptr: usize, -} + pub fn traverse(&self, rays: &mut [Ray], mut obj_ray_test: F) + where F: FnMut(&T, &mut [Ray]) + { + let mut i_stack = [0; 65]; + let mut ray_i_stack = [rays.len(); 65]; + let mut stack_ptr = 1; -impl<'a, T> BVHTraverser<'a, T> { - pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, rays: &'a mut [Ray]) -> BVHTraverser<'a, T> { - BVHTraverser { - bvh: bvh, - rays: (&mut rays[0] as *mut Ray, rays.len()), - _ray_marker: marker::PhantomData, - i_stack: [0; 65], - ray_i_stack: [rays.len(); 65], - stack_ptr: 1, - } - } -} - -impl<'a, T> Iterator for BVHTraverser<'a, T> { - type Item = (&'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) }; - while self.stack_ptr > 0 { - match self.bvh.nodes[self.i_stack[self.stack_ptr]] { + while stack_ptr > 0 { + match self.nodes[i_stack[stack_ptr]] { BVHNode::Internal { bounds, second_child_index } => { - let part = partition(&mut rays[..self.ray_i_stack[self.stack_ptr]], + let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| bounds.intersect_ray(r)); if part > 0 { - self.i_stack[self.stack_ptr] += 1; - self.i_stack[self.stack_ptr + 1] = second_child_index; - self.ray_i_stack[self.stack_ptr] = part; - self.ray_i_stack[self.stack_ptr + 1] = part; - self.stack_ptr += 1; + i_stack[stack_ptr] += 1; + i_stack[stack_ptr + 1] = second_child_index; + ray_i_stack[stack_ptr] = part; + ray_i_stack[stack_ptr + 1] = part; + stack_ptr += 1; } else { - self.stack_ptr -= 1; + stack_ptr -= 1; } } 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]], + let part = partition(&mut rays[..ray_i_stack[stack_ptr]], |r| bounds.intersect_ray(r)); - self.stack_ptr -= 1; if part > 0 { - return Some((&self.bvh.objects[object_range.0..object_range.1], - &mut rays[..part])); + for obj in &self.objects[object_range.0..object_range.1] { + obj_ray_test(obj, &mut rays[..part]); + } } + + stack_ptr -= 1; } } } - - return None; } } diff --git a/src/main.rs b/src/main.rs index a313ac8..ef7c26e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -143,19 +143,17 @@ fn main() { isects.push((false, 0.0, 0.0)); } - // Test ray against scene - for (tris, rs) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut rays[..]) { - 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 t < r.max_t { - isects[r.id as usize] = (true, tri_u, tri_v); - r.max_t = t; - } + // Test rays against scene + scene.traverse(&mut rays, |tri, rs| { + for r in rs { + if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) { + if t < r.max_t { + isects[r.id as usize] = (true, tri_u, tri_v); + r.max_t = t; } } } - } + }); // Calculate color based on ray hits let mut r = 0.0;