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

Panic "Invalid parent body part handle" when creating and deleting a body in the same frame #248

Open
aclysma opened this issue Jan 23, 2020 · 0 comments

Comments

@aclysma
Copy link

aclysma commented Jan 23, 2020

I ran across a panic: thread 'main' panicked at 'Invalid parent body part handle.', src/libcore/option.rs:1188:5 that happens if a body is created/destroyed in the same frame. It looks like the source of this is that handle_insertions runs after the body is removed.

    fn handle_insertions<Bodies, Colliders>(&mut self, bodies: &mut Bodies, colliders: &mut Colliders)
        where Bodies: BodySet<N, Handle = Handle>,
              Colliders: ColliderSet<N, Handle, Handle = CollHandle> {
        while let Some(handle) = colliders.pop_insertion_event() {
            if let Some(collider) = colliders.get_mut(handle) {
                self.register_collider(handle, collider);

                match collider.anchor() {
                    ColliderAnchor::OnBodyPart { body_part, position_wrt_body_part } => {
                        let body = bodies.get_mut(body_part.0).expect("Invalid parent body part handle.");

It looks like normally this bit of code at the top of MechanicalWorld::maintain would have used GeometricalWorld::body_colliders to find and remove the colliders ahead of time, causing GeometricalWorld::handle_insertions to do nothing.

        // NOTE: the order of handling events matters.
        // In particular, handling body removal events must be done first because it
        // can itself cause constraints or colliders to be automatically removed too.

        let mut at_least_one_body_removed = false; // If at least one body is removed we need to find the constraints to remove too.

        while let Some(handle) = bodies.pop_removal_event() {
            // Remove every colliders attached to this body.
            if let Some(colls_to_remove) = gworld.body_colliders(handle) {
                for collider in colls_to_remove {
                    let _ = colliders.remove(*collider);
                }
            }

            at_least_one_body_removed = true;
        }

However, GeometricalWorld::body_colliders doesn't get populated until handle_insertions runs, so the colliders are not removed.

@Ralith and I discussed a bit on discord, three general approaches to addressing this came up:

  1. Find and remove the queued handle_insertions if the body is removed
  2. Make the handle_insertions code detect the situation and do nothing
  3. Process insertions/removals in the order they actually occur instead of batching them together

While I think approach 1 or 2 might yield a quick fix, I think @Ralith and I both feel that the third approach might be less error prone

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

No branches or pull requests

1 participant