use super::Point3; use super::Ray; use super::Vec3; pub struct HitRecord { p: Point3, normal: Vec3, t: f64, } pub struct Sphere { center: Point3, radius: f64, } pub trait Hittable { fn hit(&self, r: Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool; } impl Sphere { fn new(cen: Point3, r: f64) -> Self { Sphere { center: cen, radius: r, } } } impl Hittable for Sphere { fn hit(&self, r: Ray, t_min: f64, t_max: f64, rec: &mut HitRecord) -> bool { let oc = r.origin() - self.center; let a = r.direction().length_squared(); // gleiches Ergebnis wie Skalarprodukt let b = 2.0 * Vec3::dot(oc, r.direction()); let c = oc.length_squared() - self.radius * self.radius; let discriminant = b * b - 4.0 * a * c; if discriminant < 0.0 { return false; } let sqrtd = discriminant.sqrt(); let root = (-b / 2.0 - sqrtd) / a; if root < t_min || t_max < root { let root2 = (-b / 2.0 + sqrtd) / a; if root2 < t_min || t_max < root { return false; } } rec.t = root; rec.p = r.at(rec.t); rec.normal = (rec.p - self.center) / self.radius; return true; } }