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

CollisionWorld::update hits 'assertion failed: self.pts[2] == id' #311

Open
bonsairobo opened this issue Oct 1, 2019 · 2 comments
Open

Comments

@bonsairobo
Copy link

bonsairobo commented Oct 1, 2019

Here's the stack:

thread '<unnamed>' panicked at 'assertion failed: self.pts[2] == id', /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/query/algorithms/epa3.rs:143:13
stack backtrace:
   0: std::panicking::default_hook::{{closure}}
   1: std::panicking::default_hook
   2: <std::panicking::begin_panic::PanicPayload<A> as core::panic::BoxMeUp>::get
   3: std::panicking::begin_panic
   4: ncollide3d::query::algorithms::epa3::EPA<N>::compute_silhouette
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/query/algorithms/epa3.rs:0
   5: ncollide3d::query::algorithms::epa3::EPA<N>::closest_points
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/query/algorithms/epa3.rs:364
   6: ncollide3d::query::contact::contact_support_map_support_map::contact_support_map_support_map_with_params
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/query/contact/contact_support_map_support_map.rs:72
   7: <ncollide3d::pipeline::narrow_phase::contact_generator::convex_polyhedron_convex_polyhedron_manifold_generator::ConvexPolyhedronConvexPolyhedronManifoldGenerator<N> as ncollide3d::pipeline::narrow_phase::contact_generator::contact_manifold_generator::ContactManifoldGenerator<N>>::generate_contacts
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/narrow_phase/contact_generator/convex_polyhedron_convex_polyhedron_manifold_generator.rs:95
   8: ncollide3d::pipeline::narrow_phase::narrow_phase::NarrowPhase<N,Handle>::update_contact
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/narrow_phase/narrow_phase.rs:73
   9: ncollide3d::pipeline::narrow_phase::narrow_phase::NarrowPhase<N,Handle>::update_interaction
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/narrow_phase/narrow_phase.rs:152
  10: ncollide3d::pipeline::narrow_phase::narrow_phase::NarrowPhase<N,Handle>::update
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/narrow_phase/narrow_phase.rs:180
  11: ncollide3d::pipeline::glue::update::perform_narrow_phase
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/glue/update.rs:93
  12: ncollide3d::pipeline::glue::update::perform_all_pipeline
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/glue/update.rs:109
  13: ncollide3d::pipeline::world::CollisionWorld<N,T>::update
             at /Users/duncan/.cargo/registry/src/github.com-1ecc6299db9ec823/ncollide3d-0.20.1/src/pipeline/world.rs:105

I'm not really sure what leads to this. All I know is that it happens more often with large density of cuboids in my world.

My code is generating a bunch of random (integer size and location) axis-aligned cuboids inside some 3D region.

EDIT: Just see the code in my next comment.

@sebcrozet
Copy link
Member

Hi! It will be difficult to debug without being able to reproduce this. Is your code publicly available? Or do you have any way to extract the code used for initializing your collision objects?

Perhaps a small video could give us a better idea of the configuration of your scene?

@bonsairobo
Copy link
Author

Here's the full source that reproduces this:

use nalgebra::{Isometry3, Translation, Vector3, zero};
use ncollide3d::{
    pipeline::{CollisionGroups, GeometricQueryType},
    shape::{Cuboid, ShapeHandle},
    world::CollisionWorld,
};
use rand::{
    distributions::Uniform,
    prelude::*,
};
use std::collections::HashMap;

fn many_colliding_cuboids() {
    let mut world = CollisionWorld::new(0.0);

    // Add two intersecting cuboids to the world.
    let mut groups = CollisionGroups::new();
    groups.set_membership(&[1]);
    groups.set_whitelist(&[1]);
    let contacts_query = GeometricQueryType::Contacts(0.0, 0.0);

    println!("Making cuboids");
    let mut rng = StdRng::from_seed([3; 32]);
    let size_dist = Uniform::new(15, 25);
    let pos_dist = Uniform::new(-50, 50);
    for i in 0..500 {
        let half_extents = Vector3::new(
            size_dist.sample(&mut rng) as f32,
            size_dist.sample(&mut rng) as f32,
            size_dist.sample(&mut rng) as f32,
        );
        let pos = Vector3::new(
            pos_dist.sample(&mut rng) as f32,
            pos_dist.sample(&mut rng) as f32,
            pos_dist.sample(&mut rng) as f32,
        );
        let shape = ShapeHandle::new(Cuboid::new(half_extents));
        let pos = Isometry3::new(pos, zero());
        println!("pos = {}", pos);
        println!("half_extents = {}", half_extents);
        world.add(pos, shape, groups, contacts_query, i);
    }
    println!("Done making cuboids");

    loop {
        // BUG: updating doesn't clear out the old contact pairs, so in the loop below, we will try
        // pushing apart objects that, according to their positions and shapes, should not be
        // in contact anymore.
        world.update();

        // Resolve intersections by pushing cubes apart along the contact normal.
        let mut move_actions = HashMap::new();
        for (handle1, handle2, _, manifold) in world.contact_pairs(true) {
            // Once a room from a contact has been moved, it may invalidate other contacts that
            // it was a part of, so skip them.
            if move_actions.contains_key(&handle1) || move_actions.contains_key(&handle2) {
                continue;
            }

            let contact = &manifold.deepest_contact()
                .expect("No penetration in contact").contact;

            if contact.depth < 0.1 {
                continue;
            }

            // The normal should be parallel to some axis. To ensure that there are no endless
            // cycles of resolutions, only allow resolutions to push in the positive direction
            // along each axis.
            let n: Vector3<f32> = contact.depth * contact.normal.into_inner();
            let (push_v, move_handle) = if n.x > 0.0 || n.y > 0.0 || n.z > 0.0 {
                println!("Pushing room 1");
                (-n, handle1)
            } else {
                println!("Pushing room 2");
                (n, handle2)
            };

            move_actions.insert(move_handle, push_v);

            let obj1 = world.collision_object(handle1).unwrap();
            let obj2 = world.collision_object(handle2).unwrap();
            println!("C1 = {:?}", obj1.shape().as_shape::<Cuboid<f32>>());
            println!("C2 = {:?}", obj2.shape().as_shape::<Cuboid<f32>>());
            println!("C1 = {:?}", obj1.position().translation.vector);
            println!("C2 = {:?}", obj2.position().translation.vector);
            println!("Depth = {}", contact.depth);
            println!("N = {}", contact.normal.into_inner());
        }

        // Need to perform movements after releasing the borrow on world.
        for (handle, push_v) in move_actions.iter() {
            let move_obj = world.get_mut(*handle)
                .expect("Collision object does not exist for handle");
            let mut pos = move_obj.position().clone();
            pos.append_translation_mut(&Translation::from(*push_v));
            move_obj.set_position(pos);
        }

        if move_actions.is_empty() {
            break;
        }
    }
}

fn main() {
    many_colliding_cuboids();
}

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

2 participants