diff options
Diffstat (limited to 'src/hittable/bvh_node.rs')
-rw-r--r-- | src/hittable/bvh_node.rs | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/src/hittable/bvh_node.rs b/src/hittable/bvh_node.rs index d215bc3..405ab5b 100644 --- a/src/hittable/bvh_node.rs +++ b/src/hittable/bvh_node.rs @@ -2,7 +2,7 @@ use std::{cmp, sync::Arc}; use rand::seq::SliceRandom; -use crate::hittable::{HitRecord, Hittable, AABB, hittable_list::HittableList}; +use crate::hittable::{hittable_list::HittableList, HitRecord, Hittable, AABB}; use crate::ray::Ray; pub struct BVHNode { @@ -20,34 +20,72 @@ enum Axis { impl BVHNode { pub fn new(hittable_list: &HittableList, time_start: f64, time_end: f64) -> BVHNode { - Self::from_objects(&hittable_list.objects, 0, hittable_list.objects.len(), time_start, time_end) + Self::from_objects( + &hittable_list.objects, + 0, + hittable_list.objects.len(), + time_start, + time_end, + ) } - fn from_objects(src_objects: &Vec<Arc<dyn Hittable>>, start: usize, end: usize, time_start: f64, time_end: f64) -> BVHNode { + fn from_objects( + src_objects: &Vec<Arc<dyn Hittable>>, + start: usize, + end: usize, + time_start: f64, + time_end: f64, + ) -> BVHNode { let mut objects = src_objects.clone(); let comparator = [ - |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| Self::box_compare(a.clone(), b.clone(), Axis::X), - |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| Self::box_compare(a.clone(), b.clone(), Axis::Y), - |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| Self::box_compare(a.clone(), b.clone(), Axis::Z), - ].choose(&mut rand::thread_rng()).unwrap(); + |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| { + Self::box_compare(a.clone(), b.clone(), Axis::X) + }, + |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| { + Self::box_compare(a.clone(), b.clone(), Axis::Y) + }, + |a: &Arc<dyn Hittable>, b: &Arc<dyn Hittable>| { + Self::box_compare(a.clone(), b.clone(), Axis::Z) + }, + ] + .choose(&mut rand::thread_rng()) + .unwrap(); let object_span = end - start; let (left, right) = match object_span { - 1 => (objects.get(start).unwrap().clone(), objects.get(start).unwrap().clone()), + 1 => ( + objects.get(start).unwrap().clone(), + objects.get(start).unwrap().clone(), + ), 2 => match comparator(objects.get(start).unwrap(), objects.get(start + 1).unwrap()) { - cmp::Ordering::Less => (objects.get(start).unwrap().clone(), objects.get(start + 1).unwrap().clone()), - _ => (objects.get(start + 1).unwrap().clone(), objects.get(start).unwrap().clone()), - } + cmp::Ordering::Less => ( + objects.get(start).unwrap().clone(), + objects.get(start + 1).unwrap().clone(), + ), + _ => ( + objects.get(start + 1).unwrap().clone(), + objects.get(start).unwrap().clone(), + ), + }, _ => { objects[start..end].sort_by(comparator); let mid = start + object_span / 2; - (Arc::new(BVHNode::from_objects(&objects, start, mid, time_start, time_end)) as Arc<dyn Hittable>, - Arc::new(BVHNode::from_objects(&objects, mid, end, time_start, time_end)) as Arc<dyn Hittable>) - + ( + Arc::new(BVHNode::from_objects( + &objects, start, mid, time_start, time_end, + )) as Arc<dyn Hittable>, + Arc::new(BVHNode::from_objects( + &objects, mid, end, time_start, time_end, + )) as Arc<dyn Hittable>, + ) } }; - let box_left = left.bounding_box(time_start, time_end).expect("No bounding box in bvh_node constructor!"); - let box_right = right.bounding_box(time_start, time_end).expect("No bounding box in bvh_node constructor!"); + let box_left = left + .bounding_box(time_start, time_end) + .expect("No bounding box in bvh_node constructor!"); + let box_right = right + .bounding_box(time_start, time_end) + .expect("No bounding box in bvh_node constructor!"); BVHNode { left, @@ -56,19 +94,28 @@ impl BVHNode { } } - fn box_compare (a: Arc<dyn Hittable>, b: Arc<dyn Hittable>, axis: Axis) -> cmp::Ordering { - let box_a = a.bounding_box(0.0, 0.0).expect("No bounding box in bvh_node constructor!"); - let box_b = b.bounding_box(0.0, 0.0).expect("No bounding box in bvh_node constructor!"); + fn box_compare(a: Arc<dyn Hittable>, b: Arc<dyn Hittable>, axis: Axis) -> cmp::Ordering { + let box_a = a + .bounding_box(0.0, 0.0) + .expect("No bounding box in bvh_node constructor!"); + let box_b = b + .bounding_box(0.0, 0.0) + .expect("No bounding box in bvh_node constructor!"); // TODO: total_cmp is unstable :( - box_a.minimum.get(axis as usize).unwrap().partial_cmp(box_b.minimum.get(axis as usize).unwrap()).unwrap() + box_a + .minimum + .get(axis as usize) + .unwrap() + .partial_cmp(box_b.minimum.get(axis as usize).unwrap()) + .unwrap() } } impl Hittable for BVHNode { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> { if !self.aabb.hit(ray, t_min, t_max) { - return None + return None; } let hit_left = self.left.hit(ray, t_min, t_max); let hit_right_threshold = if let Some(hit_record_left) = &hit_left { |