Add rotate
This commit is contained in:
parent
f5f46a7a0b
commit
c6b0fb59ae
86
src/rotate_y.rs
Normal file
86
src/rotate_y.rs
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
use crate::hittable::{HitRecord, Hittable};
|
||||||
|
use crate::{Aabb, Point3, Ray, Vec3};
|
||||||
|
|
||||||
|
pub struct RotateY<H: Hittable> {
|
||||||
|
hittable: H,
|
||||||
|
sin_theta: f64,
|
||||||
|
cos_theta: f64,
|
||||||
|
bounding_box: Option<Aabb>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<H: Hittable> RotateY<H> {
|
||||||
|
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<H: Hittable> Hittable for RotateY<H> {
|
||||||
|
fn hit(&self, ray: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord> {
|
||||||
|
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<Aabb> {
|
||||||
|
self.bounding_box
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user