aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Crozet <sebcrozet@dimforge.com>2024-04-07 22:25:08 +0200
committerSébastien Crozet <sebastien@crozet.re>2024-04-30 23:10:46 +0200
commit15c07cfeb3d59f116b26eec32e4590dc45d6c26c (patch)
tree4dafc58922f2476df27871b20dc96eec1e29b5b0
parenta44f39a7b6156f1cbbb988082be1ea3e29b957c2 (diff)
downloadrapier-15c07cfeb3d59f116b26eec32e4590dc45d6c26c.tar.gz
rapier-15c07cfeb3d59f116b26eec32e4590dc45d6c26c.tar.bz2
rapier-15c07cfeb3d59f116b26eec32e4590dc45d6c26c.zip
feat: make narrow-phase filter-out predictive solver contact based on contact velocity
-rw-r--r--src/geometry/narrow_phase.rs43
1 files changed, 20 insertions, 23 deletions
diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs
index c644b4d..bcf31b0 100644
--- a/src/geometry/narrow_phase.rs
+++ b/src/geometry/narrow_phase.rs
@@ -789,6 +789,7 @@ impl NarrowPhase {
pub(crate) fn compute_contacts(
&mut self,
prediction_distance: Real,
+ dt: Real,
bodies: &RigidBodySet,
colliders: &ColliderSet,
impulse_joints: &ImpulseJointSet,
@@ -819,17 +820,11 @@ impl NarrowPhase {
return;
}
- // TODO: avoid lookup into bodies.
- let mut rb_type1 = RigidBodyType::Fixed;
- let mut rb_type2 = RigidBodyType::Fixed;
+ let rb1 = co1.parent.map(|co_parent1| &bodies[co_parent1.handle]);
+ let rb2 = co2.parent.map(|co_parent2| &bodies[co_parent2.handle]);
- if let Some(co_parent1) = &co1.parent {
- rb_type1 = bodies[co_parent1.handle].body_type;
- }
-
- if let Some(co_parent2) = &co2.parent {
- rb_type2 = bodies[co_parent2.handle].body_type;
- }
+ let rb_type1 = rb1.map(|rb| rb.body_type).unwrap_or(RigidBodyType::Fixed);
+ let rb_type2 = rb2.map(|rb| rb.body_type).unwrap_or(RigidBodyType::Fixed);
// Deal with contacts disabled between bodies attached by joints.
if let (Some(co_parent1), Some(co_parent2)) = (&co1.parent, &co2.parent) {
@@ -924,14 +919,8 @@ impl NarrowPhase {
);
let zero = RigidBodyDominance(0); // The value doesn't matter, it will be MAX because of the effective groups.
- let dominance1 = co1
- .parent
- .map(|p1| bodies[p1.handle].dominance)
- .unwrap_or(zero);
- let dominance2 = co2
- .parent
- .map(|p2| bodies[p2.handle].dominance)
- .unwrap_or(zero);
+ let dominance1 = rb1.map(|rb| rb.dominance).unwrap_or(zero);
+ let dominance2 = rb2.map(|rb| rb.dominance).unwrap_or(zero);
pair.has_any_active_contact = false;
@@ -948,12 +937,20 @@ impl NarrowPhase {
// Generate solver contacts.
for (contact_id, contact) in manifold.points.iter().enumerate() {
- assert!(
- contact_id <= u8::MAX as usize,
- "A contact manifold cannot contain more than 255 contacts currently."
- );
+ if contact_id > u8::MAX as usize {
+ log::warn!("A contact manifold cannot contain more than 255 contacts currently, dropping contact in excess.");
+ break;
+ }
+
+ let keep_solver_contact = contact.dist < prediction_distance || {
+ let world_pt1 = world_pos1 * contact.local_p1;
+ let world_pt2 = world_pos2 * contact.local_p2;
+ let vel1 = rb1.map(|rb| rb.velocity_at_point(&world_pt1)).unwrap_or_default();
+ let vel2 = rb2.map(|rb| rb.velocity_at_point(&world_pt2)).unwrap_or_default();
+ contact.dist + (vel2 - vel1).dot(&manifold.data.normal) * dt < prediction_distance
+ };
- if contact.dist < prediction_distance {
+ if keep_solver_contact {
// Generate the solver contact.
let world_pt1 = world_pos1 * contact.local_p1;
let world_pt2 = world_pos2 * contact.local_p2;