Made a BVHTraverser iterator that traverses a BVH with a ray.
It yields the objects that the ray needs to be tested against. Thus it is the responsibility of the code using the iterator to actually do the object-level ray tests and update the ray's max_t etc. accordingly. This keeps all of the BVH-related code generic with respect to what kind of object/data the BVH actually contains, which means the same BVH code can be used for both scene-level and triangle-level data.
This commit is contained in:
parent
1c660dda13
commit
53c9ff9534
62
src/bvh.rs
62
src/bvh.rs
|
@ -1,9 +1,9 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use std::marker;
|
||||
|
||||
use bbox::BBox;
|
||||
use math::Point;
|
||||
use ray::Ray;
|
||||
use triangle;
|
||||
use algorithm::partition;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -129,48 +129,50 @@ impl<'a, T> BVH<'a, T> {
|
|||
}
|
||||
|
||||
|
||||
pub fn intersect_bvh(bvh: &BVH<(Point, Point, Point)>, ray: &mut Ray) -> Option<(f32, f32, f32)> {
|
||||
if bvh.nodes.len() == 0 {
|
||||
return None;
|
||||
pub struct BVHTraverser<'a, T: 'a> {
|
||||
bvh: &'a BVH<'a, T>,
|
||||
ray: *mut Ray,
|
||||
_ray_marker: marker::PhantomData<&'a mut Ray>,
|
||||
i_stack: [usize; 65],
|
||||
stack_ptr: usize,
|
||||
}
|
||||
|
||||
let mut i_stack = [0; 65];
|
||||
let mut stack_ptr: usize = 1;
|
||||
let mut hit = false;
|
||||
let mut u = 0.0;
|
||||
let mut v = 0.0;
|
||||
impl<'a, T> BVHTraverser<'a, T> {
|
||||
pub fn from_bvh_and_ray(bvh: &'a BVH<'a, T>, ray: &'a mut Ray) -> BVHTraverser<'a, T> {
|
||||
BVHTraverser {
|
||||
bvh: bvh,
|
||||
ray: ray as *mut Ray,
|
||||
_ray_marker: marker::PhantomData,
|
||||
i_stack: [0; 65],
|
||||
stack_ptr: 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while stack_ptr > 0 {
|
||||
match bvh.nodes[i_stack[stack_ptr]] {
|
||||
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)> {
|
||||
while self.stack_ptr > 0 {
|
||||
match self.bvh.nodes[self.i_stack[self.stack_ptr]] {
|
||||
BVHNode::Internal { bounds, second_child_index } => {
|
||||
if bounds.intersect_ray(ray) {
|
||||
i_stack[stack_ptr] += 1;
|
||||
i_stack[stack_ptr + 1] = second_child_index;
|
||||
stack_ptr += 1;
|
||||
if bounds.intersect_ray(&(unsafe { *self.ray })) {
|
||||
self.i_stack[self.stack_ptr] += 1;
|
||||
self.i_stack[self.stack_ptr + 1] = second_child_index;
|
||||
self.stack_ptr += 1;
|
||||
} else {
|
||||
stack_ptr -= 1;
|
||||
self.stack_ptr -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
BVHNode::Leaf { bounds: _, object_index } => {
|
||||
if let Some((t, tri_u, tri_v)) =
|
||||
triangle::intersect_ray(ray, bvh.objects[object_index]) {
|
||||
if t < ray.max_t {
|
||||
hit = true;
|
||||
ray.max_t = t;
|
||||
u = tri_u;
|
||||
v = tri_v;
|
||||
self.stack_ptr -= 1;
|
||||
unsafe {
|
||||
return Some((&self.bvh.objects[object_index], &mut (*self.ray)));
|
||||
}
|
||||
}
|
||||
|
||||
stack_ptr -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if hit {
|
||||
return Some((ray.max_t, u, v));
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
|
24
src/main.rs
24
src/main.rs
|
@ -75,8 +75,8 @@ fn main() {
|
|||
// Generate a scene of triangles
|
||||
let mut triangles = {
|
||||
let mut triangles = Vec::new();
|
||||
let xres = 512;
|
||||
let yres = 512;
|
||||
let xres = 16;
|
||||
let yres = 16;
|
||||
let xinc = 512.0 / (xres as f32);
|
||||
let yinc = 512.0 / (yres as f32);
|
||||
for x in 0..xres {
|
||||
|
@ -113,6 +113,7 @@ fn main() {
|
|||
let offset = hash_u32(((x as u32) << 16) ^ (y as u32), 0);
|
||||
const SAMPLES: usize = 16;
|
||||
for si in 0..SAMPLES {
|
||||
// Generate ray
|
||||
let mut ray = Ray::new(Point::new(x as f32 +
|
||||
fast_logit(halton::sample(0,
|
||||
offset + si as u32),
|
||||
|
@ -123,7 +124,23 @@ fn main() {
|
|||
1.5),
|
||||
0.0),
|
||||
Vector::new(0.0, 0.0, 1.0));
|
||||
if let Some((_, u, v)) = bvh::intersect_bvh(&scene, &mut ray) {
|
||||
|
||||
// Test ray against scene
|
||||
let (mut u, mut v) = (0.0, 0.0);
|
||||
let mut hit = false;
|
||||
for (tri, r) in bvh::BVHTraverser::from_bvh_and_ray(&scene, &mut ray) {
|
||||
if let Some((t, tri_u, tri_v)) = triangle::intersect_ray(r, *tri) {
|
||||
if t < r.max_t {
|
||||
hit = true;
|
||||
r.max_t = t;
|
||||
u = tri_u;
|
||||
v = tri_v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update color based on ray hit
|
||||
if hit {
|
||||
r += u;
|
||||
g += v;
|
||||
b += (1.0 - u - v).max(0.0);
|
||||
|
@ -136,6 +153,7 @@ fn main() {
|
|||
b += 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
r *= 255.0 / SAMPLES as f32;
|
||||
g *= 255.0 / SAMPLES as f32;
|
||||
b *= 255.0 / SAMPLES as f32;
|
||||
|
|
Loading…
Reference in New Issue
Block a user