nphysics icon indicating copy to clipboard operation
nphysics copied to clipboard

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

Open aclysma opened this issue 4 years ago • 0 comments

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

aclysma avatar Jan 23 '20 06:01 aclysma