oxiphysics_collision/query/
querybox_traits.rs1use super::functions::*;
12use super::types::{PointQueryResult, QueryBox, RayCastResult};
13
14impl ShapeQuery for QueryBox {
15 fn ray_cast(
16 &self,
17 ray_origin: [f64; 3],
18 ray_dir: [f64; 3],
19 max_toi: f64,
20 ) -> Option<RayCastResult> {
21 let lo = sub(self.center, self.half_extents);
22 let hi = add(self.center, self.half_extents);
23 let mut t_min = 0.0_f64;
24 let mut t_max = max_toi;
25 let mut hit_axis = 0usize;
26 let mut hit_sign = 1.0_f64;
27 for i in 0..3 {
28 let d = ray_dir[i];
29 let o = ray_origin[i];
30 if d.abs() < 1e-15 {
31 if o < lo[i] || o > hi[i] {
32 return None;
33 }
34 } else {
35 let inv_d = 1.0 / d;
36 let mut t1 = (lo[i] - o) * inv_d;
37 let mut t2 = (hi[i] - o) * inv_d;
38 let sign = if t1 <= t2 { -1.0_f64 } else { 1.0_f64 };
39 if t1 > t2 {
40 core::mem::swap(&mut t1, &mut t2);
41 }
42 if t1 > t_min {
43 t_min = t1;
44 hit_axis = i;
45 hit_sign = sign;
46 }
47 if t2 < t_max {
48 t_max = t2;
49 }
50 if t_min > t_max {
51 return None;
52 }
53 }
54 }
55 if t_min < 0.0 || t_min > max_toi {
56 return None;
57 }
58 let point = add(ray_origin, scale(ray_dir, t_min));
59 let mut normal = [0.0; 3];
60 normal[hit_axis] = hit_sign;
61 Some(RayCastResult {
62 toi: t_min,
63 normal,
64 point,
65 })
66 }
67 fn point_query(&self, point: [f64; 3]) -> PointQueryResult {
68 let lo = sub(self.center, self.half_extents);
69 let hi = add(self.center, self.half_extents);
70 let clamped = [
71 clamp(point[0], lo[0], hi[0]),
72 clamp(point[1], lo[1], hi[1]),
73 clamp(point[2], lo[2], hi[2]),
74 ];
75 let inside = point[0] >= lo[0]
76 && point[0] <= hi[0]
77 && point[1] >= lo[1]
78 && point[1] <= hi[1]
79 && point[2] >= lo[2]
80 && point[2] <= hi[2];
81 if inside {
82 let depths = [
83 hi[0] - point[0],
84 point[0] - lo[0],
85 hi[1] - point[1],
86 point[1] - lo[1],
87 hi[2] - point[2],
88 point[2] - lo[2],
89 ];
90 let min_depth = depths.iter().cloned().fold(f64::INFINITY, f64::min);
91 PointQueryResult {
92 point: clamped,
93 distance: -min_depth,
94 inside: true,
95 }
96 } else {
97 let dist = norm(sub(point, clamped));
98 PointQueryResult {
99 point: clamped,
100 distance: dist,
101 inside: false,
102 }
103 }
104 }
105 fn aabb(&self) -> ([f64; 3], [f64; 3]) {
106 let lo = sub(self.center, self.half_extents);
107 let hi = add(self.center, self.half_extents);
108 (lo, hi)
109 }
110}