rapier icon indicating copy to clipboard operation
rapier copied to clipboard

set_shape() with flipped sign on half extents causes panic on next step if half_extents.abs() < position.abs()

Open Johannes0021 opened this issue 6 months ago • 0 comments

Summary:

Calling set_shape() with a SharedShape::cuboid(...) that flips the sign of one of the half extents (e.g. from 1.0 to -1.0) causes a panic during the next PhysicsPipeline::step(), but only if the absolute value of the half extent is smaller than the body's absolute position along that axis.

thread 'main' panicked at /home/johannes/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/rapier2d-0.26.1/src/geometry/broad_phase_multi_sap/sap_utils.rs:18:5:
assertion `left != right` failed
  left: 0
 right: 0

Reproduction steps:

use rapier2d::prelude::*;

fn main() {
    let mut rigid_body_set = RigidBodySet::new();
    let mut collider_set = ColliderSet::new();

    /* Create cuboid. */
    let rigid_body = RigidBodyBuilder::kinematic_position_based()
        .translation(vector![3.0, 3.0])
        .build();
    let rb_handle = rigid_body_set.insert(rigid_body);

    let collider = ColliderBuilder::cuboid(1.0, 1.0).build();
    let coll_handle = collider_set.insert_with_parent(
        collider,
        rb_handle,
        &mut rigid_body_set
    );

    /* Create other structures necessary for the simulation. */
    let gravity = vector![0.0, -9.81];
    let integration_parameters = IntegrationParameters::default();
    let mut physics_pipeline = PhysicsPipeline::new();
    let mut island_manager = IslandManager::new();
    let mut broad_phase = DefaultBroadPhase::new();
    let mut narrow_phase = NarrowPhase::new();
    let mut impulse_joint_set = ImpulseJointSet::new();
    let mut multibody_joint_set = MultibodyJointSet::new();
    let mut ccd_solver = CCDSolver::new();
    let mut query_pipeline = QueryPipeline::new();
    let physics_hooks = ();
    let event_handler = ();

    /* Run the game loop, stepping the simulation once per frame. */
    for _ in 0..2 {
        physics_pipeline.step(
            &gravity,
            &integration_parameters,
            &mut island_manager,
            &mut broad_phase,
            &mut narrow_phase,
            &mut rigid_body_set,
            &mut collider_set,
            &mut impulse_joint_set,
            &mut multibody_joint_set,
            &mut ccd_solver,
            Some(&mut query_pipeline),
            &physics_hooks,
            &event_handler,
        );

        let collider = collider_set.get_mut(coll_handle).unwrap();
        collider.set_shape(SharedShape::cuboid(1.0, -1.0));
    }
}

Rapier2d version:

rapier2d = "0.26.1"


Note:

The condition about abs(half_extent) < abs(position) is just an observation; I haven't tested it thoroughly. This happened to me by accident. I wasn’t intentionally using negative half extents. I’m not sure how critical this is.

Johannes0021 avatar Jun 26 '25 19:06 Johannes0021