59 lines
1.8 KiB
Rust
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
|
|
}
|
|
}
|