aboutsummaryrefslogtreecommitdiff
path: root/src/geometry/narrow_phase.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/geometry/narrow_phase.rs')
-rw-r--r--src/geometry/narrow_phase.rs91
1 files changed, 61 insertions, 30 deletions
diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs
index 640ce12..d05b19a 100644
--- a/src/geometry/narrow_phase.rs
+++ b/src/geometry/narrow_phase.rs
@@ -5,13 +5,14 @@ use crate::data::pubsub::Subscription;
use crate::data::Coarena;
use crate::dynamics::{BodyPair, CoefficientCombineRule, RigidBodySet};
use crate::geometry::{
- BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ContactData, ContactEvent,
- ContactManifoldData, ContactPairFilter, IntersectionEvent, IntersectionPairFilter,
- PairFilterContext, RemovedCollider, SolverContact, SolverFlags,
+ BroadPhasePairEvent, ColliderGraphIndex, ColliderHandle, ColliderSet, ContactData,
+ ContactEvent, ContactManifold, ContactManifoldData, ContactPair, InteractionGraph,
+ IntersectionEvent, RemovedCollider, SolverContact, SolverFlags,
};
-use crate::geometry::{ColliderSet, ContactManifold, ContactPair, InteractionGraph};
use crate::math::{Real, Vector};
-use crate::pipeline::EventHandler;
+use crate::pipeline::{
+ ContactModificationContext, EventHandler, PairFilterContext, PhysicsHooks, PhysicsHooksFlags,
+};
use parry::query::{DefaultQueryDispatcher, PersistentQueryDispatcher};
use parry::utils::IsometryOpt;
use std::collections::HashMap;
@@ -387,11 +388,13 @@ impl NarrowPhase {
&mut self,
bodies: &RigidBodySet,
colliders: &ColliderSet,
- pair_filter: Option<&dyn IntersectionPairFilter>,
+ hooks: &dyn PhysicsHooks,
events: &dyn EventHandler,
) {
let nodes = &self.intersection_graph.graph.nodes;
let query_dispatcher = &*self.query_dispatcher;
+ let active_hooks = hooks.active_hooks();
+
par_iter_mut!(&mut self.intersection_graph.graph.edges).for_each(|edge| {
let handle1 = nodes[edge.source().index()].weight;
let handle2 = nodes[edge.target().index()].weight;
@@ -415,12 +418,15 @@ impl NarrowPhase {
return;
}
- if pair_filter.is_none() && !rb1.is_dynamic() && !rb2.is_dynamic() {
+ if !active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR)
+ && !rb1.is_dynamic()
+ && !rb2.is_dynamic()
+ {
// Default filtering rule: no intersection between two non-dynamic bodies.
return;
}
- if let Some(filter) = pair_filter {
+ if active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR) {
let context = PairFilterContext {
rigid_body1: rb1,
rigid_body2: rb2,
@@ -430,7 +436,7 @@ impl NarrowPhase {
collider2: co2,
};
- if !filter.filter_intersection_pair(&context) {
+ if !hooks.filter_intersection_pair(&context) {
// No intersection allowed.
return;
}
@@ -458,10 +464,11 @@ impl NarrowPhase {
prediction_distance: Real,
bodies: &RigidBodySet,
colliders: &ColliderSet,
- pair_filter: Option<&dyn ContactPairFilter>,
+ hooks: &dyn PhysicsHooks,
events: &dyn EventHandler,
) {
let query_dispatcher = &*self.query_dispatcher;
+ let active_hooks = hooks.active_hooks();
par_iter_mut!(&mut self.contact_graph.graph.edges).for_each(|edge| {
let pair = &mut edge.weight;
@@ -485,12 +492,16 @@ impl NarrowPhase {
return;
}
- if pair_filter.is_none() && !rb1.is_dynamic() && !rb2.is_dynamic() {
+ if !active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR)
+ && !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 mut solver_flags = if active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR)
+ {
let context = PairFilterContext {
rigid_body1: rb1,
rigid_body2: rb2,
@@ -500,14 +511,14 @@ impl NarrowPhase {
collider2: co2,
};
- if let Some(solver_flags) = filter.filter_contact_pair(&context) {
+ if let Some(solver_flags) = hooks.filter_contact_pair(&context) {
solver_flags
} else {
// No contact allowed.
return;
}
} else {
- SolverFlags::COMPUTE_IMPULSES
+ co1.solver_flags | co2.solver_flags
};
if !co1.solver_groups.test(co2.solver_groups) {
@@ -546,38 +557,58 @@ impl NarrowPhase {
manifold.data.solver_flags = solver_flags;
manifold.data.normal = world_pos1 * manifold.local_n1;
- // Sort contacts to keep only these with distances bellow
- // the prediction, and generate solver contacts.
- let mut first_inactive_index = manifold.points.len();
+ // 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."
+ );
- while manifold.data.num_active_contacts() != first_inactive_index {
- let contact = &manifold.points[manifold.data.num_active_contacts()];
if contact.dist < prediction_distance {
// Generate the solver contact.
let solver_contact = SolverContact {
+ contact_id: contact_id as u8,
point: world_pos1 * contact.local_p1
+ manifold.data.normal * contact.dist / 2.0,
dist: contact.dist,
friction,
restitution,
- surface_velocity: Vector::zeros(),
+ tangent_velocity: Vector::zeros(),
data: contact.data,
};
- // TODO: apply the user-defined contact modification/removal, if needed.
-
manifold.data.solver_contacts.push(solver_contact);
has_any_active_contact = true;
- continue;
}
+ }
- // If we reach this code, then the contact must be ignored by the constraints solver.
- // Swap with the last contact.
- manifold.points.swap(
- manifold.data.num_active_contacts(),
- first_inactive_index - 1,
- );
- first_inactive_index -= 1;
+ // Apply the user-defined contact modification.
+ if active_hooks.contains(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS)
+ && manifold
+ .data
+ .solver_flags
+ .contains(SolverFlags::MODIFY_SOLVER_CONTACTS)
+ {
+ let mut modifiable_solver_contacts =
+ std::mem::replace(&mut manifold.data.solver_contacts, Vec::new());
+ let mut modifiable_user_data = manifold.data.user_data;
+
+ let mut context = ContactModificationContext {
+ rigid_body1: rb1,
+ rigid_body2: rb2,
+ collider_handle1: pair.pair.collider1,
+ collider_handle2: pair.pair.collider2,
+ collider1: co1,
+ collider2: co2,
+ manifold,
+ solver_contacts: &mut modifiable_solver_contacts,
+ user_data: &mut modifiable_user_data,
+ };
+
+ hooks.modify_solver_contacts(&mut context);
+
+ manifold.data.solver_contacts = modifiable_solver_contacts;
+ manifold.data.user_data = modifiable_user_data;
}
}