Files
raychel-rs/src/sphere.rs
plexx-dev b3de1760b4
All checks were successful
Build & Test / build (push) Successful in 32s
some refactoring and proper DoF support
2026-02-18 18:33:27 +01:00

60 lines
1.6 KiB
Rust

use std::ops::Deref;
use crate::hittable::*;
use crate::material::Material;
use crate::vec3::*;
use crate::Ray;
pub struct Sphere {
center: Point3,
radius: f64,
material: Box<dyn Material>,
}
impl Sphere {
pub fn new<T: Material + 'static>(center: Point3, radius: f64, material: Box<T>) -> Self {
Sphere {center, radius, material}
}
}
impl Hittable for Sphere {
fn hit(&self, r: &Ray, t_min: f64, t_max: f64) -> Option<HitRecord<'_>> {
let oc = r.origin() - self.center;
let a = r.direction().length_squared();
let half_b = oc.dot(&r.direction());
let c = oc.length_squared() - self.radius * self.radius;
let discriminant = half_b * half_b - a * c;
if discriminant < 0.0 {
return None;
}
let sqrtd = discriminant.sqrt();
// Find the nearest root that lies in the acceptable range
let mut root = (-half_b - sqrtd) / a;
if root < t_min || t_max < root {
root = (-half_b + sqrtd) / a;
if root < t_min || t_max < root {
return None;
}
}
let p = r.at(root);
let outward_normal = (p - self.center) / self.radius;
let front_face = r.direction().dot(&outward_normal) < 0.0;
let outward_normal = if front_face {
outward_normal
} else {
outward_normal * -1.0
};
Some(HitRecord {
t: root,
p: p,
normal: outward_normal,
front_face,
material: self.material.deref(),
})
}
}