dimforge / ncollide

2 and 3-dimensional collision detection library in Rust.
https://ncollide.org
Apache License 2.0
921 stars 107 forks source link

Segment <-> Cuboid contact query broken #343

Open BloodWorkXGaming opened 4 years ago

BloodWorkXGaming commented 4 years ago

The build-in segment cuboid function often gives wrong results, or rather misses out on parts.

Code example plus working own implementation:

fn test_line_box(){
    // wtf-> x_min: 114.899994, x_max: , y_min: 703.65, y_max: 1142.6; seg: Segment { a: Point { coords: Matrix { data: [-1087.5709, -369.54813] } }, b: Point { coords: Matrix { data: [600.0, 1087.5] } } }
    let min = Point2::new(114.899994, 703.65);
    let max = Point2::new(725.1, 1142.6);

    let diff = min - max;
    let center = nalgebra::center(&min, &max);

    let p1 = Point2::new(-1087.5709, -369.54813);
    let p2 = Point2::new(600.0, 1087.5);

    let c = Cuboid::new( Vector2::new((diff[0] as f32).abs() /2f32, (diff[1] as f32).abs() / 2f32));
    let c_iso = Isometry::translation(center[0], center[1]);

    let seg = Segment::new(p1, p2);
    let seg_iso = Isometry::<f32>::identity();

    let res = nc::query::contact(&c_iso, &c, &seg_iso, &seg, 0.1f32);
    let own = collide_own(min[0], max[0], min[1], max[1], &seg);

    println!("res: {:?} <-> own: {}", res, own);
}

fn collide_own(
    min_x: f32,
    max_x: f32,
    min_y: f32,
    max_y: f32,
    seg: &Segment<f32>
) -> bool {
    let s1 = Segment::new(Point2::new(min_x, min_y), Point2::new(max_x, min_y));
    let s2 = Segment::new(Point2::new(min_x, max_y), Point2::new(max_x, max_y));

    let s3 = Segment::new(Point2::new(min_x, min_y), Point2::new(min_x, max_y));
    let s4 = Segment::new(Point2::new(max_x, min_y), Point2::new(max_x, max_y));

    let res1 = nc::query::closest_points_segment_segment(&Isometry::<f32>::identity(), seg, &Isometry::<f32>::identity(), &s1, 0.1);
    let res2 = nc::query::closest_points_segment_segment(&Isometry::<f32>::identity(), seg, &Isometry::<f32>::identity(), &s2, 0.1);
    let res3 = nc::query::closest_points_segment_segment(&Isometry::<f32>::identity(), seg, &Isometry::<f32>::identity(), &s3, 0.1);
    let res4 = nc::query::closest_points_segment_segment(&Isometry::<f32>::identity(), seg, &Isometry::<f32>::identity(), &s4, 0.1);

    match res1 {
        nc::query::ClosestPoints::Intersecting => { return true; }
        nc::query::ClosestPoints::WithinMargin(_, _) => { return true; }
        nc::query::ClosestPoints::Disjoint => {}
    };

    match res2 {
        nc::query::ClosestPoints::Intersecting => { return true; }
        nc::query::ClosestPoints::WithinMargin(_, _) => { return true; }
        nc::query::ClosestPoints::Disjoint => {}
    };

    match res3 {
        nc::query::ClosestPoints::Intersecting => { return true; }
        nc::query::ClosestPoints::WithinMargin(_, _) => { return true; }
        nc::query::ClosestPoints::Disjoint => {}
    };

    match res4 {
        nc::query::ClosestPoints::Intersecting => { return true; }
        nc::query::ClosestPoints::WithinMargin(_, _) => { return true; }
        nc::query::ClosestPoints::Disjoint => {}
    };

    return false;
}