use core::f32::math::sqrt; use std::sync::Arc; use crate::objects::hit::Hit; use crate::objects::materials::traits::Material; use crate::objects::traits::Hittable; use crate::Vec3; pub struct Sphere { center: Vec3, radius: f32, material: Arc, } impl Sphere { pub fn new(center: Vec3, r: f32, mat: Arc) -> Self { Self { center: center, radius: r, material: mat, } } pub fn xyz(x: f32, y: f32, z: f32, r: f32, mat: Arc) -> Self { Self { center: Vec3::new(x, y, z), radius: r, material: mat, } } } impl Hittable for Sphere { fn hit(&self, r: &crate::ray::Ray) -> Option { let oc = self.center - r.origin(); let a = r.dir().length_squared(); let h = r.dir().dot(&oc); let c = oc.length_squared() - self.radius * self.radius; let d = h * h - a * c; if d < 0. { None } else { let t = (h - sqrt(d)) / a; let p = r.at(t); Some(Hit::new(t, p, self.normal_at(&p), self.material.clone())) } } fn normal_at(&self, p: &Vec3) -> Vec3 { (*p - self.center).get_unit() } }