Rework the event system

This commit is contained in:
Crozet Sébastien
2021-06-01 12:36:01 +02:00
parent 1bef66fea9
commit 826ce5f014
28 changed files with 382 additions and 200 deletions

View File

@@ -25,7 +25,19 @@ FIXME:
fields: `ContactPair::collider1` and `ContactPair::collider2`.
- The fields `FixedJoint::local_anchor1` and `FixedJoint::local_anchor2` have been renamed to
`FixedJoint::local_frame1` and `FixedJoint::local_frame2`.
- The list of active dynamic bodies is no retrieved with `IslandManager::active_dynamic_bodies`
instead of `RigidBodySet::iter_active_dynamic`.
- The list of active kinematic bodies is no retrieved with `IslandManager::active_kinematic_bodies`
instead of `RigidBodySet::iter_active_kinematic`.
- The `InteractionGroups` is now a structures with two `u32` integers: one integers for the groups
membership and one for the group filter mask. (Before, both were only 16-bits wide, and were
packed into a single `u32`).
- `NarrowPhase::contacts_with` now returns an `impl Iterator<Item = &ContactPair>` instead of
an `Option<impl Iterator<Item = (ColliderHandle, ColliderHandle, &ContactPair)>>`. The colliders
handles can be read from the contact-pair itself.
- `NarrowPhase::intersections_with` now returns an iterator directly instead of an `Option<impl Iterator>`.
- Rename `PhysicsHooksFlags` to `ActiveHooks`.
## v0.8.0
### Modified
- Switch to nalgebra 0.26.

View File

@@ -34,6 +34,7 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::cuboid(ground_thickness, ground_size)
.translation(vector![2.5, 0.0])
.sensor(true)
.active_events(ActiveEvents::INTERSECTION_EVENTS)
.build();
let sensor_handle = colliders.insert_with_parent(collider, ground_handle, &mut bodies);

View File

@@ -72,12 +72,12 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::cuboid(25.0, 0.5)
.translation(vector![30.0, 2.0])
.active_hooks(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS)
.active_hooks(ActiveHooks::MODIFY_SOLVER_CONTACTS)
.build();
let platform1 = colliders.insert_with_parent(collider, handle, &mut bodies);
let collider = ColliderBuilder::cuboid(25.0, 0.5)
.translation(vector![-30.0, -2.0])
.active_hooks(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS)
.active_hooks(ActiveHooks::MODIFY_SOLVER_CONTACTS)
.build();
let platform2 = colliders.insert_with_parent(collider, handle, &mut bodies);

View File

