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