Skip to content

fix: keep friction when the tangent effective-mass matrix is singular - #1048

Open
Quacky2200 wants to merge 1 commit into
dimforge:masterfrom
Quacky2200:fix/plane-locked-friction
Open

Quacky2200 wants to merge 1 commit into
dimforge:masterfrom
Quacky2200:fix/plane-locked-friction

Conversation

@Quacky2200

@Quacky2200 Quacky2200 commented Oct 19, 2026 •

Copy link
Copy Markdown

Fixes #1047

Description

The 3D friction solve inverts the 2x2 tangent effective-mass matrix K to solve both friction directions together. When one tangent has no effective mass, K is singular: a body whose z translation and x/y rotations are locked (kept in a plane, as 2D bodies in a 3D world are) has k22 = 0 and k12 = 0. simd_inv(det) then returns 0, so friction along both tangents was dropped and the body slid as if on ice.

The shared solve moves into tangent_delta_impulse, used by both ContactConstraintTangentPart (Coulomb) and ContactConstraintTangentPartSlim (Simplified). When det(K) <= 1e-6 * k11 * k22, each tangent is solved on its own (dvel_i / k_ii, a no-op for a zero k_ii); otherwise the result is the same as before. The 2D build and the generic (multibody) constraints already solve per tangent and are unchanged.

tests/plane_locked_friction.rs: a plane-locked cuboid shoved at 3 m/s now stops where a free one does (0.91 m); it slid 9 m before.

image-1792424318986

Edit: Uploaded gif

The 3D friction solve inverts the 2x2 tangent effective-mass matrix K to
solve both friction directions together. When one tangent has no
effective mass, K is singular: a body whose z translation and x/y
rotations are locked (kept in a plane, as 2D bodies in a 3D world are)
has k22 = 0 and k12 = 0. simd_inv(det) then returns 0, so friction along
both tangents was dropped and the body slid as if on ice.

The shared solve moves into tangent_delta_impulse, used by both
ContactConstraintTangentPart (Coulomb) and ContactConstraintTangentPartSlim
(Simplified). When det(K) <= 1e-6 * k11 * k22, each tangent is solved on
its own (dvel_i / k_ii, a no-op for a zero k_ii); otherwise the result is
the same as before. The 2D build and the generic (multibody) constraints
already solve per tangent and are unchanged.

tests/plane_locked_friction.rs: a plane-locked cuboid shoved at 3 m/s now
stops where a free one does (0.91 m); it slid 9 m before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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

Successfully merging this pull request may close these issues.

Friction is lost for 3D bodies locked to a plane (locked translation + perpendicular rotations)

1 participant