Closed eldyer closed 2 years ago
Hi! Do you have an example for us to reproduce this inconsistency?
Hi! Not yet, I observed it in a larger project only. I'll try to construct a minimal example using the testbed.
I quickly hacked something together based on the sensor3 example that should do the job - see below.
The green marked cubes have the handle indices: 34, 44, 54, 64, 74.
cube body handle: RigidBodyHandle(Index { index: 34, generation: 0 })
cube collider handle: ColliderHandle(Index { index: 34, generation: 0 })
cube body handle: RigidBodyHandle(Index { index: 44, generation: 0 })
cube collider handle: ColliderHandle(Index { index: 44, generation: 0 })
cube body handle: RigidBodyHandle(Index { index: 54, generation: 0 })
cube collider handle: ColliderHandle(Index { index: 54, generation: 0 })
cube body handle: RigidBodyHandle(Index { index: 64, generation: 0 })
cube collider handle: ColliderHandle(Index { index: 64, generation: 0 })
cube body handle: RigidBodyHandle(Index { index: 74, generation: 0 })
cube collider handle: ColliderHandle(Index { index: 74, generation: 0 })
The sensor has body handle index 101 / collider index 102:
sensor handle: RigidBodyHandle(Index { index: 101, generation: 0 })
sensor collider handle: ColliderHandle(Index { index: 102, generation: 0 })
After 3 seconds, the above green marked cubes are removed.
The resulting 3 STOPPED events are strange:
removed!
collider handle 1: ColliderHandle(Index { index: 74, generation: 0 })
collider handle 2: ColliderHandle(Index { index: 102, generation: 0 })
removed!
collider handle 1: ColliderHandle(Index { index: 78, generation: 0 })
collider handle 2: ColliderHandle(Index { index: 102, generation: 0 })
removed!
collider handle 1: ColliderHandle(Index { index: 56, generation: 0 })
collider handle 2: ColliderHandle(Index { index: 102, generation: 0 })
While the first one seems correct, the other ones have wrong handles of bodies that weren't removed (78, 56). Also, two STOPPED events are missing completely. Here the code:
use rapier3d::prelude::*;
use rapier_testbed3d::{Testbed, TestbedApp};
pub fn init_world(testbed: &mut Testbed) {
/*
* World
*/
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let impulse_joints = ImpulseJointSet::new();
let multibody_joints = MultibodyJointSet::new();
/*
* Ground.
*/
let ground_size = 200.1;
let ground_height = 0.1;
let rigid_body = RigidBodyBuilder::fixed().translation(vector![0.0, -ground_height, 0.0]);
let ground_handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(ground_size, ground_height, ground_size);
colliders.insert_with_parent(collider, ground_handle, &mut bodies);
/*
* Create some boxes.
*/
let num = 10;
let rad = 0.2;
let shift = rad * 2.0;
let centerx = shift * num as f32 / 2.0;
let centerz = shift * num as f32 / 2.0;
let mut test_cubes = Vec::new();
for i in 0usize..num {
for k in 0usize..num {
let x = i as f32 * shift - centerx;
let y = 3.0;
let z = k as f32 * shift - centerz;
// Build the rigid body.
let rigid_body = RigidBodyBuilder::dynamic().translation(vector![x, y, z]);
let handle = bodies.insert(rigid_body);
let collider = ColliderBuilder::cuboid(rad, rad, rad);
let collider_handle = colliders.insert_with_parent(collider, handle, &mut bodies);
testbed.set_initial_body_color(handle, [0.5, 0.5, 1.0]);
if i >= 3 && i <= 7 && k == 3 {
println!("cube body handle: {:?}", handle);
println!("cube collider handle: {:?}", collider_handle);
test_cubes.push(handle);
testbed.set_initial_body_color(handle, [0.0, 1.0, 0.0]);
}
}
}
println!("============");
/*
* Create a cube that will have a ball-shaped sensor attached.
*/
// Rigid body so that the sensor can move.
let sensor = RigidBodyBuilder::dynamic().translation(vector![0.0, 5.0, 0.0]);
let sensor_handle = bodies.insert(sensor);
println!("sensor handle: {:?}", sensor_handle);
// Solid cube attached to the sensor which
// other colliders can touch.
let collider = ColliderBuilder::cuboid(rad, rad, rad);
colliders.insert_with_parent(collider, sensor_handle, &mut bodies);
// We create a collider desc without density because we don't
// want it to contribute to the rigid body mass.
let sensor_collider = ColliderBuilder::ball(rad * 5.0)
.density(0.0)
.sensor(true)
.active_events(ActiveEvents::COLLISION_EVENTS);
let sensor_collider_handle =
colliders.insert_with_parent(sensor_collider, sensor_handle, &mut bodies);
println!("sensor collider handle: {:?}", sensor_collider_handle);
println!("==============");
testbed.set_initial_body_color(sensor_handle, [0.5, 1.0, 1.0]);
let mut done = false;
// Callback that will be executed on the main loop to handle proximities.
testbed.add_callback(move |_, physics, events, run_state| {
while let Ok(prox) = events.events.try_recv() {
if prox.removed() {
println!("removed!");
println!("collider handle 1: {:?}", prox.collider1());
println!("collider handle 2: {:?}", prox.collider2());
}
}
if run_state.time >= 3.0 && !done {
done = true;
for test_cube in &test_cubes {
physics.bodies.remove(
*test_cube,
&mut physics.islands,
&mut physics.colliders,
&mut physics.impulse_joints,
&mut physics.multibody_joints,
true,
);
}
}
});
/*
* Set up the testbed.
*/
testbed.set_world(bodies, colliders, impulse_joints, multibody_joints);
testbed.look_at(point![-6.0, 4.0, -6.0], point![0.0, 1.0, 0.0]);
}
pub fn main() {
let testbedapp = TestbedApp::from_builders(0, vec![("test", init_world)]);
testbedapp.run()
}
Thank you for the code reproducing the bug. This will be fixed by #337.
Rapier 0.12.0 introduced the emission of
CollisionEvent::Stopped
events after a collider is removed.This seems to work for non-sensor collisions. But for contacts where the other (non-removed) collider is a sensor, stopped events are either missing or wrong. By wrong I mean: the stopped events point to uninvolved contacts and to collider handles that haven't been removed at all, while the
CollisionEventFlags::REMOVED
flag still being set in these events.