use aabb::AABB; use hitable::Hit; use hitable::HitRecord; use material::Material; use ray::Ray; use vec3::dot; use vec3::Vec3; pub struct Sphere { center: Vec3, radius: f32, material: Box, } impl Sphere { pub fn new(center: Vec3, radius: f32, material: Box) -> Sphere { Sphere { center, radius, material, } } } impl Hit for Sphere { fn hit(&self, r: Ray, t_min: f32, t_max: f32) -> Option { let oc = r.origin - self.center; let a = dot(r.direction, r.direction); let b = dot(oc, r.direction); let c = dot(oc, oc) - self.radius * self.radius; let discriminant = b * b - a * c; if discriminant > 0. { let temp = (-b - (b * b - a * c).sqrt()) / a; if temp < t_max && temp > t_min { let point = r.point_at_parameter(temp); return Some(HitRecord { t: temp, p: point, normal: (point - self.center) / self.radius, material: &*self.material, }); } let temp = (-b + (b * b - a * c).sqrt()) / a; if temp < t_max && temp > t_min { let point = r.point_at_parameter(temp); return Some(HitRecord { t: temp, p: point, normal: (point - self.center) / self.radius, material: &*self.material, }); } } None } fn bounding_box(&self, _t_min: f32, _t_max: f32) -> Option { Some(AABB::new( self.center - Vec3::new(self.radius, self.radius, self.radius), self.center + Vec3::new(self.radius, self.radius, self.radius), )) } }