aboutsummaryrefslogtreecommitdiff
path: root/src/geometry/interaction_groups.rs
diff options
context:
space:
mode:
authorSébastien Crozet <developer@crozet.re>2020-10-27 16:10:10 +0100
committerGitHub <noreply@github.com>2020-10-27 16:10:10 +0100
commita52fb8d7e4649dce02e2131d848b84166df82d64 (patch)
treedc6b38ebd73ca5fd62b200417dcc0b114a894572 /src/geometry/interaction_groups.rs
parentc336ae64557a4981b9cfbd2f6fbe7b7a9d383493 (diff)
parent7cafc5471c7fb22b4034b8fe90e848cd0912204d (diff)
downloadrapier-a52fb8d7e4649dce02e2131d848b84166df82d64.tar.gz
rapier-a52fb8d7e4649dce02e2131d848b84166df82d64.tar.bz2
rapier-a52fb8d7e4649dce02e2131d848b84166df82d64.zip
Merge pull request #43 from dimforge/interaction_groups
Add collision filtering based in bit masks
Diffstat (limited to 'src/geometry/interaction_groups.rs')
-rw-r--r--src/geometry/interaction_groups.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/geometry/interaction_groups.rs b/src/geometry/interaction_groups.rs
new file mode 100644
index 0000000..48808de
--- /dev/null
+++ b/src/geometry/interaction_groups.rs
@@ -0,0 +1,60 @@
+#[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:
+/// ```ignore
+/// ((self.0 >> 16) & rhs.0) != 0 && ((rhs.0 >> 16) & self.0) != 0
+/// ```
+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 const fn all() -> Self {
+ Self(u32::MAX)
+ }
+
+ /// Prevent all interactions.
+ pub const fn none() -> Self {
+ Self(0)
+ }
+
+ /// Sets the group this filter is part of.
+ 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 const 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.
+ #[inline]
+ pub const 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()
+ }
+}