From 63ccb552fd45677e74cda64d261f9f005f75d217 Mon Sep 17 00:00:00 2001 From: dengqn Date: Sun, 3 Aug 2025 01:33:15 +0800 Subject: [PATCH] 6.3.An Abstraction for Hittable Objects --- src/hittable.rs | 5 +++++ src/sphere.rs | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 src/hittable.rs create mode 100644 src/sphere.rs diff --git a/src/hittable.rs b/src/hittable.rs new file mode 100644 index 0000000..765d700 --- /dev/null +++ b/src/hittable.rs @@ -0,0 +1,5 @@ +use crate::types_defined::{HitRecord, Ray}; + +pub trait Hittable { + fn hit(self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord; +} \ No newline at end of file diff --git a/src/sphere.rs b/src/sphere.rs new file mode 100644 index 0000000..a63d907 --- /dev/null +++ b/src/sphere.rs @@ -0,0 +1,41 @@ +use crate::hittable; +use crate::types_defined::{HitRecord, Point, Ray, Sphere}; + +impl Sphere { + pub fn new(c: Point, r: f32) -> Self { + Self { + center: c, + radius: r, + } + } +} + +impl hittable::Hittable for Sphere { + fn hit(self, r: &Ray, t_min: f32, t_max: f32) -> HitRecord { + let a: f32 = r.direction.length_squared(); + let h = r.direction.dot(self.center - r.point); + // let b = -2.0 * r.direction.dot(sphere_center - r.point); + let c = (self.center - r.point).length_squared() - self.radius * self.radius; + + let discriminant = h * h - a * c; + + // // 两个焦点 + let disc_sqrt = discriminant.sqrt(); + let near = (h - disc_sqrt) / a; + let far = (h + disc_sqrt) / a; + + let mut root = near; + if root <= t_min || root >= t_max { + root = far; + if root <= t_min || root >= t_max { + root = -1.0; + } + } + + HitRecord { + t: root, + p: r.at(root), + normal: r.at(root) - self.center, + } + } +}