From c6b0fb59ae432876b0ad4014750479c855ddd277 Mon Sep 17 00:00:00 2001 From: "max.nuding" Date: Mon, 11 Jul 2022 07:33:25 +0200 Subject: [PATCH] Add rotate --- src/rotate_y.rs | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/rotate_y.rs diff --git a/src/rotate_y.rs b/src/rotate_y.rs new file mode 100644 index 0000000..b922717 --- /dev/null +++ b/src/rotate_y.rs @@ -0,0 +1,86 @@ +use crate::hittable::{HitRecord, Hittable}; +use crate::{Aabb, Point3, Ray, Vec3}; + +pub struct RotateY { + hittable: H, + sin_theta: f64, + cos_theta: f64, + bounding_box: Option +} + +impl RotateY { + pub fn new(hittable: H, degrees: f64) -> Self { + let radians = degrees.to_radians(); + let sin_theta = radians.sin(); + let cos_theta = radians.cos(); + let mut bounding_box = hittable.bounding_box(0.0, 1.0); + + if let Some(bbox) = bounding_box { + let mut min = Point3::new(f64::INFINITY, f64::INFINITY, f64::INFINITY); + let mut max = Point3::new(f64::NEG_INFINITY, f64::NEG_INFINITY, f64::NEG_INFINITY); + for i in 0..2 { + for j in 0..2 { + for k in 0..2 { + let x = (i as f64)*bbox.maximum.x() + ((1 - i) as f64)*bbox.minimum.x(); + let y = (i as f64)*bbox.maximum.y() + ((1 - j) as f64)*bbox.minimum.y(); + let z = (i as f64)*bbox.maximum.z() + ((1 - k) as f64)*bbox.minimum.z(); + + let x = cos_theta * x + sin_theta * z; + let z = -sin_theta * x + cos_theta * z; + + let tester = Vec3::new(x, y, z); + for c in 0..3 { + min[c] = min[c].min(tester[c]); + max[c] = max[c].max(tester[c]); + } + } + } + } + bounding_box = Some(Aabb { + minimum: min, + maximum: max + }); + } + Self { hittable, sin_theta, cos_theta, bounding_box } + } +} +impl Hittable for RotateY { + fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option { + let mut origin = ray.origin(); + let mut direction = ray.direction(); + + origin[0] = self.cos_theta * ray.origin()[0] - self.sin_theta*ray.origin()[2]; + origin[2] = self.sin_theta * ray.origin()[0] + self.cos_theta*ray.origin()[2]; + + direction[0] = self.cos_theta * ray.direction()[0] - self.sin_theta*ray.direction()[2]; + direction[2] = self.sin_theta * ray.direction()[0] + self.cos_theta*ray.direction()[2]; + let rotated = Ray::new(origin, direction, ray.time()); + match self.hittable.hit(&rotated, t_min, t_max) { + Some(rec) => { + let mut p = rec.point; + let mut normal = rec.normal; + p[0] = self.cos_theta*rec.point[0] + self.sin_theta * rec.point[2]; + p[2] = -self.sin_theta*rec.point[0] + self.cos_theta * rec.point[2]; + + normal[0] = self.cos_theta*rec.normal[0] + self.sin_theta * rec.normal[2]; + normal[2] = -self.sin_theta*rec.normal[0] + self.cos_theta * rec.normal[2]; + let mut new_rec = HitRecord { + point: p, + normal, + t: rec.t, + u: rec.u, + v: rec.v, + front_face: rec.front_face, + material: rec.material, + }; + new_rec.normalized(&rotated); + Some(new_rec) + }, + _ => None + } + } + + fn bounding_box(&self, _time0: f64, _time1: f64) -> Option { + self.bounding_box + } +}