use std::sync::Arc; use crate::{ objects::{materials::traits::Material, traits::Hittable}, ray::Ray, vec3::Vec3, }; pub struct Hit { t: f32, p: Vec3, n: Vec3, mat: Arc, front_face: bool, u: f32, v: f32, } impl Hit { pub fn new( t: f32, p: Vec3, n: Vec3, mat: Arc, front_face: bool, u: f32, v: f32, ) -> Self { Self { t, p, n: if front_face { n } else { -n }, mat, front_face, u, v, } } pub fn from_minimal( mh: MinimalHit, n: Vec3, mat: Arc, front_face: bool, u: f32, v: f32, ) -> Self { Self { t: mh.t, p: mh.p, n, mat, front_face, u, v, } } pub fn t(&self) -> &f32 { &self.t } pub fn p(&self) -> &Vec3 { &self.p } pub fn n(&self) -> &Vec3 { &self.n } pub fn mat(&self) -> Arc { self.mat.clone() } pub fn front_face(&self) -> bool { self.front_face } pub fn uv(&self) -> (f32, f32) { (self.u, self.v) } // TODO: use front_face to discard back-hits for culling pub fn hit_list(hittables: &Vec>, r: &Ray) -> Option { let mut closest: Option = None; for hittable in hittables { if let Some(hit) = hittable.hit(r) { // hit happens in front of camera and is closer than closest if *hit.t() > 0.001 && (closest.is_none() || closest.as_ref().unwrap().t() > hit.t()) { closest = Some(hit); } } } closest } } pub struct MinimalHit { t: f32, p: Vec3, } impl MinimalHit { pub fn new(t: f32, p: Vec3) -> Self { Self { t, p } } pub fn t(&self) -> f32 { self.t } pub fn p(&self) -> &Vec3 { &self.p } }