Skip to content

Commit

Permalink
Fix bug with colliders without rigid bodies
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
kanerogers authored and sebcrozet committed Aug 26, 2021
1 parent 1d55e84 commit 3f223aa
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/geometry/narrow_phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
106 changes: 106 additions & 0 deletions src/pipeline/collision_pipeline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}

0 comments on commit 3f223aa

Please sign in to comment.