Add collision groups to filter collision pairs.

This commit is contained in:
Crozet Sébastien
2020-10-27 12:08:46 +01:00
parent c336ae6455
commit 3def91d62e
4 changed files with 87 additions and 129 deletions

View File

@@ -0,0 +1,54 @@
#[repr(transparent)]
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
/// Pairwise filtering using bit masks.
///
/// This filtering method is based on two 16-bit values:
/// - The interaction groups (the 16 left-most bits of `self.0`).
/// - The interaction mask (the 16 right-most bits of `self.0`).
///
/// An interaction is allowed between two filters `a` and `b` two conditions
/// are met simultaneously:
/// - The interaction groups of `a` has at least one bit set to `1` in common with the interaction mask of `b`.
/// - The interaction groups of `b` has at least one bit set to `1` in common with the interaction mask of `a`.
/// In other words, interactions are allowed between two filter iff. the following condition is met:
/// ```rust
/// ((self.0 >> 16) & rhs.0) != 0 && ((rhs.0 >> 16) & self.0) != 0
/// ```
pub struct InteractionGroups(pub u32);
impl InteractionGroups {
/// Allow interaction with everything.
pub fn all() -> Self {
Self(u32::MAX)
}
/// Prevent all interactions.
pub fn none() -> Self {
Self(0)
}
/// Sets the group this filter is part of.
pub fn with_groups(self, groups: u16) -> Self {
Self((self.0 & 0x0000ffff) | ((groups as u32) << 16))
}
/// Sets the interaction mask of this filter.
pub fn with_mask(self, mask: u16) -> Self {
Self((self.0 & 0xffff0000) | (mask as u32))
}
/// Check if interactions should be allowed based on the interaction groups and mask.
///
/// An interaction is allowed iff. the groups of `self` contain at least one bit set to 1 in common
/// with the mask of `rhs`, and vice-versa.
pub fn test(self, rhs: Self) -> bool {
((self.0 >> 16) & rhs.0) != 0 && ((rhs.0 >> 16) & self.0) != 0
}
}
impl Default for InteractionGroups {
fn default() -> Self {
Self::all()
}
}