@@ -66,6 +66,7 @@ pub fn init_world(testbed: &mut Testbed) {
let sensor_collider = ColliderBuilder::ball(rad * 5.0)
.density(0.0)
.sensor(true)
.active_events(ActiveEvents::INTERSECTION_EVENTS)
.build();
colliders.insert_with_parent(sensor_collider, sensor_handle, &mut bodies);

View File

@@ -96,6 +96,7 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::ball(1.0)
.density(10.0)
.sensor(true)
.active_events(ActiveEvents::INTERSECTION_EVENTS)
.build();
let rigid_body = RigidBodyBuilder::new_dynamic()
.linvel(vector![1000.0, 0.0, 0.0])

View File

@@ -72,12 +72,12 @@ pub fn init_world(testbed: &mut Testbed) {
let collider = ColliderBuilder::cuboid(9.0, 0.5, 25.0)
.translation(vector![0.0, 2.0, 30.0])
.active_hooks(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS)
.active_hooks(ActiveHooks::MODIFY_SOLVER_CONTACTS)
.build();
let platform1 = colliders.insert_with_parent(collider, handle, &mut bodies);
let collider = ColliderBuilder::cuboid(9.0, 0.5, 25.0)
.translation(vector![0.0, -2.0, -30.0])
.active_hooks(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS)
.active_hooks(ActiveHooks::MODIFY_SOLVER_CONTACTS)
.build();
let platform2 = colliders.insert_with_parent(collider, handle, &mut bodies);

View File

@@ -70,6 +70,7 @@ pub fn init_world(testbed: &mut Testbed) {
let sensor_collider = ColliderBuilder::ball(rad * 5.0)
.density(0.0)
.sensor(true)
.active_events(ActiveEvents::INTERSECTION_EVENTS)
.build();
colliders.insert_with_parent(sensor_collider, sensor_handle, &mut bodies);

View File

@@ -10,6 +10,7 @@ use crate::geometry::{
use crate::math::Real;
use crate::parry::utils::SortedPair;
use crate::pipeline::{EventHandler, QueryPipeline, QueryPipelineMode};
use crate::prelude::{ActiveEvents, ColliderFlags};
use parry::query::{DefaultQueryDispatcher, QueryDispatcher};
use parry::utils::hashmap::HashMap;
use std::collections::BinaryHeap;
@@ -66,7 +67,7 @@ impl CCDSolver {
&RigidBodyCcd,
&RigidBodyMassProps,
) = bodies.index_bundle(handle.0);
let local_com = &mprops.mass_properties.local_com;
let local_com = &mprops.local_mprops.local_com;
let min_toi = (ccd.ccd_thickness
* 0.15
@@ -272,7 +273,8 @@ impl CCDSolver {
Colliders: ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderShape>
+ ComponentSet<ColliderType>,
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>,
{
let mut frozen = HashMap::<_, Real>::default();
let mut all_toi = BinaryHeap::new();
@@ -522,10 +524,16 @@ impl CCDSolver {
// - If the intersection isn't active anymore, and it wasn't intersecting
// before, then we need to generate one interaction-start and one interaction-stop
// events because it will never be detected by the narrow-phase because of tunneling.
let (co_pos1, co_shape1): (&ColliderPosition, &ColliderShape) =
colliders.index_bundle(toi.c1.0);
let (co_pos2, co_shape2): (&ColliderPosition, &ColliderShape) =
colliders.index_bundle(toi.c2.0);
let (co_pos1, co_shape1, co_flags1): (
&ColliderPosition,
&ColliderShape,
&ColliderFlags,
) = colliders.index_bundle(toi.c1.0);
let (co_pos2, co_shape2, co_flags2): (
&ColliderPosition,
&ColliderShape,
&ColliderFlags,
) = colliders.index_bundle(toi.c2.0);
let co_next_pos1 = if let Some(b1) = toi.b1 {
let co_parent1: &ColliderParent = colliders.get(toi.c1.0).unwrap();
@@ -535,7 +543,7 @@ impl CCDSolver {
&RigidBodyMassProps,
) = bodies.index_bundle(b1.0);
let local_com1 = &rb_mprops1.mass_properties.local_com;
let local_com1 = &rb_mprops1.local_mprops.local_com;
let frozen1 = frozen.get(&b1);
let pos1 = frozen1
.map(|t| rb_vels1.integrate(*t, &rb_pos1.position, local_com1))
@@ -553,7 +561,7 @@ impl CCDSolver {
&RigidBodyMassProps,
) = bodies.index_bundle(b2.0);
let local_com2 = &rb_mprops2.mass_properties.local_com;
let local_com2 = &rb_mprops2.local_mprops.local_com;
let frozen2 = frozen.get(&b2);
let pos2 = frozen2
.map(|t| rb_vels2.integrate(*t, &rb_pos2.position, local_com2))
@@ -575,7 +583,11 @@ impl CCDSolver {
.intersection_test(&next_coll_pos12, co_shape1.as_ref(), co_shape2.as_ref())
.unwrap_or(false);
if !intersect_before && !intersect_after {
if !intersect_before
&& !intersect_after
&& (co_flags1.active_events | co_flags2.active_events)
.contains(ActiveEvents::INTERSECTION_EVENTS)
{
// Emit one intersection-started and one intersection-stopped event.
events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, true));
events.handle_intersection_event(IntersectionEvent::new(toi.c1, toi.c2, false));

View File

@@ -173,7 +173,7 @@ impl TOIEntry {
if ccd.ccd_active {
NonlinearRigidMotion::new(
poss.position,
mprops.mass_properties.local_com,
mprops.local_mprops.local_com,
vels.linvel,
vels.angvel,
)

View File

@@ -229,19 +229,17 @@ impl IslandManager {
stack: &mut Vec<RigidBodyHandle>,
) {
for collider_handle in &rb_colliders.0 {
if let Some(contacts) = narrow_phase.contacts_with(*collider_handle) {
for inter in contacts {
for manifold in &inter.2.manifolds {
if !manifold.data.solver_contacts.is_empty() {
let other = crate::utils::select_other(
(inter.0, inter.1),
*collider_handle,
);
if let Some(other_body) = colliders.get(other.0) {
stack.push(other_body.handle);
}
break;
for inter in narrow_phase.contacts_with(*collider_handle) {
for manifold in &inter.manifolds {
if !manifold.data.solver_contacts.is_empty() {
let other = crate::utils::select_other(
(inter.collider1, inter.collider2),
*collider_handle,
);
if let Some(other_body) = colliders.get(other.0) {
stack.push(other_body.handle);
}
break;
}
}
}

View File

@@ -4,8 +4,7 @@ use crate::dynamics::{
RigidBodyMassPropsFlags, RigidBodyPosition, RigidBodyType, RigidBodyVelocity,
};
use crate::geometry::{
Collider, ColliderHandle, ColliderMassProperties, ColliderParent, ColliderPosition,
ColliderShape,
Collider, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition, ColliderShape,
};
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector};
use crate::utils::{self, WCross};
@@ -48,7 +47,7 @@ impl RigidBody {
rb_ccd: RigidBodyCcd::default(),
rb_ids: RigidBodyIds::default(),
rb_colliders: RigidBodyColliders::default(),
rb_activation: RigidBodyActivation::new_active(),
rb_activation: RigidBodyActivation::active(),
changes: RigidBodyChanges::all(),
rb_type: RigidBodyType::Dynamic,
rb_dominance: RigidBodyDominance::default(),
@@ -112,7 +111,7 @@ impl RigidBody {
/// The mass properties of this rigid-body.
#[inline]
pub fn mass_properties(&self) -> &MassProperties {
&self.rb_mprops.mass_properties
&self.rb_mprops.local_mprops
}
/// The dominance group of this rigid-body.
@@ -256,7 +255,7 @@ impl RigidBody {
self.wake_up(true);
}
self.rb_mprops.mass_properties = props;
self.rb_mprops.local_mprops = props;
self.update_world_mass_properties();
}
@@ -290,7 +289,7 @@ impl RigidBody {
///
/// Returns zero if this rigid body has an infinite mass.
pub fn mass(&self) -> Real {
utils::inv(self.rb_mprops.mass_properties.inv_mass)
utils::inv(self.rb_mprops.local_mprops.inv_mass)
}
/// The predicted position of this rigid-body.
@@ -335,7 +334,7 @@ impl RigidBody {
co_parent: &ColliderParent,
co_pos: &mut ColliderPosition,
co_shape: &ColliderShape,
co_mprops: &ColliderMassProperties,
co_mprops: &ColliderMassProps,
) {
self.rb_colliders.attach_collider(
&mut self.changes,
@@ -359,7 +358,7 @@ impl RigidBody {
let mass_properties = coll
.mass_properties()
.transform_by(coll.position_wrt_parent().unwrap());
self.rb_mprops.mass_properties -= mass_properties;
self.rb_mprops.local_mprops -= mass_properties;
self.update_world_mass_properties();
}
}
@@ -463,8 +462,8 @@ impl RigidBody {
/// The translational part of this rigid-body's position.
#[inline]
pub fn translation(&self) -> Vector<Real> {
self.rb_pos.position.translation.vector
pub fn translation(&self) -> &Vector<Real> {
&self.rb_pos.position.translation.vector
}
/// Sets the translational part of this rigid-body's position.
@@ -482,8 +481,8 @@ impl RigidBody {
/// The translational part of this rigid-body's position.
#[inline]
pub fn rotation(&self) -> Rotation<Real> {
self.rb_pos.position.rotation
pub fn rotation(&self) -> &Rotation<Real> {
&self.rb_pos.position.rotation
}
/// Sets the rotational part of this rigid-body's position.
@@ -692,7 +691,7 @@ impl RigidBody {
pub fn gravitational_potential_energy(&self, dt: Real, gravity: Vector<Real>) -> Real {
let world_com = self
.rb_mprops
.mass_properties
.local_mprops
.world_com(&self.rb_pos.position)
.coords;
@@ -979,7 +978,7 @@ impl RigidBodyBuilder {
rb.rb_vels.angvel = self.angvel;
rb.rb_type = self.rb_type;
rb.user_data = self.user_data;
rb.rb_mprops.mass_properties = self.mass_properties;
rb.rb_mprops.local_mprops = self.mass_properties;
rb.rb_mprops.flags = self.mprops_flags;
rb.rb_damping.linear_damping = self.linear_damping;
rb.rb_damping.angular_damping = self.angular_damping;

View File

@@ -1,7 +1,7 @@
use crate::data::{ComponentSetMut, ComponentSetOption};
use crate::dynamics::MassProperties;
use crate::geometry::{
ColliderChanges, ColliderHandle, ColliderMassProperties, ColliderParent, ColliderPosition,
ColliderChanges, ColliderHandle, ColliderMassProps, ColliderParent, ColliderPosition,
ColliderShape, InteractionGraph, RigidBodyGraphIndex,
};
use crate::math::{AngVector, AngularInertia, Isometry, Point, Real, Translation, Vector};
@@ -166,7 +166,7 @@ impl RigidBodyPosition {
mprops: &RigidBodyMassProps,
) -> Isometry<Real> {
let new_vels = forces.integrate(dt, vels, mprops);
new_vels.integrate(dt, &self.position, &mprops.mass_properties.local_com)
new_vels.integrate(dt, &self.position, &mprops.local_mprops.local_com)
}
}
@@ -208,7 +208,7 @@ pub struct RigidBodyMassProps {
/// Flags for locking rotation and translation.
pub flags: RigidBodyMassPropsFlags,
/// The local mass properties of the rigid-body.
pub mass_properties: MassProperties,
pub local_mprops: MassProperties,
/// The world-space center of mass of the rigid-body.
pub world_com: Point<Real>,
/// The inverse mass taking into account translation locking.
@@ -222,7 +222,7 @@ impl Default for RigidBodyMassProps {
fn default() -> Self {
Self {
flags: RigidBodyMassPropsFlags::empty(),
mass_properties: MassProperties::zero(),
local_mprops: MassProperties::zero(),
world_com: Point::origin(),
effective_inv_mass: 0.0,
effective_world_inv_inertia_sqrt: AngularInertia::zero(),
@@ -239,11 +239,20 @@ impl From<RigidBodyMassPropsFlags> for RigidBodyMassProps {
}
}
impl From<MassProperties> for RigidBodyMassProps {
fn from(local_mprops: MassProperties) -> Self {
Self {
local_mprops,
..Default::default()
}
}
}
impl RigidBodyMassProps {
/// The mass of the rigid-body.
#[must_use]
pub fn mass(&self) -> Real {
crate::utils::inv(self.mass_properties.inv_mass)
crate::utils::inv(self.local_mprops.inv_mass)
}
/// The effective mass (that takes the potential translation locking into account) of
@@ -255,11 +264,10 @@ impl RigidBodyMassProps {
/// Update the world-space mass properties of `self`, taking into account the new position.
pub fn update_world_mass_properties(&mut self, position: &Isometry<Real>) {
self.world_com = self.mass_properties.world_com(&position);
self.effective_inv_mass = self.mass_properties.inv_mass;
self.effective_world_inv_inertia_sqrt = self
.mass_properties
.world_inv_inertia_sqrt(&position.rotation);
self.world_com = self.local_mprops.world_com(&position);
self.effective_inv_mass = self.local_mprops.inv_mass;
self.effective_world_inv_inertia_sqrt =
self.local_mprops.world_inv_inertia_sqrt(&position.rotation);
// Take into account translation/rotation locking.
if self
@@ -665,7 +673,7 @@ impl RigidBodyColliders {
co_pos: &mut ColliderPosition,
co_parent: &ColliderParent,
co_shape: &ColliderShape,
co_mprops: &ColliderMassProperties,
co_mprops: &ColliderMassProps,
) {
rb_changes.set(
RigidBodyChanges::MODIFIED | RigidBodyChanges::COLLIDERS,
@@ -684,7 +692,7 @@ impl RigidBodyColliders {
.mass_properties(&**co_shape)
.transform_by(&co_parent.pos_wrt_parent);
self.0.push(co_handle);
rb_mprops.mass_properties += mass_properties;
rb_mprops.local_mprops += mass_properties;
rb_mprops.update_world_mass_properties(&rb_pos.position);
}
@@ -759,7 +767,7 @@ pub struct RigidBodyActivation {
impl Default for RigidBodyActivation {
fn default() -> Self {
Self::new_active()
Self::active()
}
}
@@ -770,7 +778,7 @@ impl RigidBodyActivation {
}
/// Create a new rb_activation status initialised with the default rb_activation threshold and is active.
pub fn new_active() -> Self {
pub fn active() -> Self {
RigidBodyActivation {
threshold: Self::default_threshold(),
energy: Self::default_threshold() * 4.0,
@@ -779,7 +787,7 @@ impl RigidBodyActivation {
}
/// Create a new rb_activation status initialised with the default rb_activation threshold and is inactive.
pub fn new_inactive() -> Self {
pub fn inactive() -> Self {
RigidBodyActivation {
threshold: Self::default_threshold(),
energy: 0.0,
@@ -787,6 +795,14 @@ impl RigidBodyActivation {
}
}
/// Create a new activation status that prevents the rigid-body from sleeping.
pub fn cannot_sleep() -> Self {
RigidBodyActivation {
threshold: -Real::MAX,
..Self::active()
}
}
/// Returns `true` if the body is not asleep.
#[inline]
pub fn is_active(&self) -> bool {

View File

@@ -113,7 +113,7 @@ impl IslandSolver {
let mut new_poss = *poss;
let new_vels = vels.apply_damping(params.dt, damping);
new_poss.next_position =
vels.integrate(params.dt, &poss.position, &mprops.mass_properties.local_com);
vels.integrate(params.dt, &poss.position, &mprops.local_mprops.local_com);
bodies.set_internal(handle.0, new_vels);
bodies.set_internal(handle.0, new_poss);
@@ -140,7 +140,7 @@ impl IslandSolver {
.integrate(params.dt, vels, mprops)
.apply_damping(params.dt, &damping);
new_poss.next_position =
vels.integrate(params.dt, &poss.position, &mprops.mass_properties.local_com);
vels.integrate(params.dt, &poss.position, &mprops.local_mprops.local_com);
bodies.set_internal(handle.0, new_vels);
bodies.set_internal(handle.0, new_poss);

View File

@@ -34,8 +34,8 @@ impl BallPositionConstraint {
let (mprops2, ids2) = rb2;
Self {
local_com1: mprops1.mass_properties.local_com,
local_com2: mprops2.mass_properties.local_com,
local_com1: mprops1.local_mprops.local_com,
local_com2: mprops2.local_mprops.local_com,
im1: mprops1.effective_inv_mass,
im2: mprops2.effective_inv_mass,
ii1: mprops1.effective_world_inv_inertia_sqrt.squared(),
@@ -131,7 +131,7 @@ impl BallPositionGroundConstraint {
ii2: mprops2.effective_world_inv_inertia_sqrt.squared(),
local_anchor2: cparams.local_anchor1,
position2: ids2.active_set_offset,
local_com2: mprops2.mass_properties.local_com,
local_com2: mprops2.local_mprops.local_com,
}
} else {
Self {
@@ -140,7 +140,7 @@ impl BallPositionGroundConstraint {
ii2: mprops2.effective_world_inv_inertia_sqrt.squared(),
local_anchor2: cparams.local_anchor2,
position2: ids2.active_set_offset,
local_com2: mprops2.mass_properties.local_com,
local_com2: mprops2.local_mprops.local_com,
}
}
}

View File

@@ -40,8 +40,8 @@ impl WBallPositionConstraint {
let (mprops1, ids1) = rbs1;
let (mprops2, ids2) = rbs2;
let local_com1 = Point::from(gather![|ii| mprops1[ii].mass_properties.local_com]);
let local_com2 = Point::from(gather![|ii| mprops2[ii].mass_properties.local_com]);
let local_com1 = Point::from(gather![|ii| mprops1[ii].local_mprops.local_com]);
let local_com2 = Point::from(gather![|ii| mprops2[ii].local_mprops.local_com]);
let im1 = SimdReal::from(gather![|ii| mprops1[ii].effective_inv_mass]);
let im2 = SimdReal::from(gather![|ii| mprops2[ii].effective_inv_mass]);
let ii1 = AngularInertia::<SimdReal>::from(gather![
@@ -169,7 +169,7 @@ impl WBallPositionGroundConstraint {
cparams[ii].local_anchor2
}]);
let position2 = gather![|ii| ids2[ii].active_set_offset];
let local_com2 = Point::from(gather![|ii| mprops2[ii].mass_properties.local_com]);
let local_com2 = Point::from(gather![|ii| mprops2[ii].local_mprops.local_com]);
Self {
anchor1,

View File

@@ -46,8 +46,8 @@ impl FixedPositionConstraint {
im2,
ii1,
ii2,
local_com1: mprops1.mass_properties.local_com,
local_com2: mprops2.mass_properties.local_com,
local_com1: mprops1.local_mprops.local_com,
local_com2: mprops2.local_mprops.local_com,
lin_inv_lhs,
ang_inv_lhs,
}
@@ -125,7 +125,7 @@ impl FixedPositionGroundConstraint {
position2: ids2.active_set_offset,
im2: mprops2.effective_inv_mass,
ii2: mprops2.effective_world_inv_inertia_sqrt.squared(),
local_com2: mprops2.mass_properties.local_com,
local_com2: mprops2.local_mprops.local_com,
impulse: 0.0,
}
}

View File

@@ -41,8 +41,8 @@ impl GenericPositionConstraint {
im2,
ii1,
ii2,
local_com1: rb1.mass_properties.local_com,
local_com2: rb2.mass_properties.local_com,
local_com1: rb1.local_mprops.local_com,
local_com2: rb2.local_mprops.local_com,
joint: *joint,
}
}
@@ -215,7 +215,7 @@ impl GenericPositionGroundConstraint {
position2: rb2.active_set_offset,
im2: rb2.effective_inv_mass,
ii2: rb2.effective_world_inv_inertia_sqrt.squared(),
local_com2: rb2.mass_properties.local_com,
local_com2: rb2.local_mprops.local_com,
joint: *joint,
}
}

View File

@@ -51,8 +51,8 @@ impl RevolutePositionConstraint {
ii1,
ii2,
ang_inv_lhs,
local_com1: mprops1.mass_properties.local_com,
local_com2: mprops2.mass_properties.local_com,
local_com1: mprops1.local_mprops.local_com,
local_com2: mprops2.local_mprops.local_com,
local_anchor1: cparams.local_anchor1,
local_anchor2: cparams.local_anchor2,
local_axis1: cparams.local_axis1,
@@ -183,7 +183,7 @@ impl RevolutePositionGroundConstraint {
local_anchor2,
im2: mprops2.effective_inv_mass,
ii2: mprops2.effective_world_inv_inertia_sqrt.squared(),
local_com2: mprops2.mass_properties.local_com,
local_com2: mprops2.local_mprops.local_com,
axis1,
local_axis2,
position2: ids2.active_set_offset,

View File

@@ -392,7 +392,7 @@ impl ParallelIslandSolver {
let new_rb_vels = new_rb_vels.apply_damping(params.dt, rb_damping);
new_rb_pos.next_position =
new_rb_vels.integrate(params.dt, &rb_pos.position, &rb_mprops.mass_properties.local_com);
new_rb_vels.integrate(params.dt, &rb_pos.position, &rb_mprops.local_mprops.local_com);
bodies.set_internal(handle.0, new_rb_vels);
bodies.set_internal(handle.0, new_rb_pos);

View File

@@ -1,12 +1,12 @@
use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
use crate::geometry::{
ColliderBroadPhaseData, ColliderChanges, ColliderGroups, ColliderMassProperties,
ColliderBroadPhaseData, ColliderChanges, ColliderFlags, ColliderGroups, ColliderMassProps,
ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType,
InteractionGroups, SharedShape,
};
use crate::math::{AngVector, Isometry, Point, Real, Rotation, Vector, DIM};
use crate::parry::transformation::vhacd::VHACDParameters;
use crate::pipeline::PhysicsHooksFlags;
use crate::pipeline::{ActiveEvents, ActiveHooks};
use na::Unit;
use parry::bounding_volume::AABB;
use parry::shape::Shape;
@@ -19,11 +19,12 @@ use parry::shape::Shape;
pub struct Collider {
pub(crate) co_type: ColliderType,
pub(crate) co_shape: ColliderShape,
pub(crate) co_mprops: ColliderMassProperties,
pub(crate) co_mprops: ColliderMassProps,
pub(crate) co_changes: ColliderChanges,
pub(crate) co_parent: Option<ColliderParent>,
pub(crate) co_pos: ColliderPosition,
pub(crate) co_material: ColliderMaterial,
pub(crate) co_flags: ColliderFlags,
pub(crate) co_groups: ColliderGroups,
pub(crate) co_bf_data: ColliderBroadPhaseData,
/// User-defined data associated to this rigid-body.
@@ -48,13 +49,23 @@ impl Collider {
}
/// The physics hooks enabled for this collider.
pub fn active_hooks(&self) -> PhysicsHooksFlags {
self.co_material.active_hooks
pub fn active_hooks(&self) -> ActiveHooks {
self.co_flags.active_hooks
}
/// Sets the physics hooks enabled for this collider.
pub fn set_active_hooks(&mut self, active_hooks: PhysicsHooksFlags) {
self.co_material.active_hooks = active_hooks;
pub fn set_active_hooks(&mut self, active_hooks: ActiveHooks) {
self.co_flags.active_hooks = active_hooks;
}
/// The physics hooks enabled for this collider.
pub fn active_events(&self) -> ActiveEvents {
self.co_flags.active_events
}
/// Sets the physics hooks enabled for this collider.
pub fn set_active_events(&mut self, active_events: ActiveEvents) {
self.co_flags.active_events = active_events;
}
/// The friction coefficient of this collider.
@@ -201,8 +212,8 @@ impl Collider {
/// The density of this collider, if set.
pub fn density(&self) -> Option<Real> {
match &self.co_mprops {
ColliderMassProperties::Density(density) => Some(*density),
ColliderMassProperties::MassProperties(_) => None,
ColliderMassProps::Density(density) => Some(*density),
ColliderMassProps::MassProperties(_) => None,
}
}
@@ -242,8 +253,8 @@ impl Collider {
/// Compute the local-space mass properties of this collider.
pub fn mass_properties(&self) -> MassProperties {
match &self.co_mprops {
ColliderMassProperties::Density(density) => self.co_shape.mass_properties(*density),
ColliderMassProperties::MassProperties(mass_properties) => **mass_properties,
ColliderMassProps::Density(density) => self.co_shape.mass_properties(*density),
ColliderMassProps::MassProperties(mass_properties) => **mass_properties,
}
}
}
@@ -272,7 +283,9 @@ pub struct ColliderBuilder {
/// Is this collider a sensor?
pub is_sensor: bool,
/// Physics hooks enabled for this collider.
pub active_hooks: PhysicsHooksFlags,
pub active_hooks: ActiveHooks,
/// Events enabled for this collider.
pub active_events: ActiveEvents,
/// The user-data of the collider being built.
pub user_data: u128,
/// The collision groups for the collider being built.
@@ -297,7 +310,8 @@ impl ColliderBuilder {
solver_groups: InteractionGroups::all(),
friction_combine_rule: CoefficientCombineRule::Average,
restitution_combine_rule: CoefficientCombineRule::Average,
active_hooks: PhysicsHooksFlags::empty(),
active_hooks: ActiveHooks::empty(),
active_events: ActiveEvents::empty(),
}
}
@@ -581,11 +595,17 @@ impl ColliderBuilder {
}
/// The set of physics hooks enabled for this collider.
pub fn active_hooks(mut self, active_hooks: PhysicsHooksFlags) -> Self {
pub fn active_hooks(mut self, active_hooks: ActiveHooks) -> Self {
self.active_hooks = active_hooks;
self
}
/// The set of events enabled for this collider.
pub fn active_events(mut self, active_events: ActiveEvents) -> Self {
self.active_events = active_events;
self
}
/// Sets the friction coefficient of the collider this builder will build.
pub fn friction(mut self, friction: Real) -> Self {
self.friction = friction;
@@ -672,12 +692,22 @@ impl ColliderBuilder {
/// Builds a new collider attached to the given rigid-body.
pub fn build(&self) -> Collider {
let (co_changes, co_pos, co_bf_data, co_shape, co_type, co_groups, co_material, co_mprops) =
self.components();
let (
co_changes,
co_pos,
co_bf_data,
co_shape,
co_type,
co_groups,
co_material,
co_flags,
co_mprops,
) = self.components();
Collider {
co_shape,
co_mprops,
co_material,
co_flags,
co_parent: None,
co_changes,
co_pos,
@@ -699,14 +729,15 @@ impl ColliderBuilder {
ColliderType,
ColliderGroups,
ColliderMaterial,
ColliderMassProperties,
ColliderFlags,
ColliderMassProps,
) {
let mass_info = if let Some(mp) = self.mass_properties {
ColliderMassProperties::MassProperties(Box::new(mp))
ColliderMassProps::MassProperties(Box::new(mp))
} else {
let default_density = Self::default_density();
let density = self.density.unwrap_or(default_density);
ColliderMassProperties::Density(density)
ColliderMassProps::Density(density)
};
let co_shape = self.shape.clone();
@@ -716,7 +747,10 @@ impl ColliderBuilder {
restitution: self.restitution,
friction_combine_rule: self.friction_combine_rule,
restitution_combine_rule: self.restitution_combine_rule,
};
let co_flags = ColliderFlags {
active_hooks: self.active_hooks,
active_events: self.active_events,
};
let co_changes = ColliderChanges::all();
let co_pos = ColliderPosition(self.position);
@@ -739,6 +773,7 @@ impl ColliderBuilder {
co_type,
co_groups,
co_material,
co_flags,
co_mprops,
)
}

View File

@@ -2,7 +2,7 @@ use crate::dynamics::{CoefficientCombineRule, MassProperties, RigidBodyHandle};
use crate::geometry::{InteractionGroups, SAPProxyIndex, Shape, SharedShape};
use crate::math::{Isometry, Real};
use crate::parry::partitioning::IndexedData;
use crate::pipeline::PhysicsHooksFlags;
use crate::pipeline::{ActiveEvents, ActiveHooks};
use std::ops::Deref;
/// The unique identifier of a collider added to a collider set.
@@ -118,7 +118,7 @@ pub type ColliderShape = SharedShape;
#[derive(Clone)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
/// The mass-properties of a collider.
pub enum ColliderMassProperties {
pub enum ColliderMassProps {
/// The collider is given a density.
///
/// Its actual `MassProperties` are computed automatically with
@@ -128,13 +128,19 @@ pub enum ColliderMassProperties {
MassProperties(Box<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
@@ -242,8 +248,6 @@ pub struct ColliderMaterial {
pub friction_combine_rule: CoefficientCombineRule,
/// The rule applied to combine the restitution coefficients of two colliders.
pub restitution_combine_rule: CoefficientCombineRule,
/// The physics hooks enabled for contact pairs and intersection pairs involving this collider.
pub active_hooks: PhysicsHooksFlags,
}
impl ColliderMaterial {
@@ -264,7 +268,43 @@ impl Default for ColliderMaterial {
restitution: 0.0,
friction_combine_rule: CoefficientCombineRule::default(),
restitution_combine_rule: CoefficientCombineRule::default(),
active_hooks: PhysicsHooksFlags::empty(),
}
}
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
/// A set of flags controlling the active hooks and events for this colliders.
pub struct ColliderFlags {
/// The physics hooks enabled for contact pairs and intersection pairs involving this collider.
pub active_hooks: ActiveHooks,
/// The events enabled for this collider.
pub active_events: ActiveEvents,
}
impl Default for ColliderFlags {
fn default() -> Self {
Self {
active_hooks: ActiveHooks::empty(),
active_events: ActiveEvents::empty(),
}
}
}
impl From<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()
}
}
}

View File

@@ -2,8 +2,8 @@ use crate::data::arena::Arena;
use crate::data::{ComponentSet, ComponentSetMut, ComponentSetOption};
use crate::dynamics::{IslandManager, RigidBodyHandle, RigidBodySet};
use crate::geometry::{
Collider, ColliderBroadPhaseData, ColliderGroups, ColliderMassProperties, ColliderMaterial,
ColliderParent, ColliderPosition, ColliderShape, ColliderType,
Collider, ColliderBroadPhaseData, ColliderFlags, ColliderGroups, ColliderMassProps,
ColliderMaterial, ColliderParent, ColliderPosition, ColliderShape, ColliderType,
};
use crate::geometry::{ColliderChanges, ColliderHandle};
use std::ops::{Index, IndexMut};
@@ -59,10 +59,11 @@ macro_rules! impl_field_component_set(
impl_field_component_set!(ColliderType, co_type);
impl_field_component_set!(ColliderShape, co_shape);
impl_field_component_set!(ColliderMassProperties, co_mprops);
impl_field_component_set!(ColliderMassProps, co_mprops);
impl_field_component_set!(ColliderChanges, co_changes);
impl_field_component_set!(ColliderPosition, co_pos);
impl_field_component_set!(ColliderMaterial, co_material);
impl_field_component_set!(ColliderFlags, co_flags);
impl_field_component_set!(ColliderGroups, co_groups);
impl_field_component_set!(ColliderBroadPhaseData, co_bf_data);

View File

@@ -14,8 +14,10 @@ use crate::geometry::{
};
use crate::math::{Real, Vector};
use crate::pipeline::{
ContactModificationContext, EventHandler, PairFilterContext, PhysicsHooks, PhysicsHooksFlags,
ActiveEvents, ActiveHooks, ContactModificationContext, EventHandler, PairFilterContext,
PhysicsHooks,
};
use crate::prelude::ColliderFlags;
use parry::query::{DefaultQueryDispatcher, PersistentQueryDispatcher};
use parry::utils::IsometryOpt;
use std::collections::HashMap;
@@ -101,21 +103,26 @@ impl NarrowPhase {
///
/// It is strongly recommended to use the [`NarrowPhase::contacts_with`] method instead. This
/// method can be used if the generation number of the collider handle isn't known.
pub fn contacts_with_unknown_gen(
&self,
collider: u32,
) -> Option<impl Iterator<Item = (ColliderHandle, ColliderHandle, &ContactPair)>> {
let id = self.graph_indices.get_unknown_gen(collider)?;
Some(self.contact_graph.interactions_with(id.contact_graph_index))
pub fn contacts_with_unknown_gen(&self, collider: u32) -> impl Iterator<Item = &ContactPair> {
self.graph_indices
.get_unknown_gen(collider)
.map(|id| id.contact_graph_index)
.into_iter()
.flat_map(move |id| self.contact_graph.interactions_with(id))
.map(|pair| pair.2)
}
/// All the contacts involving the given collider.
pub fn contacts_with(
pub fn contacts_with<'a>(
&self,
collider: ColliderHandle,
) -> Option<impl Iterator<Item = (ColliderHandle, ColliderHandle, &ContactPair)>> {
let id = self.graph_indices.get(collider.0)?;
Some(self.contact_graph.interactions_with(id.contact_graph_index))
) -> impl Iterator<Item = &ContactPair> {
self.graph_indices
.get(collider.0)
.map(|id| id.contact_graph_index)
.into_iter()
.flat_map(move |id| self.contact_graph.interactions_with(id))
.map(|pair| pair.2)
}
/// All the intersections involving the given collider.
@@ -125,26 +132,32 @@ impl NarrowPhase {
pub fn intersections_with_unknown_gen(
&self,
collider: u32,
) -> Option<impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_> {
let id = self.graph_indices.get_unknown_gen(collider)?;
Some(
self.intersection_graph
.interactions_with(id.intersection_graph_index)
.map(|e| (e.0, e.1, *e.2)),
)
) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
self.graph_indices
.get_unknown_gen(collider)
.map(|id| id.intersection_graph_index)
.into_iter()
.flat_map(move |id| {
self.intersection_graph
.interactions_with(id)
.map(|e| (e.0, e.1, *e.2))
})
}
/// All the intersections involving the given collider.
pub fn intersections_with(
&self,
collider: ColliderHandle,
) -> Option<impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_> {
let id = self.graph_indices.get(collider.0)?;
Some(
self.intersection_graph
.interactions_with(id.intersection_graph_index)
.map(|e| (e.0, e.1, *e.2)),
)
) -> impl Iterator<Item = (ColliderHandle, ColliderHandle, bool)> + '_ {
self.graph_indices
.get(collider.0)
.map(|id| id.intersection_graph_index)
.into_iter()
.flat_map(move |id| {
self.intersection_graph
.interactions_with(id)
.map(|e| (e.0, e.1, *e.2))
})
}
/// The contact pair involving two specific colliders.
@@ -244,8 +257,9 @@ impl NarrowPhase {
+ ComponentSet<RigidBodyType>
+ ComponentSetMut<RigidBodyIds>,
Colliders: ComponentSet<ColliderChanges>
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>,
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>
+ ComponentSetOption<ColliderParent>,
{
// TODO: avoid these hash-maps.
// They are necessary to handle the swap-remove done internally
@@ -340,8 +354,9 @@ impl NarrowPhase {
+ ComponentSet<RigidBodyType>
+ ComponentSetMut<RigidBodyIds>,
Colliders: ComponentSet<ColliderChanges>
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>,
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>
+ ComponentSetOption<ColliderParent>,
{
let mut pairs_to_remove = vec![];
@@ -456,7 +471,9 @@ impl NarrowPhase {
Bodies: ComponentSetMut<RigidBodyActivation>
+ ComponentSet<RigidBodyType>
+ ComponentSetMut<RigidBodyIds>,
Colliders: ComponentSet<ColliderType> + ComponentSetOption<ColliderParent>,
Colliders: ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>
+ ComponentSetOption<ColliderParent>,
{
let co_type1: Option<&ColliderType> = colliders.get(pair.collider1.0);
let co_type2: Option<&ColliderType> = colliders.get(pair.collider2.0);
@@ -478,9 +495,16 @@ impl NarrowPhase {
// Emit an intersection lost event if we had an intersection before removing the edge.
if Some(true) == was_intersecting {
let prox_event =
IntersectionEvent::new(pair.collider1, pair.collider2, false);
events.handle_intersection_event(prox_event)
let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0);
let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0);
if (co_flag1.active_events | co_flag2.active_events)
.contains(ActiveEvents::INTERSECTION_EVENTS)
{
let prox_event =
IntersectionEvent::new(pair.collider1, pair.collider2, false);
events.handle_intersection_event(prox_event)
}
}
} else {
let contact_pair = self
@@ -506,10 +530,17 @@ impl NarrowPhase {
}
}
events.handle_contact_event(ContactEvent::Stopped(
pair.collider1,
pair.collider2,
))
let co_flag1: &ColliderFlags = colliders.index(pair.collider1.0);
let co_flag2: &ColliderFlags = colliders.index(pair.collider2.0);
if (co_flag1.active_events | co_flag2.active_events)
.contains(ActiveEvents::CONTACT_EVENTS)
{
events.handle_contact_event(
ContactEvent::Stopped(pair.collider1, pair.collider2),
&ctct,
)
}
}
}
}
@@ -606,9 +637,11 @@ impl NarrowPhase {
events: &dyn EventHandler,
) where
Bodies: ComponentSetMut<RigidBodyActivation>
+ ComponentSet<RigidBodyType>
+ ComponentSetMut<RigidBodyIds>,
Colliders: ComponentSet<ColliderType> + ComponentSetOption<ColliderParent>,
+ ComponentSetMut<RigidBodyIds>
+ ComponentSet<RigidBodyType>,
Colliders: ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>
+ ComponentSetOption<ColliderParent>,
{
for event in broad_phase_events {
match event {
@@ -645,7 +678,8 @@ impl NarrowPhase {
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderShape>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
if modified_colliders.is_empty() {
return;
@@ -660,21 +694,21 @@ impl NarrowPhase {
let handle2 = nodes[edge.target().index()].weight;
let co_parent1: Option<&ColliderParent> = colliders.get(handle1.0);
let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1): (
let (co_changes1, co_groups1, co_shape1, co_pos1, co_flags1): (
&ColliderChanges,
&ColliderGroups,
&ColliderShape,
&ColliderPosition,
&ColliderMaterial,
&ColliderFlags,
) = colliders.index_bundle(handle1.0);
let co_parent2: Option<&ColliderParent> = colliders.get(handle2.0);
let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2): (
let (co_changes2, co_groups2, co_shape2, co_pos2, co_flags2): (
&ColliderChanges,
&ColliderGroups,
&ColliderShape,
&ColliderPosition,
&ColliderMaterial,
&ColliderFlags,
) = colliders.index_bundle(handle2.0);
if !co_changes1.needs_narrow_phase_update() && !co_changes2.needs_narrow_phase_update()
@@ -717,9 +751,10 @@ impl NarrowPhase {
return;
}
let active_hooks = co_material1.active_hooks | co_material2.active_hooks;
let active_hooks = co_flags1.active_hooks | co_flags2.active_hooks;
let active_events = co_flags1.active_events | co_flags2.active_events;
if !active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR)
if !active_hooks.contains(ActiveHooks::FILTER_INTERSECTION_PAIR)
&& !status1.is_dynamic()
&& !status2.is_dynamic()
{
@@ -727,7 +762,7 @@ impl NarrowPhase {
return;
}
if active_hooks.contains(PhysicsHooksFlags::FILTER_INTERSECTION_PAIR) {
if active_hooks.contains(ActiveHooks::FILTER_INTERSECTION_PAIR) {
let context = PairFilterContext {
bodies,
colliders,
@@ -748,7 +783,9 @@ impl NarrowPhase {
if let Ok(intersection) =
query_dispatcher.intersection_test(&pos12, &**co_shape1, &**co_shape2)
{
if intersection != edge.weight {
if active_events.contains(ActiveEvents::INTERSECTION_EVENTS)
&& intersection != edge.weight
{
edge.weight = intersection;
events.handle_intersection_event(IntersectionEvent::new(
handle1,
@@ -777,7 +814,8 @@ impl NarrowPhase {
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderShape>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
if modified_colliders.is_empty() {
return;
@@ -790,21 +828,23 @@ impl NarrowPhase {
let pair = &mut edge.weight;
let co_parent1: Option<&ColliderParent> = colliders.get(pair.collider1.0);
let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1): (
let (co_changes1, co_groups1, co_shape1, co_pos1, co_material1, co_flags1): (
&ColliderChanges,
&ColliderGroups,
&ColliderShape,
&ColliderPosition,
&ColliderMaterial,
&ColliderFlags,
) = colliders.index_bundle(pair.collider1.0);
let co_parent2: Option<&ColliderParent> = colliders.get(pair.collider2.0);
let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2): (
let (co_changes2, co_groups2, co_shape2, co_pos2, co_material2, co_flags2): (
&ColliderChanges,
&ColliderGroups,
&ColliderShape,
&ColliderPosition,
&ColliderMaterial,
&ColliderFlags,
) = colliders.index_bundle(pair.collider2.0);
if !co_changes1.needs_narrow_phase_update() && !co_changes2.needs_narrow_phase_update()
@@ -847,8 +887,10 @@ impl NarrowPhase {
return;
}
let active_hooks = co_material1.active_hooks | co_material2.active_hooks;
if !active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR)
let active_hooks = co_flags1.active_hooks | co_flags2.active_hooks;
let active_events = co_flags1.active_events | co_flags2.active_events;
if !active_hooks.contains(ActiveHooks::FILTER_CONTACT_PAIRS)
&& !status1.is_dynamic()
&& !status2.is_dynamic()
{
@@ -856,8 +898,7 @@ impl NarrowPhase {
return;
}
let mut solver_flags = if active_hooks.contains(PhysicsHooksFlags::FILTER_CONTACT_PAIR)
{
let mut solver_flags = if active_hooks.contains(ActiveHooks::FILTER_CONTACT_PAIRS) {
let context = PairFilterContext {
bodies,
colliders,
@@ -959,7 +1000,7 @@ impl NarrowPhase {
}
// Apply the user-defined contact modification.
if active_hooks.contains(PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS) {
if active_hooks.contains(ActiveHooks::MODIFY_SOLVER_CONTACTS) {
let mut modifiable_solver_contacts =
std::mem::replace(&mut manifold.data.solver_contacts, Vec::new());
let mut modifiable_user_data = manifold.data.user_data;
@@ -987,16 +1028,18 @@ impl NarrowPhase {
}
if has_any_active_contact != pair.has_any_active_contact {
if has_any_active_contact {
events.handle_contact_event(ContactEvent::Started(
pair.collider1,
pair.collider2,
));
} else {
events.handle_contact_event(ContactEvent::Stopped(
pair.collider1,
pair.collider2,
));
if active_events.contains(ActiveEvents::CONTACT_EVENTS) {
if has_any_active_contact {
events.handle_contact_event(
ContactEvent::Started(pair.collider1, pair.collider2),
pair,
);
} else {
events.handle_contact_event(
ContactEvent::Stopped(pair.collider1, pair.collider2),
pair,
);
}
}
pair.has_any_active_contact = has_any_active_contact;

View File

@@ -6,9 +6,9 @@ use crate::dynamics::{
RigidBodyIds, RigidBodyPosition, RigidBodyType, RigidBodyVelocity,
};
use crate::geometry::{
BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups,
ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition,
ColliderShape, ColliderType, NarrowPhase,
BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags,
ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent,
ColliderPosition, ColliderShape, ColliderType, NarrowPhase,
};
use crate::math::Real;
use crate::pipeline::{EventHandler, PhysicsHooks};
@@ -66,7 +66,8 @@ impl CollisionPipeline {
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
// Update broad-phase.
self.broad_phase_events.clear();
@@ -173,7 +174,8 @@ impl CollisionPipeline {
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
super::user_changes::handle_user_changes_to_colliders(
bodies,

View File

@@ -1,6 +1,23 @@
use crate::geometry::{ContactEvent, IntersectionEvent};
use crate::geometry::{ContactEvent, ContactPair, IntersectionEvent};
use crossbeam::channel::Sender;
bitflags::bitflags! {
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
/// Flags affecting the behavior of the constraints solver for a given contact manifold.
pub struct ActiveEvents: u32 {
/// If set, Rapier will call `PhysicsHooks::FILTER_CONTACT_PAIRS` whenever relevant.
const INTERSECTION_EVENTS = 0b0001;
/// If set, Rapier will call `PhysicsHooks::filter_intersection_pair` whenever relevant.
const CONTACT_EVENTS = 0b0010;
}
}
impl Default for ActiveEvents {
fn default() -> Self {
ActiveEvents::empty()
}
}
/// Trait implemented by structures responsible for handling events generated by the physics engine.
///
/// Implementors of this trait will typically collect these events for future processing.
@@ -13,12 +30,12 @@ pub trait EventHandler: Send + Sync {
///
/// A contact event is emitted when two collider start or stop touching, independently from the
/// number of contact points involved.
fn handle_contact_event(&self, event: ContactEvent);
fn handle_contact_event(&self, event: ContactEvent, contact_pair: &ContactPair);
}
impl EventHandler for () {
fn handle_intersection_event(&self, _event: IntersectionEvent) {}
fn handle_contact_event(&self, _event: ContactEvent) {}
fn handle_contact_event(&self, _event: ContactEvent, _contact_pair: &ContactPair) {}
}
/// A physics event handler that collects events into a crossbeam channel.
@@ -45,7 +62,7 @@ impl EventHandler for ChannelEventCollector {
let _ = self.intersection_event_sender.send(event);
}
fn handle_contact_event(&self, event: ContactEvent) {
fn handle_contact_event(&self, event: ContactEvent, _: &ContactPair) {
let _ = self.contact_event_sender.send(event);
}
}

View File

@@ -1,10 +1,8 @@
//! Structure for combining the various physics components to perform an actual simulation.
pub use collision_pipeline::CollisionPipeline;
pub use event_handler::{ChannelEventCollector, EventHandler};
pub use physics_hooks::{
ContactModificationContext, PairFilterContext, PhysicsHooks, PhysicsHooksFlags,
};
pub use event_handler::{ActiveEvents, ChannelEventCollector, EventHandler};
pub use physics_hooks::{ActiveHooks, ContactModificationContext, PairFilterContext, PhysicsHooks};
pub use physics_pipeline::PhysicsPipeline;
pub use query_pipeline::{QueryPipeline, QueryPipelineMode};

View File

@@ -118,24 +118,23 @@ impl<'a, Bodies, Colliders> ContactModificationContext<'a, Bodies, Colliders> {
bitflags::bitflags! {
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
/// Flags affecting the behavior of the constraints solver for a given contact manifold.
pub struct PhysicsHooksFlags: u32 {
pub struct ActiveHooks: u32 {
/// If set, Rapier will call `PhysicsHooks::filter_contact_pair` whenever relevant.
const FILTER_CONTACT_PAIR = 0b0001;
const FILTER_CONTACT_PAIRS = 0b0001;
/// If set, Rapier will call `PhysicsHooks::filter_intersection_pair` whenever relevant.
const FILTER_INTERSECTION_PAIR = 0b0010;
/// If set, Rapier will call `PhysicsHooks::modify_solver_contact` whenever relevant.
const MODIFY_SOLVER_CONTACTS = 0b0100;
}
}
impl Default for PhysicsHooksFlags {
impl Default for ActiveHooks {
fn default() -> Self {
PhysicsHooksFlags::empty()
ActiveHooks::empty()
}
}
#[cfg(target_arch = "wasm32")]
pub trait PhysicsHooks<Bodies, Colliders> {
fn active_hooks(&self) -> PhysicsHooksFlags;
fn filter_contact_pair(
&self,
_context: &PairFilterContext<Bodies, Colliders>,
@@ -155,7 +154,7 @@ pub trait PhysicsHooks<Bodies, Colliders>: Send + Sync {
/// Applies the contact pair filter.
///
/// Note that this method will only be called if at least one of the colliders
/// involved in the contact contains the `PhysicsHooksFlags::FILTER_CONTACT_PAIR` flags
/// involved in the contact contains the `ActiveHooks::FILTER_CONTACT_PAIRS` flags
/// in its physics hooks flags.
///
/// User-defined filter for potential contact pairs detected by the broad-phase.
@@ -186,7 +185,7 @@ pub trait PhysicsHooks<Bodies, Colliders>: Send + Sync {
/// Applies the intersection pair filter.
///
/// Note that this method will only be called if at least one of the colliders
/// involved in the contact contains the `PhysicsHooksFlags::FILTER_INTERSECTION_PAIR` flags
/// involved in the contact contains the `ActiveHooks::FILTER_INTERSECTION_PAIR` flags
/// in its physics hooks flags.
///
/// User-defined filter for potential intersection pairs detected by the broad-phase.
@@ -210,7 +209,7 @@ pub trait PhysicsHooks<Bodies, Colliders>: Send + Sync {
/// Modifies the set of contacts seen by the constraints solver.
///
/// Note that this method will only be called if at least one of the colliders
/// involved in the contact contains the `PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS` flags
/// involved in the contact contains the `ActiveHooks::MODIFY_SOLVER_CONTACTS` flags
/// in its physics hooks flags.
///
/// By default, the content of `solver_contacts` is computed from `manifold.points`.
@@ -237,7 +236,10 @@ pub trait PhysicsHooks<Bodies, Colliders>: Send + Sync {
}
impl<Bodies, Colliders> PhysicsHooks<Bodies, Colliders> for () {
fn filter_contact_pair(&self, _: &PairFilterContext<Bodies, Colliders>) -> Option<SolverFlags> {
fn filter_contact_pair(
&self,
_context: &PairFilterContext<Bodies, Colliders>,
) -> Option<SolverFlags> {
Some(SolverFlags::default())
}

View File

@@ -13,9 +13,9 @@ use crate::dynamics::{
#[cfg(feature = "parallel")]
use crate::dynamics::{JointGraphEdge, ParallelIslandSolver as IslandSolver};
use crate::geometry::{
BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderGroups,
ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent, ColliderPosition,
ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase,
BroadPhase, BroadPhasePairEvent, ColliderBroadPhaseData, ColliderChanges, ColliderFlags,
ColliderGroups, ColliderHandle, ColliderMaterial, ColliderPair, ColliderParent,
ColliderPosition, ColliderShape, ColliderType, ContactManifoldIndex, NarrowPhase,
};
use crate::math::{Real, Vector};
use crate::pipeline::{EventHandler, PhysicsHooks};
@@ -104,7 +104,8 @@ impl PhysicsPipeline {
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
self.counters.stages.collision_detection_time.resume();
self.counters.cd.broad_phase_time.resume();
@@ -365,7 +366,8 @@ impl PhysicsPipeline {
Colliders: ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderPosition>
+ ComponentSet<ColliderShape>
+ ComponentSet<ColliderType>,
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderFlags>,
{
self.counters.ccd.toi_computation_time.start();
// Handle CCD
@@ -520,7 +522,8 @@ impl PhysicsPipeline {
+ ComponentSetOption<ColliderParent>
+ ComponentSet<ColliderType>
+ ComponentSet<ColliderGroups>
+ ComponentSet<ColliderMaterial>,
+ ComponentSet<ColliderMaterial>
+ ComponentSet<ColliderFlags>,
{
self.counters.reset();
self.counters.step_started();