Skip to main content

oxiphysics_collision/query/
querybox_traits.rs

1// # QueryBox - Trait Implementations
2//
3// This module contains trait implementations for `QueryBox`.
4//
5// ## Implemented Traits
6//
7// - `ShapeQuery`
8//
9// 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
10
11use 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}