use crate::material::MaterialKind; use crate::types_defined::{HitRecord, Ray, Vec3}; pub trait Hittable { fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool; } pub struct HittableList { pub objects: Vec>, } impl HittableList { pub fn new() -> Self { HittableList { objects: vec![] } } pub fn put(&mut self, object: Box) { let _ = &self.objects.push(object); } pub fn hit(&self, r: &Ray, t_min: f32, t_max: f32, hit_record: &mut HitRecord) -> bool { let mut hits = false; let mut closest_so_far = t_max; let temp_hit_record = &mut HitRecord { t: 0.0, normal: Vec3::new(0.0, 0.0, 0.0), p: Vec3::new(0.0, 0.0, 0.0), front_face: false, material: None, }; for object in &self.objects { let hit = object.hit(r, t_min, closest_so_far, temp_hit_record); if hit { hits = true; closest_so_far = temp_hit_record.t; hit_record.t = temp_hit_record.t; hit_record.p = temp_hit_record.p; hit_record.front_face = temp_hit_record.front_face; hit_record.normal = temp_hit_record.normal; hit_record.material = if let Some(ref m) = temp_hit_record.material { match m { MaterialKind::Lambertian(l) => Some(MaterialKind::Lambertian(l.clone())), MaterialKind::Metal(m) => Some(MaterialKind::Metal(m.clone())), } } else { None }; if temp_hit_record.t >= 0.0 { return true; } } } hits } }