From 826ce5f014281fd04b7a18238f102f2591d0b255 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 1 Jun 2021 12:36:01 +0200 Subject: Rework the event system --- src/dynamics/ccd/ccd_solver.rs | 30 ++-- src/dynamics/ccd/toi_entry.rs | 2 +- src/dynamics/island_manager.rs | 22 ++- src/dynamics/rigid_body.rs | 27 ++-- src/dynamics/rigid_body_components.rs | 46 ++++-- src/dynamics/solver/island_solver.rs | 4 +- .../joint_constraint/ball_position_constraint.rs | 8 +- .../ball_position_constraint_wide.rs | 6 +- .../joint_constraint/fixed_position_constraint.rs | 6 +- .../generic_position_constraint.rs | 6 +- .../revolute_position_constraint.rs | 6 +- src/dynamics/solver/parallel_island_solver.rs | 2 +- src/geometry/collider.rs | 73 ++++++--- src/geometry/collider_components.rs | 56 ++++++- src/geometry/collider_set.rs | 7 +- src/geometry/narrow_phase.rs | 177 +++++++++++++-------- src/pipeline/collision_pipeline.rs | 12 +- src/pipeline/event_handler.rs | 25 ++- src/pipeline/mod.rs | 6 +- src/pipeline/physics_hooks.rs | 20 +-- src/pipeline/physics_pipeline.rs | 15 +- 21 files changed, 361 insertions(+), 195 deletions(-) (limited to 'src') diff --git a/src/dynamics/ccd/ccd_solver.rs b/src/dynamics/ccd/ccd_solver.rs index b348283..354f183 100644 --- a/src/dynamics/ccd/ccd_solver.rs +++ b/src/dynamics/ccd/ccd_solver.rs @@ -10,6 +10,7 @@ use crate::geometry::{ use crate::math::Real; use crate::parry::utils::SortedPair; use crate::pipeline::{EventHandler, QueryPipeline, QueryPipelineMode}; +use crate::prelude::{ActiveEvents, ColliderFlags}; use parry::query::{DefaultQueryDispatcher, QueryDispatcher}; use parry::utils::hashmap::HashMap; use std::collections::BinaryHeap; @@ -66,7 +67,7 @@ impl CCDSolver { &RigidBodyCcd, &RigidBodyMassProps, ) = bodies.index_bundle(handle.0); - let local_com = &mprops.mass_properties.local_com; + let local_com = &mprops.local_mprops.local_com; let min_toi = (ccd.ccd_thickness * 0.15 @@ -272,7 +273,8 @@ impl CCDSolver { Colliders: ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { let mut frozen = HashMap::<_, Real>::default(); let mut all_toi = BinaryHeap::new(); @@ -522,10 +524,16 @@ impl CCDSolver { // - If the intersection isn't active anymore, and it wasn't intersecting // before, then we need to generate one interaction-start and one interaction-stop // events because it will never be detected by the narrow-phase because of tunneling. - let (co_pos1, co_shape1): (&ColliderPosition, &ColliderShape) = - colliders.index_bundle(toi.c1.0); - let (co_pos2, co_shape2): (&ColliderPosition, &ColliderShape) = - colliders.index_bundle(toi.c2.0); + let (co_pos1, co_shape1, co_flags1): ( + &ColliderPosition, + &ColliderShape, + &ColliderFlags, + ) = colliders.index_bundle(toi.c1.0); + let (co_pos2, co_shape2, co_flags2): ( + &ColliderPosition, + &ColliderShape, + &ColliderFlags, + ) = colliders.index_bundle(toi.c2.0); let co_next_pos1 = if let Some(b1) = toi.b1 { let co_parent1: &ColliderParent = colliders.get(toi.c1.0).unwrap(); @@ -535,7 +543,7 @@ impl CCDSolver { &RigidBodyMassProps, ) = bodies.index_bundle(b1.0); - let local_com1 = &rb_mprops1.mass_properties.local_com; + let local_com1 = &rb_mprops1.local_mprops.local_com; let frozen1 = frozen.get(&b1); let pos1 = frozen1 .map(|t| rb_vels1.integrate(*t, &rb_pos1.position, local_com1)) @@ -553,7 +561,7 @@ impl CCDSolver { &RigidBodyMassProps, ) = bodies.index_bundle(b2.0); - let local_com2 = &rb_mprops2.mass_properties.local_com; + let local_com2 = &rb_mprops2.local_mprops.local_com; let frozen2 = frozen.get(&b2); let pos2 = frozen2 .map(|t| rb_vels2.integrate(*t, &rb_pos2.position, local_com2)) @@ -575,7 +583,11 @@ impl CCDSolver { .intersection_test(&next_coll_pos12, co_shape1.as_ref(), co_shape2.as_ref()) .unwrap_or(false); - if !intersect_before && !intersect_after { + if !intersect_before + && !intersect_after + && (co_flags1.active_events | co_flags2.active_events) + .contains(ActiveEvents::INTERSECTION_EVENTS) + { // Emit one intersection-started and one intersection-stopped event. events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, true)); events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, false)); diff --git a/src/dynamics/ccd/toi_entry.rs b/src/dynamics/ccd/toi_entry.rs index 4637940..78396c0 100644 --- a/src/dynamics/ccd/toi_entry.rs +++ b/src/dynamics/ccd/toi_entry.rs @@ -173,7 +173,7 @@ impl TOIEntry { if ccd.ccd_active { NonlinearRigidMotion::new( poss.position, - mprops.mass_properties.local_com, + mprops.local_mprops.local_com, vels.linvel, vels.angvel, ) diff --git a/src/dynamics/island_manager.rs b/src/dynamics/island_manager.rs index b79cdb2..34fa3bd 100644 --- a/src/dynamics/island_manager.rs +++ b/src/dynamics/island_manager.rs @@ -229,19 +229,17 @@ impl IslandManager { stack: &mut Vec, ) { for collider_handle in &rb_colliders.0 { - if let Some(contacts) = narrow_phase.contacts_with(*collider_handle) { - for inter in contacts { - for manifold in &inter.2.manifolds { - if !manifold.data.solver_contacts.is_empty() { - let other = crate::utils::select_other( - (inter.0, inter.1), - *collider_handle, - ); - if let Some(other_body) = colliders.get(other.0) { - stack.push(other_body.handle); - } - break; + for inter in narrow_phase.contacts_with(*collider_handle) { + for manifold in &inter.manifolds { + if !manifold.data.solver_contacts.is_empty() { + let other = crate::utils::select_other( + (inter.collider1, inter.collider2), + *collider_handle, + ); + if let Some(other_body) = colliders.get(other.0) { + stack.push(other_body.handle); } + break; } } } diff --git a/src/dynamics/rigid_body.rs b/src/dynamics/rigid_body.rs index d53ff98..07e362d 100644 --- a/src/dynamics/rigid_body.rs +++ b/src/dynamics/rigid_body.rs @@ -4,8 +4,7 @@ use crate::dynamics::{ RigidBodyMassPropsFlags, RigidBodyPosition, RigidBodyType, RigidBodyVelocity, }; use crate::geometry::{ - Collider, ColliderHandle, ColliderMassProperties, ColliderParent, ColliderPosition, - ColliderShape, + Collider, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition, ColliderShape, }; use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector}; use crate::utils::{self, WCross}; @@ -48,7 +47,7 @@ impl RigidBody { rb_ccd: RigidBodyCcd::default(), rb_ids: RigidBodyIds::default(), rb_colliders: RigidBodyColliders::default(), - rb_activation: RigidBodyActivation::new_active(), + rb_activation: RigidBodyActivation::active(), changes: RigidBodyChanges::all(), rb_type: RigidBodyType::Dynamic, rb_dominance: RigidBodyDominance::default(), @@ -112,7 +111,7 @@ impl RigidBody { /// The mass properties of this rigid-body. #[inline] pub fn mass_properties(&self) -> &MassProperties { - &self.rb_mprops.mass_properties + &self.rb_mprops.local_mprops } /// The dominance group of this rigid-body. @@ -256,7 +255,7 @@ impl RigidBody { self.wake_up(true); } - self.rb_mprops.mass_properties = props; + self.rb_mprops.local_mprops = props; self.update_world_mass_properties(); } @@ -290,7 +289,7 @@ impl RigidBody { /// /// Returns zero if this rigid body has an infinite mass. pub fn mass(&self) -> Real { - utils::inv(self.rb_mprops.mass_properties.inv_mass) + utils::inv(self.rb_mprops.local_mprops.inv_mass) } /// The predicted position of this rigid-body. @@ -335,7 +334,7 @@ impl RigidBody { co_parent: &ColliderParent, co_pos: &mut ColliderPosition, co_shape: &ColliderShape, - co_mprops: &ColliderMassProperties, + co_mprops: &ColliderMassProps, ) { self.rb_colliders.attach_collider( &mut self.changes, @@ -359,7 +358,7 @@ impl RigidBody { let mass_properties = coll .mass_properties() .transform_by(coll.position_wrt_parent().unwrap()); - self.rb_mprops.mass_properties -= mass_properties; + self.rb_mprops.local_mprops -= mass_properties; self.update_world_mass_properties(); } } @@ -463,8 +462,8 @@ impl RigidBody { /// The translational part of this rigid-body's position. #[inline] - pub fn translation(&self) -> Vector { - self.rb_pos.position.translation.vector + pub fn translation(&self) -> &Vector { + &self.rb_pos.position.translation.vector } /// Sets the translational part of this rigid-body's position. @@ -482,8 +481,8 @@ impl RigidBody { /// The translational part of this rigid-body's position. #[inline] - pub fn rotation(&self) -> Rotation { - self.rb_pos.position.rotation + pub fn rotation(&self) -> &Rotation { + &self.rb_pos.position.rotation } /// Sets the rotational part of this rigid-body's position. @@ -692,7 +691,7 @@ impl RigidBody { pub fn gravitational_potential_energy(&self, dt: Real, gravity: Vector) -> Real { let world_com = self .rb_mprops - .mass_properties + .local_mprops .world_com(&self.rb_pos.position) .coords; @@ -979,7 +978,7 @@ impl RigidBodyBuilder { rb.rb_vels.angvel = self.angvel; rb.rb_type = self.rb_type; rb.user_data = self.user_data; - rb.rb_mprops.mass_properties = self.mass_properties; + rb.rb_mprops.local_mprops = self.mass_properties; rb.rb_mprops.flags = self.mprops_flags; rb.rb_damping.linear_damping = self.linear_damping; rb.rb_damping.angular_damping = self.angular_damping; diff --git a/src/dynamics/rigid_body_components.rs b/src/dynamics/rigid_body_components.rs index 2a652f7..b536d07 100644 --- a/src/dynamics/rigid_body_components.rs +++ b/src/dynamics/rigid_body_components.rs @@ -1,7 +1,7 @@ use crate::data::{ComponentSetMut, ComponentSetOption}; use crate::dynamics::MassProperties; use crate::geometry::{ - ColliderChanges, ColliderHandle, ColliderMassProperties, ColliderParent, ColliderPosition, + ColliderChanges, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition, ColliderShape, InteractionGraph, RigidBodyGraphIndex, }; use crate::math::{AngVector, AngularInertia, Isometry, Point, Real, Translation, Vector}; @@ -166,7 +166,7 @@ impl RigidBodyPosition { mprops: &RigidBodyMassProps, ) -> Isometry { let new_vels = forces.integrate(dt, vels, mprops); - new_vels.integrate(dt, &self.position, &mprops.mass_properties.local_com) + new_vels.integrate(dt, &self.position, &mprops.local_mprops.local_com) } } @@ -208,7 +208,7 @@ pub struct RigidBodyMassProps { /// Flags for locking rotation and translation. pub flags: RigidBodyMassPropsFlags, /// The local mass properties of the rigid-body. - pub mass_properties: MassProperties, + pub local_mprops: MassProperties, /// The world-space center of mass of the rigid-body. pub world_com: Point, /// The inverse mass taking into account translation locking. @@ -222,7 +222,7 @@ impl Default for RigidBodyMassProps { fn default() -> Self { Self { flags: RigidBodyMassPropsFlags::empty(), - mass_properties: MassProperties::zero(), + local_mprops: MassProperties::zero(), world_com: Point::origin(), effective_inv_mass: 0.0, effective_world_inv_inertia_sqrt: AngularInertia::zero(), @@ -239,11 +239,20 @@ impl From for RigidBodyMassProps { } } +impl From for RigidBodyMassProps { + fn from(local_mprops: MassProperties) -> Self { + Self { + local_mprops, + ..Default::default() + } + } +} + impl RigidBodyMassProps { /// The mass of the rigid-body. #[must_use] pub fn mass(&self) -> Real { - crate::utils::inv(self.mass_properties.inv_mass) + crate::utils::inv(self.local_mprops.inv_mass) } /// The effective mass (that takes the potential translation locking into account) of @@ -255,11 +264,10 @@ impl RigidBodyMassProps { /// Update the world-space mass properties of `self`, taking into account the new position. pub fn update_world_mass_properties(&mut self, position: &Isometry) { - self.world_com = self.mass_properties.world_com(&position); - self.effective_inv_mass = self.mass_properties.inv_mass; - self.effective_world_inv_inertia_sqrt = self - .mass_properties - .world_inv_inertia_sqrt(&position.rotation); + self.world_com = self.local_mprops.world_com(&position); + self.effective_inv_mass = self.local_mprops.inv_mass; + self.effective_world_inv_inertia_sqrt = + self.local_mprops.world_inv_inertia_sqrt(&position.rotation); // Take into account translation/rotation locking. if self @@ -665,7 +673,7 @@ impl RigidBodyColliders { co_pos: &mut ColliderPosition, co_parent: &ColliderParent, co_shape: &ColliderShape, - co_mprops: &ColliderMassProperties, + co_mprops: &ColliderMassProps, ) { rb_changes.set( RigidBodyChanges::MODIFIED | RigidBodyChanges::COLLIDERS, @@ -684,7 +692,7 @@ impl RigidBodyColliders { .mass_properties(&**co_shape) .transform_by(&co_parent.pos_wrt_parent); self.0.push(co_handle); - rb_mprops.mass_properties += mass_properties; + rb_mprops.local_mprops += mass_properties; rb_mprops.update_world_mass_properties(&rb_pos.position); } @@ -759,7 +767,7 @@ pub struct RigidBodyActivation { impl Default for RigidBodyActivation { fn default() -> Self { - Self::new_active() + Self::active() } } @@ -770,7 +778,7 @@ impl RigidBodyActivation { } /// Create a new rb_activation status initialised with the default rb_activation threshold and is active. - pub fn new_active() -> Self { + pub fn active() -> Self { RigidBodyActivation { threshold: Self::default_threshold(), energy: Self::default_threshold() * 4.0, @@ -779,7 +787,7 @@ impl RigidBodyActivation { } /// Create a new rb_activation status initialised with the default rb_activation threshold and is inactive. - pub fn new_inactive() -> Self { + pub fn inactive() -> Self { RigidBodyActivation { threshold: Self::default_threshold(), energy: 0.0, @@ -787,6 +795,14 @@ impl RigidBodyActivation { } } + /// Create a new activation status that prevents the rigid-body from sleeping. + pub fn cannot_sleep() -> Self { + RigidBodyActivation { + threshold: -Real::MAX, + ..Self::active() + } + } + /// Returns `true` if the body is not asleep. #[inline] pub fn is_active(&self) -> bool { diff --git a/src/dynamics/solver/island_solver.rs b/src/dynamics/solver/island_solver.rs index 1e65341..0c4c323 100644 --- a/src/dynamics/solver/island_solver.rs +++ b/src/dynamics/solver/island_solver.rs @@ -113,7 +113,7 @@ impl IslandSolver { let mut new_poss = *poss; let new_vels = vels.apply_damping(params.dt, damping); new_poss.next_position = - vels.integrate(params.dt, &poss.position, &mprops.mass_properties.local_com); + vels.integrate(params.dt, &poss.position, &mprops.local_mprops.local_com); bodies.set_internal(handle.0, new_vels); bodies.set_internal(handle.0, new_poss); @@ -140,7 +140,7 @@ impl IslandSolver { .integrate(params.dt, vels, mprops) .apply_damping(params.dt, &damping); new_poss.next_position = - vels.integrate(params.dt, &poss.position, &mprops.mass_properties.local_com); + vels.integrate(params.dt, &poss.position, &mprops.local_mprops.local_com); bodies.set_internal(handle.0, new_vels); bodies.set_internal(handle.0, new_poss); diff --git a/src/dynamics/solver/joint_constraint/ball_position_constraint.rs b/src/dynamics/solver/joint_constraint/ball_position_constraint.rs index 159cc77..0227960 100644 --- a/src/dynamics/solver/joint_constraint/ball_position_constraint.rs +++ b/src/dynamics/solver/joint_constraint/ball_position_constraint.rs @@ -34,8 +34,8 @@ impl BallPositionConstraint { let (mprops2, ids2) = rb2; Self { - local_com1: mprops1.mass_properties.local_com, - local_com2: mprops2.mass_properties.local_com, + local_com1: mprops1.local_mprops.local_com, + local_com2: mprops2.local_mprops.local_com, im1: mprops1.effective_inv_mass, im2: mprops2.effective_inv_mass, ii1: mprops1.effective_world_inv_inertia_sqrt.squared(), @@ -131,7 +131,7 @@ impl BallPositionGroundConstraint { ii2: mprops2.effective_world_inv_inertia_sqrt.squared(), local_anchor2: cparams.local_anchor1, position2: ids2.active_set_offset, - local_com2: mprops2.mass_properties.local_com, + local_com2: mprops2.local_mprops.local_com, } } else { Self { @@ -140,7 +140,7 @@ impl BallPositionGroundConstraint { ii2: mprops2.effective_world_inv_inertia_sqrt.squared(), local_anchor2: cparams.local_anchor2, position2: ids2.active_set_offset, - local_com2: mprops2.mass_properties.local_com, + local_com2: mprops2.local_mprops.local_com, } } } diff --git a/src/dynamics/solver/joint_constraint/ball_position_constraint_wide.rs b/src/dynamics/solver/joint_constraint/ball_position_constraint_wide.rs index 6b00639..ea462ed 100644 --- a/src/dynamics/solver/joint_constraint/ball_position_constraint_wide.rs +++ b/src/dynamics/solver/joint_constraint/ball_position_constraint_wide.rs @@ -40,8 +40,8 @@ impl WBallPositionConstraint { let (mprops1, ids1) = rbs1; let (mprops2, ids2) = rbs2; - let local_com1 = Point::from(gather![|ii| mprops1[ii].mass_properties.local_com]); - let local_com2 = Point::from(gather![|ii| mprops2[ii].mass_properties.local_com]); + let local_com1 = Point::from(gather![|ii| mprops1[ii].local_mprops.local_com]); + let local_com2 = Point::from(gather![|ii| mprops2[ii].local_mprops.local_com]); let im1 = SimdReal::from(gather![|ii| mprops1[ii].effective_inv_mass]); let im2 = SimdReal::from(gather![|ii| mprops2[ii].effective_inv_mass]); let ii1 = AngularInertia::::from(gather![ @@ -169,7 +169,7 @@ impl WBallPositionGroundConstraint { cparams[ii].local_anchor2 }]); let position2 = gather![|ii| ids2[ii].active_set_offset]; - let local_com2 = Point::from(gather![|ii| mprops2[ii].mass_properties.local_com]); + let local_com2 = Point::from(gather![|ii| mprops2[ii].local_mprops.local_com]); Self { anchor1, diff --git a/src/dynamics/solver/joint_constraint/fixed_position_constraint.rs b/src/dynamics/solver/joint_constraint/fixed_position_constraint.rs index f8945c3..3ab13f7 100644 --- a/src/dynamics/solver/joint_constraint/fixed_position_constraint.rs +++ b/src/dynamics/solver/joint_constraint/fixed_position_constraint.rs @@ -46,8 +46,8 @@ impl FixedPositionConstraint { im2, ii1, ii2, - local_com1: mprops1.mass_properties.local_com, - local_com2: mprops2.mass_properties.local_com, + local_com1: mprops1.local_mprops.local_com, + local_com2: mprops2.local_mprops.local_com, lin_inv_lhs, ang_inv_lhs, } @@ -125,7 +125,7 @@ impl FixedPositionGroundConstraint { position2: ids2.active_set_offset, im2: mprops2.effective_inv_mass, ii2: mprops2.effective_world_inv_inertia_sqrt.squared(), - local_com2: mprops2.mass_properties.local_com, + local_com2: mprops2.local_mprops.local_com, impulse: 0.0, } } diff --git a/src/dynamics/solver/joint_constraint/generic_position_constraint.rs b/src/dynamics/solver/joint_constraint/generic_position_constraint.rs index 76901b1..a7b5ea0 100644 --- a/src/dynamics/solver/joint_constraint/generic_position_constraint.rs +++ b/src/dynamics/solver/joint_constraint/generic_position_constraint.rs @@ -41,8 +41,8 @@ impl GenericPositionConstraint { im2, ii1, ii2, - local_com1: rb1.mass_properties.local_com, - local_com2: rb2.mass_properties.local_com, + local_com1: rb1.local_mprops.local_com, + local_com2: rb2.local_mprops.local_com, joint: *joint, } } @@ -215,7 +215,7 @@ impl GenericPositionGroundConstraint { position2: rb2.active_set_offset, im2: rb2.effective_inv_mass, ii2: rb2.effective_world_inv_inertia_sqrt.squared(), - local_com2: rb2.mass_properties.local_com, + local_com2: rb2.local_mprops.local_com, joint: *joint, } } diff --git a/src/dynamics/solver/joint_constraint/revolute_position_constraint.rs b/src/dynamics/solver/joint_constraint/revolute_position_constraint.rs index 1b3e23a..731d0e2 100644 --- a/src/dynamics/solver/joint_constraint/revolute_position_constraint.rs +++ b/src/dynamics/solver/joint_constraint/revolute_position_constraint.rs @@ -51,8 +51,8 @@ impl RevolutePositionConstraint { ii1, ii2, ang_inv_lhs, - local_com1: mprops1.mass_properties.local_com, - local_com2: mprops2.mass_properties.local_com, + local_com1: mprops1.local_mprops.local_com, + local_com2: mprops2.local_mprops.local_com, local_anchor1: cparams.local_anchor1, local_anchor2: cparams.local_anchor2, local_axis1: cparams.local_axis1, @@ -183,7 +183,7 @@ impl RevolutePositionGroundConstraint { local_anchor2, im2: mprops2.effective_inv_mass, ii2: mprops2.effective_world_inv_inertia_sqrt.squared(), - local_com2: mprops2.mass_properties.local_com, + local_com2: mprops2.local_mprops.local_com, axis1, local_axis2, position2: ids2.active_set_offset, diff --git a/src/dynamics/solver/parallel_island_solver.rs b/src/dynamics/solver/parallel_island_solver.rs index 9d565c1..e12e7af 100644 --- a/src/dynamics/solver/parallel_island_solver.rs +++ b/src/dynamics/solver/parallel_island_solver.rs @@ -392,7 +392,7 @@ impl ParallelIslandSolver { let new_rb_vels = new_rb_vels.apply_damping(params.dt, rb_damping); new_rb_pos.next_position = - new_rb_vels.integrate(params.dt, &rb_pos.position, &rb_mprops.mass_properties.local_com); + new_rb_vels.integrate(params.dt, &rb_pos.position, &rb_mprops.local_mprops.local_com); bodies.set_internal(handle.0, new_rb_vels); bodies.set_internal(handle.0, new_rb_pos); diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index e73c518..612df3c 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -1,12 +1,12 @@ use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; use crate::geometry::{ - ColliderBroadPhaseData, ColliderChanges, ColliderGroups, ColliderMassProperties, + ColliderBroadPhaseData, ColliderChanges, ColliderFlags, ColliderGroups, ColliderMassProps, ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, InteractionGroups, SharedShape, }; use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector, DIM}; use crate::parry::transformation::vhacd::VHACDParameters; -use crate::pipeline::PhysicsHooksFlags; +use crate::pipeline::{ActiveEvents, ActiveHooks}; use na::Unit; use parry::bounding_volume::AABB; use parry::shape::Shape; @@ -19,11 +19,12 @@ use parry::shape::Shape; pub struct Collider { pub(crate) co_type: ColliderType, pub(crate) co_shape: ColliderShape, - pub(crate) co_mprops: ColliderMassProperties, + pub(crate) co_mprops: ColliderMassProps, pub(crate) co_changes: ColliderChanges, pub(crate) co_parent: Option, pub(crate) co_pos: ColliderPosition, pub(crate) co_material: ColliderMaterial, + pub(crate) co_flags: ColliderFlags, pub(crate) co_groups: ColliderGroups, pub(crate) co_bf_data: ColliderBroadPhaseData, /// User-defined data associated to this rigid-body. @@ -48,13 +49,23 @@ impl Collider { } /// The physics hooks enabled for this collider. - pub fn active_hooks(&self) -> PhysicsHooksFlags { - self.co_material.active_hooks + pub fn active_hooks(&self) -> ActiveHooks { + self.co_flags.active_hooks } /// Sets the physics hooks enabled for this collider. - pub fn set_active_hooks(&mut self, active_hooks: PhysicsHooksFlags) { - self.co_material.active_hooks = active_hooks; + pub fn set_active_hooks(&mut self, active_hooks: ActiveHooks) { + self.co_flags.active_hooks = active_hooks; + } + + /// The physics hooks enabled for this collider. + pub fn active_events(&self) -> ActiveEvents { + self.co_flags.active_events + } + + /// Sets the physics hooks enabled for this collider. + pub fn set_active_events(&mut self, active_events: ActiveEvents) { + self.co_flags.active_events = active_events; } /// The friction coefficient of this collider. @@ -201,8 +212,8 @@ impl Collider { /// The density of this collider, if set. pub fn density(&self) -> Option { match &self.co_mprops { - ColliderMassProperties::Density(density) => Some(*density), - ColliderMassProperties::MassProperties(_) => None, + ColliderMassProps::Density(density) => Some(*density), + ColliderMassProps::MassProperties(_) => None, } } @@ -242,8 +253,8 @@ impl Collider { /// Compute the local-space mass properties of this collider. pub fn mass_properties(&self) -> MassProperties { match &self.co_mprops { - ColliderMassProperties::Density(density) => self.co_shape.mass_properties(*density), - ColliderMassProperties::MassProperties(mass_properties) => **mass_properties, + ColliderMassProps::Density(density) => self.co_shape.mass_properties(*density), + ColliderMassProps::MassProperties(mass_properties) => **mass_properties, } } } @@ -272,7 +283,9 @@ pub struct ColliderBuilder { /// Is this collider a sensor? pub is_sensor: bool, /// Physics hooks enabled for this collider. - pub active_hooks: PhysicsHooksFlags, + pub active_hooks: ActiveHooks, + /// Events enabled for this collider. + pub active_events: ActiveEvents, /// The user-data of the collider being built. pub user_data: u128, /// The collision groups for the collider being built. @@ -297,7 +310,8 @@ impl ColliderBuilder { solver_groups: InteractionGroups::all(), friction_combine_rule: CoefficientCombineRule::Average, restitution_combine_rule: CoefficientCombineRule::Average, - active_hooks: PhysicsHooksFlags::empty(), + active_hooks: ActiveHooks::empty(), + active_events: ActiveEvents::empty(), } } @@ -581,11 +595,17 @@ impl ColliderBuilder { } /// The set of physics hooks enabled for this collider. - pub fn active_hooks(mut self, active_hooks: PhysicsHooksFlags) -> Self { + pub fn active_hooks(mut self, active_hooks: ActiveHooks) -> Self { self.active_hooks = active_hooks; self } + /// The set of events enabled for this collider. + pub fn active_events(mut self, active_events: ActiveEvents) -> Self { + self.active_events = active_events; + self + } + /// Sets the friction coefficient of the collider this builder will build. pub fn friction(mut self, friction: Real) -> Self { self.friction = friction; @@ -672,12 +692,22 @@ impl ColliderBuilder { /// Builds a new collider attached to the given rigid-body. pub fn build(&self) -> Collider { - let (co_changes, co_pos, co_bf_data, co_shape, co_type, co_groups, co_material, co_mprops) = - self.components(); + let ( + co_changes, + co_pos, + co_bf_data, + co_shape, + co_type, + co_groups, + co_material, + co_flags, + co_mprops, + ) = self.components(); Collider { co_shape, co_mprops, co_material, + co_flags, co_parent: None, co_changes, co_pos, @@ -699,14 +729,15 @@ impl ColliderBuilder { ColliderType, ColliderGroups, ColliderMaterial, - ColliderMassProperties, + ColliderFlags, + ColliderMassProps, ) { let mass_info = if let Some(mp) = self.mass_properties { - ColliderMassProperties::MassProperties(Box::new(mp)) + ColliderMassProps::MassProperties(Box::new(mp)) } else { let default_density = Self::default_density(); let density = self.density.unwrap_or(default_density); - ColliderMassProperties::Density(density) + ColliderMassProps::Density(density) }; let co_shape = self.shape.clone(); @@ -716,7 +747,10 @@ impl ColliderBuilder { restitution: self.restitution, friction_combine_rule: self.friction_combine_rule, restitution_combine_rule: self.restitution_combine_rule, + }; + let co_flags = ColliderFlags { active_hooks: self.active_hooks, + active_events: self.active_events, }; let co_changes = ColliderChanges::all(); let co_pos = ColliderPosition(self.position); @@ -739,6 +773,7 @@ impl ColliderBuilder { co_type, co_groups, co_material, + co_flags, co_mprops, ) } diff --git a/src/geometry/collider_components.rs b/src/geometry/collider_components.rs index b63b290..5923a42 100644 --- a/src/geometry/collider_components.rs +++ b/src/geometry/collider_components.rs @@ -2,7 +2,7 @@ use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; use crate::geometry::{InteractionGroups, SAPProxyIndex, Shape, SharedShape}; use crate::math::{Isometry, Real}; use crate::parry::partitioning::IndexedData; -use crate::pipeline::PhysicsHooksFlags; +use crate::pipeline::{ActiveEvents, ActiveHooks}; use std::ops::Deref; /// The unique identifier of a collider added to a collider set. @@ -118,7 +118,7 @@ pub type ColliderShape = SharedShape; #[derive(Clone)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// The mass-properties of a collider. -pub enum ColliderMassProperties { +pub enum ColliderMassProps { /// The collider is given a density. /// /// Its actual `MassProperties` are computed automatically with @@ -128,13 +128,19 @@ pub enum ColliderMassProperties { MassProperties(Box), } -impl Default for ColliderMassProperties { +impl Default for ColliderMassProps { fn default() -> Self { - ColliderMassProperties::Density(1.0) + ColliderMassProps::Density(1.0) } } -impl ColliderMassProperties { +impl From for ColliderMassProps { + fn from(mprops: MassProperties) -> Self { + ColliderMassProps::MassProperties(Box::new(mprops)) + } +} + +impl ColliderMassProps { /// The mass-properties of this collider. /// /// If `self` is the `Density` variant, then this computes the mass-properties based @@ -242,8 +248,6 @@ pub struct ColliderMaterial { pub friction_combine_rule: CoefficientCombineRule, /// The rule applied to combine the restitution coefficients of two colliders. pub restitution_combine_rule: CoefficientCombineRule, - /// The physics hooks enabled for contact pairs and intersection pairs involving this collider. - pub active_hooks: PhysicsHooksFlags, } impl ColliderMaterial { @@ -264,7 +268,43 @@ impl Default for ColliderMaterial { restitution: 0.0, friction_combine_rule: CoefficientCombineRule::default(), restitution_combine_rule: CoefficientCombineRule::default(), - active_hooks: PhysicsHooksFlags::empty(), + } + } +} + +#[derive(Copy, Clone, Debug)] +#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] +/// A set of flags controlling the active hooks and events for this colliders. +pub struct ColliderFlags { + /// The physics hooks enabled for contact pairs and intersection pairs involving this collider. + pub active_hooks: ActiveHooks, + /// The events enabled for this collider. + pub active_events: ActiveEvents, +} + +impl Default for ColliderFlags { + fn default() -> Self { + Self { + active_hooks: ActiveHooks::empty(), + active_events: ActiveEvents::empty(), + } + } +} + +impl From for ColliderFlags { + fn from(active_hooks: ActiveHooks) -> Self { + Self { + active_hooks, + ..Default::default() + } + } +} + +impl From for ColliderFlags { + fn from(active_events: ActiveEvents) -> Self { + Self { + active_events, + ..Default::default() } } } diff --git a/src/geometry/collider_set.rs b/src/geometry/collider_set.rs index 268dbdd..d8603cd 100644 --- a/src/geometry/collider_set.rs +++ b/src/geometry/collider_set.rs @@ -2,8 +2,8 @@ use crate::data::arena::Arena; use crate::data::{ComponentSet, ComponentSetMut, ComponentSetOption}; use crate::dynamics::{IslandManager, RigidBodyHandle, RigidBodySet}; use crate::geometry::{ - Collider, ColliderBroadPhaseData, ColliderGroups, ColliderMassProperties, ColliderMaterial, - ColliderParent, ColliderPosition, ColliderShape, ColliderType, + Collider, ColliderBroadPhaseData, ColliderFlags, ColliderGroups, ColliderMassProps, + ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, }; use crate::geometry::{ColliderChanges, ColliderHandle}; use std::ops::{Index, IndexMut}; @@ -59,10 +59,11 @@ macro_rules! impl_field_component_set( impl_field_component_set!(ColliderType, co_type); impl_field_component_set!(ColliderShape, co_shape); -impl_field_component_set!(ColliderMassProperties, co_mprops); +impl_field_component_set!(ColliderMassProps, co_mprops); impl_field_component_set!(ColliderChanges, co_changes); impl_field_component_set!(ColliderPosition, co_pos); impl_field_component_set!(ColliderMaterial, co_material); +impl_field_component_set!(ColliderFlags, co_flags); impl_field_component_set!(ColliderGroups, co_groups); impl_field_component_set!(ColliderBroadPhaseData, co_bf_data); diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index e196798..61bb4c0 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -14,8 +14,10 @@ use crate::geometry::{ }; use crate::math::{Real, Vector}; use crate::pipeline::{ - ContactModificationContext, EventHandler, PairFilterContext, PhysicsHooks, PhysicsHooksFlags, + ActiveEvents, ActiveHooks, ContactModificationContext, EventHandler, PairFilterContext, + PhysicsHooks, }; +use crate::prelude::ColliderFlags; use parry::query::{DefaultQueryDispatcher, PersistentQueryDispatcher}; use parry::utils::IsometryOpt; use std::collections::HashMap; @@ -101,21 +103,26 @@ impl NarrowPhase { /// /// It is strongly recommended to use the [`NarrowPhase::contacts_with`] method instead. This /// method can be used if the generation number of the collider handle isn't known. - pub fn contacts_with_unknown_gen( - &self, - collider: u32, - ) -> Option> { - let id = self.graph_indices.get_unknown_gen(collider)?; - Some(self.contact_graph.interactions_with(id.contact_graph_index)) + pub fn contacts_with_unknown_gen(&self, collider: u32) -> impl Iterator { + self.graph_indices + .get_unknown_gen(collider) + .map(|id| id.contact_graph_index) + .into_iter() + .flat_map(move |id| self.contact_graph.interactions_with(id)) + .map(|pair| pair.2) } /// All the contacts involving the given collider. - pub fn contacts_with( + pub fn contacts_with<'a>( &self, collider: ColliderHandle, - ) -> Option> { - let id = self.graph_indices.get(collider.0)?; - Some(self.contact_graph.interactions_with(id.contact_graph_index)) + ) -> impl Iterator { + self.graph_indices + .get(collider.0) + .map(|id| id.contact_graph_index) + .into_iter() + .flat_map(move |id| self.contact_graph.interactions_with(id)) + .map(|pair| pair.2) } /// All the intersections involving the given collider. @@ -125,26 +132,32 @@ impl NarrowPhase { pub fn intersections_with_unknown_gen( &self, collider: u32, - ) -> Option + '_> { - let id = self.graph_indices.get_unknown_gen(collider)?; - Some( - self.intersection_graph - .interactions_with(id.intersection_graph_index) - .map(|e| (e.0, e.1, *e.2)), - ) + ) -> impl Iterator + '_ { + self.graph_indices + .get_unknown_gen(collider) + .map(|id| id.intersection_graph_index) + .into_iter() + .flat_map(move |id| { + self.intersection_graph + .interactions_with(id) + .map(|e| (e.0, e.1, *e.2)) + }) } /// All the intersections involving the given collider. pub fn intersections_with( &self, collider: ColliderHandle, - ) -> Option + '_> { - let id = self.graph_indices.get(collider.0)?; - Some( - self.intersection_graph - .interactions_with(id.intersection_graph_index) - .map(|e| (e.0, e.1, *e.2)), - ) + ) -> impl Iterator + '_ { + self.graph_indices + .get(collider.0) + .map(|id| id.intersection_graph_index) + .into_iter() + .flat_map(move |id| { + self.intersection_graph + .interactions_with(id) + .map(|e| (e.0, e.1, *e.2)) + }) } /// The contact pair involving two specific colliders. @@ -244,8 +257,9 @@ impl NarrowPhase { + ComponentSet + ComponentSetMut, Colliders: ComponentSet - + ComponentSetOption - + ComponentSet, + + ComponentSet + + ComponentSet + + ComponentSetOption, { // TODO: avoid these hash-maps. // They are necessary to handle the swap-remove done internally @@ -340,8 +354,9 @@ impl NarrowPhase { + ComponentSet + ComponentSetMut, Colliders: ComponentSet - + ComponentSetOption - + ComponentSet, + + ComponentSet + + ComponentSet + + ComponentSetOption, { let mut pairs_to_remove = vec![]; @@ -456,7 +471,9 @@ impl NarrowPhase { Bodies: ComponentSetMut + ComponentSet + ComponentSetMut, - Colliders: ComponentSet + ComponentSetOption, + Colliders: ComponentSet + + ComponentSet + + ComponentSetOption, { let co_type1: Option<&ColliderType> = colliders.get(pair.collider1.0); let co_type2: Option<&ColliderType> = colliders.get(pair.collider2.0); @@ -478,9 +495,16 @@ impl NarrowPhase { // Emit an intersection lost event if we had an intersection before removing the edge. if Some(true) == was_intersecting { - let prox_event = - IntersectionEvent::new(pair.collider1, pair.collider2, false); - events.handle_intersection_event(prox_event) + let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0); + let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0); + + if (co_flag1.active_events | co_flag2.active_events) + .contains(ActiveEvents::INTERSECTION_EVENTS) + { + let prox_event = + IntersectionEvent::new(pair.collider1, pair.collider2, false); + events.handle_intersection_event(prox_event) + } } } else { let contact_pair = self @@ -506,10 +530,17 @@ impl NarrowPhase { } } - events.handle_contact_event(ContactEvent::Stopped( - pair.collider1, - pair.collider2, - )) + let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0); + let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0); + + if (co_flag1.active_events | co_flag2.active_events) + .contains(ActiveEvents::CONTACT_EVENTS) + { + events.handle_contact_event( + ContactEvent::Stopped(pair.collider1, pair.collider2), + &ctct, + ) + } } } } @@ -606,9 +637,11 @@ impl NarrowPhase { events: &dyn EventHandler, ) where Bodies: ComponentSetMut - + ComponentSet - + ComponentSetMut, - Colliders: ComponentSet + ComponentSetOption, + + ComponentSetMut + + ComponentSet, + Colliders: ComponentSet + + ComponentSet + + ComponentSetOption, { for event in broad_phase_events { match event { @@ -645,7 +678,8 @@ impl NarrowPhase { + ComponentSet + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { if modified_colliders.is_empty() { return; @@ -660,21 +694,21 @@ impl NarrowPhase { let handle2 = nodes[edge.target().index()].weight; let co_parent1: Option<&ColliderParent> = colliders.get(handle1.0); - let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1): ( + let (co_changes1, co_groups1, co_shape1, co_pos1, co_flags1): ( &ColliderChanges, &ColliderGroups, &ColliderShape, &ColliderPosition, - &ColliderMaterial, + &ColliderFlags, ) = colliders.index_bundle(handle1.0); let co_parent2: Option<&ColliderParent> = colliders.get(handle2.0); - let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2): ( + let (co_changes2, co_groups2, co_shape2, co_pos2, co_flags2): ( &ColliderChanges, &ColliderGroups, &ColliderShape, &ColliderPosition, - &ColliderMaterial, + &ColliderFlags, ) = colliders.index_bundle(handle2.0); if !co_changes1.needs_narrow_phase_update() && !co_changes2.needs_narrow_phase_update() @@ -717,9 +751,10 @@ impl NarrowPhase { return; } - let active_hooks = co_material1.active_hooks | co_material2.active_hooks; + let active_hooks = co_flags1.active_hooks | co_flags2.active_hooks; + let active_events = co_flags1.active_events | co_flags2.active_events; - if !active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR) + if !active_hooks.contains(ActiveHooks::FILTER_INTERSECTION_PAIR) && !status1.is_dynamic() && !status2.is_dynamic() { @@ -727,7 +762,7 @@ impl NarrowPhase { return; } - if active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR) { + if active_hooks.contains(ActiveHooks::FILTER_INTERSECTION_PAIR) { let context = PairFilterContext { bodies, colliders, @@ -748,7 +783,9 @@ impl NarrowPhase { if let Ok(intersection) = query_dispatcher.intersection_test(&pos12, &**co_shape1, &**co_shape2) { - if intersection != edge.weight { + if active_events.contains(ActiveEvents::INTERSECTION_EVENTS) + && intersection != edge.weight + { edge.weight = intersection; events.handle_intersection_event(IntersectionEvent::new( handle1, @@ -777,7 +814,8 @@ impl NarrowPhase { + ComponentSet + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { if modified_colliders.is_empty() { return; @@ -790,21 +828,23 @@ impl NarrowPhase { let pair = &mut edge.weight; let co_parent1: Option<&ColliderParent> = colliders.get(pair.collider1.0); - let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1): ( + let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1, co_flags1): ( &ColliderChanges, &ColliderGroups, &ColliderShape, &ColliderPosition, &ColliderMaterial, + &ColliderFlags, ) = colliders.index_bundle(pair.collider1.0); let co_parent2: Option<&ColliderParent> = colliders.get(pair.collider2.0); - let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2): ( + let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2, co_flags2): ( &ColliderChanges, &ColliderGroups, &ColliderShape, &ColliderPosition, &ColliderMaterial, + &ColliderFlags, ) = colliders.index_bundle(pair.collider2.0); if !co_changes1.needs_narrow_phase_update() && !co_changes2.needs_narrow_phase_update() @@ -847,8 +887,10 @@ impl NarrowPhase { return; } - let active_hooks = co_material1.active_hooks | co_material2.active_hooks; - if !active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR) + let active_hooks = co_flags1.active_hooks | co_flags2.active_hooks; + let active_events = co_flags1.active_events | co_flags2.active_events; + + if !active_hooks.contains(ActiveHooks::FILTER_CONTACT_PAIRS) && !status1.is_dynamic() && !status2.is_dynamic() { @@ -856,8 +898,7 @@ impl NarrowPhase { return; } - let mut solver_flags = if active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR) - { + let mut solver_flags = if active_hooks.contains(ActiveHooks::FILTER_CONTACT_PAIRS) { let context = PairFilterContext { bodies, colliders, @@ -959,7 +1000,7 @@ impl NarrowPhase { } // Apply the user-defined contact modification. - if active_hooks.contains(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS) { + if active_hooks.contains(ActiveHooks::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; @@ -987,16 +1028,18 @@ impl NarrowPhase { } if has_any_active_contact != pair.has_any_active_contact { - if has_any_active_contact { - events.handle_contact_event(ContactEvent::Started( - pair.collider1, - pair.collider2, - )); - } else { - events.handle_contact_event(ContactEvent::Stopped( - pair.collider1, - pair.collider2, - )); + if active_events.contains(ActiveEvents::CONTACT_EVENTS) { + if has_any_active_contact { + events.handle_contact_event( + ContactEvent::Started(pair.collider1, pair.collider2), + pair, + ); + } else { + events.handle_contact_event( + ContactEvent::Stopped(pair.collider1, pair.collider2), + pair, + ); + } } pair.has_any_active_contact = has_any_active_contact; diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index 455e75d..e4ea157 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -6,9 +6,9 @@ use crate::dynamics::{ RigidBodyIds, RigidBodyPosition, RigidBodyType, RigidBodyVelocity, }; use crate::geometry::{ - BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups, - ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, - ColliderShape, ColliderType, NarrowPhase, + BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, + ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, + ColliderPosition, ColliderShape, ColliderType, NarrowPhase, }; use crate::math::Real; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -66,7 +66,8 @@ impl CollisionPipeline { + ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { // Update broad-phase. self.broad_phase_events.clear(); @@ -173,7 +174,8 @@ impl CollisionPipeline { + ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { super::user_changes::handle_user_changes_to_colliders( bodies, diff --git a/src/pipeline/event_handler.rs b/src/pipeline/event_handler.rs index 9d7b17a..4ee5387 100644 --- a/src/pipeline/event_handler.rs +++ b/src/pipeline/event_handler.rs @@ -1,6 +1,23 @@ -use crate::geometry::{ContactEvent, IntersectionEvent}; +use crate::geometry::{ContactEvent, ContactPair, IntersectionEvent}; use crossbeam::channel::Sender; +bitflags::bitflags! { + #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] + /// Flags affecting the behavior of the constraints solver for a given contact manifold. + pub struct ActiveEvents: u32 { + /// If set, Rapier will call `PhysicsHooks::FILTER_CONTACT_PAIRS` whenever relevant. + const INTERSECTION_EVENTS = 0b0001; + /// If set, Rapier will call `PhysicsHooks::filter_intersection_pair` whenever relevant. + const CONTACT_EVENTS = 0b0010; + } +} + +impl Default for ActiveEvents { + fn default() -> Self { + ActiveEvents::empty() + } +} + /// Trait implemented by structures responsible for handling events generated by the physics engine. /// /// Implementors of this trait will typically collect these events for future processing. @@ -13,12 +30,12 @@ pub trait EventHandler: Send + Sync { /// /// A contact event is emitted when two collider start or stop touching, independently from the /// number of contact points involved. - fn handle_contact_event(&self, event: ContactEvent); + fn handle_contact_event(&self, event: ContactEvent, contact_pair: &ContactPair); } impl EventHandler for () { fn handle_intersection_event(&self, _event: IntersectionEvent) {} - fn handle_contact_event(&self, _event: ContactEvent) {} + fn handle_contact_event(&self, _event: ContactEvent, _contact_pair: &ContactPair) {} } /// A physics event handler that collects events into a crossbeam channel. @@ -45,7 +62,7 @@ impl EventHandler for ChannelEventCollector { let _ = self.intersection_event_sender.send(event); } - fn handle_contact_event(&self, event: ContactEvent) { + fn handle_contact_event(&self, event: ContactEvent, _: &ContactPair) { let _ = self.contact_event_sender.send(event); } } diff --git a/src/pipeline/mod.rs b/src/pipeline/mod.rs index ad288d6..2c0393e 100644 --- a/src/pipeline/mod.rs +++ b/src/pipeline/mod.rs @@ -1,10 +1,8 @@ //! Structure for combining the various physics components to perform an actual simulation. pub use collision_pipeline::CollisionPipeline; -pub use event_handler::{ChannelEventCollector, EventHandler}; -pub use physics_hooks::{ - ContactModificationContext, PairFilterContext, PhysicsHooks, PhysicsHooksFlags, -}; +pub use event_handler::{ActiveEvents, ChannelEventCollector, EventHandler}; +pub use physics_hooks::{ActiveHooks, ContactModificationContext, PairFilterContext, PhysicsHooks}; pub use physics_pipeline::PhysicsPipeline; pub use query_pipeline::{QueryPipeline, QueryPipelineMode}; diff --git a/src/pipeline/physics_hooks.rs b/src/pipeline/physics_hooks.rs index 181c254..bb09452 100644 --- a/src/pipeline/physics_hooks.rs +++ b/src/pipeline/physics_hooks.rs @@ -118,24 +118,23 @@ impl<'a, Bodies, Colliders> ContactModificationContext<'a, Bodies, Colliders> { bitflags::bitflags! { #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// Flags affecting the behavior of the constraints solver for a given contact manifold. - pub struct PhysicsHooksFlags: u32 { + pub struct ActiveHooks: u32 { /// If set, Rapier will call `PhysicsHooks::filter_contact_pair` whenever relevant. - const FILTER_CONTACT_PAIR = 0b0001; + const FILTER_CONTACT_PAIRS = 0b0001; /// If set, Rapier will call `PhysicsHooks::filter_intersection_pair` whenever relevant. const FILTER_INTERSECTION_PAIR = 0b0010; /// If set, Rapier will call `PhysicsHooks::modify_solver_contact` whenever relevant. const MODIFY_SOLVER_CONTACTS = 0b0100; } } -impl Default for PhysicsHooksFlags { +impl Default for ActiveHooks { fn default() -> Self { - PhysicsHooksFlags::empty() + ActiveHooks::empty() } } #[cfg(target_arch = "wasm32")] pub trait PhysicsHooks { - fn active_hooks(&self) -> PhysicsHooksFlags; fn filter_contact_pair( &self, _context: &PairFilterContext, @@ -155,7 +154,7 @@ pub trait PhysicsHooks: Send + Sync { /// Applies the contact pair filter. /// /// Note that this method will only be called if at least one of the colliders - /// involved in the contact contains the `PhysicsHooksFlags::FILTER_CONTACT_PAIR` flags + /// involved in the contact contains the `ActiveHooks::FILTER_CONTACT_PAIRS` flags /// in its physics hooks flags. /// /// User-defined filter for potential contact pairs detected by the broad-phase. @@ -186,7 +185,7 @@ pub trait PhysicsHooks: Send + Sync { /// Applies the intersection pair filter. /// /// Note that this method will only be called if at least one of the colliders - /// involved in the contact contains the `PhysicsHooksFlags::FILTER_INTERSECTION_PAIR` flags + /// involved in the contact contains the `ActiveHooks::FILTER_INTERSECTION_PAIR` flags /// in its physics hooks flags. /// /// User-defined filter for potential intersection pairs detected by the broad-phase. @@ -210,7 +209,7 @@ pub trait PhysicsHooks: Send + Sync { /// Modifies the set of contacts seen by the constraints solver. /// /// Note that this method will only be called if at least one of the colliders - /// involved in the contact contains the `PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS` flags + /// involved in the contact contains the `ActiveHooks::MODIFY_SOLVER_CONTACTS` flags /// in its physics hooks flags. /// /// By default, the content of `solver_contacts` is computed from `manifold.points`. @@ -237,7 +236,10 @@ pub trait PhysicsHooks: Send + Sync { } impl PhysicsHooks for () { - fn filter_contact_pair(&self, _: &PairFilterContext) -> Option { + fn filter_contact_pair( + &self, + _context: &PairFilterContext, + ) -> Option { Some(SolverFlags::default()) } diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index 2f2a95d..74249af 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -13,9 +13,9 @@ use crate::dynamics::{ #[cfg(feature = "parallel")] use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver}; use crate::geometry::{ - BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups, - ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, - ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase, + BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, + ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, + ColliderPosition, ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase, }; use crate::math::{Real, Vector}; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -104,7 +104,8 @@ impl PhysicsPipeline { + ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { self.counters.stages.collision_detection_time.resume(); self.counters.cd.broad_phase_time.resume(); @@ -365,7 +366,8 @@ impl PhysicsPipeline { Colliders: ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { self.counters.ccd.toi_computation_time.start(); // Handle CCD @@ -520,7 +522,8 @@ impl PhysicsPipeline { + ComponentSetOption + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet + + ComponentSet, { self.counters.reset(); self.counters.step_started(); -- cgit