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

epa3.rs panic in closest_points #253

Open
bellwether-softworks opened this issue Aug 13, 2024 · 4 comments · May be fixed by #282
Open

epa3.rs panic in closest_points #253

bellwether-softworks opened this issue Aug 13, 2024 · 4 comments · May be fixed by #282

Comments

@bellwether-softworks
Copy link
Contributor

Didn't want to hijack #246 since my conditions are different, but I am running into my own crash for the epa3.rs *self.heap.peek() statement. I can reliably encounter it in the wild, but despite my best efforts to reproduce it outside of that environment I've been unable to.

I've modified the affected statement (and added some Debug annotations where appropriate) to be able to capture the state of the process at the time of failure:

let Some(mut best_face_id) = self.heap.peek().cloned() else {
    eprintln!("dim {}, vertices = {:?}, faces = {:?}, silhouette = {:?}, heap = {:?}", simplex.dimension(), self.vertices, self.faces, self.silhouette, self.heap);
    panic!("Failed to identify best face ID")
};

...which results in the following output:

dim 3, vertices = [CSOPoint { point: [29.890513266324994, -24.872264105217, 0.4688], orig1: [5.953013266325, -47.813363182955, 0.0], orig2: [-23.937499999999996, -22.941099077738002, -0.4688] }, CSOPoint { point: [-3.552713678800501e-15, 3.552713678800501e-15, 0.0], orig1: [-23.9375, -22.941099077738, -0.4688], orig2: [-23.937499999999996, -22.941099077738002, -0.4688] }, CSOPoint { point: [-47.875000000302, 24.872264105232002, 0.0], orig1: [-23.9375, -22.941099077738, -0.4688], orig2: [23.937500000302002, -47.81336318297, -0.4688] }, CSOPoint { point: [29.890513266303003, -47.875000000023995, 0.4688], orig1: [5.953013266325, -47.813363182955, 0.0], orig2: [-23.937499999978, 0.06163681706899734, -0.4688] }], faces = [Face { pts: [0, 1, 2], adj: [3, 1, 2], normal: [[0.026025342318247643, 0.05009448509481979, 0.9984053405908359]], bcoords: [0.0, 0.0, 0.0], deleted: false }, Face { pts: [1, 3, 2], adj: [3, 2, 0], normal: [[-0.007528594704585582, -0.014491301232543998, -0.999866652334381]], bcoords: [0.0, 0.0, 0.0], deleted: false }, Face { pts: [0, 2, 3], adj: [0, 1, 3], normal: [[-0.0060282696291206455, 5.7632045364500204e-15, 0.9999818298175616]], bcoords: [0.0, 0.0, 0.0], deleted: false }, Face { pts: [0, 3, 1], adj: [2, 1, 0], normal: [[0.0156819773416449, -1.4992435394608913e-14, -0.9998770302325463]], bcoords: [0.0, 0.0, 0.0], deleted: false }], silhouette = [], heap = []

Despite it not actually panicking, I'm also pasting my attempt to reproduce my problems:

[package]
name = "eps3_panic"
version = "0.1.0"
edition = "2021"

[dependencies]
rapier3d-f64 = { version = "0.22.0", features = ["parallel", "serde-serialize", "simd-stable"] }
use rapier3d_f64::dynamics::{RigidBodyBuilder, RigidBodySet};
use rapier3d_f64::geometry::{ActiveCollisionTypes, BroadPhaseMultiSap, ColliderBuilder, ColliderSet, CollisionEvent, ContactPair, NarrowPhase};
use rapier3d_f64::na::{Isometry3, Point3, Quaternion, Translation3, UnitQuaternion};
use rapier3d_f64::pipeline::{ActiveEvents, CollisionPipeline, EventHandler, PhysicsHooks};

fn to_points(data: &[[f64; 3]]) -> Vec<Point3<f64>> {
    data.iter().map(|[x, y, z]| Point3::new(*x, *y, *z)).collect()
}

