use crate::material::Material;
use crate::ray::Ray;
use crate::vec3::Vec3;
use std::sync::Arc;
#[derive(Clone)]
pub struct HitRecord {
pub p: Vec3,
pub normal: Vec3,
pub t: f32,
pub front_face: bool,
pub material: Arc<dyn Material>,
}
impl HitRecord {
#[inline]
pub fn set_face_normal(&mut self, ray: &Ray, outward_normal: Vec3) {
self.front_face = ray.dir.dot(outward_normal) < 0.0;
self.normal = if self.front_face { outward_normal } else { -outward_normal };
}
}
pub trait Hittable: Send + Sync {
fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option<HitRecord>;
}
pub struct HittableList {
pub objects: Vec<Arc<dyn Hittable>>,
}
impl HittableList {
pub fn new() -> Self { Self { objects: Vec::new() } }
pub fn push(&mut self, obj: Arc<dyn Hittable>) { self.objects.push(obj); }
}
impl Hittable for HittableList {
fn hit(&self, ray: &Ray, t_min: f32, t_max: f32) -> Option<HitRecord> {
let mut closest = t_max;
let mut best = None;
for obj in &self.objects {
if let Some(rec) = obj.hit(ray, t_min, closest) {
closest = rec.t;
best = Some(rec);
}
}
best
}
}