parry3d/query/ray/
ray_voxels.rs1use crate::math::{Real, Vector};
2use crate::query::{Ray, RayCast, RayIntersection};
3use crate::shape::{FeatureId, Voxels};
4
5impl RayCast for Voxels {
6 #[inline]
7 fn cast_local_ray_and_get_normal(
8 &self,
9 ray: &Ray,
10 max_time_of_impact: Real,
11 solid: bool,
12 ) -> Option<RayIntersection> {
13 use num_traits::Bounded;
14
15 let aabb = self.local_aabb();
16 let (min_t, mut max_t) = aabb.clip_ray_parameters(ray)?;
17
18 #[cfg(feature = "dim2")]
19 let ii = [0, 1];
20 #[cfg(feature = "dim3")]
21 let ii = [0, 1, 2];
22
23 if min_t > max_time_of_impact {
24 return None;
25 }
26
27 max_t = max_t.min(max_time_of_impact);
28 let clip_ray_a = ray.point_at(min_t);
29 let voxel_key_signed = self.voxel_at_point_unchecked(clip_ray_a);
30 let mut voxel_key = self.clamp_voxel(voxel_key_signed);
31 let [domain_mins, domain_maxs] = self.domain();
32
33 loop {
34 let voxel = self.voxel_state(voxel_key);
35 let aabb = self.voxel_aabb(voxel_key);
36
37 if !voxel.is_empty() {
38 let hit = aabb.cast_local_ray_and_get_normal(ray, max_t, solid);
42
43 if let Some(mut hit) = hit {
44 hit.feature = FeatureId::Face(self.linear_index(voxel_key));
46 return Some(hit);
47 }
48 }
49
50 let toi = ii.map(|i| {
54 if ray.dir[i] > 0.0 {
55 let t = (aabb.maxs[i] - ray.origin[i]) / ray.dir[i];
56 if t < 0.0 {
57 (Real::max_value(), true)
58 } else {
59 (t, true)
60 }
61 } else if ray.dir[i] < 0.0 {
62 let t = (aabb.mins[i] - ray.origin[i]) / ray.dir[i];
63 if t < 0.0 {
64 (Real::max_value(), false)
65 } else {
66 (t, false)
67 }
68 } else {
69 (Real::max_value(), false)
70 }
71 });
72
73 #[cfg(feature = "dim2")]
74 if toi[0].0 > max_t && toi[1].0 > max_t {
75 break;
76 }
77
78 #[cfg(feature = "dim3")]
79 if toi[0].0 > max_t && toi[1].0 > max_t && toi[2].0 > max_t {
80 break;
81 }
82
83 let imin = Vector::from(toi.map(|t| t.0)).imin();
84
85 if toi[imin].1 {
86 if voxel_key[imin] < domain_maxs[imin] - 1 {
87 voxel_key[imin] += 1;
88 } else {
89 break;
91 }
92 } else if voxel_key[imin] > domain_mins[imin] {
93 voxel_key[imin] -= 1;
94 } else {
95 break;
97 }
98 }
99
100 None
101 }
102}