diff options
| author | Sébastien Crozet <developer@crozet.re> | 2020-10-27 17:36:45 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-10-27 17:36:45 +0100 |
| commit | e279c7050cd55426cb28c8c9fb2ac9d4f0205d7c (patch) | |
| tree | 446cbf59cf32a82a67ed889f0041ab886c5ace7e /src/geometry/narrow_phase.rs | |
| parent | a52fb8d7e4649dce02e2131d848b84166df82d64 (diff) | |
| parent | 74f0297221607e1929db75e79089d7cb75558dfe (diff) | |
| download | rapier-e279c7050cd55426cb28c8c9fb2ac9d4f0205d7c.tar.gz rapier-e279c7050cd55426cb28c8c9fb2ac9d4f0205d7c.tar.bz2 rapier-e279c7050cd55426cb28c8c9fb2ac9d4f0205d7c.zip | |
Merge pull request #44 from dimforge/custom_callbacks_filtering
Added user-implementable traits for collision/proximity pair filtering.
Diffstat (limited to 'src/geometry/narrow_phase.rs')
| -rw-r--r-- | src/geometry/narrow_phase.rs | 78 |
1 files changed, 64 insertions, 14 deletions
diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index f5517ba..c1bd411 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -14,8 +14,9 @@ use crate::geometry::proximity_detector::{ // proximity_detector::ProximityDetectionContextSimd, WBall, //}; use crate::geometry::{ - BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ProximityEvent, - ProximityPair, RemovedCollider, SolverFlags, + BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactEvent, ContactPairFilter, + PairFilterContext, ProximityEvent, ProximityPair, ProximityPairFilter, RemovedCollider, + SolverFlags, }; use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph}; //#[cfg(feature = "simd-is-enabled")] @@ -290,6 +291,7 @@ impl NarrowPhase { prediction_distance: f32, bodies: &RigidBodySet, colliders: &ColliderSet, + pair_filter: Option<&dyn ProximityPairFilter>, events: &dyn EventHandler, ) { par_iter_mut!(&mut self.proximity_graph.graph.edges).for_each(|edge| { @@ -301,16 +303,38 @@ impl NarrowPhase { let rb1 = &bodies[co1.parent]; let rb2 = &bodies[co2.parent]; - if (rb1.is_sleeping() || rb1.is_static()) && (rb2.is_sleeping() || rb2.is_static()) { - // No need to update this contact because nothing moved. + if (rb1.is_sleeping() && rb2.is_static()) + || (rb2.is_sleeping() && rb1.is_static()) + || (rb1.is_sleeping() && rb2.is_sleeping()) + { + // No need to update this proximity because nothing moved. return; } if !co1.collision_groups.test(co2.collision_groups) { - // The collision is not allowed. + // The proximity is not allowed. + return; + } + + if pair_filter.is_none() && !rb1.is_dynamic() && !rb2.is_dynamic() { + // Default filtering rule: no proximity between two non-dynamic bodies. return; } + if let Some(filter) = pair_filter { + let context = PairFilterContext { + rigid_body1: rb1, + rigid_body2: rb2, + collider1: co1, + collider2: co2, + }; + + if !filter.filter_proximity_pair(&context) { + // No proximity allowed. + return; + } + } + let dispatcher = DefaultProximityDispatcher; if pair.detector.is_none() { // We need a redispatch for this detector. @@ -341,6 +365,7 @@ impl NarrowPhase { prediction_distance: f32, bodies: &RigidBodySet, colliders: &ColliderSet, + pair_filter: Option<&dyn ContactPairFilter>, events: &dyn EventHandler, ) { par_iter_mut!(&mut self.contact_graph.graph.edges).for_each(|edge| { @@ -352,8 +377,9 @@ impl NarrowPhase { let rb1 = &bodies[co1.parent]; let rb2 = &bodies[co2.parent]; - if ((rb1.is_sleeping() || rb1.is_static()) && (rb2.is_sleeping() || rb2.is_static())) - || (!rb1.is_dynamic() && !rb2.is_dynamic()) + if (rb1.is_sleeping() && rb2.is_static()) + || (rb2.is_sleeping() && rb1.is_static()) + || (rb1.is_sleeping() && rb2.is_sleeping()) { // No need to update this contact because nothing moved. return; @@ -364,6 +390,33 @@ impl NarrowPhase { return; } + if pair_filter.is_none() && !rb1.is_dynamic() && !rb2.is_dynamic() { + // Default filtering rule: no contact between two non-dynamic bodies. + return; + } + + let mut solver_flags = if let Some(filter) = pair_filter { + let context = PairFilterContext { + rigid_body1: rb1, + rigid_body2: rb2, + collider1: co1, + collider2: co2, + }; + + if let Some(solver_flags) = filter.filter_contact_pair(&context) { + solver_flags + } else { + // No contact allowed. + return; + } + } else { + SolverFlags::COMPUTE_IMPULSES + }; + + if !co1.solver_groups.test(co2.solver_groups) { + solver_flags.remove(SolverFlags::COMPUTE_IMPULSES); + } + let dispatcher = DefaultContactDispatcher; if pair.generator.is_none() { // We need a redispatch for this generator. @@ -374,12 +427,6 @@ impl NarrowPhase { pair.generator_workspace = workspace; } - let solver_flags = if co1.solver_groups.test(co2.solver_groups) { - SolverFlags::COMPUTE_FORCES - } else { - SolverFlags::empty() - }; - let context = ContactGenerationContext { dispatcher: &dispatcher, prediction_distance, @@ -413,8 +460,11 @@ impl NarrowPhase { for manifold in &mut inter.weight.manifolds { let rb1 = &bodies[manifold.body_pair.body1]; let rb2 = &bodies[manifold.body_pair.body2]; - if manifold.solver_flags.contains(SolverFlags::COMPUTE_FORCES) + if manifold + .solver_flags + .contains(SolverFlags::COMPUTE_IMPULSES) && manifold.num_active_contacts() != 0 + && (rb1.is_dynamic() || rb2.is_dynamic()) && (!rb1.is_dynamic() || !rb1.is_sleeping()) && (!rb2.is_dynamic() || !rb2.is_sleeping()) { |
