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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions