aboutsummaryrefslogtreecommitdiff
path: root/src/geometry
diff options
context:
space:
mode:
Diffstat (limited to 'src/geometry')
-rw-r--r--src/geometry/broad_phase_multi_sap/broad_phase.rs4
-rw-r--r--src/geometry/collider.rs266
-rw-r--r--src/geometry/collider_components.rs171
-rw-r--r--src/geometry/collider_set.rs58
-rw-r--r--src/geometry/contact_pair.rs16
-rw-r--r--src/geometry/interaction_groups.rs54
-rw-r--r--src/geometry/narrow_phase.rs328
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