Files
rustpt/src/sphere.rs
Robert Garrett 5cc0b49cd9 Mid-Material save point
I get lazy with commits when following guided material. There's a design
challenge to approach, now. I'm saving here so I can revert changes in
case it goes sideways.

Materials are proving to be a little complicated in Rust semantics. The
Ray Tracing in a Weekend book uses shared_ptr's, but Rust doesn't really
like that. I'm doing references with lifetime annotations. Hopefully I
can get that the right way around to work out.

The materials themselves look like reasonable candidates for describing
as Enums. This takes away the ability to add new ones by simply impl'ing
a trait, but that was never gonna happen anyway. The code would be
modified and recompiled. There's no difference in maintenance cost if
that's a new struct impl'ing a trait, or adding enum members.
2023-06-03 09:48:54 -05:00

52 lines
1.3 KiB
Rust

use crate::vec3::Vec3;
use crate::hittable::{
Hittable,
HitRecord,
};
use crate::material::Material;
use crate::ray::Ray;
pub struct Sphere<'a>{
pub center: Vec3,
pub radius: f32,
pub material: &'a Material,
}
impl<'a> Hittable for Sphere<'a> {
fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option<HitRecord>{
let oc = r.orig - self.center;
let a = r.dir.length_squared();
let half_b = Vec3::dot(oc, r.dir);
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();
// nearest root that lies within tolerance
let root = (-half_b - sqrtd) / a;
if root < t_min || root > t_max {
let root = (-half_b + sqrtd) / a;
if root < t_min || root > t_max {
return None;
}
}
let mut record = HitRecord{
p: r.at(root),
normal: (r.at(root) - self.center) / self.radius,
material: Some(self.material),
t: root,
front_face: false,
};
let outward_normal = (record.p - self.center) / self.radius;
record.set_face_normal(r, outward_normal);
Some(record)
}
}