Forces, Springs and Hooke's Law
A keyframed F-curve tells an object exactly where to be at every instant. A
physics-driven object is told nothing of the sort — instead you tell it what
forces push on it, and it works out its own motion. That single change of mindset —
from scripting positions to summing forces — is the engine behind everything that reacts in a
modern film or game: a cape that swings, hair that trails, cloth that settles, a camera that eases
after its target, a jelly that wobbles. And astonishingly, almost all of it is built from one humble
primitive: the damped spring.
This page builds motion the physical way. We accumulate forces into a net force, turn it into
acceleration with a = F/m, and then meet the spring — Hooke's law with a
dash of damping — as the workhorse from which cloth, hair, soft constraints and buttery UI follows are
all assembled. Along the way we meet the villain of real-time physics: a stiff spring that
explodes unless you tiptoe through time.
Accumulating forces
Newton's second law says the net force on a particle sets its acceleration. In an animation loop you
don't get one tidy force — you get a pile of them, and your job each frame is to add them up.
A particle starts each step with a zero force accumulator, and every influence in the scene throws its
contribution in:
- Gravity pulls straight down with a force m\mathbf{g}
(constant acceleration \mathbf{g}, independent of mass).
- Linear drag opposes motion in proportion to velocity,
-c\,\mathbf{v} — cheap, stable, good for "air".
- Quadratic drag opposes motion in proportion to speed squared,
-c\lvert\mathbf{v}\rvert\,\mathbf{v} — the real fluid law, for fast
projectiles.
- Applied forces — wind, thrust, an explosion impulse, a spring — each add their
own vector.
Sum them into \mathbf{F} = \sum_i \mathbf{F}_i, then
\mathbf{a} = \frac{\mathbf{F}}{m}.
Once you have \mathbf{a}, an integrator advances velocity and position over
the timestep \Delta t — that's the subject of
numerical integration.
The elegance is that forces compose: to add wind, you don't rewrite the solver, you just drop
another vector into the accumulator. That is why the same tiny loop can drive a single bouncing pebble
or a hundred thousand cloth particles.
The spring: Hooke's law
Connect two particles with an ideal spring of rest length
L and stiffness k. When the
spring is stretched or squashed away from L, it pulls (or pushes) the ends
back toward that comfortable length, and — this is Hooke's great observation — the force grows
linearly with how far you deform it.
Let \mathbf{x} be the vector from one end to the other,
\lvert\mathbf{x}\rvert its current length, and
\hat{\mathbf{x}} = \mathbf{x}/\lvert\mathbf{x}\rvert the unit direction
along it. The spring force on the far end is
\mathbf{F}_{\text{spring}} = -k\,\bigl(\lvert\mathbf{x}\rvert - L\bigr)\,\hat{\mathbf{x}}.
Read it piece by piece: \lvert\mathbf{x}\rvert - L is the
extension (positive when stretched, negative when compressed);
\hat{\mathbf{x}} points along the spring; the leading minus sign makes the
force restoring — a stretched spring pulls inward, a squashed spring pushes outward. Double
the stretch and you double the force. That linearity is what makes springs so predictable and so easy
to network together.
Only within limits. Hooke's law is a first-order approximation — the leading term of the
restoring force for small deformations. Stretch a metal spring too far and it yields; squash real
cloth and the fibres jam and the force shoots up nonlinearly. Animators exploit both: for gentle,
well-behaved motion the linear law is perfect and fast, but a cloth solver often adds a stiff
nonlinear term near full stretch so fabric refuses to pass through itself. The linear spring is the
honest, useful lie you start from.
Adding damping so it settles
A pure Hooke spring is a perpetual-motion machine: give it energy and it oscillates forever,
trading stretch for speed and back, never settling. Real springs lose energy to friction, and so must
ours — otherwise your cloth quivers eternally and your camera never stops ringing. We add a
damping force that opposes the rate at which the spring is changing length. With
\mathbf{v}_{\text{rel}} the relative velocity of the two ends, only the
component along the spring stretches it, so we damp exactly that:
\mathbf{F}_{\text{damp}} = -c\,\bigl(\mathbf{v}_{\text{rel}}\cdot\hat{\mathbf{x}}\bigr)\,\hat{\mathbf{x}}.
Here c is the damping coefficient. Projecting onto
\hat{\mathbf{x}} matters: it damps stretching without secretly braking a
particle that is merely swinging sideways, which would sap energy the spring never stored. The total
spring-plus-damper force is the sum of the two, and it always drains the oscillation toward rest.
The spring–mass equation and its four moods
Collapse the problem to one dimension — a mass on a spring, measuring
x as displacement from the rest length — and Newton's law
m\ddot{x} = \sum F becomes the most famous ODE in engineering:
m\,\ddot{x} = -k\,x - c\,\dot{x}.
Its character is governed entirely by the damping ratio
\zeta = \dfrac{c}{2\sqrt{km}}, comparing the actual damping to the special
value that just barely kills oscillation. Four moods:
- Undamped (\zeta = 0): a pure sine — it rings
forever at the natural frequency \omega_0 = \sqrt{k/m}.
- Underdamped (0 < \zeta < 1): a decaying
oscillation — it overshoots, wobbles, and eventually settles.
- Critically damped (\zeta = 1): the
fastest return to rest with no overshoot — the sweet spot for smooth
follows.
- Overdamped (\zeta > 1): no overshoot either, but
sluggish — it crawls home slower than critical.
The critical value falls out of setting \zeta = 1:
c_{\text{crit}} = 2\sqrt{km}.
Below it you get wobble; above it you get molasses; right at it you get the crispest settle physics
allows. Play with the slider below to feel all four.
Watching it settle
Below is the trajectory of a mass released from a unit stretch at rest (m=k=1,
so \omega_0 = 1). Slide the damping ratio \zeta
and watch the bold curve change mood. The faint line is the undamped reference
(\zeta=0, a cosine that never dies); the dashed curve is
critical damping (\zeta=1). Notice how any
\zeta < 1 dips below the axis — that dip is the overshoot — while
\zeta \ge 1 glides home without ever crossing zero.
For a smooth camera or UI "follow", \zeta = 1 is almost always what you
want: chase a target with a critically-damped spring and the object slides after it and stops dead on
arrival — no jelly wobble, no lag-then-snap. Tuning that one number is the difference between a camera
that feels alive and one that feels seasick.
Worked example: release from a stretch, damp it just right
A 2\,\text{kg} mass hangs on a spring of stiffness
k = 200\,\text{N/m}. We pull it 0.1\,\text{m}
below its rest length and release it from rest. We want it to return as fast as possible without
overshooting — critical damping. What forces act, and what c do we
pick?
1. The forces. Measuring x from the rest length (gravity's
constant pull just shifts where "rest" is, so it drops out of the deviation), the spring pulls with
-kx = -200x and the damper with -c\dot{x}. The
equation of motion is 2\ddot{x} = -200x - c\dot{x}.
2. Critical damping. Set \zeta = 1:
c_{\text{crit}} = 2\sqrt{km} = 2\sqrt{200 \cdot 2} = 2\sqrt{400} = 40\ \text{N·s/m}.
3. The settle. The natural frequency is
\omega_0 = \sqrt{k/m} = \sqrt{100} = 10\,\text{rad/s}. At critical damping
the motion is
x(t) = x_0\,e^{-\omega_0 t}\,(1 + \omega_0 t) = 0.1\,e^{-10t}(1 + 10t). It
eases straight back toward zero, never crossing the axis, and is practically home within a few
multiples of the time constant 1/\omega_0 = 0.1\,\text{s} — about a third of
a second. Nudge c below 40 and it would overshoot
and wobble; push it above and it would crawl. Forty is the crisp answer.
Springs everywhere
Once you trust the damped spring, you stop building special-case animation systems and start wiring
springs together:
- Cloth — a grid of masses joined by structural springs (along the weave),
shear springs (diagonals) and bend springs (skip-a-neighbour), each a Hooke term.
Wind is just another force in the accumulator.
- Hair & ropes — a chain of masses with stiff springs (or length constraints)
between beads; damping keeps the strand from whipping forever.
- Soft bodies & jelly — fill a shape with springs and it wobbles and recovers
its form.
- Soft constraints — instead of rigidly pinning A to B, connect them with a stiff
damped spring: a "goal" that's mostly obeyed but yields under stress, which looks far more natural
than a hard weld.
- Camera & UI follow — drag a value toward a target with a critically-damped
spring for that smooth, overshoot-free "chase" — the secret behind good camera lag and springy menus.
Each of these is the same force law, replicated and connected. Learn the one primitive and you
have learned a large slice of production animation.
Stiffness, and why hard springs bite
Turn k up and the spring gets stiff: it snaps back
violently, oscillating at a high frequency \omega_0 = \sqrt{k/m}. That
speed is exactly the problem for a solver. An explicit integrator estimates the future from the
current force, which is only trustworthy while the force barely changes over one step. A
stiff spring's force swings wildly within a single frame, so unless \Delta t
is tiny — roughly \Delta t \lesssim 2/\omega_0 for stability — the estimate
overshoots, then over-corrects harder, and the numbers blow up to infinity. This is a
stiff ODE: the physics is fine, the method can't keep up.
The cures all trade against each other: shrink \Delta t (accurate but
slow), substep (run several small physics steps per rendered frame), soften the
spring (lower k, if the look allows), or switch to a method built for
stiffness — an implicit integrator (solves for the next force, stable at any
step) or a position-based scheme (satisfies constraints directly rather than through
forces). Which to reach for is the whole story of
numerical integration.
Two classic ways a spring rig goes wrong, and their fixes:
- The explosion. A stiff spring (large k) with
explicit integration and a normal-sized \Delta t doesn't just look
wrong — it diverges to \pm\infty (cloth flings off to the horizon, "NaN
soup"). The step is too big for how fast the force changes. Fix: shrink or
substep \Delta t, lower k,
or move to an implicit / position-based method that stays stable at any step.
- The eternal ring. Forget the damping term and even a stable spring oscillates
forever — your cloth shivers, your camera bobs and never settles. Fix: add the
-c\dot{x} damper, and for a clean settle aim near
c = 2\sqrt{km} (critical).
Because frequency is \omega_0 = \sqrt{k/m} — mass sits in the denominator.
Quadruple the mass and the oscillation slows by half (the period doubles). This is why animators cheat
weight with springs: to make an object read as heavy, you don't redraw it, you lower its
natural frequency — a slower, lazier wobble — and add a touch more damping so it settles ponderously.
A light, twitchy prop gets a high k/m and a fast, nervous ring. The same
spring math, retuned, becomes a performance dial for weight.