aboutsummaryrefslogtreecommitdiff
path: root/src/geometry/interaction_groups.rs
diff options
context:
space:
mode:
authorCrozet Sébastien <developer@crozet.re>2020-10-27 12:08:46 +0100
committerCrozet Sébastien <developer@crozet.re>2020-10-27 14:35:01 +0100
commit3def91d62eba6ca2486fdaa386f78d82923c705a (patch)
treef2b8a3b2367c5d73c5d00724aa3022a8aa79ecbc /src/geometry/interaction_groups.rs
parentc336ae64557a4981b9cfbd2f6fbe7b7a9d383493 (diff)
downloadrapier-3def91d62eba6ca2486fdaa386f78d82923c705a.tar.gz
rapier-3def91d62eba6ca2486fdaa386f78d82923c705a.tar.bz2
rapier-3def91d62eba6ca2486fdaa386f78d82923c705a.zip
Add collision groups to filter collision pairs.
Diffstat (limited to 'src/geometry/interaction_groups.rs')
-rw-r--r--src/geometry/interaction_groups.rs54
1 files changed, 54 insertions, 0 deletions
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()
+ }
+}