aboutsummaryrefslogtreecommitdiff
path: root/src/hittable
diff options
context:
space:
mode:
Diffstat (limited to 'src/hittable')
-rw-r--r--src/hittable/bvh_node.rs89
-rw-r--r--src/hittable/constant_medium.rs20
-rw-r--r--src/hittable/hittable_box.rs75
-rw-r--r--src/hittable/instance/moving.rs29
-rw-r--r--src/hittable/instance/rotate_x.rs56
-rw-r--r--src/hittable/instance/rotate_y.rs54
-rw-r--r--src/hittable/instance/rotate_z.rs54
-rw-r--r--src/hittable/instance/translate.rs12
-rw-r--r--src/hittable/mod.rs4
-rw-r--r--src/hittable/model.rs118
-rw-r--r--src/hittable/sphere.rs22
-rw-r--r--src/hittable/triangle.rs15
-rw-r--r--src/hittable/xy_rect.rs31
-rw-r--r--src/hittable/xz_rect.rs31
-rw-r--r--src/hittable/yz_rect.rs31
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,
+ },
+ }),
}
}
}