raytracing-rs

https://raytracing.github.io in Rust

git clone https://code.pdelong.com/raytracing-rs.git

 1use super::HitRecord;
 2use super::Hittable;
 3use crate::math::Interval;
 4use crate::math::NotNanF64;
 5use crate::math::Point;
 6
 7pub struct Sphere {
 8    center: Point,
 9    radius: f64,
10}
11
12impl Sphere {
13    pub fn new(center: Point, radius: f64) -> Sphere {
14        Sphere { center, radius }
15    }
16}
17
18impl Hittable for Sphere {
19    fn hit(&self, r: &crate::math::Ray, range: &Interval) -> Option<HitRecord> {
20        let oc = self.center - r.orig;
21        // a is always 1, so we can remove it from all calculations below.
22        //   let a = r.dir.length_squared();
23        let a = r.dir.length_squared();
24        let h = r.dir.dot(&oc);
25        let c = oc.length_squared() - self.radius * self.radius;
26
27        let descriminant = h * h - (a * c);
28        if descriminant < 0. {
29            return None;
30        }
31
32        let sqrtd = descriminant.sqrt();
33
34        let mut t = (h - sqrtd) / a;
35        if !range.surrounds(t) {
36            t = h + sqrtd;
37            if !range.surrounds(t) {
38                return None;
39            }
40        }
41
42        let point = r.at(t);
43        // FIXME: Should be able to divide by radius, but there seems to be some
44        // precision error creeping in somewhere.
45        let normal = (point - self.center).normalize();
46
47        Some(HitRecord::new(r, point, normal, NotNanF64::new(t).unwrap()))
48    }
49}