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

Feature request: Panic if QueryPipeline fails to be updated #445

Closed
RedBreadcat opened this issue Jan 25, 2023 · 2 comments
Closed

Feature request: Panic if QueryPipeline fails to be updated #445

RedBreadcat opened this issue Jan 25, 2023 · 2 comments
Labels
C-Bug Something isn't working

Comments

@RedBreadcat
Copy link

The following code softlocks within physics.step(); in the loop, after "Step: 9" is printed. The freeze does not occur if self.query_pipeline.update(&self.bodies, &self.colliders); is uncommented.

use rapier2d::{
    na::{Isometry2, Vector2},
    prelude::*,
};

struct Physics {
    pipeline: PhysicsPipeline,
    query_pipeline: QueryPipeline,
    integration_parameters: IntegrationParameters,
    island_manager: IslandManager,
    broad_phase: BroadPhase,
    narrow_phase: NarrowPhase,
    bodies: RigidBodySet,
    colliders: ColliderSet,
    impulse_joints: ImpulseJointSet,
    multibody_joints: MultibodyJointSet,
    ccd_solver: CCDSolver,
}

impl Physics {
    fn step(&mut self) {
        self.pipeline.step(
            &Vector2::default(),
            &self.integration_parameters,
            &mut self.island_manager,
            &mut self.broad_phase,
            &mut self.narrow_phase,
            &mut self.bodies,
            &mut self.colliders,
            &mut self.impulse_joints,
            &mut self.multibody_joints,
            &mut self.ccd_solver,
            Some(&mut self.query_pipeline),
            &(),
            &(),
        );

        //self.query_pipeline.update(&self.bodies, &self.colliders);
    }

    fn build_rb_kinematic_with_collider(
        &mut self,
        pos: Vector2<f32>,
    ) -> (RigidBodyHandle, ColliderHandle) {
        println!("build");
        let rb = Self::build_rigidbody_kinematic_template(pos);
        let rbh = self.bodies.insert(rb);
        let col = Self::build_primary_collider_kinematic_template();
        let colh = self
            .colliders
            .insert_with_parent(col, rbh, &mut self.bodies);

        (rbh, colh)
    }

    fn build_rigidbody_kinematic_template(pos: Vector2<f32>) -> RigidBody {
        RigidBodyBuilder::new(RigidBodyType::KinematicVelocityBased)
            .position(Isometry2::new(pos, 0.0))
            .gravity_scale(0.0)
            .can_sleep(true)
            .build()
    }

    fn build_primary_collider_kinematic_template() -> Collider {
        let shape = SharedShape::ball(1.0);
        let cb = ColliderBuilder::new(shape);

        cb.build()
    }
}

impl Default for Physics {
    fn default() -> Self {
        let pipeline = PhysicsPipeline::new();
        let query_pipeline = QueryPipeline::new();
        let integration_parameters = IntegrationParameters {
            dt: 0.01,
            ..Default::default()
        };
        let island_manager = IslandManager::new();
        let broad_phase = BroadPhase::new();
        let narrow_phase = NarrowPhase::new();
        let bodies = RigidBodySet::new();
        let colliders = ColliderSet::new();
        let impulse_joints = ImpulseJointSet::new();
        let multibody_joints = MultibodyJointSet::new();
        let ccd_solver = CCDSolver::new();

        Self {
            pipeline,
            query_pipeline,
            integration_parameters,
            island_manager,
            broad_phase,
            narrow_phase,
            bodies,
            colliders,
            impulse_joints,
            multibody_joints,
            ccd_solver,
        }
    }
}

fn main() {
    let mut physics = Physics::default();

    let a = Vector::new(1.0, 0.0);
    let b = Vector::new(0.0, 0.0);

    physics.build_rb_kinematic_with_collider(a);

    let mut step = 0;
    loop {
        // 2 are needed
        physics.build_rb_kinematic_with_collider(b);
        physics.build_rb_kinematic_with_collider(b);

        step += 1;
        println!("Step: {}", step);
        physics.step();
    }
}

It was a bit difficult to figure out what was happening, as the freeze only occurred when rigidbodies were in certain positions. (If a == b, I could not trigger a freeze). If possible, it would be nice if the code panicked, or a more elegant solution that made it impossible for one to forget to update the QueryPipeline.

The freeze itself occurred inside this function call:

let _ = self.qbvh.refit(0.0, &mut self.workspace, |handle| {

In more complex code that periodically deleted rigidbodies and colliders, and had dynamic physics objects too, I occasionally panicked inside the closure on the next line, due to the handle's two internal integer components being huge numbers that looked like uninitialized memory.

Thank you for your work!

@sebcrozet sebcrozet added the C-Bug Something isn't working label Mar 26, 2023
@sebcrozet
Copy link
Member

The qbvh::refit should not freeze (and, more generally, the query pipeline’s update should never fail). This is a bug in the QBVH update code.

@sebcrozet
Copy link
Member

I wasn’t able to reproduce the bug with the provided code, but, other similar issues were reported and a fix just got merged in dimforge/parry#185. So I’m closing this issue, but, feel free to open a new issue if this happens again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants