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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use crate::geom::{Hit, Ray, Scan, Trace, Tree};
impl<'a, T: Clone> Tree<'a, T> {
#[inline]
#[must_use]
pub fn observe(&self, mut ray: Ray, bump_dist: f64, max_dist: f64) -> Option<Hit<T>> {
debug_assert!(bump_dist > 0.0);
debug_assert!(max_dist > 0.0);
let mut dist_travelled = 0.0;
if !self.boundary().contains(ray.pos()) {
if let Some(dist) = self.boundary().dist(&ray) {
let d = dist + bump_dist;
ray.travel(d);
dist_travelled += d;
} else {
return None;
}
}
while let Some(cell) = self.find_terminal_cell(ray.pos()) {
if dist_travelled > max_dist {
return None;
}
match cell.hit_scan(&ray, bump_dist) {
Scan::Surface(mut hit) => {
*hit.dist_mut() += dist_travelled;
return Some(hit);
}
Scan::Boundary(dist) => {
let d = dist + bump_dist;
ray.travel(d);
dist_travelled += d;
}
}
}
None
}
#[inline]
#[must_use]
pub fn hit_scan(&self, ray: &Ray, bump_dist: f64) -> Scan<T> {
debug_assert!(self.boundary().contains(ray.pos()));
debug_assert!(bump_dist > 0.0);
match *self {
Self::Leaf {
ref boundary,
ref tris,
} => {
let mut nearest: Option<Hit<T>> = None;
for &(ref key, tri) in tris {
if let Some((dist, side)) = tri.dist_side(ray) {
if nearest.is_none() || (dist < nearest.as_ref().unwrap().dist()) {
nearest = Some(Hit::new(key.clone(), dist, side));
}
}
}
let boundary_dist = boundary.dist(ray).unwrap();
if let Some(hit) = nearest {
if hit.dist() < (boundary_dist + bump_dist) {
return Scan::new_surface(hit);
}
}
Scan::new_boundary(boundary_dist)
}
Self::Empty { ref boundary } => Scan::new_boundary(boundary.dist(ray).unwrap()),
Self::Root { .. } | Self::Branch { .. } => {
panic!("Should not be performing hit scans on branching cells!");
}
}
}
}