Drop a wooden crate onto a floor in a game and it just… sits there. Boring? It shouldn't be. Nothing in the physics engine knows what a floor is. Gravity is still tugging the crate downward at every single frame, trying to shove it straight through the ground. The reason it rests, flat and calm, is that the engine is doing hidden, frantic bookkeeping — computing exactly the right pushes, thousands of times a second, so that the crate is stopped precisely at the surface, tilts back if you lean it, and doesn't slide off a gentle slope. That bookkeeping is the world of constraints, contacts and friction.
This is the machinery that holds a ragdoll's limbs onto its joints, keeps a stack of boxes from
sinking into each other, lets a car's wheels grip a road, and stops a resting object from jittering
itself to death. It's the quiet other half of rigid-body simulation — the first half being
A constraint is a restriction on how bodies are permitted to move. We write it as a function of the positions that must stay zero:
For a hinge that pins two bodies at a shared point,
Here
The single most important distinction is whether the constraint is an equality or an inequality.
A ball-and-socket joint fixes 3 translational DOFs (the two anchor points must coincide) but leaves
all rotation free — a shoulder. A hinge additionally locks 2 rotational DOFs, leaving a single spin
axis — a door or an elbow. A slider (prismatic joint) leaves exactly one translational DOF — a
drawer. Each is just a different choice of which rows go into
Contacts are harder precisely because of the one-sidedness. At the velocity level a resting contact
demands the normal velocity stay non-negative,
Consider the humble worked example: a box resting on the ground. When the box's flat bottom face
meets the flat floor, the true contact is an area, not a point. But a solver works with a
finite set of points, so the collision system reduces that face-to-face touch to a small
contact manifold — typically the 4 corners of the overlapping
rectangle, each a contact point with its own outward normal
Why four? Imagine the engine kept only one contact point, say under the box's centre. That single upward push balances gravity vertically — but it applies no torque to resist tipping. The tiniest sideways nudge, or even floating-point noise, gives the box a rotation that the lone contact cannot oppose, and it teeters and rolls like a plank balanced on a pencil. With four contacts spread to the corners, a tip lifts one side: the contacts on the far side press harder (their non-penetration constraints fight the downward corner), the net of the four pushes produces a restoring torque, and the box settles flat. A stable rest needs a manifold wide enough to generate the righting torque — points, plural, spread across the contact area.
Non-penetration handles the normal direction. Friction handles the tangential one — the sliding along the surface. The classical model is Coulomb friction: the tangential friction force is bounded by a multiple of the normal force,
where
The circular friction cone couples the two tangent directions in a way that's expensive to solve
exactly, so real-time engines usually linearise it into a friction
pyramid — a box (or a polygonal prism) that approximates the cone with a few flat faces.
That turns the friction limit into simple per-axis clamps
A stack of boxes on a floor might have dozens of contacts, each with a non-penetration inequality and two friction limits, all coupled — pushing one contact changes the load on its neighbours. Written out, the normal-contact problem has exactly the complementarity structure we noticed earlier and forms a Linear Complementarity Problem (LCP):
Read the three pieces together: the surfaces may only separate (
Solving a big LCP exactly every frame is too slow for real time. The workhorse instead is an
iterative method: Projected Gauss–Seidel, known in the game-physics
world as sequential impulses. Walk through the constraints one at a time; for each,
compute the impulse that would satisfy that constraint in isolation, apply it immediately so
later constraints see the updated velocities, and project the result back into its
legal range — clamp the normal impulse to
Working purely at the velocity level has a flaw: it only stops things from getting worse. If
a box has already sunk a little into the floor (from a big timestep, or an accumulated error), keeping
a gentle bias velocity (with
The second trick is warm-starting. A resting stack barely changes from one frame to the next, so the impulses it needed last frame are an excellent first guess for this frame. Storing each contact's accumulated impulse and reapplying it before iterating means the solver starts already close to the answer — a stack that would take dozens of iterations to settle from scratch holds rock-steady with only a few, because it remembers how it was standing.
A joint constraint is enforced by an iterative solver that runs a fixed, small number of
passes per frame — it converges towards
Three closely-related traps sink beginner rigid-body code:
1. One impulse pass is not enough. Because the contacts are coupled, a single sweep over them under-solves the stack — the bottom box gets pushed up, but by the time you've processed it the boxes above have already been resolved against stale velocities. The visible result is a stack that jitters, sinks, or slowly collapses. You must iterate the projected Gauss–Seidel sweep several times per frame (and warm-start) for a tall stack to stand still.
2. Too few contact points let a resting object wobble. Reduce a flat face-face rest to a single point and the object has no torque resisting tip — it teeters. A resting object needs a contact manifold of enough points, spread across the contact area, to be stable.
3. Friction is an inequality — clamp it. The single most common friction bug is
treating it like an equality and applying whatever tangential impulse "kills" the sliding velocity.
That can apply more force than the surface can supply, gluing objects to walls or letting them climb
slopes they should slide down. You must clamp the tangential impulse to