fn given_data() -> Vec<(Vec<Point3<f64>>, Vec<[u32; 3]>)> {
    vec![
        (to_points(&[[-23.9375, -22.941099077738, 0.0], [23.937500000302, -47.81336318297, 0.0], [5.953013266325, -47.813363182955, 0.0]]), vec![[0, 1, 2], [2, 1, 0]]),
        (to_points(&[[5.953013266325, -47.813363182955, 0.0], [-23.9375, -22.941099077738, 0.0], [-23.9375, -22.941099077738, -0.4688], [5.953013266325, -47.813363182955, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[-23.9375, -22.941099077738, -0.4688], [23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [-23.9375, -22.941099077738, 0.0]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [5.953013266325, -47.813363182955, 0.0], [5.953013266325, -47.813363182955, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[-23.9375, -22.941099077738, -0.4688], [23.937500000302, -47.81336318297, -0.4688], [5.953013266325, -47.813363182955, -0.4688]]), vec![[0, 1, 2], [2, 1, 0]]),
        (to_points(&[[-23.937499999978, 0.061636817069, 0.0], [23.937500000302, -47.81336318297, 0.0], [-23.9375, -22.941099077738, 0.0]]), vec![[0, 1, 2], [2, 1, 0]]),
        (to_points(&[[-23.9375, -22.941099077738, 0.0], [-23.937499999978, 0.061636817069, 0.0], [-23.937499999978, 0.061636817069, -0.4688], [-23.9375, -22.941099077738, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[-23.937499999978, 0.061636817069, -0.4688], [23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [-23.937499999978, 0.061636817069, 0.0]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [-23.9375, -22.941099077738, 0.0], [-23.9375, -22.941099077738, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[-23.937499999978, 0.061636817069, -0.4688], [23.937500000302, -47.81336318297, -0.4688], [-23.9375, -22.941099077738, -0.4688]]), vec![[0, 1, 2], [2, 1, 0]]),
        (to_points(&[[23.937500000302, -47.81336318297, 0.0], [-23.937499999978, 0.061636817069, 0.0], [23.937500000109, 0.061636817029, 0.0]]), vec![[0, 1, 2], [2, 1, 0]]),
        (to_points(&[[23.937500000109, 0.061636817029, 0.0], [-23.937499999978, 0.061636817069, 0.0], [-23.937499999978, 0.061636817069, -0.4688], [23.937500000109, 0.061636817029, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[23.937500000109, 0.061636817029, -0.4688], [23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [23.937500000109, 0.061636817029, 0.0]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[23.937500000302, -47.81336318297, -0.4688], [23.937500000302, -47.81336318297, 0.0], [-23.937499999978, 0.061636817069, 0.0], [-23.937499999978, 0.061636817069, -0.4688]]), vec![[0, 1, 2], [0, 2, 3], [3, 1, 0], [3, 2, 1]]),
        (to_points(&[[23.937500000302, -47.81336318297, -0.4688], [-23.937499999978, 0.061636817069, -0.4688], [23.937500000109, 0.061636817029, -0.4688]]), vec![[0, 1, 2], [2, 1, 0]]),
    ]
}

fn main() {
    let mut rigid_bodies = RigidBodySet::new();
    let mut collider_set = ColliderSet::new();
    let event_handler = CustomContactEventHandler::new();
    let isometry = Isometry3::from_parts(
        Translation3::new(181.62011133541, 288.9152079550468, 154.9445640326959),
        UnitQuaternion::from_quaternion(Quaternion::new(0.676779498744411, -0.20490470825103754, -0.2049119891163854, -0.6767530179707012))
    );

    for (index, (vertices, indices)) in given_data().into_iter().enumerate() {
        add_collider(
            &mut rigid_bodies,
            &mut collider_set,
            isometry,
            vertices,
            indices,
            index as u128,
        );
    }

    let mut collision_pipeline = CollisionPipeline::new();
    let mut broad_phase = BroadPhaseMultiSap::new();
    let mut narrow_phase = NarrowPhase::new();

    collision_pipeline.step(
        0.005,
        &mut broad_phase,
        &mut narrow_phase,
        &mut rigid_bodies,
        &mut collider_set,
        None,
        &(),
        &event_handler,
    );
}

fn add_collider(
    mut rigid_bodies: &mut RigidBodySet,
    collider_set: &mut ColliderSet,
    isometry: Isometry3<f64>,
    vertices: Vec<Point3<f64>>,
    indices: Vec<[u32; 3]>,
    index: u128,
) {
    let collider_builder = ColliderBuilder::trimesh(vertices, indices);
    let rigid_body = RigidBodyBuilder::dynamic()
        .position(isometry)
        .additional_mass(1.)
        .build();
    let collider = collider_builder
        .active_collision_types(ActiveCollisionTypes::all())
        .active_events(ActiveEvents::COLLISION_EVENTS)
        .user_data(index)
        .build();

    let rigid_body_handle = rigid_bodies.insert(rigid_body);

    collider_set.insert_with_parent(collider, rigid_body_handle, &mut rigid_bodies);
}

pub struct CustomContactEventHandler;

impl CustomContactEventHandler {
    pub fn new() -> Self {
        Self
    }
}

impl EventHandler for CustomContactEventHandler {
    fn handle_collision_event(
        &self,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        _event: CollisionEvent,
        contact_pair: Option<&ContactPair>,
    ) {
        if let Some(_pair) = contact_pair {
            println!("Pair encountered");
        }
    }

    fn handle_contact_force_event(
        &self,
        _dt: f64,
        _bodies: &RigidBodySet,
        _colliders: &ColliderSet,
        _contact_pair: &ContactPair,
        _total_force_magnitude: f64,
    ) { /* NOP */ }
}

impl PhysicsHooks for CustomContactEventHandler {}
@wlinna
Copy link
Contributor

wlinna commented Aug 18, 2024

I ran into this issue today. I don't use any sort of rigid bodies or parent-child relationships. I simply add my static model, call step and boom. I've encountered this in both Parry 0.17 and 0.14. I'm now wondering how to reproduce it myself

@wlinna
Copy link
Contributor

wlinna commented Aug 18, 2024

Here's a repro with just two triangles. I simplified it as much as I could, even removing digits after decimal points.
Interestingly enough, if I center the triangle pair, the panic doesn't occur.

use rapier3d::na::Point3;
    use rapier3d::prelude::Triangle;
    use rapier3d::
        prelude::{
            ActiveCollisionTypes, ColliderBuilder, ColliderSet, CollisionPipeline, DefaultBroadPhase, NarrowPhase, QueryPipeline, RigidBodySet, SharedShape,
        }
    ;

    #[test]
    fn down_to_triangles_v2() {
        let mesh1 = Triangle::new(
            Point3::new(-13.174434, 1.0, 8.736801),
            Point3::new(3.5251038, 1.0, 12.1),
            Point3::new(3.2048466, 1.0, 12.218325),
        );
        let mesh2 = Triangle::new(
            Point3::new(-1.63, 0.0, 11.19),
            Point3::new(-2.349647, 0.0, 11.037681),
            Point3::new(-2.349647, 1.0, 11.037681),
        );

        let collider1 = ColliderBuilder::new(SharedShape::new(mesh1))
            .active_collision_types(ActiveCollisionTypes::FIXED_FIXED)
            .build();

        let collider2 = ColliderBuilder::new(SharedShape::new(mesh2))
            .active_collision_types(ActiveCollisionTypes::FIXED_FIXED)
            .build();

        let mut collision_pipeline = CollisionPipeline::new();
        let mut broad_phase = DefaultBroadPhase::new();
        let mut narrow_phase = NarrowPhase::new();
        let physics_hooks = ();
        let event_handler = ();
        let mut query_pipeline = QueryPipeline::new();
        let mut rigid_body_set = RigidBodySet::new();
        let mut collider_set = ColliderSet::new();

        collider_set.insert(collider1);
        collider_set.insert(collider2);

        collision_pipeline.step(
            0.01,
            &mut broad_phase,
            &mut narrow_phase,
            &mut rigid_body_set,
            &mut collider_set,
            Some(&mut query_pipeline),
            &physics_hooks,
            &event_handler,
        );
    }

@wlinna
Copy link
Contributor

wlinna commented Aug 19, 2024

I further simplified the repro to just the following code:

let mesh1 = Triangle::new(
    Point3::new(-13.174434, 1.0, 8.736801),
    Point3::new(3.5251038, 1.0, 12.1),
    Point3::new(3.2048466, 1.0, 12.218325),
);
let mesh2 = Triangle::new(
    Point3::new(-1.63, 0.0, 11.19),
    Point3::new(-2.349647, 0.0, 11.037681),
    Point3::new(-2.349647, 1.0, 11.037681),
);

query::details::contact_support_map_support_map_with_params(
    &Isometry3::identity(),
    &mesh1,
    &mesh2,
    0.00999999977,
    &mut VoronoiSimplex::new(),
    None,
);

@wlinna
Copy link
Contributor

wlinna commented Sep 2, 2024

Here is what the triangles look like when rendered

TriangleCrash1
TriangleCrash2

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

Successfully merging a pull request may close this issue.

2 participants