diff options
Diffstat (limited to 'src/geometry')
| -rw-r--r-- | src/geometry/broad_phase_multi_sap/broad_phase.rs | 4 | ||||
| -rw-r--r-- | src/geometry/collider.rs | 266 | ||||
| -rw-r--r-- | src/geometry/collider_components.rs | 171 | ||||
| -rw-r--r-- | src/geometry/collider_set.rs | 58 | ||||
| -rw-r--r-- | src/geometry/contact_pair.rs | 16 | ||||
| -rw-r--r-- | src/geometry/interaction_groups.rs | 54 | ||||
| -rw-r--r-- | src/geometry/narrow_phase.rs | 328 |
7 files changed, 595 insertions, 302 deletions
diff --git a/src/geometry/broad_phase_multi_sap/broad_phase.rs b/src/geometry/broad_phase_multi_sap/broad_phase.rs index 4b35e53..63f1a55 100644 --- a/src/geometry/broad_phase_multi_sap/broad_phase.rs +++ b/src/geometry/broad_phase_multi_sap/broad_phase.rs @@ -598,7 +598,7 @@ mod test { let rb = RigidBodyBuilder::new_dynamic().build(); let co = ColliderBuilder::ball(0.5).build(); let hrb = bodies.insert(rb); - let coh = colliders.insert(co, hrb, &mut bodies); + let coh = colliders.insert_with_parent(co, hrb, &mut bodies); let mut events = Vec::new(); broad_phase.update(0.0, &mut colliders, &[coh], &[], &mut events); @@ -610,7 +610,7 @@ mod test { let rb = RigidBodyBuilder::new_dynamic().build(); let co = ColliderBuilder::ball(0.5).build(); let hrb = bodies.insert(rb); - let coh = colliders.insert(co, hrb, &mut bodies); + let coh = colliders.insert_with_parent(co, hrb, &mut bodies); // Make sure the proxy handles is recycled properly. broad_phase.update(0.0, &mut colliders, &[coh], &[], &mut events); diff --git a/src/geometry/collider.rs b/src/geometry/collider.rs index 08295c1..0101a09 100644 --- a/src/geometry/collider.rs +++ b/src/geometry/collider.rs @@ -1,11 +1,12 @@ use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; use crate::geometry::{ - ColliderBroadPhaseData, ColliderChanges, ColliderGroups, ColliderMassProperties, - ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, - InteractionGroups, SharedShape, SolverFlags, + 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; +use crate::pipeline::{ActiveEvents, ActiveHooks}; use na::Unit; use parry::bounding_volume::AABB; use parry::shape::Shape; @@ -18,12 +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: ColliderParent, + pub(crate) co_parent: Option<ColliderParent>, pub(crate) co_pos: ColliderPosition, pub(crate) co_material: ColliderMaterial, - pub(crate) co_groups: ColliderGroups, + pub(crate) co_flags: ColliderFlags, pub(crate) co_bf_data: ColliderBroadPhaseData, /// User-defined data associated to this rigid-body. pub user_data: u128, @@ -31,14 +32,13 @@ pub struct Collider { impl Collider { pub(crate) fn reset_internal_references(&mut self) { - self.co_parent.handle = RigidBodyHandle::invalid(); self.co_bf_data.proxy_index = crate::INVALID_U32; self.co_changes = ColliderChanges::all(); } /// The rigid body this collider is attached to. - pub fn parent(&self) -> RigidBodyHandle { - self.co_parent.handle + pub fn parent(&self) -> Option<RigidBodyHandle> { + self.co_parent.map(|parent| parent.handle) } /// Is this collider a sensor? @@ -46,6 +46,46 @@ impl Collider { self.co_type.is_sensor() } + /// The physics hooks enabled for this collider. + 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: ActiveHooks) { + self.co_flags.active_hooks = active_hooks; + } + + /// The events enabled for this collider. + pub fn active_events(&self) -> ActiveEvents { + self.co_flags.active_events + } + + /// 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 + } + + /// Sets the friction coefficient of this collider. + pub fn set_friction(&mut self, coefficient: Real) { + self.co_material.friction = coefficient + } + /// The combine rule used by this collider to combine its friction /// coefficient with the friction coefficient of the other collider it /// is in contact with. @@ -60,6 +100,16 @@ impl Collider { self.co_material.friction_combine_rule = rule; } + /// The restitution coefficient of this collider. + pub fn restitution(&self) -> Real { + self.co_material.restitution + } + + /// Sets the restitution coefficient of this collider. + pub fn set_restitution(&mut self, coefficient: Real) { + self.co_material.restitution = coefficient + } + /// The combine rule used by this collider to combine its restitution /// coefficient with the restitution coefficient of the other collider it /// is in contact with. @@ -86,15 +136,22 @@ impl Collider { } } - #[doc(hidden)] - pub fn set_position_debug(&mut self, position: Isometry<Real>) { - self.co_pos.0 = position; + /// Sets the translational part of this collider's position. + pub fn set_translation(&mut self, translation: Vector<Real>) { + self.co_changes.insert(ColliderChanges::POSITION); + self.co_pos.0.translation.vector = translation; } - /// The position of this collider expressed in the local-space of the rigid-body it is attached to. - #[deprecated(note = "use `.position_wrt_parent()` instead.")] - pub fn delta(&self) -> &Isometry<Real> { - &self.co_parent.pos_wrt_parent + /// Sets the rotational part of this collider's position. + pub fn set_rotation(&mut self, rotation: AngVector<Real>) { + self.co_changes.insert(ColliderChanges::POSITION); + self.co_pos.0.rotation = Rotation::new(rotation); + } + + /// Sets the position of this collider. + pub fn set_position(&mut self, position: Isometry<Real>) { + self.co_changes.insert(ColliderChanges::POSITION); + self.co_pos.0 = position; } /// The world-space position of this collider. @@ -102,40 +159,56 @@ impl Collider { &self.co_pos } + /// The translational part of this rigid-body's position. + pub fn translation(&self) -> &Vector<Real> { + &self.co_pos.0.translation.vector + } + + /// The rotational part of this rigid-body's position. + pub fn rotation(&self) -> &Rotation<Real> { + &self.co_pos.0.rotation + } + /// The position of this collider wrt the body it is attached to. - pub fn position_wrt_parent(&self) -> &Isometry<Real> { - &self.co_parent.pos_wrt_parent + pub fn position_wrt_parent(&self) -> Option<&Isometry<Real>> { + self.co_parent.as_ref().map(|p| &p.pos_wrt_parent) } /// Sets the position of this collider wrt. its parent rigid-body. - pub fn set_position_wrt_parent(&mut self, position: Isometry<Real>) { + /// + /// Panics if the collider is not attached to a rigid-body. + pub fn set_position_wrt_parent(&mut self, pos_wrt_parent: Isometry<Real>) { self.co_changes.insert(ColliderChanges::PARENT); - self.co_parent.pos_wrt_parent = position; + let co_parent = self + .co_parent + .as_mut() + .expect("This collider has no parent."); + co_parent.pos_wrt_parent = pos_wrt_parent; } /// 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; } } @@ -147,8 +220,8 @@ impl Collider { /// The density of this collider, if set. pub fn density(&self) -> Option<Real> { match &self.co_mprops { - ColliderMassProperties::Density(density) => Some(*density), - ColliderMassProperties::MassProperties(_) => None, + ColliderMassProps::Density(density) => Some(*density), + ColliderMassProps::MassProperties(_) => None, } } @@ -188,8 +261,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, } } } @@ -213,13 +286,16 @@ pub struct ColliderBuilder { pub restitution: Real, /// The rule used to combine two restitution coefficients. pub restitution_combine_rule: CoefficientCombineRule, - /// The position of this collider relative to the local frame of the rigid-body it is attached to. - pub pos_wrt_parent: Isometry<Real>, + /// The position of this collider. + pub position: Isometry<Real>, /// Is this collider a sensor? pub is_sensor: bool, - /// Do we have to always call the contact modifier - /// on this collider? - pub modify_solver_contacts: 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. + pub active_events: ActiveEvents, /// The user-data of the collider being built. pub user_data: u128, /// The collision groups for the collider being built. @@ -237,14 +313,16 @@ impl ColliderBuilder { mass_properties: None, friction: Self::default_friction(), restitution: 0.0, - pos_wrt_parent: Isometry::identity(), + position: Isometry::identity(), is_sensor: false, user_data: 0, collision_groups: InteractionGroups::all(), solver_groups: InteractionGroups::all(), friction_combine_rule: CoefficientCombineRule::Average, restitution_combine_rule: CoefficientCombineRule::Average, - modify_solver_contacts: false, + active_collision_types: ActiveCollisionTypes::default(), + active_hooks: ActiveHooks::empty(), + active_events: ActiveEvents::empty(), } } @@ -489,6 +567,11 @@ impl ColliderBuilder { 0.5 } + /// The default density used by the collider builder. + pub fn default_density() -> Real { + 1.0 + } + /// Sets an arbitrary user-defined 128-bit integer associated to the colliders built by this builder. pub fn user_data(mut self, data: u128) -> Self { self.user_data = data; @@ -522,10 +605,21 @@ impl ColliderBuilder { self } - /// If set to `true` then the physics hooks will always run to modify - /// contacts involving this collider. - pub fn modify_solver_contacts(mut self, modify_solver_contacts: bool) -> Self { - self.modify_solver_contacts = modify_solver_contacts; + /// The set of physics hooks enabled for this collider. + 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 + } + + /// 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 } @@ -571,71 +665,61 @@ impl ColliderBuilder { self } - /// Sets the initial translation of the collider to be created, - /// relative to the rigid-body it is attached to. - #[cfg(feature = "dim2")] - pub fn translation(mut self, x: Real, y: Real) -> Self { - self.pos_wrt_parent.translation.x = x; - self.pos_wrt_parent.translation.y = y; - self - } - - /// Sets the initial translation of the collider to be created, - /// relative to the rigid-body it is attached to. - #[cfg(feature = "dim3")] - pub fn translation(mut self, x: Real, y: Real, z: Real) -> Self { - self.pos_wrt_parent.translation.x = x; - self.pos_wrt_parent.translation.y = y; - self.pos_wrt_parent.translation.z = z; + /// Sets the initial translation of the collider to be created. + /// + /// If the collider will be attached to a rigid-body, this sets the translation relative to the + /// rigid-body it will be attached to. + pub fn translation(mut self, translation: Vector<Real>) -> Self { + self.position.translation.vector = translation; self } - /// Sets the initial orientation of the collider to be created, - /// relative to the rigid-body it is attached to. + /// Sets the initial orientation of the collider to be created. + /// + /// If the collider will be attached to a rigid-body, this sets the orientation relative to the + /// rigid-body it will be attached to. pub fn rotation(mut self, angle: AngVector<Real>) -> Self { - self.pos_wrt_parent.rotation = Rotation::new(angle); + self.position.rotation = Rotation::new(angle); self } - /// Sets the initial position (translation and orientation) of the collider to be created, - /// relative to the rigid-body it is attached to. - pub fn position_wrt_parent(mut self, pos: Isometry<Real>) -> Self { - self.pos_wrt_parent = pos; + /// Sets the initial position (translation and orientation) of the collider to be created. + /// + /// If the collider will be attached to a rigid-body, this sets the position relative + /// to the rigid-body it will be attached to. + pub fn position(mut self, pos: Isometry<Real>) -> Self { + self.position = pos; self } /// Sets the initial position (translation and orientation) of the collider to be created, /// relative to the rigid-body it is attached to. - #[deprecated(note = "Use `.position_wrt_parent` instead.")] - pub fn position(mut self, pos: Isometry<Real>) -> Self { - self.pos_wrt_parent = pos; + #[deprecated(note = "Use `.position` instead.")] + pub fn position_wrt_parent(mut self, pos: Isometry<Real>) -> Self { + self.position = pos; self } /// Set the position of this collider in the local-space of the rigid-body it is attached to. - #[deprecated(note = "Use `.position_wrt_parent` instead.")] + #[deprecated(note = "Use `.position` instead.")] pub fn delta(mut self, delta: Isometry<Real>) -> Self { - self.pos_wrt_parent = delta; + self.position = delta; self } /// 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) = + let (co_changes, co_pos, co_bf_data, co_shape, co_type, co_material, co_flags, co_mprops) = self.components(); - let co_parent = ColliderParent { - pos_wrt_parent: co_pos.0, - handle: RigidBodyHandle::invalid(), - }; Collider { co_shape, co_mprops, co_material, - co_parent, + co_parent: None, co_changes, co_pos, co_bf_data, - co_groups, + co_flags, co_type, user_data: self.user_data, } @@ -650,24 +734,18 @@ impl ColliderBuilder { ColliderBroadPhaseData, ColliderShape, 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 = if self.is_sensor { 0.0 } else { 1.0 }; + let default_density = Self::default_density(); let density = self.density.unwrap_or(default_density); - ColliderMassProperties::Density(density) + ColliderMassProps::Density(density) }; - let mut solver_flags = SolverFlags::default(); - solver_flags.set( - SolverFlags::MODIFY_SOLVER_CONTACTS, - self.modify_solver_contacts, - ); - let co_shape = self.shape.clone(); let co_mprops = mass_info; let co_material = ColliderMaterial { @@ -675,15 +753,17 @@ impl ColliderBuilder { restitution: self.restitution, friction_combine_rule: self.friction_combine_rule, restitution_combine_rule: self.restitution_combine_rule, - solver_flags, }; - let co_changes = ColliderChanges::all(); - let co_pos = ColliderPosition(self.pos_wrt_parent); - let co_bf_data = ColliderBroadPhaseData::default(); - let co_groups = ColliderGroups { + 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_type = if self.is_sensor { ColliderType::Sensor } else { @@ -696,8 +776,8 @@ 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 a02c706..111f527 100644 --- a/src/geometry/collider_components.rs +++ b/src/geometry/collider_components.rs @@ -1,7 +1,8 @@ -use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle}; -use crate::geometry::{InteractionGroups, SAPProxyIndex, Shape, SharedShape, SolverFlags}; +use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle, RigidBodyType}; +use crate::geometry::{InteractionGroups, SAPProxyIndex, Shape, SharedShape}; use crate::math::{Isometry, Real}; use crate::parry::partitioning::IndexedData; +use crate::pipeline::{ActiveEvents, ActiveHooks}; use std::ops::Deref; /// The unique identifier of a collider added to a collider set. @@ -117,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 @@ -127,13 +128,19 @@ pub enum ColliderMassProperties { MassProperties(Box<MassProperties>), } -impl Default for ColliderMassProperties { +impl Default for ColliderMassProps { fn default() -> Self { - ColliderMassProperties::Density(1.0) + ColliderMassProps::Density(1.0) } } -impl ColliderMassProperties { +impl From<MassProperties> 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 @@ -203,27 +210,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.) pub struct ColliderMaterial { /// The friction coefficient of this collider. @@ -241,9 +227,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 solver flags attached to this collider in order to customize the way the - /// constraints solver will work with contacts involving this collider. - pub solver_flags: SolverFlags, } impl ColliderMaterial { @@ -264,7 +247,133 @@ impl Default for ColliderMaterial { restitution: 0.0, friction_combine_rule: CoefficientCombineRule::default(), restitution_combine_rule: CoefficientCombineRule::default(), - solver_flags: SolverFlags::default(), + } + } +} + +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 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. + pub active_events: ActiveEvents, +} + +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(), + } + } +} + +impl From<ActiveHooks> for ColliderFlags { + fn from(active_hooks: ActiveHooks) -> Self { + Self { + active_hooks, + ..Default::default() + } + } +} + +impl From<ActiveEvents> 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 14eb54c..9584015 100644 --- a/src/geometry/collider_set.rs +++ b/src/geometry/collider_set.rs @@ -2,7 +2,7 @@ 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, + Collider, ColliderBroadPhaseData, ColliderFlags, ColliderMassProps, ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType, }; use crate::geometry::{ColliderChanges, ColliderHandle}; @@ -59,14 +59,21 @@ 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!(ColliderParent, co_parent); impl_field_component_set!(ColliderPosition, co_pos); impl_field_component_set!(ColliderMaterial, co_material); -impl_field_component_set!(ColliderGroups, co_groups); +impl_field_component_set!(ColliderFlags, co_flags); impl_field_component_set!(ColliderBroadPhaseData, co_bf_data); +impl ComponentSetOption<ColliderParent> for ColliderSet { + #[inline(always)] + fn get(&self, handle: crate::data::Index) -> Option<&ColliderParent> { + self.get(ColliderHandle(handle)) + .and_then(|b| b.co_parent.as_ref()) + } +} + impl ColliderSet { /// Create a new empty set of colliders. pub fn new() -> Self { @@ -122,16 +129,35 @@ impl ColliderSet { } /// Inserts a new collider to this set and retrieve its handle. - pub fn insert( + pub fn insert(&mut self, mut coll: Collider) -> ColliderHandle { + // Make sure the internal links are reset, they may not be + // if this rigid-body was obtained by cloning another one. + coll.reset_internal_references(); + coll.co_parent = None; + let handle = ColliderHandle(self.colliders.insert(coll)); + self.modified_colliders.push(handle); + handle + } + + /// Inserts a new collider to this set, attach it to the given rigid-body, and retrieve its handle. + pub fn insert_with_parent( &mut self, mut coll: Collider, parent_handle: RigidBodyHandle, bodies: &mut RigidBodySet, ) -> ColliderHandle { // Make sure the internal links are reset, they may not be - // if this rigid-body was obtained by cloning another one. + // if this collider was obtained by cloning another one. coll.reset_internal_references(); - coll.co_parent.handle = parent_handle; + + if let Some(prev_parent) = &mut coll.co_parent { + prev_parent.handle = parent_handle; + } else { + coll.co_parent = Some(ColliderParent { + handle: parent_handle, + pos_wrt_parent: coll.co_pos.0, + }); + } // NOTE: we use `get_mut` instead of `get_mut_internal` so that the // modification flag is updated properly. @@ -144,7 +170,7 @@ impl ColliderSet { let coll = self.colliders.get_mut(handle.0).unwrap(); parent.add_collider( handle, - &mut coll.co_parent, + coll.co_parent.as_mut().unwrap(), &mut coll.co_pos, &coll.co_shape, &coll.co_mprops, @@ -170,13 +196,15 @@ impl ColliderSet { */ // NOTE: we use `get_mut_internal_with_modification_tracking` instead of `get_mut_internal` so that the // modification flag is updated properly. - if let Some(parent) = - bodies.get_mut_internal_with_modification_tracking(collider.co_parent.handle) - { - parent.remove_collider_internal(handle, &collider); - - if wake_up { - islands.wake_up(bodies, collider.co_parent.handle, true); + if let Some(co_parent) = &collider.co_parent { + if let Some(parent) = + bodies.get_mut_internal_with_modification_tracking(co_parent.handle) + { + parent.remove_collider_internal(handle, &collider); + + if wake_up { + islands.wake_up(bodies, co_parent.handle, true); + } } } diff --git a/src/geometry/contact_pair.rs b/src/geometry/contact_pair.rs index 5a568fa..f4e7834 100644 --- a/src/geometry/contact_pair.rs +++ b/src/geometry/contact_pair.rs @@ -1,5 +1,5 @@ use crate::dynamics::RigidBodyHandle; -use crate::geometry::{ColliderPair, Contact, ContactManifold}; +use crate::geometry::{ColliderHandle, Contact, ContactManifold}; use crate::math::{Point, Real, Vector}; use parry::query::ContactManifoldsWorkspace; @@ -10,9 +10,6 @@ bitflags::bitflags! { /// The constraint solver will take this contact manifold into /// account for force computation. const COMPUTE_IMPULSES = 0b001; - /// The user-defined physics hooks will be used to - /// modify the solver contacts of this contact manifold. - const MODIFY_SOLVER_CONTACTS = 0b010; } } @@ -56,8 +53,10 @@ impl Default for ContactData { #[derive(Clone)] /// The description of all the contacts between a pair of colliders. pub struct ContactPair { - /// The pair of colliders involved. - pub pair: ColliderPair, + /// The first collider involved in the contact pair. + pub collider1: ColliderHandle, + /// The second collider involved in the contact pair. + pub collider2: ColliderHandle, /// The set of contact manifolds between the two colliders. /// /// All contact manifold contain themselves contact points between the colliders. @@ -68,9 +67,10 @@ pub struct ContactPair { } impl ContactPair { - pub(crate) fn new(pair: ColliderPair) -> Self { + pub(crate) fn new(collider1: ColliderHandle, collider2: ColliderHandle) -> Self { Self { - pair, + collider1, + collider2, has_any_active_contact: false, manifolds: Vec::new(), workspace |
