Repository navigation
Shape casting returns incorrect normals #193
Copy link
Copy link
Closed
Labels
Description
Activity
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 normalsIn 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); } }
Reacted by sweglord227- added 2 commits that reference this issue
on Aug 7, 2026
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.