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

Shape casting returns incorrect normals #193

Open
sweglord227 opened this issue Apr 29, 2024 · 1 comment
Open

Shape casting returns incorrect normals #193

sweglord227 opened this issue Apr 29, 2024 · 1 comment

Comments

@sweglord227
Copy link

Coming from bevy_xpbd, normals are very imprecise when using shape casts via bevy_xpbd's spacial query's shape_hits function. i am creating a kinematic character controller, and it gives incorrect values when moving almost orthogonal to colliders, even when they are completely aligned to grid. it isn't by a ton, but it's enough to clip through colliders. after discussing it with the creator of bevy_xpbd and a mod of the bevy discord, i was told it was likely a parry issue and to report it here.

i've also noticed that normals are almost never returned normalized. there tends to be a bit of fluff in one axis or the other, even when colliding head on.

if you need anything else from me, please let me know.

in the image i was clipping into a 10x5x0.1 (bevy coordinates) meter wall aligned to grid. collisions work fine when pushing directly against the wall, but fail when moving into it at a shallow angle.

image

@HeartofPhos
Copy link

HeartofPhos commented Nov 29, 2024

I've created some examples where normals behave strangely
In all cases a target shape is intersecting slightly with the Y+ face of a cuboid, but a minor difference in penetration results in very different normals

In this case I believe the intended functionality is to always have N2 be [0.0, 1.0, 0.0] (with some floating point imprecision)

Tested on version 0.17.4

use parry3d::{
    math::{Isometry, Vector},
    query::{self, ShapeCastOptions},
    shape::{Ball, Capsule, Cuboid, Shape},
};

fn main() {
    let cases: [fn() -> (Box<dyn Shape>, Isometry<f32>); 4] = [
        // broken
        // N1 [[0.7068505, 0.026921066, 0.7068505]]
        // N2 [[-0.7068505, -0.026921066, -0.7068505]]
        || {
            let g = Capsule::new_y(5.0, 1.0);
            let pos = Isometry::translation(0.0, g.half_height() - 0.01, 0.0);

            (Box::new(g), pos)
        },
        // working
        // N1 [[4.7682978e-8, -1.0, 4.7682978e-8]]
        // N2 [[-4.7682978e-8, 1.0, -4.7682978e-8]]
        || {
            let g = Capsule::new_y(5.0, 1.0);
            let pos = Isometry::translation(0.0, g.half_height() - 0.02, 0.0);

            (Box::new(g), pos)
        },
        // broken
        // N1 [[-0.70708853, -0.007185684, -0.70708853]]
        // N2 [[0.70708853, 0.007185684, 0.70708853]]
        || {
            let g = Ball::new(1.0);
            let pos = Isometry::translation(0.0, g.radius - 0.2, 0.0);

            (Box::new(g), pos)
        },
        // working
        // N1 [[-0.0, -1.0, -0.0]]
        // N2 [[0.0, 1.0, 0.0]]
        || {
            let g = Ball::new(1.0);
            let pos = Isometry::translation(0.0, g.radius - 0.200001, 0.0);

            (Box::new(g), pos)
        },
    ];

    let (g1, pos1) = cases[0]();
    // velocity not being straight down seems to play a part
    let vel1 = Vector::new(0.1, 1.0, 0.0);

    let g2 = Cuboid::new(Vector::new(20.0, 1.0, 20.0));
    let pos2 = Isometry::translation(0.0, -g2.half_extents.y, 0.0);
    let vel2 = Vector::new(0.0, 0.0, 0.0);

    let options = ShapeCastOptions {
        compute_impact_geometry_on_penetration: true,
        ..Default::default()
    };

    let result = query::cast_shapes(&pos1, &vel1, &*g1, &pos2, &vel2, &g2, options);

    if let Some(result) = result.unwrap() {
        println!("// N1 {:?}", result.normal1);
        println!("// N2 {:?}", result.normal2);
        println!("{:?}", result.status);
    }
}

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