oxiphysics_collision/query/
querysphere_traits.rs1use super::functions::*;
12use super::types::{PointQueryResult, QuerySphere, RayCastResult};
13
14impl ShapeQuery for QuerySphere {
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 m = sub(ray_origin, self.center);
22 let b = dot(m, ray_dir);
23 let c = dot(m, m) - self.radius * self.radius;
24 let disc = b * b - c;
25 if disc < 0.0 {
26 return None;
27 }
28 let sqrt_disc = disc.sqrt();
29 let t0 = -b - sqrt_disc;
30 let t1 = -b + sqrt_disc;
31 let toi = if t0 >= 0.0 {
32 t0
33 } else if t1 >= 0.0 {
34 t1
35 } else {
36 return None;
37 };
38 if toi > max_toi {
39 return None;
40 }
41 let point = add(ray_origin, scale(ray_dir, toi));
42 let normal = normalize(sub(point, self.center));
43 Some(RayCastResult { toi, normal, point })
44 }
45 fn point_query(&self, point: [f64; 3]) -> PointQueryResult {
46 let d = sub(point, self.center);
47 let dist_from_center = norm(d);
48 let signed_dist = dist_from_center - self.radius;
49 let inside = signed_dist < 0.0;
50 let closest = if dist_from_center < 1e-15 {
51 add(self.center, [self.radius, 0.0, 0.0])
52 } else {
53 add(self.center, scale(normalize(d), self.radius))
54 };
55 PointQueryResult {
56 point: closest,
57 distance: signed_dist,
58 inside,
59 }
60 }
61 fn aabb(&self) -> ([f64; 3], [f64; 3]) {
62 let r = self.radius;
63 let c = self.center;
64 (
65 [c[0] - r, c[1] - r, c[2] - r],
66 [c[0] + r, c[1] + r, c[2] + r],
67 )
68 }
69}