parry3d/query/contact/
contact_support_map_support_map.rs1use crate::math::{Isometry, Real, Vector};
2use crate::query::epa::EPA;
3use crate::query::gjk::{self, CSOPoint, GJKResult, VoronoiSimplex};
4use crate::query::Contact;
5use crate::shape::SupportMap;
6
7use na::Unit;
8
9pub fn contact_support_map_support_map<G1, G2>(
11 pos12: &Isometry<Real>,
12 g1: &G1,
13 g2: &G2,
14 prediction: Real,
15) -> Option<Contact>
16where
17 G1: ?Sized + SupportMap,
18 G2: ?Sized + SupportMap,
19{
20 let simplex = &mut VoronoiSimplex::new();
21 match contact_support_map_support_map_with_params(pos12, g1, g2, prediction, simplex, None) {
22 GJKResult::ClosestPoints(point1, point2_1, normal1) => {
23 let dist = (point2_1 - point1).dot(&normal1);
24 let point2 = pos12.inverse_transform_point(&point2_1);
25 let normal2 = pos12.inverse_transform_unit_vector(&-normal1);
26 Some(Contact::new(point1, point2, normal1, normal2, dist))
27 }
28 GJKResult::NoIntersection(_) => None,
29 GJKResult::Intersection => unreachable!(),
30 GJKResult::Proximity(_) => unreachable!(),
31 }
32}
33
34pub fn contact_support_map_support_map_with_params<G1, G2>(
41 pos12: &Isometry<Real>,
42 g1: &G1,
43 g2: &G2,
44 prediction: Real,
45 simplex: &mut VoronoiSimplex,
46 init_dir: Option<Unit<Vector<Real>>>,
47) -> GJKResult
48where
49 G1: ?Sized + SupportMap,
50 G2: ?Sized + SupportMap,
51{
52 let dir = if let Some(init_dir) = init_dir {
53 init_dir
54 } else if let Some(init_dir) =
55 Unit::try_new(pos12.translation.vector, crate::math::DEFAULT_EPSILON)
56 {
57 init_dir
58 } else {
59 Vector::x_axis()
60 };
61
62 simplex.reset(CSOPoint::from_shapes(pos12, g1, g2, &dir));
63
64 let cpts = gjk::closest_points(pos12, g1, g2, prediction, true, simplex);
65 if cpts != GJKResult::Intersection {
66 return cpts;
67 }
68
69 let mut epa = EPA::new();
71 if let Some((p1, p2, n)) = epa.closest_points(pos12, g1, g2, simplex) {
72 return GJKResult::ClosestPoints(p1, p2, n);
73 }
74
75 GJKResult::NoIntersection(Vector::x_axis())
77}