-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathhit.rs
55 lines (48 loc) · 1.5 KB
/
hit.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
use std::fmt::Debug;
use crate::bvh::Aabb;
use crate::material::Material;
use crate::math::float::Float;
use crate::ray::Ray;
use crate::vec3::Vec3;
use crate::Rng;
pub trait Hit<T: Rng>: Sync + Send + Debug {
fn hit(&self, ray: &Ray, t_min: Float, t_max: Float, rng: &mut T) -> Option<HitRecord<'_>>;
fn bounding_box(&self, time_start: Float, time_end: Float) -> Option<Aabb>;
}
pub struct HitRecord<'a> {
pub t: Float,
pub u: Float,
pub v: Float,
pub p: Vec3,
pub normal: Vec3,
pub material: &'a Material,
}
impl<R: Rng> Hit<R> for [Box<dyn Hit<R>>] {
fn hit(&self, ray: &Ray, t_min: Float, t_max: Float, rng: &mut R) -> Option<HitRecord<'_>> {
self.iter()
.fold((None, t_max), |(closest_hit, closest_t), item| {
match item.hit(ray, t_min, closest_t, rng) {
Some(hit_record) => {
let t = hit_record.t;
(Some(hit_record), t)
}
None => (closest_hit, closest_t),
}
})
.0
}
fn bounding_box(&self, time_start: Float, time_end: Float) -> Option<Aabb> {
if self.is_empty() {
return None;
}
let mut aabb = Aabb::empty();
for hit in self {
if let Some(new_aabb) = hit.bounding_box(time_start, time_end) {
aabb = aabb.union(&new_aabb)
} else {
return None;
}
}
Some(aabb)
}
}