Skip to content

bug: parry2d_f64::query::contact not returning proper contact #415

@winux138

Description

@winux138

When having this Segment and this Aabb:

    let segment = Segment {
        a: Vector::new(60.0, 10.0),
        b: Vector::new(10.0, 0.0),
    };
    let aabb = Aabb {
        mins: Vector::new(40.0, -50.0),
        maxs: Vector::new(60.0, 150.0),
    };

parry2d_f64::query::contact returns Ok(None).

My expectation is that it should return a Ok(Some(Contact)) with a negative distance.


Here is a minimal reproducible example:

use parry2d_f64::bounding_volume::Aabb;
use parry2d_f64::math::{Pose, Vector};
use parry2d_f64::query::contact;
use parry2d_f64::shape::{Cuboid, Segment};

fn main() {
    let segment_above = Segment {
        a: Vector::new(-10.0, 170.0),
        b: Vector::new(70.0, 170.0),
    };
    let segment_graze_top = Segment {
        a: Vector::new(-10.0, 150.0),
        b: Vector::new(70.0, 150.0),
    };
    let segment_through = Segment {
        a: Vector::new(-10.0, 100.0),
        b: Vector::new(70.0, 100.0),
    };

    let segment_bug = Segment {
        a: Vector::new(60.0, 10.0),
        b: Vector::new(10.0, 0.0),
    };

    let aabb = Aabb {
        mins: Vector::new(40.0, -50.0),
        maxs: Vector::new(60.0, 150.0),
    };

    let half_extents = (aabb.maxs - aabb.mins) / 2.0;
    let center = (aabb.mins + aabb.maxs) / 2.0;
    let cuboid = Cuboid::new(half_extents);
    let pos_cuboid = Pose::translation(center.x, center.y);

    // Works as expected
    assert!(matches!(
        contact(&Pose::identity(), &segment_above, &pos_cuboid, &cuboid, 1.),
        Ok(None),
    ));

    // Works as expected
    assert!(matches!(
        contact(&Pose::identity(), &segment_graze_top, &pos_cuboid, &cuboid, 1.),
        Ok(Some(contact)) if contact.dist == 0.
    ));

    // Works as expected
    assert!(matches!(
        contact(&Pose::identity(), &segment_through, &pos_cuboid, &cuboid, 1.),
        Ok(Some(contact)) if contact.dist < 0.
    ));

    // Returns a `Ok(None)`
    assert!(matches!(
        contact(&Pose::identity(), &segment_bug, &pos_cuboid, &cuboid, 1.),
        Ok(Some(contact)) if contact.dist < 0.
    ));
}

Some extra context:

Initially I was using parry2d_f64::query::details::intersection_test_aabb_segment(), but if the segment is on the edge of the Aabb I don't want to consider this a collision.
(And deflation was not an option)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions