Skip to content

Commit

Permalink
Fix solver contact normal for rotated child colliders (#409)
Browse files Browse the repository at this point in the history
# Objective

Fixes #407.

The solver rework caused a regression where contact normals didn't take the rotation of child colliders into account in the contact solver, leading to buggy collisions.

## Solution

Transform the normal correctly. Also remove unnecessary transformations of the normals of the individual contact points in the contact solver, as they are not used anywhere.
  • Loading branch information
Jondolf committed Jul 9, 2024
1 parent 5f24434 commit 803ec63
Showing 1 changed file with 9 additions and 4 deletions.
13 changes: 9 additions & 4 deletions src/dynamics/solver/contact/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,14 @@ impl ContactConstraint {
let collision_margin: Scalar = collision_margin.into().0;
let speculative_margin: Scalar = speculative_margin.into().0;

let normal = *body1.rotation * manifold.normal1;
// Local-space outward contact normal on the first body.
// The normal is transformed from collider-space to body-space.
let local_normal1 = collider_transform1.map_or(manifold.normal1, |transform| {
transform.rotation * manifold.normal1
});

// The world-space normal used for the contact solve.
let normal = *body1.rotation * local_normal1;

// TODO: Cache these?
// TODO: How should we properly take the locked axes into account for the mass here?
Expand All @@ -126,14 +133,12 @@ impl ContactConstraint {
constraint.tangent_directions(body1.linear_velocity.0, body2.linear_velocity.0);

for mut contact in manifold.contacts.iter().copied() {
// Transform contact data from collider-space to body-space.
// Transform contact points from collider-space to body-space.
if let Some(transform) = collider_transform1 {
contact.point1 = transform.rotation * contact.point1 + transform.translation;
contact.normal1 = transform.rotation * contact.normal1;
}
if let Some(transform) = collider_transform2 {
contact.point2 = transform.rotation * contact.point2 + transform.translation;
contact.normal2 = transform.rotation * contact.normal2;
}

contact.penetration += collision_margin;
Expand Down

0 comments on commit 803ec63

Please sign in to comment.