Skip to content

Commit 0db7c72

Browse files
committed
Implement interaction groups test mode and cofficient combine rule
update fix docs cargo format fix update feedback update Update CHANGELOG.md ignore line for error docs fix update
1 parent 76357e3 commit 0db7c72

7 files changed

Lines changed: 78 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88

99
### Added
1010

11+
- `InteractionTestMode`: Specifies which method should be used to test interactions. Supports `AND` and `OR`.
12+
- `CoefficientCombineRule::Sum` - Adds the two coefficients and does a clamp to have at most 1.
1113
- `RigidBodySet` and `ColliderSet` have a new constructor `with_capacity`.
1214

1315
### Modified
1416

1517
- `InteractionGroups` default value for `memberships` is now `GROUP_1` (#706)
1618
- `ImpulseJointSet::get_mut` has a new parameter `wake_up: bool`, to wake up connected bodies.
19+
- `InteractionGroups` struct now contains `InteractionTestMode`. Continues [rapier/pull/170](https://github.com/dimforge/rapier/pull/170) for [rapier/issues/622](https://github.com/dimforge/rapier/issues/622)
20+
- `InteractionGroups` constructor now requires an `InteractionTestMode` parameter. If you want same behaviour as before, use `InteractionTestMode::AND` (eg. `InteractionGroups::new(Group::GROUP_1, Group::GROUP_1, InteractionTestMode::AND)`)
21+
- `CoefficientCombineRule::Min` - now makes sure it uses a non zero value as result by using `coeff1.min(coeff2).abs()`
1722

1823
## v0.22.0 (20 July 2024)
1924

examples2d/collision_groups2.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ pub fn init_world(testbed: &mut Testbed) {
2424
/*
2525
* Setup groups
2626
*/
27-
const GREEN_GROUP: InteractionGroups = InteractionGroups::new(Group::GROUP_1, Group::GROUP_1);
28-
const BLUE_GROUP: InteractionGroups = InteractionGroups::new(Group::GROUP_2, Group::GROUP_2);
27+
const GREEN_GROUP: InteractionGroups =
28+
InteractionGroups::new(Group::GROUP_1, Group::GROUP_1, InteractionTestMode::AND);
29+
const BLUE_GROUP: InteractionGroups =
30+
InteractionGroups::new(Group::GROUP_2, Group::GROUP_2, InteractionTestMode::AND);
2931

3032
/*
3133
* A green floor that will collide with the GREEN group only.

examples3d/collision_groups3.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ pub fn init_world(testbed: &mut Testbed) {
2424
/*
2525
* Setup groups
2626
*/
27-
const GREEN_GROUP: InteractionGroups = InteractionGroups::new(Group::GROUP_1, Group::GROUP_1);
28-
const BLUE_GROUP: InteractionGroups = InteractionGroups::new(Group::GROUP_2, Group::GROUP_2);
27+
const GREEN_GROUP: InteractionGroups =
28+
InteractionGroups::new(Group::GROUP_1, Group::GROUP_1, InteractionTestMode::AND);
29+
const BLUE_GROUP: InteractionGroups =
30+
InteractionGroups::new(Group::GROUP_2, Group::GROUP_2, InteractionTestMode::AND);
2931

3032
/*
3133
* A green floor that will collide with the GREEN group only.

examples3d/vehicle_joints3.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ pub fn init_world(testbed: &mut Testbed) {
5353

5454
let body_co = ColliderBuilder::cuboid(0.65, 0.3, 0.9)
5555
.density(100.0)
56-
.collision_groups(InteractionGroups::new(CAR_GROUP, !CAR_GROUP));
56+
.collision_groups(InteractionGroups::new(
57+
CAR_GROUP,
58+
!CAR_GROUP,
59+
InteractionTestMode::AND,
60+
));
5761
let body_rb = RigidBodyBuilder::dynamic()
5862
.position(body_position.into())
5963
.build();
@@ -85,7 +89,11 @@ pub fn init_world(testbed: &mut Testbed) {
8589
// is mathematically simpler than a cylinder and cheaper to compute for collision-detection.
8690
let wheel_co = ColliderBuilder::ball(wheel_radius)
8791
.density(100.0)
88-
.collision_groups(InteractionGroups::new(CAR_GROUP, !CAR_GROUP))
92+
.collision_groups(InteractionGroups::new(
93+
CAR_GROUP,
94+
!CAR_GROUP,
95+
InteractionTestMode::AND,
96+
))
8997
.friction(1.0);
9098
let wheel_rb = RigidBodyBuilder::dynamic().position(wheel_center.into());
9199
let wheel_handle = bodies.insert(wheel_rb);

src/dynamics/coefficient_combine_rule.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ pub enum CoefficientCombineRule {
1919
Multiply,
2020
/// The greatest coefficient is chosen.
2121
Max,
22+
/// The sum of the two coefficients.
23+
Sum,
2224
}
2325

2426
impl CoefficientCombineRule {
@@ -27,8 +29,10 @@ impl CoefficientCombineRule {
2729

2830
match effective_rule {
2931
0 => (coeff1 + coeff2) / 2.0,
30-
1 => coeff1.min(coeff2),
32+
1 => coeff1.min(coeff2).abs(),
3133
2 => coeff1 * coeff2,
34+
4 => (coeff1 + coeff2).clamp(0.0, 1.0),
35+
// 3 is missing as Max is the default one in case of mismatch.
3236
_ => coeff1.max(coeff2),
3337
}
3438
}

src/geometry/interaction_groups.rs

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@
77
/// - The interaction groups filter.
88
///
99
/// An interaction is allowed between two filters `a` and `b` when two conditions
10-
/// are met simultaneously:
10+
/// are met simultaneously for [`InteractionTestMode::AND`] or individually for [`InteractionTestMode::OR`]::
1111
/// - The groups membership of `a` has at least one bit set to `1` in common with the groups filter of `b`.
1212
/// - The groups membership of `b` has at least one bit set to `1` in common with the groups filter of `a`.
1313
///
14-
/// In other words, interactions are allowed between two filter iff. the following condition is met:
14+
/// In other words, interactions are allowed between two filter iff. the following condition is met
15+
/// for [`InteractionTestMode::AND`]:
1516
/// ```ignore
16-
/// (self.memberships & rhs.filter) != 0 && (rhs.memberships & self.filter) != 0
17+
/// (self.memberships.bits() & rhs.filter.bits()) != 0 && (rhs.memberships.bits() & self.filter.bits()) != 0
18+
/// ```
19+
/// or for [`InteractionTestMode::OR`]:
20+
/// ```ignore
21+
/// (self.memberships.bits() & rhs.filter.bits()) != 0 || (rhs.memberships.bits() & self.filter.bits()) != 0
1722
/// ```
1823
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
1924
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
@@ -23,25 +28,39 @@ pub struct InteractionGroups {
2328
pub memberships: Group,
2429
/// Groups filter.
2530
pub filter: Group,
31+
/// Interaction test mode
32+
pub test_mode: InteractionTestMode,
33+
}
34+
35+
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
36+
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, Default)]
37+
/// Specifies which method should be used to test interactions
38+
pub enum InteractionTestMode {
39+
/// Use [`InteractionGroups::test_and`].
40+
#[default]
41+
AND,
42+
/// Use [`InteractionGroups::test_or`].
43+
OR,
2644
}
2745

2846
impl InteractionGroups {
2947
/// Initializes with the given interaction groups and interaction mask.
30-
pub const fn new(memberships: Group, filter: Group) -> Self {
48+
pub const fn new(memberships: Group, filter: Group, test_mode: InteractionTestMode) -> Self {
3149
Self {
3250
memberships,
3351
filter,
52+
test_mode,
3453
}
3554
}
3655

3756
/// Allow interaction with everything.
3857
pub const fn all() -> Self {
39-
Self::new(Group::ALL, Group::ALL)
58+
Self::new(Group::ALL, Group::ALL, InteractionTestMode::AND)
4059
}
4160

4261
/// Prevent all interactions.
4362
pub const fn none() -> Self {
44-
Self::new(Group::NONE, Group::NONE)
63+
Self::new(Group::NONE, Group::NONE, InteractionTestMode::AND)
4564
}
4665

4766
/// Sets the group this filter is part of.
@@ -59,21 +78,41 @@ impl InteractionGroups {
5978
/// Check if interactions should be allowed based on the interaction memberships and filter.
6079
///
6180
/// An interaction is allowed iff. the memberships of `self` contain at least one bit set to 1 in common
62-
/// with the filter of `rhs`, and vice-versa.
81+
/// with the filter of `rhs`, **and** vice-versa.
6382
#[inline]
64-
pub const fn test(self, rhs: Self) -> bool {
65-
// NOTE: since const ops is not stable, we have to convert `Group` into u32
66-
// to use & operator in const context.
83+
pub const fn test_and(self, rhs: Self) -> bool {
6784
(self.memberships.bits() & rhs.filter.bits()) != 0
6885
&& (rhs.memberships.bits() & self.filter.bits()) != 0
6986
}
87+
88+
/// Check if interactions should be allowed based on the interaction memberships and filter.
89+
///
90+
/// An interaction is allowed iff. the groups of `self` contain at least one bit set to 1 in common
91+
/// with the mask of `rhs`, **or** vice-versa.
92+
#[inline]
93+
pub const fn test_or(self, rhs: Self) -> bool {
94+
(self.memberships.bits() & rhs.filter.bits()) != 0
95+
|| (rhs.memberships.bits() & self.filter.bits()) != 0
96+
}
97+
98+
/// Check if interactions should be allowed based on the interaction memberships and filter.
99+
///
100+
/// See [`InteractionTestMode`] for more info.
101+
#[inline]
102+
pub const fn test(self, rhs: Self) -> bool {
103+
match self.test_mode {
104+
InteractionTestMode::AND => self.test_and(rhs),
105+
InteractionTestMode::OR => self.test_or(rhs),
106+
}
107+
}
70108
}
71109

72110
impl Default for InteractionGroups {
73111
fn default() -> Self {
74112
Self {
75113
memberships: Group::GROUP_1,
76114
filter: Group::ALL,
115+
test_mode: InteractionTestMode::AND,
77116
}
78117
}
79118
}

src/geometry/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub use self::contact_pair::{
1111
pub use self::interaction_graph::{
1212
ColliderGraphIndex, InteractionGraph, RigidBodyGraphIndex, TemporaryInteractionIndex,
1313
};
14-
pub use self::interaction_groups::{Group, InteractionGroups};
14+
pub use self::interaction_groups::{Group, InteractionGroups, InteractionTestMode};
1515
pub use self::mesh_converter::{MeshConverter, MeshConverterError};
1616
pub use self::narrow_phase::NarrowPhase;
1717

0 commit comments

Comments
 (0)