From 3def91d62eba6ca2486fdaa386f78d82923c705a Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 27 Oct 2020 12:08:46 +0100 Subject: Add collision groups to filter collision pairs. --- src/geometry/interaction_groups.rs | 54 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/geometry/interaction_groups.rs (limited to 'src/geometry/interaction_groups.rs') diff --git a/src/geometry/interaction_groups.rs b/src/geometry/interaction_groups.rs new file mode 100644 index 0000000..9596345 --- /dev/null +++ b/src/geometry/interaction_groups.rs @@ -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() + } +} -- cgit From 2509e42d7b7e1bed2f1dca1f9eac8c6484fadf25 Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 27 Oct 2020 14:24:25 +0100 Subject: Add a construstructor to InteractionGroups + make its methods const. --- src/geometry/interaction_groups.rs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/geometry/interaction_groups.rs') diff --git a/src/geometry/interaction_groups.rs b/src/geometry/interaction_groups.rs index 9596345..6812fbf 100644 --- a/src/geometry/interaction_groups.rs +++ b/src/geometry/interaction_groups.rs @@ -18,23 +18,28 @@ pub struct InteractionGroups(pub u32); impl InteractionGroups { + /// Initializes with the given interaction groups and interaction mask. + pub const fn new(groups: u16, masks: u16) -> Self { + Self::none().with_groups(groups).with_mask(masks) + } + /// Allow interaction with everything. - pub fn all() -> Self { + pub const fn all() -> Self { Self(u32::MAX) } /// Prevent all interactions. - pub fn none() -> Self { + pub const fn none() -> Self { Self(0) } /// Sets the group this filter is part of. - pub fn with_groups(self, groups: u16) -> Self { + pub const 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 { + pub const fn with_mask(self, mask: u16) -> Self { Self((self.0 & 0xffff0000) | (mask as u32)) } @@ -42,7 +47,8 @@ impl InteractionGroups { /// /// 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 { + #[inline] + pub const fn test(self, rhs: Self) -> bool { ((self.0 >> 16) & rhs.0) != 0 && ((rhs.0 >> 16) & self.0) != 0 } } -- cgit From 7cafc5471c7fb22b4034b8fe90e848cd0912204d Mon Sep 17 00:00:00 2001 From: Crozet Sébastien Date: Tue, 27 Oct 2020 15:05:10 +0100 Subject: Ignore the code block in the InteractionGroups doc. --- src/geometry/interaction_groups.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/geometry/interaction_groups.rs') diff --git a/src/geometry/interaction_groups.rs b/src/geometry/interaction_groups.rs index 6812fbf..48808de 100644 --- a/src/geometry/interaction_groups.rs +++ b/src/geometry/interaction_groups.rs @@ -12,7 +12,7 @@ /// - 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 +/// ```ignore /// ((self.0 >> 16) & rhs.0) != 0 && ((rhs.0 >> 16) & self.0) != 0 /// ``` pub struct InteractionGroups(pub u32); -- cgit