parry3d/query/sat/sat_support_map_support_map.rs
1use crate::math::{Pose, Real, Vector};
2use crate::shape::SupportMap;
3
4/// Computes the separation distance between two convex shapes along a given direction.
5///
6/// This is the most general SAT separation computation function in Parry. It works with any
7/// two convex shapes that implement the [`SupportMap`] trait, which includes spheres, capsules,
8/// cones, convex polyhedra, and more.
9///
10/// # What is a Support Map?
11///
12/// A support map is a function that, given a direction vector, returns the furthest point on
13/// the shape in that direction. This is a fundamental operation in collision detection algorithms
14/// like GJK, EPA, and SAT.
15///
16/// # How This Function Works
17///
18/// 1. Finds the furthest point on `sm1` in direction `dir1` (the "support point")
19/// 2. Finds the furthest point on `sm2` in direction `-dir1` (opposite direction)
20/// 3. Transforms `sm2`'s support point to `sm1`'s coordinate space
21/// 4. Computes the signed distance between these points along `dir1`
22///
23/// # Parameters
24///
25/// - `sm1`: The first convex shape
26/// - `sm2`: The second convex shape
27/// - `pos12`: The position of `sm2` relative to `sm1`
28/// - `dir1`: The unit direction vector (in `sm1`'s local space) along which to compute separation
29///
30/// # Returns
31///
32/// The separation distance as a `Real`:
33/// - **Positive**: The shapes are separated by at least this distance along `dir1`
34/// - **Negative**: The shapes are overlapping (the absolute value is the penetration depth)
35/// - **Zero**: The shapes are exactly touching along this axis
36///
37/// # Example
38///
39/// ```rust
40/// # #[cfg(all(feature = "dim3", feature = "f32"))] {
41/// use parry3d::shape::{Ball, Cuboid};
42/// use parry3d::query::sat::support_map_support_map_compute_separation;
43/// use parry3d::math::{Pose, Vector};
44///
45/// let sphere = Ball::new(1.0);
46/// let cube = Cuboid::new(Vector::splat(1.0));
47///
48/// // Position cube to the right of the sphere
49/// let pos12 = Pose::translation(3.0, 0.0, 0.0);
50///
51/// // Test separation along the X axis
52/// let dir = Vector::X.normalize();
53/// let separation = support_map_support_map_compute_separation(
54/// &sphere,
55/// &cube,
56/// &pos12,
57/// dir
58/// );
59///
60/// // They should be separated (sphere radius 1.0 + cube extent 1.0 = 2.0, distance 3.0)
61/// assert!(separation > 0.0);
62/// # }
63/// ```
64///
65/// # Use Cases
66///
67/// This function is typically used as a building block in SAT implementations. You would:
68/// 1. Generate candidate separating axes (face normals, edge cross products, etc.)
69/// 2. Call this function for each candidate axis
70/// 3. Track the axis with maximum separation
71/// 4. If the maximum separation is positive, the shapes don't collide
72///
73/// # Performance Note
74///
75/// This function is generic and works with any support map shapes, but specialized implementations
76/// (like [`cuboid_cuboid_find_local_separating_normal_oneway`](super::cuboid_cuboid_find_local_separating_normal_oneway))
77/// may be more efficient for specific shape pairs.
78#[allow(dead_code)]
79pub fn support_map_support_map_compute_separation(
80 sm1: &impl SupportMap,
81 sm2: &impl SupportMap,
82 pos12: &Pose,
83 dir1: Vector,
84) -> Real {
85 let p1 = sm1.local_support_point_toward(dir1);
86 let p2 = sm2.support_point_toward(pos12, -dir1);
87 (p2 - p1).dot(dir1)
88}