Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug with CollisionEvent::Stopped events after removal if a sensor is involved #330

Closed
eldyer opened this issue May 23, 2022 · 4 comments · Fixed by #337
Closed

Bug with CollisionEvent::Stopped events after removal if a sensor is involved #330

eldyer opened this issue May 23, 2022 · 4 comments · Fixed by #337

Comments

@eldyer
Copy link

eldyer commented May 23, 2022

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.

@sebcrozet
Copy link
Member

Hi! Do you have an example for us to reproduce this inconsistency?

@eldyer
Copy link
Author

eldyer commented May 31, 2022

Hi! Not yet, I observed it in a larger project only. I'll try to construct a minimal example using the testbed.

@eldyer
Copy link
Author

eldyer commented May 31, 2022

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()
}

@sebcrozet
Copy link
Member

Thank you for the code reproducing the bug. This will be fixed by #337.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants