ray-trace-w1/src/hittable.rs

59 lines
1.8 KiB
Rust

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<Box<dyn Hittable>>,
}
impl HittableList {
pub fn new() -> Self {
HittableList { objects: vec![] }
}
pub fn put(&mut self, object: Box<dyn Hittable>) {
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
}
}