parry3d/query/contact_manifolds/
contact_manifolds_ball_ball.rs1use crate::math::{Isometry, Real, Vector};
2use crate::query::{ContactManifold, TrackedContact};
3use crate::shape::{Ball, PackedFeatureId, Shape};
4
5pub fn contact_manifold_ball_ball_shapes<ManifoldData, ContactData: Default + Copy>(
7 pos12: &Isometry<Real>,
8 shape1: &dyn Shape,
9 shape2: &dyn Shape,
10 prediction: Real,
11 manifold: &mut ContactManifold<ManifoldData, ContactData>,
12) {
13 if let (Some(ball1), Some(ball2)) = (shape1.as_ball(), shape2.as_ball()) {
14 contact_manifold_ball_ball(pos12, ball1, ball2, prediction, manifold);
15 }
16}
17
18pub fn contact_manifold_ball_ball<ManifoldData, ContactData: Default + Copy>(
20 pos12: &Isometry<Real>,
21 ball1: &Ball,
22 ball2: &Ball,
23 prediction: Real,
24 manifold: &mut ContactManifold<ManifoldData, ContactData>,
25) {
26 let radius_a = ball1.radius;
27 let radius_b = ball2.radius;
28
29 let dcenter = pos12.translation.vector;
30 let center_dist = dcenter.magnitude();
31 let dist = center_dist - radius_a - radius_b;
32
33 if dist < prediction {
34 let local_n1 = if center_dist != 0.0 {
35 dcenter / center_dist
36 } else {
37 Vector::y()
38 };
39
40 let local_n2 = pos12.inverse_transform_vector(&-local_n1);
41 let local_p1 = local_n1 * radius_a;
42 let local_p2 = local_n2 * radius_b;
43 let fid = PackedFeatureId::face(0);
44 let contact = TrackedContact::new(local_p1.into(), local_p2.into(), fid, fid, dist);
45
46 if !manifold.points.is_empty() {
47 manifold.points[0].copy_geometry_from(contact);
48 } else {
49 manifold.points.push(contact);
50 }
51
52 manifold.local_n1 = local_n1;
53 manifold.local_n2 = local_n2;
54 } else {
55 manifold.points.clear();
56 }
57}