rapier
rapier copied to clipboard
[Bug?] Contact of circle and polyline at its vertex produces 0 normal
Not sure if this is something fixable as I'm not familiar with the math, but (seemingly) when a circle touches a line just at its vertex, a normal of 0 is produced.
In the case of a one-way platform, this can cause spurious collisions on the very ends of a platform when pass-through is supposed to happen.
Edit: I did some further testing and it seems that the circle wasn't even touching the line when this happens. See below ASCII art.
______o
Zero normal contact is reported when the circle sits right beside the line, aligned but not touching it.
Here's a minimal test case:
use rapier2d::pipeline::*;
use rapier2d::dynamics::*;
use rapier2d::geometry::*;
use rapier2d::na::*;
fn main() {
let mut pipeline = PhysicsPipeline::new();
let gravity = Vector2::new(0.0, 0.0);
let integration_parameters = IntegrationParameters::default();
let mut broad_phase = BroadPhase::new();
let mut narrow_phase = NarrowPhase::new();
let mut bodies = RigidBodySet::new();
let mut colliders = ColliderSet::new();
let mut joints = JointSet::new();
let mut ccd_solver = CCDSolver::new();
// Circle
let body = RigidBodyBuilder::new_dynamic()
.translation(11.0, 0.0).build(); // Sits beyond the edge of the ground defined below.
let handle = bodies.insert(body);
let collider = ColliderBuilder::ball(1.0)
.translation(0.0, 1.0)
.modify_solver_contacts(true)
.build();
colliders.insert(collider, handle, &mut bodies);
// Ground
let body = RigidBodyBuilder::new_static().build();
let handle = bodies.insert(body);
let collider = ColliderBuilder::polyline(vec![
Point2::new(-10.0, 0.0),
Point2::new(10.0, 0.0),
], None).build();
colliders.insert(collider, handle, &mut bodies);
loop {
pipeline.step(
&gravity,
&integration_parameters,
&mut broad_phase,
&mut narrow_phase,
&mut bodies,
&mut colliders,
&mut joints,
&mut ccd_solver,
&MyHook,
&(),
);
}
}
// Convenience to detect contacts
struct MyHook;
impl PhysicsHooks for MyHook {
fn active_hooks(&self) -> PhysicsHooksFlags {
PhysicsHooksFlags::MODIFY_SOLVER_CONTACTS
}
fn modify_solver_contacts(&self, context: &mut ContactModificationContext) {
if context.manifold.local_n1.x == 0.0 && context.manifold.local_n1.y == 0.0 {
println!("Zero normal!");
}
}
}
Hi! This is a bug. A zero normal may be returned in the case where the center of the circle is located on the line. But it should not be zero in other cases.
Thanks for the reply! It looks like I'll wait for the fix rather than try to terribly hack my code then :)