bvh: add some tests and fmt::Display implementations.
This commit is contained in:
111
rtiow/src/bvh.rs
111
rtiow/src/bvh.rs
@@ -1,4 +1,5 @@
|
||||
use std;
|
||||
use std::fmt;
|
||||
|
||||
use rand;
|
||||
use rand::Rng;
|
||||
@@ -18,10 +19,30 @@ enum BVHNode {
|
||||
},
|
||||
}
|
||||
|
||||
impl fmt::Display for BVHNode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
BVHNode::Leaf(ref hit) => write!(
|
||||
f,
|
||||
"Leaf: {}",
|
||||
hit.bounding_box(0., 0.)
|
||||
.map_or("NO BBOX".to_owned(), |bb| bb.to_string())
|
||||
),
|
||||
BVHNode::Branch { bbox, .. } => write!(
|
||||
f,
|
||||
"Branch: {}",
|
||||
// TODO(wathiede): removing this .clone() results in a complaint about moving out
|
||||
// of a borrow.
|
||||
bbox.clone()
|
||||
.map_or("NO BBOX".to_owned(), |bb| bb.to_string())
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn box_x_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||
(Some(box_left), Some(box_right)) => {
|
||||
eprintln!("box_x_compare {} < {}", box_left.min, box_right.min);
|
||||
return box_left.min.x.partial_cmp(&box_right.min.x).unwrap();
|
||||
}
|
||||
_ => panic!("hit missing bounding box"),
|
||||
@@ -31,7 +52,6 @@ fn box_x_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||
fn box_y_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||
(Some(box_left), Some(box_right)) => {
|
||||
eprintln!("box_y_compare {} < {}", box_left.min, box_right.min);
|
||||
return box_left.min.y.partial_cmp(&box_right.min.y).unwrap();
|
||||
}
|
||||
_ => panic!("hit missing bounding box"),
|
||||
@@ -41,7 +61,6 @@ fn box_y_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||
fn box_z_compare(ah: &Box<Hit>, bh: &Box<Hit>) -> std::cmp::Ordering {
|
||||
match (ah.bounding_box(0., 0.), bh.bounding_box(0., 0.)) {
|
||||
(Some(box_left), Some(box_right)) => {
|
||||
eprintln!("box_z_compare {} < {}", box_left.min, box_right.min);
|
||||
return box_left.min.z.partial_cmp(&box_right.min.z).unwrap();
|
||||
}
|
||||
_ => panic!("hit missing bounding box"),
|
||||
@@ -118,6 +137,7 @@ impl Hit for BVHNode {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn bounding_box(&self, t_min: f32, t_max: f32) -> Option<AABB> {
|
||||
match self {
|
||||
BVHNode::Leaf(ref hit) => hit.bounding_box(t_min, t_max),
|
||||
@@ -138,6 +158,23 @@ impl BVH {
|
||||
}
|
||||
}
|
||||
|
||||
fn print_tree(f: &mut fmt::Formatter, depth: usize, bvhn: &BVHNode) -> fmt::Result {
|
||||
// TODO(wathiede): recurse and indent
|
||||
write!(f, "{}{}\n", " ".repeat(depth * 2), bvhn)?;
|
||||
if let BVHNode::Branch { left, right, .. } = bvhn {
|
||||
print_tree(f, depth + 1, left)?;
|
||||
print_tree(f, depth + 1, right)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
impl fmt::Display for BVH {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "Root\n")?;
|
||||
print_tree(f, 1, &self.root)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hit for BVH {
|
||||
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
||||
self.root.hit(r, t_min, t_max)
|
||||
@@ -147,3 +184,71 @@ impl Hit for BVH {
|
||||
self.root.bounding_box(t_min, t_max)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use aabb::AABB;
|
||||
use material::Lambertian;
|
||||
use material::Metal;
|
||||
use sphere::Sphere;
|
||||
use vec3::Vec3;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn bbox_two_spheres() {
|
||||
let two_spheres_bvh = BVH::new(
|
||||
vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., 0.),
|
||||
0.5,
|
||||
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(1., 0., 0.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)),
|
||||
)),
|
||||
],
|
||||
0.,
|
||||
1.,
|
||||
);
|
||||
assert_eq!(
|
||||
AABB::new(Vec3::new(-0.5, -0.5, -0.5), Vec3::new(1.5, 0.5, 0.5)),
|
||||
two_spheres_bvh.bounding_box(0., 1.).unwrap(),
|
||||
"BVH:\n{}",
|
||||
two_spheres_bvh
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bbox_three_spheres() {
|
||||
let three_spheres_bvh = BVH::new(
|
||||
vec![
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 0., 0.),
|
||||
0.5,
|
||||
Box::new(Lambertian::new(Vec3::new(0.1, 0.2, 0.5))),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(1., 0., 0.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)),
|
||||
)),
|
||||
Box::new(Sphere::new(
|
||||
Vec3::new(0., 1., 0.),
|
||||
0.5,
|
||||
Box::new(Metal::new(Vec3::new(0.6, 0.6, 0.6), 0.2)),
|
||||
)),
|
||||
],
|
||||
0.,
|
||||
1.,
|
||||
);
|
||||
assert_eq!(
|
||||
AABB::new(Vec3::new(-0.5, -0.5, -0.5), Vec3::new(1.5, 1.5, 0.5)),
|
||||
three_spheres_bvh.bounding_box(0., 1.).unwrap(),
|
||||
"BVH:\n{}",
|
||||
three_spheres_bvh
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user