The Problem: Computers Can't Do Calculus
Physics equations describe change with derivatives: velocity is the rate of change of position, acceleration is the rate of change of velocity. In continuous maths, this is calculus. In a computer, time has to be chopped into small discrete steps (called a timestep, Δt). The question is: how accurately can we approximate the continuous motion with these tiny steps?
The answer depends on the integration method. A poor method drifts over time — energy builds up artificially until simulated springs explode. A good method holds the total energy of the system nearly constant for thousands of steps.
Key insight: Every physics simulation on this site is running one of these three methods (or a combination) hundreds of times per second. The choice directly affects whether a pendulum stays stable for 10 minutes or oscillates into infinity after 30 seconds.
The Three Methods
The simplest method: use the current velocity to estimate where you'll be after Δt, then update. One function evaluation per step. Fast, but accumulates error — energy slowly increases, causing orbits to spiral outward and springs to explode.
// Explicit Euler
position += velocity * dt;
velocity += acceleration * dt;
Takes four estimates of the derivative within each timestep and takes a weighted average. Dramatically better accuracy than Euler with only 4× the cost. The standard choice for ballistics, orbital mechanics, and chemistry simulations.
// Simplified RK4 for position/velocity
const k1 = f(t, state);
const k2 = f(t + dt/2, state + k1*dt/2);
const k3 = f(t + dt/2, state + k2*dt/2);
const k4 = f(t + dt, state + k3*dt);
state += (k1 + 2*k2 + 2*k3 + k4) * dt/6;
A clever trick: velocity and position are staggered by half a timestep. This keeps the total energy of the system nearly constant over very long simulations — perfect for molecular dynamics and cloth where the sim has to run indefinitely. Used internally by Cannon-es (the physics engine on this site).
// Velocity Verlet
posNext = pos + vel*dt + 0.5*acc*dt*dt;
velNext = vel + 0.5*(acc + accNext)*dt;
Which Simulations Use Which Method?
- Ballistics — RK4 with atmospheric drag; Euler would accumulate enough error to miss a target by metres.
- Cloth Simulation — Velocity Verlet via Cannon-es; the cloth would explode under sustained tension with Euler.
- Binary Stars — Symplectic Euler (a variant that conserves energy better than explicit Euler) for long-term orbital stability.
- Drug Diffusion — RK4 on an ODE system; the concentration compartments need to be tracked accurately over hours.
- Boids — Explicit Euler; steering forces change every frame anyway, so accuracy beyond Δt doesn't matter.
The Fixed-Timestep Pattern
One additional complication: monitors refresh at 60 Hz but frames don't always take exactly 1/60 second to render. If the physics timestep equals the render timestep, a slow frame means a big Δt, which can make stiff springs explode.
The solution — used in all complex simulations here — is a fixed timestep with accumulation:
const FIXED_DT = 1 / 120; // 120 Hz physics
let accumulator = 0;
function tick(realDt) {
accumulator += realDt;
while (accumulator >= FIXED_DT) {
physics.step(FIXED_DT);
accumulator -= FIXED_DT;
}
render(); // runs at display rate
}
Physics always advances in identical, safe steps regardless of how long rendering takes. The render just draws wherever the physics currently is.