Bill Thiede 4066bf4b85 rtiow: add blox with gloxy edges.
Fixed bug in kdtree that this uncovered.
Marked Hit and it's dependencies as needing to implement the Debug
trait.
2022-09-17 16:45:29 -07:00

100 lines
3.0 KiB
Rust

use std::f32::{consts::PI, MAX, MIN};
use crate::{
aabb::AABB,
hitable::{Hit, HitRecord},
ray::Ray,
vec3::Vec3,
};
#[derive(Debug)]
pub struct RotateY<H>
where
H: Hit,
{
hitable: H,
sin_theta: f32,
cos_theta: f32,
bbox: Option<AABB>,
}
impl<H> RotateY<H>
where
H: Hit,
{
pub fn new(hitable: H, angle: f32) -> RotateY<H> {
let radians = PI / 180. * angle;
let sin_theta = radians.sin();
let cos_theta = radians.cos();
let mut min = vec![MAX, MAX, MAX];
let mut max = vec![MIN, MIN, MIN];
let bbox = hitable.bounding_box(0., 1.).unwrap();
for i in 0..2 {
for j in 0..2 {
for k in 0..2 {
let x = i as f32 * bbox.max().x + (1 - i) as f32 * bbox.min().x;
let y = j as f32 * bbox.max().y + (1 - j) as f32 * bbox.min().y;
let z = k as f32 * bbox.max().z + (1 - k) as f32 * bbox.min().z;
let new_x = cos_theta * x + sin_theta * z;
let new_z = -sin_theta * x + cos_theta * z;
let tester = Vec3::new(new_x, y, new_z);
for c in 0..3 {
if tester[c] > max[c] {
max[c] = tester[c];
}
if tester[c] < min[c] {
min[c] = tester[c];
}
}
}
}
}
RotateY {
hitable,
sin_theta,
cos_theta,
bbox: Some(AABB::new(
Vec3::new(min[0], min[1], min[2]),
Vec3::new(max[0], max[1], max[2]),
)),
}
}
}
impl<H> Hit for RotateY<H>
where
H: Hit,
{
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
let origin = Vec3::new(
self.cos_theta * r.origin[0] - self.sin_theta * r.origin[2],
r.origin.y,
self.sin_theta * r.origin[0] + self.cos_theta * r.origin[2],
);
let direction = Vec3::new(
self.cos_theta * r.direction[0] - self.sin_theta * r.direction[2],
r.direction.y,
self.sin_theta * r.direction[0] + self.cos_theta * r.direction[2],
);
let rotated_r = Ray::new(origin, direction, r.time);
if let Some(rec) = self.hitable.hit(rotated_r, t_min, t_max) {
let p = Vec3::new(
self.cos_theta * rec.p[0] + self.sin_theta * rec.p[2],
rec.p[1],
-self.sin_theta * rec.p[0] + self.cos_theta * rec.p[2],
);
let normal = Vec3::new(
self.cos_theta * rec.normal[0] + self.sin_theta * rec.normal[2],
rec.normal[1],
-self.sin_theta * rec.normal[0] + self.cos_theta * rec.normal[2],
);
return Some(HitRecord { p, normal, ..rec });
}
None
}
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
self.bbox.clone()
}
}