parry3d/query/sat/
sat_cuboid_support_map.rs1use crate::math::{Isometry, Real, Vector, DIM};
2use crate::shape::{Cuboid, SupportMap};
3
4use na::Unit;
5
6#[cfg(feature = "dim3")]
10pub fn cuboid_support_map_compute_separation_wrt_local_line(
11 cube1: &Cuboid,
12 shape2: &impl SupportMap,
13 pos12: &Isometry<Real>,
14 axis1: &Unit<Vector<Real>>,
15) -> (Real, Unit<Vector<Real>>) {
16 let axis1_2 = pos12.inverse_transform_unit_vector(axis1);
17 let separation1 = {
18 let axis2 = -axis1_2;
19 let local_pt1 = cube1.local_support_point_toward(axis1);
20 let local_pt2 = shape2.local_support_point_toward(&axis2);
21 let pt2 = pos12 * local_pt2;
22 (pt2 - local_pt1).dot(axis1)
23 };
24
25 let separation2 = {
26 let axis2 = axis1_2;
27 let local_pt1 = cube1.local_support_point_toward(&-*axis1);
28 let local_pt2 = shape2.local_support_point_toward(&axis2);
29 let pt2 = pos12 * local_pt2;
30 (pt2 - local_pt1).dot(&-*axis1)
31 };
32
33 if separation1 > separation2 {
34 (separation1, *axis1)
35 } else {
36 (separation2, -*axis1)
37 }
38}
39
40#[cfg(feature = "dim3")]
44pub fn cuboid_support_map_find_local_separating_edge_twoway(
45 cube1: &Cuboid,
46 shape2: &impl SupportMap,
47 axes: &[Vector<Real>],
48 pos12: &Isometry<Real>,
49) -> (Real, Vector<Real>) {
50 use approx::AbsDiffEq;
51 let mut best_separation = -Real::MAX;
52 let mut best_dir = Vector::zeros();
53
54 for axis1 in axes {
55 if let Some(axis1) = Unit::try_new(*axis1, Real::default_epsilon()) {
56 let (separation, axis1) =
57 cuboid_support_map_compute_separation_wrt_local_line(cube1, shape2, pos12, &axis1);
58
59 if separation > best_separation {
60 best_separation = separation;
61 best_dir = *axis1;
62 }
63 }
64 }
65
66 (best_separation, best_dir)
67}
68
69pub fn cuboid_support_map_find_local_separating_normal_oneway<S: SupportMap>(
73 cube1: &Cuboid,
74 shape2: &S,
75 pos12: &Isometry<Real>,
76) -> (Real, Vector<Real>) {
77 let mut best_separation = -Real::MAX;
78 let mut best_dir = Vector::zeros();
79
80 for i in 0..DIM {
81 for sign in &[-1.0, 1.0] {
82 let axis1 = Vector::ith(i, *sign);
83 let pt2 = shape2.support_point_toward(pos12, &Unit::new_unchecked(-axis1));
84 let separation = pt2[i] * *sign - cube1.half_extents[i];
85
86 if separation > best_separation {
87 best_separation = separation;
88 best_dir = axis1;
89 }
90 }
91 }
92
93 (best_separation, best_dir)
94}