66 lines
2.0 KiB
Rust
66 lines
2.0 KiB
Rust
use aabb::AABB;
|
|
use hitable::Hit;
|
|
use hitable::HitRecord;
|
|
use material::Material;
|
|
use ray::Ray;
|
|
use vec3::dot;
|
|
use vec3::Vec3;
|
|
|
|
// Cube is an axis-aligned cube with dimensions length x length x length with center in the middle.
|
|
pub struct Cube {
|
|
center: Vec3,
|
|
length: f32,
|
|
material: Box<Material>,
|
|
}
|
|
|
|
impl Cube {
|
|
pub fn new(center: Vec3, length: f32, material: Box<Material>) -> Cube {
|
|
Cube {
|
|
center,
|
|
length,
|
|
material,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Hit for Cube {
|
|
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
|
|
// See if it hit the positive X wall first.
|
|
let oc = r.origin - self.center;
|
|
let a = dot(r.direction, r.direction);
|
|
let b = dot(oc, r.direction);
|
|
let c = dot(oc, oc) - self.length * self.length;
|
|
let discriminant = b * b - a * c;
|
|
if discriminant > 0. {
|
|
let temp = (-b - (b * b - a * c).sqrt()) / a;
|
|
if temp < t_max && temp > t_min {
|
|
let point = r.point_at_parameter(temp);
|
|
return Some(HitRecord {
|
|
t: temp,
|
|
p: point,
|
|
normal: (point - self.center) / self.length,
|
|
material: &*self.material,
|
|
});
|
|
}
|
|
let temp = (-b + (b * b - a * c).sqrt()) / a;
|
|
if temp < t_max && temp > t_min {
|
|
let point = r.point_at_parameter(temp);
|
|
return Some(HitRecord {
|
|
t: temp,
|
|
p: point,
|
|
normal: (point - self.center) / self.length,
|
|
material: &*self.material,
|
|
});
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option<AABB> {
|
|
Some(AABB::new(
|
|
self.center - Vec3::new(self.length / 2., self.length / 2., self.length / 2.),
|
|
self.center + Vec3::new(self.length / 2., self.length / 2., self.length / 2.),
|
|
))
|
|
}
|
|
}
|