2022-04-27 18:27:07 +02:00
|
|
|
use super::Point3;
|
|
|
|
use super::Ray;
|
|
|
|
use super::Vec3;
|
|
|
|
|
|
|
|
pub struct HitRecord {
|
|
|
|
p: Point3,
|
2022-05-04 18:21:48 +02:00
|
|
|
pub normal: Vec3,
|
|
|
|
pub t: f64,
|
|
|
|
front_face: bool,
|
2022-04-27 18:27:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
pub struct Sphere {
|
|
|
|
center: Point3,
|
|
|
|
radius: f64,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait Hittable {
|
2022-05-04 18:21:48 +02:00
|
|
|
fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HitRecord {
|
|
|
|
fn set_face_normal(&mut self, r: &Ray, outward_normal: Vec3) {
|
|
|
|
self.front_face = Vec3::dot(r.direction(), outward_normal) < 0.0;
|
|
|
|
if self.front_face {
|
|
|
|
self.normal = outward_normal;
|
|
|
|
} else {
|
2022-05-11 18:38:30 +02:00
|
|
|
self.normal = (-1.0) * outward_normal;
|
2022-05-04 18:21:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new(p: Point3, normal: Vec3, t: f64, front_face: bool) -> Self {
|
|
|
|
HitRecord {
|
|
|
|
p: p,
|
|
|
|
normal: normal,
|
|
|
|
t: t,
|
|
|
|
front_face: front_face,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn empty() -> Self {
|
2022-05-11 18:38:30 +02:00
|
|
|
Self::new(
|
|
|
|
Point3::new(0.0, 0.0, 0.0),
|
|
|
|
Vec3::new(0.0, 0.0, 0.0),
|
|
|
|
0.0,
|
|
|
|
false,
|
|
|
|
)
|
2022-05-04 18:21:48 +02:00
|
|
|
}
|
2022-04-27 18:27:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Sphere {
|
2022-05-04 18:21:48 +02:00
|
|
|
pub fn new(cen: Point3, r: f64) -> Self {
|
2022-04-27 18:27:07 +02:00
|
|
|
Sphere {
|
|
|
|
center: cen,
|
|
|
|
radius: r,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Hittable for Sphere {
|
2022-05-04 18:21:48 +02:00
|
|
|
fn hit(&self, r: &Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool {
|
2022-04-27 18:27:07 +02:00
|
|
|
let oc = r.origin() - self.center;
|
|
|
|
let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt
|
2022-05-04 18:21:48 +02:00
|
|
|
let half_b = Vec3::dot(oc, r.direction());
|
2022-04-27 18:27:07 +02:00
|
|
|
let c = oc.length_squared() - self.radius * self.radius;
|
|
|
|
|
2022-05-04 18:21:48 +02:00
|
|
|
let discriminant = half_b * half_b - a * c;
|
2022-04-27 18:27:07 +02:00
|
|
|
if discriminant < 0.0 {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
let sqrtd = discriminant.sqrt();
|
|
|
|
|
2022-05-04 18:21:48 +02:00
|
|
|
let root = (-half_b - sqrtd) / a;
|
2022-04-27 18:27:07 +02:00
|
|
|
if root < t_min || t_max < root {
|
2022-05-04 18:21:48 +02:00
|
|
|
let root2 = (-half_b + sqrtd) / a;
|
2022-04-27 18:27:07 +02:00
|
|
|
if root2 < t_min || t_max < root {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
rec.t = root;
|
|
|
|
rec.p = r.at(rec.t);
|
2022-05-04 18:21:48 +02:00
|
|
|
let outward_normal = (rec.p - self.center) / self.radius;
|
|
|
|
rec.set_face_normal(r, outward_normal);
|
2022-04-27 18:27:07 +02:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|