use crate::math::{Isometry, Real, Vector};
use crate::query::{ContactManifold, TrackedContact};
use crate::shape::{Ball, PackedFeatureId, Shape};
pub fn contact_manifold_ball_ball_shapes<ManifoldData, ContactData: Default + Copy>(
pos12: &Isometry<Real>,
shape1: &dyn Shape,
shape2: &dyn Shape,
prediction: Real,
manifold: &mut ContactManifold<ManifoldData, ContactData>,
) {
if let (Some(ball1), Some(ball2)) = (shape1.as_ball(), shape2.as_ball()) {
contact_manifold_ball_ball(pos12, ball1, ball2, prediction, manifold);
}
}
pub fn contact_manifold_ball_ball<ManifoldData, ContactData: Default + Copy>(
pos12: &Isometry<Real>,
ball1: &Ball,
ball2: &Ball,
prediction: Real,
manifold: &mut ContactManifold<ManifoldData, ContactData>,
) {
let radius_a = ball1.radius;
let radius_b = ball2.radius;
let dcenter = pos12.translation.vector;
let center_dist = dcenter.magnitude();
let dist = center_dist - radius_a - radius_b;
if dist < prediction {
let local_n1 = if center_dist != 0.0 {
dcenter / center_dist
} else {
Vector::y()
};
let local_n2 = pos12.inverse_transform_vector(&-local_n1);
let local_p1 = local_n1 * radius_a;
let local_p2 = local_n2 * radius_b;
let fid = PackedFeatureId::face(0);
let contact = TrackedContact::new(local_p1.into(), local_p2.into(), fid, fid, dist);
if !manifold.points.is_empty() {
manifold.points[0].copy_geometry_from(contact);
} else {
manifold.points.push(contact);
}
manifold.local_n1 = local_n1;
manifold.local_n2 = local_n2;
} else {
manifold.points.clear();
}
}