Fixed bug in kdtree that this uncovered. Marked Hit and it's dependencies as needing to implement the Debug trait.
102 lines
2.8 KiB
Rust
102 lines
2.8 KiB
Rust
use crate::{
|
|
aabb::{surrounding_box, AABB},
|
|
hitable::{Hit, HitRecord},
|
|
material::Material,
|
|
ray::Ray,
|
|
sphere::get_sphere_uv,
|
|
vec3::{dot, Vec3},
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct MovingSphere<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
center0: Vec3,
|
|
center1: Vec3,
|
|
radius: f32,
|
|
material: M,
|
|
time0: f32,
|
|
time1: f32,
|
|
}
|
|
|
|
impl<M> MovingSphere<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
pub fn new(
|
|
center0: Vec3,
|
|
center1: Vec3,
|
|
radius: f32,
|
|
time0: f32,
|
|
time1: f32,
|
|
material: M,
|
|
) -> MovingSphere<M> {
|
|
MovingSphere {
|
|
center0,
|
|
center1,
|
|
radius,
|
|
material,
|
|
time0,
|
|
time1,
|
|
}
|
|
}
|
|
fn center(&self, time: f32) -> Vec3 {
|
|
self.center0
|
|
+ ((time - self.time0) / (self.time1 - self.time0)) * (self.center1 - self.center0)
|
|
}
|
|
}
|
|
|
|
impl<M> Hit for MovingSphere<M>
|
|
where
|
|
M: Material,
|
|
{
|
|
fn hit(&self, r: Ray, t0: f32, t1: f32) -> Option<HitRecord> {
|
|
let oc = r.origin - self.center(r.time);
|
|
let a = dot(r.direction, r.direction);
|
|
let b = dot(oc, r.direction);
|
|
let c = dot(oc, oc) - self.radius * self.radius;
|
|
let discriminant = b * b - a * c;
|
|
if discriminant > 0. {
|
|
let temp = (-b - (b * b - a * c).sqrt()) / a;
|
|
if temp < t1 && temp > t0 {
|
|
let point = r.point_at_parameter(temp);
|
|
let uv = get_sphere_uv((point - self.center(r.time)) / self.radius);
|
|
return Some(HitRecord {
|
|
t: temp,
|
|
uv,
|
|
p: point,
|
|
normal: (point - self.center(r.time)) / self.radius,
|
|
material: &self.material,
|
|
});
|
|
}
|
|
let temp = (-b + (b * b - a * c).sqrt()) / a;
|
|
if temp < t1 && temp > t0 {
|
|
let point = r.point_at_parameter(temp);
|
|
let uv = get_sphere_uv((point - self.center(r.time)) / self.radius);
|
|
return Some(HitRecord {
|
|
t: temp,
|
|
uv,
|
|
p: point,
|
|
normal: (point - self.center(r.time)) / self.radius,
|
|
material: &self.material,
|
|
});
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
|
let t_min_bb = AABB::new(
|
|
self.center0 - Vec3::new(self.radius, self.radius, self.radius),
|
|
self.center0 + Vec3::new(self.radius, self.radius, self.radius),
|
|
);
|
|
|
|
let t_max_bb = AABB::new(
|
|
self.center1 - Vec3::new(self.radius, self.radius, self.radius),
|
|
self.center1 + Vec3::new(self.radius, self.radius, self.radius),
|
|
);
|
|
Some(surrounding_box(&t_min_bb, &t_max_bb))
|
|
}
|
|
}
|