diff options
Diffstat (limited to 'src/hittable')
-rw-r--r-- | src/hittable/bvh_node.rs | 89 | ||||
-rw-r--r-- | src/hittable/constant_medium.rs | 20 | ||||
-rw-r--r-- | src/hittable/hittable_box.rs | 75 | ||||
-rw-r--r-- | src/hittable/instance/moving.rs | 29 | ||||
-rw-r--r-- | src/hittable/instance/rotate_x.rs | 56 | ||||
-rw-r--r-- | src/hittable/instance/rotate_y.rs | 54 | ||||
-rw-r--r-- | src/hittable/instance/rotate_z.rs | 54 | ||||
-rw-r--r-- | src/hittable/instance/translate.rs | 12 | ||||
-rw-r--r-- | src/hittable/mod.rs | 4 | ||||
-rw-r--r-- | src/hittable/model.rs | 118 | ||||
-rw-r--r-- | src/hittable/sphere.rs | 22 | ||||
-rw-r--r-- | src/hittable/triangle.rs | 15 | ||||
-rw-r--r-- | src/hittable/xy_rect.rs | 31 | ||||
-rw-r--r-- | src/hittable/xz_rect.rs | 31 | ||||
-rw-r--r-- | src/hittable/yz_rect.rs | 31 |
15 files changed, 477 insertions, 164 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 { diff --git a/src/hittable/constant_medium.rs b/src/hittable/constant_medium.rs index 36ac2ff..50bddc6 100644 --- a/src/hittable/constant_medium.rs +++ b/src/hittable/constant_medium.rs @@ -1,6 +1,12 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::{Isotropic, Material}, ray::Ray, texture::Texture, vec3::{Vec3, Point3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::{Isotropic, Material}, + ray::Ray, + texture::Texture, + vec3::Vec3, +}; pub struct ConstantMedium { boundary: Arc<dyn Hittable>, @@ -13,7 +19,7 @@ impl ConstantMedium { Self { boundary, phase_function: Arc::new(Isotropic::from_texture(texture)), - neg_inv_density: -1.0/density, + neg_inv_density: -1.0 / density, } } } @@ -52,10 +58,14 @@ impl Hittable for ConstantMedium { p: ray.at(t), t, material: Some(self.phase_function.clone()), - normal: Vec3 { x: 1.0, y: 0.0, z: 0.0 }, // arbitrary + normal: Vec3 { + x: 1.0, + y: 0.0, + z: 0.0, + }, // arbitrary front_face: true, // arbitrary - u: 0.0, // arbitrary - v: 0.0, // arbitrary + u: 0.0, // arbitrary + v: 0.0, // arbitrary }) } diff --git a/src/hittable/hittable_box.rs b/src/hittable/hittable_box.rs index 7b95cc7..9631635 100644 --- a/src/hittable/hittable_box.rs +++ b/src/hittable/hittable_box.rs @@ -1,6 +1,14 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB, hittable_list::HittableList, xy_rect::XYRect, xz_rect::XZRect, yz_rect::YZRect}, material::Material, ray::Ray, vec3::Point3}; +use crate::{ + hittable::{ + hittable_list::HittableList, xy_rect::XYRect, xz_rect::XZRect, yz_rect::YZRect, HitRecord, + Hittable, AABB, + }, + material::Material, + ray::Ray, + vec3::Point3, +}; pub struct HittableBox { min: Point3, @@ -12,20 +20,58 @@ impl HittableBox { pub fn new(min: Point3, max: Point3, material: Arc<dyn Material>) -> Self { let mut sides = HittableList::new(); - sides.add(Arc::new(XYRect { material: material.clone(), x0: min.x, x1: max.x, y0: min.y, y1: max.y, k: max.z })); - sides.add(Arc::new(XYRect { material: material.clone(), x0: min.x, x1: max.x, y0: min.y, y1: max.y, k: min.z })); + sides.add(Arc::new(XYRect { + material: material.clone(), + x0: min.x, + x1: max.x, + y0: min.y, + y1: max.y, + k: max.z, + })); + sides.add(Arc::new(XYRect { + material: material.clone(), + x0: min.x, + x1: max.x, + y0: min.y, + y1: max.y, + k: min.z, + })); - sides.add(Arc::new(XZRect { material: material.clone(), x0: min.x, x1: max.x, z0: min.z, z1: max.z, k: max.y })); - sides.add(Arc::new(XZRect { material: material.clone(), x0: min.x, x1: max.x, z0: min.z, z1: max.z, k: min.y })); + sides.add(Arc::new(XZRect { + material: material.clone(), + x0: min.x, + x1: max.x, + z0: min.z, + z1: max.z, + k: max.y, + })); + sides.add(Arc::new(XZRect { + material: material.clone(), + x0: min.x, + x1: max.x, + z0: min.z, + z1: max.z, + k: min.y, + })); - sides.add(Arc::new(YZRect { material: material.clone(), y0: min.y, y1: max.y, z0: min.z, z1: max.z, k: max.x })); - sides.add(Arc::new(YZRect { material: material.clone(), y0: min.y, y1: max.y, z0: min.z, z1: max.z, k: min.x })); + sides.add(Arc::new(YZRect { + material: material.clone(), + y0: min.y, + y1: max.y, + z0: min.z, + z1: max.z, + k: max.x, + })); + sides.add(Arc::new(YZRect { + material: material.clone(), + y0: min.y, + y1: max.y, + z0: min.z, + z1: max.z, + k: min.x, + })); - Self { - min, - max, - sides, - } + Self { min, max, sides } } } @@ -35,6 +81,9 @@ impl Hittable for HittableBox { } fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> { - Some(AABB { minimum: self.min.clone(), maximum: self.max.clone() }) + Some(AABB { + minimum: self.min.clone(), + maximum: self.max.clone(), + }) } } diff --git a/src/hittable/instance/moving.rs b/src/hittable/instance/moving.rs index 418fdbb..062af86 100644 --- a/src/hittable/instance/moving.rs +++ b/src/hittable/instance/moving.rs @@ -1,7 +1,7 @@ use std::sync::Arc; -use crate::{ray::Ray, vec3::Vec3}; use crate::hittable::{HitRecord, Hittable, AABB}; +use crate::{ray::Ray, vec3::Vec3}; pub struct Moving { pub hittable: Arc<dyn Hittable>, @@ -13,13 +13,19 @@ pub struct Moving { impl Moving { fn offset_at(&self, time: f64) -> Vec3 { - &self.offset_start + ((time - self.time_start) / (self.time_end - self.time_start)) * (&self.offset_end - &self.offset_start) + &self.offset_start + + ((time - self.time_start) / (self.time_end - self.time_start)) + * (&self.offset_end - &self.offset_start) } } impl Hittable for Moving { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> { - let moved_ray = Ray { origin: &ray.origin - &self.offset_at(ray.time), direction: ray.direction.clone(), time: ray.time }; + let moved_ray = Ray { + origin: &ray.origin - &self.offset_at(ray.time), + direction: ray.direction.clone(), + time: ray.time, + }; let mut hit_record = self.hittable.hit(&moved_ray, t_min, t_max)?; hit_record.p += self.offset_at(ray.time).clone(); let normal = hit_record.normal.clone(); @@ -29,12 +35,15 @@ impl Hittable for Moving { fn bounding_box(&self, time_start: f64, time_end: f64) -> Option<AABB> { let output_box = self.hittable.bounding_box(time_start, time_end)?; - Some(AABB { - minimum: &output_box.minimum + &self.offset_at(time_start), - maximum: &output_box.maximum + &self.offset_at(time_start), - }.surrounding_box(&AABB { - minimum: &output_box.minimum + &self.offset_at(time_end), - maximum: &output_box.maximum + &self.offset_at(time_end), - })) + Some( + AABB { + minimum: &output_box.minimum + &self.offset_at(time_start), + maximum: &output_box.maximum + &self.offset_at(time_start), + } + .surrounding_box(&AABB { + minimum: &output_box.minimum + &self.offset_at(time_end), + maximum: &output_box.maximum + &self.offset_at(time_end), + }), + ) } } diff --git a/src/hittable/instance/rotate_x.rs b/src/hittable/instance/rotate_x.rs index 4ebc04d..0e09223 100644 --- a/src/hittable/instance/rotate_x.rs +++ b/src/hittable/instance/rotate_x.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, ray::Ray, util::degrees_to_radians, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + ray::Ray, + util::degrees_to_radians, + vec3::{Point3, Vec3}, +}; pub struct RotateX { hittable: Arc<dyn Hittable>, @@ -14,11 +19,25 @@ impl RotateX { let radians = degrees_to_radians(angle); let sin_theta = radians.sin(); let cos_theta = radians.cos(); - match hittable.bounding_box(0.0, 1.0) { // TODO: passing in 0.0 and 1.0 for time seems suspicious. - None => Self { hittable, sin_theta, cos_theta, aabb: None }, + match hittable.bounding_box(0.0, 1.0) { + // TODO: passing in 0.0 and 1.0 for time seems suspicious. + None => Self { + hittable, + sin_theta, + cos_theta, + aabb: None, + }, Some(aabb) => { - let mut min = Point3 { x: f64::INFINITY, y: f64::INFINITY, z: f64::INFINITY }; - let mut max = Point3 { x: -f64::INFINITY, y: -f64::INFINITY, z: -f64::INFINITY }; + let mut min = Point3 { + x: f64::INFINITY, + y: f64::INFINITY, + z: f64::INFINITY, + }; + let mut max = Point3 { + x: -f64::INFINITY, + y: -f64::INFINITY, + z: -f64::INFINITY, + }; for i in 0..2 { for j in 0..2 { for k in 0..2 { @@ -28,15 +47,24 @@ impl RotateX { let new_y = cos_theta * y + sin_theta * y; let new_z = -sin_theta * y + cos_theta * z; - let tester = Vec3 { y: new_y, x, z: new_z }; + let tester = Vec3 { + y: new_y, + x, + z: new_z, + }; for c in 0..3 { - *min.get_mut(c).unwrap() = min.get(c).unwrap().min(*tester.get(c).unwrap()); - *max.get_mut(c).unwrap() = max.get(c).unwrap().max(*tester.get(c).unwrap()); + *min.get_mut(c).unwrap() = + min.get(c).unwrap().min(*tester.get(c).unwrap()); + *max.get_mut(c).unwrap() = + max.get(c).unwrap().max(*tester.get(c).unwrap()); } } } } - let aabb = AABB { minimum: min, maximum: max }; + let aabb = AABB { + minimum: min, + maximum: max, + }; Self { hittable, @@ -56,17 +84,21 @@ impl Hittable for RotateX { origin.y = self.cos_theta * ray.origin.y - self.sin_theta * ray.origin.z; origin.z = self.sin_theta * ray.origin.y + self.cos_theta * ray.origin.z; - + direction.y = self.cos_theta * ray.direction.y - self.sin_theta * ray.direction.z; direction.z = self.sin_theta * ray.direction.y + self.cos_theta * ray.direction.z; - let rotated_ray = Ray { origin, direction, time: ray.time }; + let rotated_ray = Ray { + origin, + direction, + time: ray.time, + }; let mut hit_record = self.hittable.hit(&rotated_ray, t_min, t_max)?; let mut p = hit_record.p.clone(); let mut normal = hit_record.normal.clone(); - p.y = self.cos_theta * hit_record.p.y+ self.sin_theta * hit_record.p.z; + p.y = self.cos_theta * hit_record.p.y + self.sin_theta * hit_record.p.z; p.z = -self.sin_theta * hit_record.p.y + self.cos_theta * hit_record.p.z; normal.y = self.cos_theta * hit_record.normal.y + self.sin_theta * hit_record.normal.z; diff --git a/src/hittable/instance/rotate_y.rs b/src/hittable/instance/rotate_y.rs index 8611616..8f34c09 100644 --- a/src/hittable/instance/rotate_y.rs +++ b/src/hittable/instance/rotate_y.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, ray::Ray, util::degrees_to_radians, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + ray::Ray, + util::degrees_to_radians, + vec3::{Point3, Vec3}, +}; pub struct RotateY { hittable: Arc<dyn Hittable>, @@ -14,11 +19,25 @@ impl RotateY { let radians = degrees_to_radians(angle); let sin_theta = radians.sin(); let cos_theta = radians.cos(); - match hittable.bounding_box(0.0, 1.0) { // TODO: passing in 0.0 and 1.0 for time seems suspicious. - None => Self { hittable, sin_theta, cos_theta, aabb: None }, + match hittable.bounding_box(0.0, 1.0) { + // TODO: passing in 0.0 and 1.0 for time seems suspicious. + None => Self { + hittable, + sin_theta, + cos_theta, + aabb: None, + }, Some(aabb) => { - let mut min = Point3 { x: f64::INFINITY, y: f64::INFINITY, z: f64::INFINITY }; - let mut max = Point3 { x: -f64::INFINITY, y: -f64::INFINITY, z: -f64::INFINITY }; + let mut min = Point3 { + x: f64::INFINITY, + y: f64::INFINITY, + z: f64::INFINITY, + }; + let mut max = Point3 { + x: -f64::INFINITY, + y: -f64::INFINITY, + z: -f64::INFINITY, + }; for i in 0..2 { for j in 0..2 { for k in 0..2 { @@ -28,15 +47,24 @@ impl RotateY { let new_x = cos_theta * x + sin_theta * z; let new_z = -sin_theta * x + cos_theta * z; - let tester = Vec3 { x: new_x, y, z: new_z }; + let tester = Vec3 { + x: new_x, + y, + z: new_z, + }; for c in 0..3 { - *min.get_mut(c).unwrap() = min.get(c).unwrap().min(*tester.get(c).unwrap()); - *max.get_mut(c).unwrap() = max.get(c).unwrap().max(*tester.get(c).unwrap()); + *min.get_mut(c).unwrap() = + min.get(c).unwrap().min(*tester.get(c).unwrap()); + *max.get_mut(c).unwrap() = + max.get(c).unwrap().max(*tester.get(c).unwrap()); } } } } - let aabb = AABB { minimum: min, maximum: max }; + let aabb = AABB { + minimum: min, + maximum: max, + }; Self { hittable, @@ -56,11 +84,15 @@ impl Hittable for RotateY { origin.x = self.cos_theta * ray.origin.x - self.sin_theta * ray.origin.z; origin.z = self.sin_theta * ray.origin.x + self.cos_theta * ray.origin.z; - + direction.x = self.cos_theta * ray.direction.x - self.sin_theta * ray.direction.z; direction.z = self.sin_theta * ray.direction.x + self.cos_theta * ray.direction.z; - let rotated_ray = Ray { origin, direction, time: ray.time }; + let rotated_ray = Ray { + origin, + direction, + time: ray.time, + }; let mut hit_record = self.hittable.hit(&rotated_ray, t_min, t_max)?; let mut p = hit_record.p.clone(); diff --git a/src/hittable/instance/rotate_z.rs b/src/hittable/instance/rotate_z.rs index 119baca..38601ce 100644 --- a/src/hittable/instance/rotate_z.rs +++ b/src/hittable/instance/rotate_z.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, ray::Ray, util::degrees_to_radians, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + ray::Ray, + util::degrees_to_radians, + vec3::{Point3, Vec3}, +}; pub struct RotateZ { hittable: Arc<dyn Hittable>, @@ -14,11 +19,25 @@ impl RotateZ { let radians = degrees_to_radians(angle); let sin_theta = radians.sin(); let cos_theta = radians.cos(); - match hittable.bounding_box(0.0, 1.0) { // TODO: passing in 0.0 and 1.0 for time seems suspicious. - None => Self { hittable, sin_theta, cos_theta, aabb: None }, + match hittable.bounding_box(0.0, 1.0) { + // TODO: passing in 0.0 and 1.0 for time seems suspicious. + None => Self { + hittable, + sin_theta, + cos_theta, + aabb: None, + }, Some(aabb) => { - let mut min = Point3 { x: f64::INFINITY, y: f64::INFINITY, z: f64::INFINITY }; - let mut max = Point3 { x: -f64::INFINITY, y: -f64::INFINITY, z: -f64::INFINITY }; + let mut min = Point3 { + x: f64::INFINITY, + y: f64::INFINITY, + z: f64::INFINITY, + }; + let mut max = Point3 { + x: -f64::INFINITY, + y: -f64::INFINITY, + z: -f64::INFINITY, + }; for i in 0..2 { for j in 0..2 { for k in 0..2 { @@ -28,15 +47,24 @@ impl RotateZ { let new_x = cos_theta * x + sin_theta * y; let new_y = -sin_theta * x + cos_theta * y; - let tester = Vec3 { x: new_x, z, y: new_y }; + let tester = Vec3 { + x: new_x, + z, + y: new_y, + }; for c in 0..3 { - *min.get_mut(c).unwrap() = min.get(c).unwrap().min(*tester.get(c).unwrap()); - *max.get_mut(c).unwrap() = max.get(c).unwrap().max(*tester.get(c).unwrap()); + *min.get_mut(c).unwrap() = + min.get(c).unwrap().min(*tester.get(c).unwrap()); + *max.get_mut(c).unwrap() = + max.get(c).unwrap().max(*tester.get(c).unwrap()); } } } } - let aabb = AABB { minimum: min, maximum: max }; + let aabb = AABB { + minimum: min, + maximum: max, + }; Self { hittable, @@ -56,11 +84,15 @@ impl Hittable for RotateZ { origin.x = self.cos_theta * ray.origin.x - self.sin_theta * ray.origin.y; origin.y = self.sin_theta * ray.origin.x + self.cos_theta * ray.origin.y; - + direction.x = self.cos_theta * ray.direction.x - self.sin_theta * ray.direction.y; direction.y = self.sin_theta * ray.direction.x + self.cos_theta * ray.direction.y; - let rotated_ray = Ray { origin, direction, time: ray.time }; + let rotated_ray = Ray { + origin, + direction, + time: ray.time, + }; let mut hit_record = self.hittable.hit(&rotated_ray, t_min, t_max)?; let mut p = hit_record.p.clone(); diff --git a/src/hittable/instance/translate.rs b/src/hittable/instance/translate.rs index a9c8162..8478bd4 100644 --- a/src/hittable/instance/translate.rs +++ b/src/hittable/instance/translate.rs @@ -1,6 +1,10 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, ray::Ray, vec3::Vec3}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + ray::Ray, + vec3::Vec3, +}; pub struct Translate { pub hittable: Arc<dyn Hittable>, @@ -9,7 +13,11 @@ pub struct Translate { impl Hittable for Translate { fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> { - let moved_ray = Ray { origin: &ray.origin - &self.offset, direction: ray.direction.clone(), time: ray.time }; + let moved_ray = Ray { + origin: &ray.origin - &self.offset, + direction: ray.direction.clone(), + time: ray.time, + }; let mut hit_record = self.hittable.hit(&moved_ray, t_min, t_max)?; hit_record.p += self.offset.clone(); let normal = hit_record.normal.clone(); diff --git a/src/hittable/mod.rs b/src/hittable/mod.rs index e888c71..b2b06f0 100644 --- a/src/hittable/mod.rs +++ b/src/hittable/mod.rs @@ -1,5 +1,5 @@ -pub mod instance; mod bvh_node; +pub mod instance; pub use bvh_node::BVHNode; mod constant_medium; pub use constant_medium::ConstantMedium; @@ -23,9 +23,9 @@ mod aabb; use std::sync::Arc; +use crate::material::Material; use crate::ray::Ray; use crate::vec3::{Point3, Vec3}; -use crate::material::Material; use aabb::AABB; #[derive(Clone)] diff --git a/src/hittable/model.rs b/src/hittable/model.rs index 1a652be..6357ab1 100644 --- a/src/hittable/model.rs +++ b/src/hittable/model.rs @@ -1,7 +1,12 @@ use std::sync::Arc; use std::vec::Vec; -use crate::{hittable::{HitRecord, Hittable, AABB, HittableList, Triangle}, material::Material, ray::Ray, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, HittableList, Triangle, AABB}, + material::Material, + ray::Ray, + vec3::Vec3, +}; pub struct Model { faces: HittableList, @@ -10,7 +15,15 @@ pub struct Model { impl Model { fn parse_face_triplet(triplet: &str) -> Option<(isize, Option<isize>, Option<isize>)> { let mut triplet_iter = triplet.split("/"); - Some((triplet_iter.next()?.parse::<isize>().ok()?, triplet_iter.next().and_then(|val| val.parse::<isize>().ok()) , triplet_iter.next().and_then(|val| val.parse::<isize>().ok()))) + Some(( + triplet_iter.next()?.parse::<isize>().ok()?, + triplet_iter + .next() + .and_then(|val| val.parse::<isize>().ok()), + triplet_iter + .next() + .and_then(|val| val.parse::<isize>().ok()), + )) } pub fn from_obj(obj_data: &str, material: Arc<dyn Material>) -> Self { let mut geometric_vertices: Vec<Vec3> = Vec::new(); @@ -34,95 +47,85 @@ impl Model { None => { eprintln!("Malformed {} entry in OBJ: Missing x!", operator); continue; - }, - Some(val) => { - match val.parse::<f64>() { - Err(_) => { - eprintln!("Malformed {} entry in OBJ: Malformed f64 x!", operator); - continue; - }, - Ok(val) => val, - } } + Some(val) => match val.parse::<f64>() { + Err(_) => { + eprintln!("Malformed {} entry in OBJ: Malformed f64 x!", operator); + continue; + } + Ok(val) => val, + }, }; let y = match entry_iter.next() { None => { eprintln!("Malformed {} entry in OBJ: Missing y!", operator); continue; - }, - Some(val) => { - match val.parse::<f64>() { - Err(_) => { - eprintln!("Malformed {} entry in OBJ: Malformed f64 y!", operator); - continue; - }, - Ok(val) => val, - } } + Some(val) => match val.parse::<f64>() { + Err(_) => { + eprintln!("Malformed {} entry in OBJ: Malformed f64 y!", operator); + continue; + } + Ok(val) => val, + }, }; let z = match entry_iter.next() { None => { eprintln!("Malformed {} entry in OBJ: Missing z!", operator); continue; - }, - Some(val) => { - match val.parse::<f64>() { - Err(_) => { - eprintln!("Malformed {} entry in OBJ: Malformed f64 z!", operator); - continue; - }, - Ok(val) => val, - } } + Some(val) => match val.parse::<f64>() { + Err(_) => { + eprintln!("Malformed {} entry in OBJ: Malformed f64 z!", operator); + continue; + } + Ok(val) => val, + }, }; // who cares about w match operator { - "v" => geometric_vertices.push(Vec3 {x, y, z}), - "vn" => vertex_normals.push(Vec3 {x, y, z}), + "v" => geometric_vertices.push(Vec3 { x, y, z }), + "vn" => vertex_normals.push(Vec3 { x, y, z }), _ => panic!(), } - }, + } "vt" => { let u = match entry_iter.next() { None => { eprintln!("Malformed vt entry in OBJ: Missing u!"); continue; - }, - Some(val) => { - match val.parse::<f64>() { - Err(_) => { - eprintln!("Malformed vt entry in OBJ: Malformed f64 u!"); - continue; - }, - Ok(val) => val, - } } + Some(val) => match val.parse::<f64>() { + Err(_) => { + eprintln!("Malformed vt entry in OBJ: Malformed f64 u!"); + continue; + } + Ok(val) => val, + }, }; let v = match entry_iter.next() { None => { eprintln!("Malformed vt entry in OBJ: Missing v!"); continue; - }, - Some(val) => { - match val.parse::<f64>() { - Err(_) => { - eprintln!("Malformed v entry in OBJ: Malformed f64 v!"); - continue; - }, - Ok(val) => val, - } } + Some(val) => match val.parse::<f64>() { + Err(_) => { + eprintln!("Malformed v entry in OBJ: Malformed f64 v!"); + continue; + } + Ok(val) => val, + }, }; // who cares about w texture_vertices.push((u, v)); - }, + } "f" => { - let mut triplets : Vec<(isize, Option<isize>, Option<isize>)> = Vec::new(); + let mut triplets: Vec<(isize, Option<isize>, Option<isize>)> = Vec::new(); for triplet in entry_iter { match Self::parse_face_triplet(triplet) { None => { eprintln!("Encountered malformed triplet in f operator!"); - }, + } Some(val) => { triplets.push(val); } @@ -163,7 +166,7 @@ impl Model { if let Some(vn2) = triplets.get(2).unwrap().2 { if vn0 != vn1 || vn1 != vn2 { eprintln!("Unsupported geometry in OBJ file: Multiple normals for face!"); - continue + continue; } let mut vn0 = vn0; if vn0 < 0 { @@ -171,16 +174,17 @@ impl Model { } else { vn0 = vn0 - 1; } - triangle.custom_normal = Some(vertex_normals.get(vn0 as usize).unwrap().unit_vector()); + triangle.custom_normal = + Some(vertex_normals.get(vn0 as usize).unwrap().unit_vector()); } } } faces.push(Arc::new(triangle)); - }, + } _ => { eprintln!("Ignoring unknown operator {} in OBJ!", operator); continue; - }, + } } } Self { diff --git a/src/hittable/sphere.rs b/src/hittable/sphere.rs index 783b788..f276366 100644 --- a/src/hittable/sphere.rs +++ b/src/hittable/sphere.rs @@ -1,9 +1,13 @@ -use std::sync::Arc; use std::f64::consts; +use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::Material, vec3::Vec3}; use crate::ray::Ray; use crate::vec3::Point3; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::Material, + vec3::Vec3, +}; pub struct Sphere { pub center: Point3, @@ -54,8 +58,18 @@ impl Hittable for Sphere { fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> { Some(AABB { - minimum: &self.center - Vec3 { x: self.radius, y: self.radius, z: self.radius }, - maximum: &self.center + Vec3 { x: self.radius, y: self.radius, z: self.radius }, + minimum: &self.center + - Vec3 { + x: self.radius, + y: self.radius, + z: self.radius, + }, + maximum: &self.center + + Vec3 { + x: self.radius, + y: self.radius, + z: self.radius, + }, }) } } diff --git a/src/hittable/triangle.rs b/src/hittable/triangle.rs index 0fe5fc4..82b9e18 100644 --- a/src/hittable/triangle.rs +++ b/src/hittable/triangle.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::Material, ray::Ray, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::Material, + ray::Ray, + vec3::{Point3, Vec3}, +}; pub struct Triangle { pub v0: Point3, @@ -12,7 +17,9 @@ pub struct Triangle { impl Triangle { fn has_vertex_at_infinity(&self) -> bool { - self.v0.has_infinite_member() || self.v1.has_infinite_member() || self.v2.has_infinite_member() + self.v0.has_infinite_member() + || self.v1.has_infinite_member() + || self.v2.has_infinite_member() } } @@ -71,9 +78,9 @@ impl Hittable for Triangle { maximum: Point3 { x: self.v0.x.max(self.v1.x).max(self.v2.x) + 0.0001, y: self.v0.y.max(self.v1.y).max(self.v2.y) + 0.0001, - z: self.v0.z.max(self.v1.z).max(self.v2.z) + 0.0001, + z: self.v0.z.max(self.v1.z).max(self.v2.z) + 0.0001, }, - }) + }), } } } diff --git a/src/hittable/xy_rect.rs b/src/hittable/xy_rect.rs index 8421bae..2d7dbeb 100644 --- a/src/hittable/xy_rect.rs +++ b/src/hittable/xy_rect.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::Material, ray::Ray, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::Material, + ray::Ray, + vec3::{Point3, Vec3}, +}; pub struct XYRect { pub material: Arc<dyn Material>, @@ -13,7 +18,10 @@ pub struct XYRect { impl XYRect { fn has_infinite_bounds(&self) -> bool { - self.x0.is_infinite() || self.x1.is_infinite() || self.y0.is_infinite() || self.y1.is_infinite() + self.x0.is_infinite() + || self.x1.is_infinite() + || self.y0.is_infinite() + || self.y1.is_infinite() } } @@ -32,7 +40,11 @@ impl Hittable for XYRect { hit_record.u = (x - self.x0) / (self.x1 - self.x0); hit_record.v = (y - self.y0) / (self.y1 - self.y0); hit_record.t = t; - let outward_normal = Vec3 { x: 0.0, y: 0.0, z: 1.0 }; + let outward_normal = Vec3 { + x: 0.0, + y: 0.0, + z: 1.0, + }; hit_record.set_face_normal(ray, &outward_normal); hit_record.material = Some(self.material.clone()); hit_record.p = ray.at(t); @@ -42,7 +54,18 @@ impl Hittable for XYRect { fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> { match self.has_infinite_bounds() { true => None, - false => Some(AABB { minimum: Point3 { x: self.x0, y: self.y0, z: self.k - 0.0001 }, maximum: Point3 { x: self.x1, y: self.y1, z: self.k + 0.0001 } }), + false => Some(AABB { + minimum: Point3 { + x: self.x0, + y: self.y0, + z: self.k - 0.0001, + }, + maximum: Point3 { + x: self.x1, + y: self.y1, + z: self.k + 0.0001, + }, + }), } } } diff --git a/src/hittable/xz_rect.rs b/src/hittable/xz_rect.rs index 4761f36..c990de5 100644 --- a/src/hittable/xz_rect.rs +++ b/src/hittable/xz_rect.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::Material, ray::Ray, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::Material, + ray::Ray, + vec3::{Point3, Vec3}, +}; pub struct XZRect { pub material: Arc<dyn Material>, @@ -13,7 +18,10 @@ pub struct XZRect { impl XZRect { fn has_infinite_bounds(&self) -> bool { - self.x0.is_infinite() || self.x1.is_infinite() || self.z0.is_infinite() || self.z1.is_infinite() + self.x0.is_infinite() + || self.x1.is_infinite() + || self.z0.is_infinite() + || self.z1.is_infinite() } } @@ -32,7 +40,11 @@ impl Hittable for XZRect { hit_record.u = (x - self.x0) / (self.x1 - self.x0); hit_record.v = (z - self.z0) / (self.z1 - self.z0); hit_record.t = t; - let outward_normal = Vec3 { x: 0.0, y: 1.0, z: 0.0 }; + let outward_normal = Vec3 { + x: 0.0, + y: 1.0, + z: 0.0, + }; hit_record.set_face_normal(ray, &outward_normal); hit_record.material = Some(self.material.clone()); hit_record.p = ray.at(t); @@ -42,7 +54,18 @@ impl Hittable for XZRect { fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> { match self.has_infinite_bounds() { true => None, - false => Some(AABB { minimum: Point3 { x: self.x0, y: self.k - 0.0001, z: self.z0 }, maximum: Point3 { x: self.x1, y: self.k + 0.0001, z: self.z1 } }), + false => Some(AABB { + minimum: Point3 { + x: self.x0, + y: self.k - 0.0001, + z: self.z0, + }, + maximum: Point3 { + x: self.x1, + y: self.k + 0.0001, + z: self.z1, + }, + }), } } } diff --git a/src/hittable/yz_rect.rs b/src/hittable/yz_rect.rs index dd90bdb..db068dd 100644 --- a/src/hittable/yz_rect.rs +++ b/src/hittable/yz_rect.rs @@ -1,6 +1,11 @@ use std::sync::Arc; -use crate::{hittable::{HitRecord, Hittable, AABB}, material::Material, ray::Ray, vec3::{Point3, Vec3}}; +use crate::{ + hittable::{HitRecord, Hittable, AABB}, + material::Material, + ray::Ray, + vec3::{Point3, Vec3}, +}; pub struct YZRect { pub material: Arc<dyn Material>, @@ -13,7 +18,10 @@ pub struct YZRect { impl YZRect { fn has_infinite_bounds(&self) -> bool { - self.y0.is_infinite() || self.y1.is_infinite() || self.z0.is_infinite() || self.z1.is_infinite() + self.y0.is_infinite() + || self.y1.is_infinite() + || self.z0.is_infinite() + || self.z1.is_infinite() } } @@ -32,7 +40,11 @@ impl Hittable for YZRect { hit_record.u = (y - self.y0) / (self.y1 - self.y0); hit_record.v = (z - self.z0) / (self.z1 - self.z0); hit_record.t = t; - let outward_normal = Vec3 { x: 1.0, y: 0.0, z: 0.0 }; + let outward_normal = Vec3 { + x: 1.0, + y: 0.0, + z: 0.0, + }; hit_record.set_face_normal(ray, &outward_normal); hit_record.material = Some(self.material.clone()); hit_record.p = ray.at(t); @@ -42,7 +54,18 @@ impl Hittable for YZRect { fn bounding_box(&self, _: f64, _: f64) -> Option<AABB> { match self.has_infinite_bounds() { true => None, - false => Some(AABB { minimum: Point3 { x: self.k - 0.0001, y: self.y0, z: self.z0 }, maximum: Point3 { x: self.k + 0.0001, y: self.y1, z: self.z1 } }), + false => Some(AABB { + minimum: Point3 { + x: self.k - 0.0001, + y: self.y0, + z: self.z0, + }, + maximum: Point3 { + x: self.k + 0.0001, + y: self.y1, + z: self.z1, + }, + }), } } } |