From 7153eb7779a29853289df90f28efaac738620386 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 1 Jun 2021 17:59:07 +0200 Subject: Add ActiveCollisionTypes to easily enable collision-detection between two non-static rigid-body. --- src/dynamics/ccd/ccd_solver.rs | 18 +++--- src/dynamics/ccd/toi_entry.rs | 12 ++-- src/dynamics/rigid_body_components.rs | 8 +-- src/geometry/collider.rs | 67 +++++++++++--------- src/geometry/collider_components.rs | 115 +++++++++++++++++++++++++++------- src/geometry/collider_set.rs | 5 +- src/geometry/narrow_phase.rs | 107 +++++++++++-------------------- src/pipeline/collision_pipeline.rs | 6 +- src/pipeline/event_handler.rs | 6 +- src/pipeline/physics_pipeline.rs | 9 +-- src/pipeline/query_pipeline.rs | 42 ++++++------- 11 files changed, 214 insertions(+), 181 deletions(-) (limited to 'src') diff --git a/src/dynamics/ccd/ccd_solver.rs b/src/dynamics/ccd/ccd_solver.rs index dab4f73..7e95f08 100644 --- a/src/dynamics/ccd/ccd_solver.rs +++ b/src/dynamics/ccd/ccd_solver.rs @@ -10,7 +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, ColliderGroups}; +use crate::prelude::{ActiveEvents, ColliderFlags}; use parry::query::{DefaultQueryDispatcher, QueryDispatcher}; use parry::utils::hashmap::HashMap; use std::collections::BinaryHeap; @@ -141,7 +141,7 @@ impl CCDSolver { + ComponentSet + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet, { // Update the query pipeline. self.query_pipeline.update_with_mode( @@ -202,8 +202,8 @@ impl CCDSolver { { let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0); let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0); - let c1: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch1.0); - let c2: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch2.0); + let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0); + let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0); let co_type1: &ColliderType = colliders.index(ch1.0); let co_type2: &ColliderType = colliders.index(ch1.0); @@ -281,7 +281,7 @@ impl CCDSolver { + ComponentSet + ComponentSet + ComponentSet - + ComponentSet, + + ComponentSet, { let mut frozen = HashMap::<_, Real>::default(); let mut all_toi = BinaryHeap::new(); @@ -343,8 +343,8 @@ impl CCDSolver { { let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0); let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0); - let c1: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch1.0); - let c2: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch2.0); + let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0); + let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0); let bh1 = co_parent1.map(|p| p.handle); let bh2 = co_parent2.map(|p| p.handle); @@ -470,8 +470,8 @@ impl CCDSolver { .colliders_with_aabb_intersecting_aabb(&aabb, |ch2| { let co_parent1: Option<&ColliderParent> = colliders.get(ch1.0); let co_parent2: Option<&ColliderParent> = colliders.get(ch2.0); - let c1: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch1.0); - let c2: (_, _, _, &ColliderGroups) = colliders.index_bundle(ch2.0); + let c1: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch1.0); + let c2: (_, _, _, &ColliderFlags) = colliders.index_bundle(ch2.0); let bh1 = co_parent1.map(|p| p.handle); let bh2 = co_parent2.map(|p| p.handle); diff --git a/src/dynamics/ccd/toi_entry.rs b/src/dynamics/ccd/toi_entry.rs index 918e7c4..f937979 100644 --- a/src/dynamics/ccd/toi_entry.rs +++ b/src/dynamics/ccd/toi_entry.rs @@ -2,7 +2,7 @@ use crate::dynamics::{ RigidBodyCcd, RigidBodyHandle, RigidBodyMassProps, RigidBodyPosition, RigidBodyVelocity, }; use crate::geometry::{ - ColliderGroups, ColliderHandle, ColliderParent, ColliderPosition, ColliderShape, ColliderType, + ColliderFlags, ColliderHandle, ColliderParent, ColliderPosition, ColliderShape, ColliderType, }; use crate::math::Real; use parry::query::{NonlinearRigidMotion, QueryDispatcher}; @@ -49,14 +49,14 @@ impl TOIEntry { &ColliderType, &ColliderShape, &ColliderPosition, - &ColliderGroups, + &ColliderFlags, Option<&ColliderParent>, ), c2: ( &ColliderType, &ColliderShape, &ColliderPosition, - &ColliderGroups, + &ColliderFlags, Option<&ColliderParent>, ), b1: Option<( @@ -82,8 +82,8 @@ impl TOIEntry { return None; } - let (co_type1, co_shape1, co_pos1, co_groups1, co_parent1) = c1; - let (co_type2, co_shape2, co_pos2, co_groups2, co_parent2) = c2; + let (co_type1, co_shape1, co_pos1, co_flags1, co_parent1) = c1; + let (co_type2, co_shape2, co_pos2, co_flags2, co_parent2) = c2; let linvel1 = frozen1.is_none() as u32 as Real * b1.map(|b| b.1.linvel).unwrap_or(na::zero()); @@ -110,7 +110,7 @@ impl TOIEntry { + smallest_contact_dist.max(0.0); let is_pseudo_intersection_test = co_type1.is_sensor() || co_type2.is_sensor() - || !co_groups1.solver_groups.test(co_groups2.solver_groups); + || !co_flags1.solver_groups.test(co_flags2.solver_groups); if (end_time - start_time) * vel12 < thickness { return None; diff --git a/src/dynamics/rigid_body_components.rs b/src/dynamics/rigid_body_components.rs index d1a00ce..ec67b66 100644 --- a/src/dynamics/rigid_body_components.rs +++ b/src/dynamics/rigid_body_components.rs @@ -54,23 +54,23 @@ pub type BodyStatus = RigidBodyType; /// The status of a body, governing the way it is affected by external forces. pub enum RigidBodyType { /// A `RigidBodyType::Dynamic` body can be affected by all external forces. - Dynamic, + Dynamic = 0, /// A `RigidBodyType::Static` body cannot be affected by external forces. - Static, + Static = 1, /// A `RigidBodyType::KinematicPositionBased` body cannot be affected by any external forces but can be controlled /// by the user at the position level while keeping realistic one-way interaction with dynamic bodies. /// /// One-way interaction means that a kinematic body can push a dynamic body, but a kinematic body /// cannot be pushed by anything. In other words, the trajectory of a kinematic body can only be /// modified by the user and is independent from any contact or joint it is involved in. - KinematicPositionBased, + KinematicPositionBased = 2, /// A `RigidBodyType::KinematicVelocityBased` body cannot be affected by any external forces but can be controlled /// by the user at the velocity level while keeping realistic one-way interaction with dynamic bodies. /// /// One-way interaction means that a kinematic body can push a dynamic body, but a kinematic body /// cannot be pushed by anything. In other words, the trajectory of a kinematic body can only be /// modified by the user and is independent from any contact or joint it is involved in. - KinematicVelocityBased, + KinematicVelocityBased = 3, // Semikinematic, // A kinematic that performs automatic CCD with the static environment to avoid traversing it? // Disabled, } diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index b9007bf..0101a09 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -1,8 +1,8 @@ use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; use crate::geometry::{ - ColliderBroadPhaseData, ColliderChanges, ColliderFlags, ColliderGroups, ColliderMassProps, - ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, - InteractionGroups, SharedShape, + ActiveCollisionTypes, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, + ColliderMassProps, ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, + ColliderType, InteractionGroups, SharedShape, }; use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector, DIM}; use crate::parry::transformation::vhacd::VHACDParameters; @@ -25,7 +25,6 @@ pub struct Collider { 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. pub user_data: u128, @@ -57,16 +56,26 @@ impl Collider { self.co_flags.active_hooks = active_hooks; } - /// The physics hooks enabled for this collider. + /// The events enabled for this collider. pub fn active_events(&self) -> ActiveEvents { self.co_flags.active_events } - /// Sets the physics hooks enabled for this collider. + /// Sets the events enabled for this collider. pub fn set_active_events(&mut self, active_events: ActiveEvents) { self.co_flags.active_events = active_events; } + /// The collision types enabled for this collider. + pub fn active_collision_types(&self) -> ActiveCollisionTypes { + self.co_flags.active_collision_types + } + + /// Sets the collision types enabled for this collider. + pub fn set_active_collision_types(&mut self, active_collision_types: ActiveCollisionTypes) { + self.co_flags.active_collision_types = active_collision_types; + } + /// The friction coefficient of this collider. pub fn friction(&self) -> Real { self.co_material.friction @@ -179,27 +188,27 @@ impl Collider { /// The collision groups used by this collider. pub fn collision_groups(&self) -> InteractionGroups { - self.co_groups.collision_groups + self.co_flags.collision_groups } /// Sets the collision groups of this collider. pub fn set_collision_groups(&mut self, groups: InteractionGroups) { - if self.co_groups.collision_groups != groups { + if self.co_flags.collision_groups != groups { self.co_changes.insert(ColliderChanges::GROUPS); - self.co_groups.collision_groups = groups; + self.co_flags.collision_groups = groups; } } /// The solver groups used by this collider. pub fn solver_groups(&self) -> InteractionGroups { - self.co_groups.solver_groups + self.co_flags.solver_groups } /// Sets the solver groups of this collider. pub fn set_solver_groups(&mut self, groups: InteractionGroups) { - if self.co_groups.solver_groups != groups { + if self.co_flags.solver_groups != groups { self.co_changes.insert(ColliderChanges::GROUPS); - self.co_groups.solver_groups = groups; + self.co_flags.solver_groups = groups; } } @@ -281,6 +290,8 @@ pub struct ColliderBuilder { pub position: Isometry, /// Is this collider a sensor? pub is_sensor: bool, + /// Contact pairs enabled for this collider. + pub active_collision_types: ActiveCollisionTypes, /// Physics hooks enabled for this collider. pub active_hooks: ActiveHooks, /// Events enabled for this collider. @@ -309,6 +320,7 @@ impl ColliderBuilder { solver_groups: InteractionGroups::all(), friction_combine_rule: CoefficientCombineRule::Average, restitution_combine_rule: CoefficientCombineRule::Average, + active_collision_types: ActiveCollisionTypes::default(), active_hooks: ActiveHooks::empty(), active_events: ActiveEvents::empty(), } @@ -605,6 +617,12 @@ impl ColliderBuilder { self } + /// The set of active collision types for this collider. + pub fn active_collision_types(mut self, active_collision_types: ActiveCollisionTypes) -> Self { + self.active_collision_types = active_collision_types; + self + } + /// Sets the friction coefficient of the collider this builder will build. pub fn friction(mut self, friction: Real) -> Self { self.friction = friction; @@ -691,27 +709,17 @@ 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_flags, - co_mprops, - ) = self.components(); + let (co_changes, co_pos, co_bf_data, co_shape, co_type, co_material, co_flags, co_mprops) = + self.components(); Collider { co_shape, co_mprops, co_material, - co_flags, co_parent: None, co_changes, co_pos, co_bf_data, - co_groups, + co_flags, co_type, user_data: self.user_data, } @@ -726,7 +734,6 @@ impl ColliderBuilder { ColliderBroadPhaseData, ColliderShape, ColliderType, - ColliderGroups, ColliderMaterial, ColliderFlags, ColliderMassProps, @@ -748,16 +755,15 @@ impl ColliderBuilder { restitution_combine_rule: self.restitution_combine_rule, }; let co_flags = ColliderFlags { + collision_groups: self.collision_groups, + solver_groups: self.solver_groups, + active_collision_types: self.active_collision_types, active_hooks: self.active_hooks, active_events: self.active_events, }; let co_changes = ColliderChanges::all(); let co_pos = ColliderPosition(self.position); let co_bf_data = ColliderBroadPhaseData::default(); - let co_groups = ColliderGroups { - collision_groups: self.collision_groups, - solver_groups: self.solver_groups, - }; let co_type = if self.is_sensor { ColliderType::Sensor } else { @@ -770,7 +776,6 @@ impl ColliderBuilder { co_bf_data, co_shape, 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 5923a42..111f527 100644 --- a/src/geometry/collider_components.rs +++ b/src/geometry/collider_components.rs @@ -1,4 +1,4 @@ -use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; +use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle, RigidBodyType}; use crate::geometry::{InteractionGroups, SAPProxyIndex, Shape, SharedShape}; use crate::math::{Isometry, Real}; use crate::parry::partitioning::IndexedData; @@ -208,27 +208,6 @@ where } } -#[derive(Copy, Clone, Debug)] -#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] -/// The groups of this collider, for filtering contact and solver pairs. -pub struct ColliderGroups { - /// The groups controlling the pairs of colliders that can interact (generate - /// interaction events or contacts). - pub collision_groups: InteractionGroups, - /// The groups controlling the pairs of collider that have their contact - /// points taken into account for force computation. - pub solver_groups: InteractionGroups, -} - -impl Default for ColliderGroups { - fn default() -> Self { - Self { - collision_groups: InteractionGroups::default(), - solver_groups: InteractionGroups::default(), - } - } -} - #[derive(Copy, Clone, Debug)] #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] /// The constraints solver-related properties of this collider (friction, restitution, etc.) @@ -272,10 +251,97 @@ impl Default for ColliderMaterial { } } +bitflags::bitflags! { + #[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))] + /// Flags affecting whether or not collision-detection happens between two colliders + /// depending on the type of rigid-bodies they are attached to. + pub struct ActiveCollisionTypes: u16 { + /// Enable collision-detection between a collider attached to a dynamic body + /// and another collider attached to a dynamic body. + const DYNAMIC_DYNAMIC = 0b0000_0000_0000_0001; + /// Enable collision-detection between a collider attached to a dynamic body + /// and another collider attached to a kinematic body. + const DYNAMIC_KINEMATIC = 0b0000_0000_0000_1100; + /// Enable collision-detection between a collider attached to a dynamic body + /// and another collider attached to a static body (or not attached to any body). + const DYNAMIC_STATIC = 0b0000_0000_0000_0010; + /// Enable collision-detection between a collider attached to a kinematic body + /// and another collider attached to a kinematic body. + const KINEMATIC_KINEMATIC = 0b1100_1100_0000_0000; + + /// Enable collision-detection between a collider attached to a kinematic body + /// and another collider attached to a static body (or not attached to any body). + const KINEMATIC_STATIC = 0b0010_0010_0000_0000; + + /// Enable collision-detection between a collider attached to a static body (or + /// not attached to any body) and another collider attached to a static body (or + /// not attached to any body). + const STATIC_STATIC = 0b0000_0000_0010_0000; + } +} + +impl ActiveCollisionTypes { + /// Test whether contact should be computed between two rigid-bodies with the given types. + pub fn test(self, rb_type1: RigidBodyType, rb_type2: RigidBodyType) -> bool { + // NOTE: This test is quite complicated so here is an explanation. + // First, we associate the following bit masks: + // - DYNAMIC = 0001 + // - STATIC = 0010 + // - KINEMATIC = 1100 + // These are equal to the bits indexed by `RigidBodyType as u32`. + // The bit masks defined by ActiveCollisionTypes are defined is such a way + // that the first part of the variant name (e.g. DYNAMIC_*) indicates which + // groups of four bits should be considered: + // - DYNAMIC_* = the first group of four bits. + // - STATIC_* = the second group of four bits. + // - KINEMATIC_* = the third and fourth groups of four bits. + // The second part of the variant name (e.g. *_DYNAMIC) indicates the value + // of the aforementioned groups of four bits. + // For example, DYNAMIC_STATIC means that the first group of four bits (because + // of DYNAMIC_*) must have the value 0010 (because of *_STATIC). That gives + // us 0b0000_0000_0000_0010 for the DYNAMIC_STATIC_VARIANT. + // + // The KINEMATIC_* is special because it occupies two groups of four bits. This is + // because it combines both KinematicPositionBased and KinematicVelocityBased. + // + // Now that we have a way of building these bit masks, let's see how we use them. + // Given a pair of rigid-body types, the first rigid-body type is used to select + // the group of four bits we want to test (the selection is done by to the + // `>> (rb_type1 as u32 * 4) & 0b0000_1111`) and the second rigid-body type is + // used to form the bit mask we test this group of four bits against. + // In other word, the selection of the group of four bits tells us "for this type + // of rigid-body I can have collision with rigid-body types with these bit representation". + // Then the `(1 << rb_type2)` gives us the bit-representation of the rigid-body type, + // which needs to be checked. + // + // Because that test must be symmetric, we perform two similar tests by swapping + // rb_type1 and rb_type2. + ((self.bits >> (rb_type1 as u32 * 4)) & 0b0000_1111) & (1 << rb_type2 as u32) != 0 + || ((self.bits >> (rb_type2 as u32 * 4)) & 0b0000_1111) & (1 << rb_type1 as u32) != 0 + } +} + +impl Default for ActiveCollisionTypes { + fn default() -> Self { + ActiveCollisionTypes::DYNAMIC_DYNAMIC + | ActiveCollisionTypes::DYNAMIC_KINEMATIC + | ActiveCollisionTypes::DYNAMIC_STATIC + } +} + #[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. +/// A set of flags for controlling collision/intersection filtering, modification, and events. pub struct ColliderFlags { + /// Controls whether collision-detection happens between two colliders depending on + /// the type of the rigid-bodies they are attached to. + pub active_collision_types: ActiveCollisionTypes, + /// The groups controlling the pairs of colliders that can interact (generate + /// interaction events or contacts). + pub collision_groups: InteractionGroups, + /// The groups controlling the pairs of collider that have their contact + /// points taken into account for force computation. + pub solver_groups: InteractionGroups, /// The physics hooks enabled for contact pairs and intersection pairs involving this collider. pub active_hooks: ActiveHooks, /// The events enabled for this collider. @@ -285,6 +351,9 @@ pub struct ColliderFlags { impl Default for ColliderFlags { fn default() -> Self { Self { + active_collision_types: ActiveCollisionTypes::default(), + collision_groups: InteractionGroups::all(), + solver_groups: InteractionGroups::all(), active_hooks: ActiveHooks::empty(), active_events: ActiveEvents::empty(), } diff --git a/src/geometry/collider_set.rs b/src/geometry/collider_set.rs index dc0abdc..9584015 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, ColliderFlags, ColliderGroups, ColliderMassProps, - ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, + Collider, ColliderBroadPhaseData, ColliderFlags, ColliderMassProps, ColliderMaterial, + ColliderParent, ColliderPosition, ColliderShape, ColliderType, }; use crate::geometry::{ColliderChanges, ColliderHandle}; use std::ops::{Index, IndexMut}; @@ -64,7 +64,6 @@ 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); impl ComponentSetOption for ColliderSet { diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs index 61bb4c0..185cf0c 100644 --- a/src/geometry/narrow_phase.rs +++ b/src/geometry/narrow_phase.rs @@ -7,9 +7,9 @@ use crate::dynamics::{ IslandManager, RigidBodyActivation, RigidBodyDominance, RigidBodyIds, RigidBodyType, }; use crate::geometry::{ - BroadPhasePairEvent, ColliderChanges, ColliderGraphIndex, ColliderGroups, ColliderHandle, - ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, ColliderShape, ColliderType, - ContactData, ContactEvent, ContactManifold, ContactManifoldData, ContactPair, InteractionGraph, + BroadPhasePairEvent, ColliderChanges, ColliderGraphIndex, ColliderHandle, ColliderMaterial, + ColliderPair, ColliderParent, ColliderPosition, ColliderShape, ColliderType, ContactData, + ContactEvent, ContactManifold, ContactManifoldData, ContactPair, InteractionGraph, IntersectionEvent, SolverContact, SolverFlags, }; use crate::math::{Real, Vector}; @@ -675,7 +675,6 @@ impl NarrowPhase { + ComponentSet, Colliders: ComponentSet + ComponentSetOption - + ComponentSet + ComponentSet + ComponentSet + ComponentSet @@ -694,18 +693,16 @@ 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_flags1): ( + let (co_changes1, co_shape1, co_pos1, co_flags1): ( &ColliderChanges, - &ColliderGroups, &ColliderShape, &ColliderPosition, &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_flags2): ( + let (co_changes2, co_shape2, co_pos2, co_flags2): ( &ColliderChanges, - &ColliderGroups, &ColliderShape, &ColliderPosition, &ColliderFlags, @@ -718,47 +715,36 @@ impl NarrowPhase { } // TODO: avoid lookup into bodies. - let (mut sleeping1, mut status1) = (true, RigidBodyType::Static); - let (mut sleeping2, mut status2) = (true, RigidBodyType::Static); + let mut rb_type1 = RigidBodyType::Static; + let mut rb_type2 = RigidBodyType::Static; if let Some(co_parent1) = co_parent1 { - let (rb_type1, rb_activation1): (&RigidBodyType, &RigidBodyActivation) = - bodies.index_bundle(co_parent1.handle.0); - status1 = *rb_type1; - sleeping1 = rb_activation1.sleeping; + rb_type1 = *bodies.index(co_parent1.handle.0); } if let Some(co_parent2) = co_parent2 { - let (rb_type2, rb_activation2): (&RigidBodyType, &RigidBodyActivation) = - bodies.index_bundle(co_parent2.handle.0); - status2 = *rb_type2; - sleeping2 = rb_activation2.sleeping; + rb_type2 = *bodies.index(co_parent2.handle.0); } - if (sleeping1 && status2.is_static()) - || (sleeping2 && status1.is_static()) - || (sleeping1 && sleeping2) + // Filter based on the rigid-body types. + if !co_flags1.active_collision_types.test(rb_type1, rb_type2) + && !co_flags2.active_collision_types.test(rb_type1, rb_type2) { - // No need to update this intersection because nothing moved. return; } - if !co_groups1 - .collision_groups - .test(co_groups2.collision_groups) - { - // The intersection is not allowed. + // Filter based on collision groups. + if !co_flags1.collision_groups.test(co_flags2.collision_groups) { return; } 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_INTERSECTION_PAIR) - && !status1.is_dynamic() - && !status2.is_dynamic() + // Filter based on rigid-body types. + if !co_flags1.active_collision_types.test(rb_type1, rb_type2) + && !co_flags2.active_collision_types.test(rb_type1, rb_type2) { - // Default filtering rule: no intersection between two non-dynamic bodies. return; } @@ -811,7 +797,6 @@ impl NarrowPhase { + ComponentSet, Colliders: ComponentSet + ComponentSetOption - + ComponentSet + ComponentSet + ComponentSet + ComponentSet @@ -828,9 +813,8 @@ 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, co_flags1): ( + let (co_changes1, co_shape1, co_pos1, co_material1, co_flags1): ( &ColliderChanges, - &ColliderGroups, &ColliderShape, &ColliderPosition, &ColliderMaterial, @@ -838,9 +822,8 @@ impl NarrowPhase { ) = 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, co_flags2): ( + let (co_changes2, co_shape2, co_pos2, co_material2, co_flags2): ( &ColliderChanges, - &ColliderGroups, &ColliderShape, &ColliderPosition, &ColliderMaterial, @@ -854,50 +837,32 @@ impl NarrowPhase { } // TODO: avoid lookup into bodies. - let (mut sleeping1, mut status1) = (true, RigidBodyType::Static); - let (mut sleeping2, mut status2) = (true, RigidBodyType::Static); + let mut rb_type1 = RigidBodyType::Static; + let mut rb_type2 = RigidBodyType::Static; if let Some(co_parent1) = co_parent1 { - let (rb_type1, rb_activation1): (&RigidBodyType, &RigidBodyActivation) = - bodies.index_bundle(co_parent1.handle.0); - status1 = *rb_type1; - sleeping1 = rb_activation1.sleeping; + rb_type1 = *bodies.index(co_parent1.handle.0); } if let Some(co_parent2) = co_parent2 { - let (rb_type2, rb_activation2): (&RigidBodyType, &RigidBodyActivation) = - bodies.index_bundle(co_parent2.handle.0); - status2 = *rb_type2; - sleeping2 = rb_activation2.sleeping; + rb_type2 = *bodies.index(co_parent2.handle.0); } - if (sleeping1 && status2.is_static()) - || (sleeping2 && status1.is_static()) - || (sleeping1 && sleeping2) + // Filter based on the rigid-body types. + if !co_flags1.active_collision_types.test(rb_type1, rb_type2) + && !co_flags2.active_collision_types.test(rb_type1, rb_type2) { - // No need to update this intersection because nothing moved. return; } - if !co_groups1 - .collision_groups - .test(co_groups2.collision_groups) - { - // The collision is not allowed. + // Filter based on collision groups. + if !co_flags1.collision_groups.test(co_flags2.collision_groups) { return; } 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() - { - // Default filtering rule: no contact between two non-dynamic bodies. - return; - } - let mut solver_flags = if active_hooks.contains(ActiveHooks::FILTER_CONTACT_PAIRS) { let context = PairFilterContext { bodies, @@ -918,7 +883,7 @@ impl NarrowPhase { SolverFlags::default() }; - if !co_groups1.solver_groups.test(co_groups2.solver_groups) { + if !co_flags1.solver_groups.test(co_flags2.solver_groups) { solver_flags.remove(SolverFlags::COMPUTE_IMPULSES); } @@ -969,7 +934,7 @@ impl NarrowPhase { manifold.data.rigid_body2 = co_parent2.map(|p| p.handle); manifold.data.solver_flags = solver_flags; manifold.data.relative_dominance = - dominance1.effective_group(&status1) - dominance2.effective_group(&status2); + dominance1.effective_group(&rb_type1) - dominance2.effective_group(&rb_type2); manifold.data.normal = world_pos1 * manifold.local_n1; // Generate solver contacts. @@ -1073,7 +1038,7 @@ impl NarrowPhase { .contains(SolverFlags::COMPUTE_IMPULSES) && manifold.data.num_active_contacts() != 0 { - let (active_island_id1, status1, sleeping1) = + let (active_island_id1, rb_type1, sleeping1) = if let Some(handle1) = manifold.data.rigid_body1 { let data: (&RigidBodyIds, &RigidBodyType, &RigidBodyActivation) = bodies.index_bundle(handle1.0); @@ -1082,7 +1047,7 @@ impl NarrowPhase { (0, RigidBodyType::Static, true) }; - let (active_island_id2, status2, sleeping2) = + let (active_island_id2, rb_type2, sleeping2) = if let Some(handle2) = manifold.data.rigid_body2 { let data: (&RigidBodyIds, &RigidBodyType, &RigidBodyActivation) = bodies.index_bundle(handle2.0); @@ -1091,11 +1056,11 @@ impl NarrowPhase { (0, RigidBodyType::Static, true) }; - if (status1.is_dynamic() || status2.is_dynamic()) - && (!status1.is_dynamic() || !sleeping1) - && (!status2.is_dynamic() || !sleeping2) + if (rb_type1.is_dynamic() || rb_type2.is_dynamic()) + && (!rb_type1.is_dynamic() || !sleeping1) + && (!rb_type2.is_dynamic() || !sleeping2) { - let island_index = if !status1.is_dynamic() { + let island_index = if !rb_type1.is_dynamic() { active_island_id2 } else { active_island_id1 diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs index e4ea157..d789da7 100644 --- a/src/pipeline/collision_pipeline.rs +++ b/src/pipeline/collision_pipeline.rs @@ -7,8 +7,8 @@ use crate::dynamics::{ }; use crate::geometry::{ BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, - ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, - ColliderPosition, ColliderShape, ColliderType, NarrowPhase, + ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, + ColliderShape, ColliderType, NarrowPhase, }; use crate::math::Real; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -65,7 +65,6 @@ impl CollisionPipeline { + ComponentSet + ComponentSetOption + ComponentSet - + ComponentSet + ComponentSet + ComponentSet, { @@ -173,7 +172,6 @@ impl CollisionPipeline { + ComponentSet + ComponentSetOption + ComponentSet - + ComponentSet + ComponentSet + ComponentSet, { diff --git a/src/pipeline/event_handler.rs b/src/pipeline/event_handler.rs index 4ee5387..c54acc2 100644 --- a/src/pipeline/event_handler.rs +++ b/src/pipeline/event_handler.rs @@ -3,11 +3,11 @@ 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. + /// Flags affecting the events generated for this collider. pub struct ActiveEvents: u32 { - /// If set, Rapier will call `PhysicsHooks::FILTER_CONTACT_PAIRS` whenever relevant. + /// If set, Rapier will call `EventHandler::handle_intersection_event` whenever relevant for this collider. const INTERSECTION_EVENTS = 0b0001; - /// If set, Rapier will call `PhysicsHooks::filter_intersection_pair` whenever relevant. + /// If set, Rapier will call `PhysicsHooks::handle_contact_event` whenever relevant for this collider. const CONTACT_EVENTS = 0b0010; } } diff --git a/src/pipeline/physics_pipeline.rs b/src/pipeline/physics_pipeline.rs index f5d9b27..987ca25 100644 --- a/src/pipeline/physics_pipeline.rs +++ b/src/pipeline/physics_pipeline.rs @@ -14,8 +14,8 @@ use crate::dynamics::{ use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver}; use crate::geometry::{ BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags, - ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, - ColliderPosition, ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase, + ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition, + ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase, }; use crate::math::{Real, Vector}; use crate::pipeline::{EventHandler, PhysicsHooks}; @@ -103,7 +103,6 @@ impl PhysicsPipeline { + ComponentSet + ComponentSetOption + ComponentSet - + ComponentSet + ComponentSet + ComponentSet, { @@ -367,8 +366,7 @@ impl PhysicsPipeline { + ComponentSet + ComponentSet + ComponentSet - + ComponentSet - + ComponentSet, + + ComponentSet, { self.counters.ccd.toi_computation_time.start(); // Handle CCD @@ -547,7 +545,6 @@ impl PhysicsPipeline { + ComponentSet + ComponentSetOption + ComponentSet - + ComponentSet + ComponentSet + ComponentSet, { diff --git a/src/pipeline/query_pipeline.rs b/src/pipeline/query_pipeline.rs index 31bf3a4..733d767 100644 --- a/src/pipeline/query_pipeline.rs +++ b/src/pipeline/query_pipeline.rs @@ -4,7 +4,7 @@ use crate::dynamics::{ RigidBodyVelocity, }; use crate::geometry::{ - ColliderGroups, ColliderHandle, ColliderParent, ColliderPosition, ColliderShape, + ColliderFlags, ColliderHandle, ColliderParent, ColliderPosition, ColliderShape, InteractionGroups, PointProjection, Ray, RayIntersection, AABB, QBVH, }; use crate::math::{Isometry, Point, Real, Vector}; @@ -67,7 +67,7 @@ impl<'a, Colliders> TypedSimdCompositeShape for QueryPipelineAsCompositeShape<'a where // TODO ECS: make everything optional but the shape? Colliders: - ComponentSet + ComponentSet + ComponentSet, + ComponentSet + ComponentSet + ComponentSet, { type PartShape = dyn Shape; type PartId = ColliderHandle; @@ -77,10 +77,10 @@ where shape_id: Self::PartId, mut f: impl FnMut(Option<&Isometry>, &Self::PartShape), ) { - let co_groups: Option<&ColliderGroups> = self.colliders.get(shape_id.0); + let co_flags: Option<&ColliderFlags> = self.colliders.get(shape_id.0); - if let Some(co_groups) = co_groups { - if co_groups.collision_groups.test(self.query_groups) + if let Some(co_flags) = co_flags { + if co_flags.collision_groups.test(self.query_groups) && self.filter.map(|f| f(shape_id)).unwrap_or(true) { let (co_pos, co_shape): (&ColliderPosition, &ColliderShape) = @@ -384,7 +384,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, Real)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -420,7 +420,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, RayIntersection)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -463,16 +463,16 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle, RayIntersection) -> bool, ) where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { let mut leaf_callback = &mut |handle: &ColliderHandle| { let co_shape: Option<&ColliderShape> = colliders.get(handle.0); if let Some(co_shape) = co_shape { - let (co_groups, co_pos): (&ColliderGroups, &ColliderPosition) = + let (co_flags, co_pos): (&ColliderFlags, &ColliderPosition) = colliders.index_bundle(handle.0); - if co_groups.collision_groups.test(query_groups) + if co_flags.collision_groups.test(query_groups) && filter.map(|f| f(*handle)).unwrap_or(true) { if let Some(hit) = co_shape.cast_ray_and_get_normal(co_pos, ray, max_toi, solid) @@ -509,7 +509,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -550,7 +550,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, PointProjection)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -583,7 +583,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle) -> bool, ) where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -591,10 +591,10 @@ impl QueryPipeline { let co_shape: Option<&ColliderShape> = colliders.get(handle.0); if let Some(co_shape) = co_shape { - let (co_groups, co_pos): (&ColliderGroups, &ColliderPosition) = + let (co_flags, co_pos): (&ColliderFlags, &ColliderPosition) = colliders.index_bundle(handle.0); - if co_groups.collision_groups.test(query_groups) + if co_flags.collision_groups.test(query_groups) && filter.map(|f| f(*handle)).unwrap_or(true) && co_shape.contains_point(co_pos, point) { @@ -635,7 +635,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, PointProjection, FeatureId)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -685,7 +685,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, TOI)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -733,7 +733,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, ) -> Option<(ColliderHandle, TOI)> where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -774,7 +774,7 @@ impl QueryPipeline { filter: Option<&dyn Fn(ColliderHandle) -> bool>, mut callback: impl FnMut(ColliderHandle) -> bool, ) where - Colliders: ComponentSet + Colliders: ComponentSet + ComponentSet + ComponentSet, { @@ -785,10 +785,10 @@ impl QueryPipeline { let co_shape: Option<&ColliderShape> = colliders.get(handle.0); if let Some(co_shape) = co_shape { - let (co_groups, co_pos): (&ColliderGroups, &ColliderPosition) = + let (co_flags, co_pos): (&ColliderFlags, &ColliderPosition) = colliders.index_bundle(handle.0); - if co_groups.collision_groups.test(query_groups) + if co_flags.collision_groups.test(query_groups) && filter.map(|f| f(*handle)).unwrap_or(true) { let pos12 = inv_shape_pos * co_pos.as_ref(); -- cgit