aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKane Rogers <kane.m.rogers@gmail.com>2021-08-25 15:19:52 +1000
committerSébastien Crozet <sebastien@crozet.re>2021-08-26 10:29:24 +0200
commit3f223aaf9e8334893e6ed0ca1e9e72604f5ab35d (patch)
treec2374c6854a1548bd3a52ccc93c81812c5813e67
parent1d55e841ec22ea2acd03a5293a226f37218c3b6d (diff)
downloadrapier-3f223aaf9e8334893e6ed0ca1e9e72604f5ab35d.tar.gz
rapier-3f223aaf9e8334893e6ed0ca1e9e72604f5ab35d.tar.bz2
rapier-3f223aaf9e8334893e6ed0ca1e9e72604f5ab35d.zip
Fix bug with colliders without rigid bodies
- When `NarrowPhase` adds a collision pair, it checks to make sure that they don't have the same parent - In the case where the colliders have no parents (eg. they are not attached to a `RigidBody`) this yields a false positive. - The fix is to ensure that colliders have a parent before ignoring the pair.
-rw-r--r--src/geometry/narrow_phase.rs8
-rw-r--r--src/pipeline/collision_pipeline.rs106
2 files changed, 112 insertions, 2 deletions
diff --git a/src/geometry/narrow_phase.rs b/src/geometry/narrow_phase.rs
index c3c7685..18900b9 100644
--- a/src/geometry/narrow_phase.rs
+++ b/src/geometry/narrow_phase.rs
@@ -571,8 +571,12 @@ impl NarrowPhase {
let co_parent2: Option<&ColliderParent> = colliders.get(pair.collider2.0);
if co_parent1.map(|p| p.handle) == co_parent2.map(|p| p.handle) {
- // Same parents. Ignore collisions.
- return;
+ if co_parent1.is_some() {
+ // Same parents. Ignore collisions.
+ return;
+ }
+
+ // These colliders have no parents - continue.
}
let (gid1, gid2) = self.graph_indices.ensure_pair_exists(
diff --git a/src/pipeline/collision_pipeline.rs b/src/pipeline/collision_pipeline.rs
index d789da7..83db4ac 100644
--- a/src/pipeline/collision_pipeline.rs
+++ b/src/pipeline/collision_pipeline.rs
@@ -204,3 +204,109 @@ impl CollisionPipeline {
removed_colliders.clear();
}
}
+
+#[cfg(test)]
+mod tests {
+
+ #[test]
+ #[cfg(feature = "dim3")]
+ pub fn test_no_rigid_bodies() {
+ use crate::prelude::*;
+ let mut rigid_body_set = RigidBodySet::new();
+ let mut collider_set = ColliderSet::new();
+
+ /* Create the ground. */
+ let collider_a = ColliderBuilder::cuboid(1.0, 1.0, 1.0)
+ .active_collision_types(ActiveCollisionTypes::all())
+ .sensor(true)
+ .active_events(ActiveEvents::CONTACT_EVENTS | ActiveEvents::INTERSECTION_EVENTS)
+ .build();
+
+ let a_handle = collider_set.insert(collider_a);
+
+ let collider_b = ColliderBuilder::cuboid(1.0, 1.0, 1.0)
+ .active_collision_types(ActiveCollisionTypes::all())
+ .sensor(true)
+ .active_events(ActiveEvents::CONTACT_EVENTS | ActiveEvents::INTERSECTION_EVENTS)
+ .build();
+
+ let _ = collider_set.insert(collider_b);
+
+ let integration_parameters = IntegrationParameters::default();
+ let mut broad_phase = BroadPhase::new();
+ let mut narrow_phase = NarrowPhase::new();
+ let mut collision_pipeline = CollisionPipeline::new();
+ let physics_hooks = ();
+
+ collision_pipeline.step(
+ integration_parameters.prediction_distance,
+ &mut broad_phase,
+ &mut narrow_phase,
+ &mut rigid_body_set,
+ &mut collider_set,
+ &physics_hooks,
+ &(),
+ );
+
+ let mut hit = false;
+
+ for (_, _, intersecting) in narrow_phase.intersections_with(a_handle) {
+ if intersecting {
+ hit = true;
+ }
+ }
+
+ assert!(hit, "No hit found");
+ }
+
+ #[test]
+ #[cfg(feature = "dim2")]
+ pub fn test_no_rigid_bodies() {
+ use crate::prelude::*;
+ let mut rigid_body_set = RigidBodySet::new();
+ let mut collider_set = ColliderSet::new();
+
+ /* Create the ground. */
+ let collider_a = ColliderBuilder::cuboid(1.0, 1.0)
+ .active_collision_types(ActiveCollisionTypes::all())
+ .sensor(true)
+ .active_events(ActiveEvents::CONTACT_EVENTS | ActiveEvents::INTERSECTION_EVENTS)
+ .build();
+
+ let a_handle = collider_set.insert(collider_a);
+
+ let collider_b = ColliderBuilder::cuboid(1.0, 1.0)
+ .active_collision_types(ActiveCollisionTypes::all())
+ .sensor(true)
+ .active_events(ActiveEvents::CONTACT_EVENTS | ActiveEvents::INTERSECTION_EVENTS)
+ .build();
+
+ let _ = collider_set.insert(collider_b);
+
+ let integration_parameters = IntegrationParameters::default();
+ let mut broad_phase = BroadPhase::new();
+ let mut narrow_phase = NarrowPhase::new();
+ let mut collision_pipeline = CollisionPipeline::new();
+ let physics_hooks = ();
+
+ collision_pipeline.step(
+ integration_parameters.prediction_distance,
+ &mut broad_phase,
+ &mut narrow_phase,
+ &mut rigid_body_set,
+ &mut collider_set,
+ &physics_hooks,
+ &(),
+ );
+
+ let mut hit = false;
+
+ for (_, _, intersecting) in narrow_phase.intersections_with(a_handle) {
+ if intersecting {
+ hit = true;
+ }
+ }
+
+ assert!(hit, "No hit found");
+ }
+}