💡 Reference · Physics Engines
📅 March 2026 ⏱ Reference 🎯 Real-time physics

Game Physics Formulas — Cheat Sheet

All essential equations for building real-time physics engines: impulse-momentum, collision response with friction, spring-damper systems, rigid body dynamics, inertia tensors for common shapes, and numerical integration methods compared.

1. Kinematics and Newton's Laws

Newton's 2nd Law (translational):
F = m·a     a = F/m

Newton's 2nd Law (rotational):
τ = I·α     α = I⁻¹·τ

Kinematic integration (per timestep dt):
v += a·dt
x += v·dt

Kinetic energy:
KE_trans = ½·m·v²
KE_rot = ½·ω·I·ω

Momentum:
p = m·v    (linear)
L = I·ω    (angular)
Symbol Meaning SI Unit
m mass kg
F force N = kg·m/s²
a acceleration m/s²
v velocity m/s
x position m
τ torque N·m
I moment of inertia tensor kg·m²
α angular acceleration rad/s²
ω angular velocity rad/s

2. Impulse and Collision Response

When two rigid bodies collide at contact point P, we apply an impulse J along the contact normal n̂.

Relative velocity at contact point:
v_rel = (v_A + ω_A × r_A) − (v_B + ω_B × r_B)
v_n = dot(v_rel, n̂) (normal component, negative = approaching)

Impulse magnitude (frictionless):
j = −(1 + e) · v_n / K

Effective mass K:
K = 1/m_A + 1/m_B
+ dot((I_A⁻¹·(r_A × n̂)) × r_A, n̂)
+ dot((I_B⁻¹·(r_B × n̂)) × r_B, n̂)

Velocity update:
v_A' = v_A + (j/m_A)·n̂
ω_A' = ω_A + I_A⁻¹·(r_A × j·n̂)
v_B' = v_B − (j/m_B)·n̂
ω_B' = ω_B − I_B⁻¹·(r_B × j·n̂)

e = coefficient of restitution (0 = perfectly inelastic, 1 = elastic)
Material pair e (approx)
Steel on steel 0.55–0.75
Rubber ball on floor 0.75–0.85
Superball 0.90–0.95
Clay on clay 0 (plastic impact)
Glass on glass 0.95
Golf ball 0.68
Basketball 0.70–0.75
function resolveCollision(bodyA, bodyB, contact) {
  const n = contact.normal; // unit normal A→B
  const rA = contact.point.sub(bodyA.pos);
  const rB = contact.point.sub(bodyB.pos);
  const vRel = bodyA.vel.add(rA.cross(bodyA.angVel))
                  .sub(bodyB.vel).sub(rB.cross(bodyB.angVel));
  const vn = vRel.dot(n);
  if (vn >= 0) return; // separating — skip
  const e = 0.7;
  const rAxN = rA.cross(n), rBxN = rB.cross(n);
  const K = bodyA.invMass + bodyB.invMass
          + rAxN.dot(bodyA.invInertia.mulVec(rAxN))
          + rBxN.dot(bodyB.invInertia.mulVec(rBxN));
  const j = -(1 + e) * vn / K;
  bodyA.vel = bodyA.vel.add(n.scale(j * bodyA.invMass));
  bodyB.vel = bodyB.vel.sub(n.scale(j * bodyB.invMass));
  bodyA.angVel = bodyA.angVel.add(bodyA.invInertia.mulVec(rAxN).scale(j));
  bodyB.angVel = bodyB.angVel.sub(bodyB.invInertia.mulVec(rBxN).scale(j));
}

3. Friction and Contact Forces

Coulomb friction:
|f_t| ≤ μ · |f_n|

If sliding:   f_t = −μ_k · |f_n| · t̂   (kinetic friction)
If not sliding: |f_t| ≤ μ_s · |f_n|   (static friction cone)

μ_s ≈ 1.2–1.4 × μ_k  (static always slightly larger)

Impulse-based friction (tangential impulse):
v_t = v_rel − dot(v_rel, n̂)·n̂  (tangential relative velocity)
j_t = −dot(v_t, t̂) / K_t  (tangential impulse)
Clamp: |j_t| ≤ μ·|j_n|   (friction cone)
Material pair μ_s (static) μ_k (kinetic)
Steel on steel (dry) 0.74 0.57
Steel on steel (greased) 0.15 0.09
Rubber on concrete (dry) 0.8 0.75
Wood on wood 0.4 0.2
Ice on ice 0.03 0.02
Teflon on Teflon 0.04 0.04
Simplified game friction: Most game engines use a single friction coefficient and apply friction_impulse = clamp(j_t, -μ·j_n, +μ·j_n). To distinguish static/kinetic, check if tangential slip velocity exceeds a small threshold (e.g. 0.01 m/s).

4. Spring-Damper Systems

Hooke's Law (linear spring):
F_spring = −k · (x − x_rest)

Damper (viscous):
F_damper = −c · v

Spring-damper combined:
F = −k·Δx − c·v

Critical damping:
c_critical = 2·√(k·m)

Damping ratio:
ζ = c / (2·√(k·m))
ζ < 1: underdamped (oscillates)
ζ = 1: critically damped (fastest return, no oscillation)
ζ > 1: overdamped (slow return)

Natural frequency:
ω_n = √(k/m)  [rad/s]
f_n = ω_n / (2π)  [Hz]

Rotational Spring (torsional)

τ = −k_r · (θ − θ_rest) − c_r · ω

Same damping ratio formula: ζ = c_r / (2·√(k_r · I))
// Spring-damper force between two connected bodies
function springDamper(posA, posB, velA, velB, restLength, k, c) {
  const delta = posB.sub(posA);
  const dist  = delta.length();
  if (dist < 1e-8) return Vec3.zero;
  const dir   = delta.scale(1/dist);
  const stretch = dist - restLength;
  const relVel  = velB.sub(velA).dot(dir); // signed velocity along spring
  const force   = k * stretch + c * relVel;
  return dir.scale(force); // apply to A; negate for B
}
Stability: For explicit Euler integration, a spring is numerically stable when k·dt² < 2·m. If your spring bounces/explodes, either reduce k, increase mass, or switch to semi-implicit Euler (update velocity first, then position from new velocity).

5. Rigid Body Dynamics

State representation:
Position: x ∈ ℝ³
Orientation: q ∈ SO(3) (quaternion preferred)
Linear mom: p = m·v
Angular mom: L = I_world · ω

World-space inertia tensor:
I_world = R · I_body · R^T
(R = rotation matrix from quaternion)

Equations of motion:
dx/dt = v = p/m
dp/dt = F_ext
dq/dt = ½ · Q(ω) · q  (quaternion derivative)
dL/dt = τ_ext
ω = I_world⁻¹ · L

Force from angular velocity Coriolis (rotating frame):
Note: ω × (ω × r) is centripetal, ω × v is Coriolis — only needed in rotating reference frames.

Quaternion Integration

Quaternion derivative from angular velocity ω:
dq/dt = ½ · [0, ω] ⊗ q

Integration (explicit Euler, dt small):
q += ½ · [0, ω] ⊗ q · dt
q = normalize(q)  <-- IMPORTANT: renormalise every step
function integrateRigidBody(body, dt) {
  // Update linear state
  body.vel.addScaledVector(body.force,  body.invMass  * dt);
  body.pos.addScaledVector(body.vel,    dt);
  // Update angular state
  body.angVel.addScaledVector(body.torque, body.invInertiaWorld * dt); // simplified scalar
  // Quaternion integrate
  const dq = new Quaternion(0, body.angVel.x, body.angVel.y, body.angVel.z)
               .multiply(body.orient).scale(0.5 * dt);
  body.orient.add(dq).normalize();
  // Clear forces
  body.force.set(0,0,0);
  body.torque.set(0,0,0);
}

6. Inertia Tensors Reference

All tensors are diagonal in body space (aligned with symmetry axes). R = radius, L = length, a/b/c = half-extents.

Solid Sphere (mass m, radius R)

I = (2/5)mR²·
1
0
0
0
1
0
0
0
1

Hollow Sphere (thin shell)

I = (2/3)mR² for all axes

Solid Cylinder (axis along z, radius R, height H)

I_xx = I_yy = m(3R² + H²)/12
I_zz = mR²/2

Solid Box (half-extents a, b, c along x, y, z)

I_xx = m(b² + c²)/3
I_yy = m(a² + c²)/3
I_zz = m(a² + b²)/3

Solid Cone (radius R, height H, apex at top, base centred)

I_xx = I_yy = m(3R²/20 + 3H²/80)  (about centroid, H/4 from base)
I_zz = 3mR²/10

Thin Rod (length L, axis along z)

I_xx = I_yy = mL²/12  (about centre)
I_zz ≈ 0
Parallel axis theorem: To shift inertia tensor from centroid to a point displaced by d = (dx, dy, dz):
I'_xx = I_xx + m·(dy² + dz²)
I'_yy = I_yy + m·(dx² + dz²)
I'_zz = I_zz + m·(dx² + dy²)

7. Numerical Integration

Method Order Energy Use case
Explicit Euler 1st Gains energy Simple demos, unstable for stiff springs
Semi-implicit Euler 1st (symplectic) Conserves (near) Rigid bodies, physics engines default
Verlet 2nd Conserves well Particle systems, cloth, molecular dynamics
Velocity Verlet 2nd Conserves well Standard for MD and physics engines
Leapfrog 2nd Symplectic N-body gravity, orbital mechanics
RK4 4th Slightly dissipative Accurate trajectories, small dt
Semi-implicit Euler (preferred for games):
v(t+dt) = v(t) + a(t)·dt
x(t+dt) = x(t) + v(t+dt)·dt  <-- uses new velocity

Velocity Verlet:
x(t+dt) = x(t) + v(t)·dt + ½·a(t)·dt²
a(t+dt) = F(x(t+dt))/m
v(t+dt) = v(t) + ½·(a(t) + a(t+dt))·dt

Leapfrog:
v(t+½dt) = v(t−½dt) + a(t)·dt
x(t+dt) = x(t) + v(t+½dt)·dt

8. Constraint Forces and Joints

Constraints restrict degrees of freedom by applying corrective impulses at each timestep. The constraint Jacobian J maps constraint error to generalised forces.

Distance constraint (rod):
C = |x_A − x_B| − L = 0  (positional error)
Ċ = dot((x_A−x_B)/|…|, v_A − v_B) = 0  (velocity error)

Baumgarte stabilisation (adds proportional term):
λ = −(Ċ + β/dt · C) / K
β ∈ [0,1] — stabilisation: 0.1–0.3 typical

Split impulse (position correction only):
Separate velocity correction impulse (affects vel) from
positional correction impulse (directly moves position).
Avoids artificial energy injection from positional correction.
Joint type DOF removed Equivalent
Ball-and-socket 3 translational Shoulder, hip
Hinge 3 trans + 2 rot Door hinge, elbow
Slider (prismatic) 3 trans + 3 rot − 1 Piston, linear actuator
Fixed All 6 Weld, glue
Cone (angular limit) Limits angular range Spine, shoulder limit
Position Based Dynamics (PBD): An alternative to impulse-based constraints (used in PhysX, Havok, Unity 2022+). Directly projects positions to satisfy constraints, then derives velocities from position change. Less physically accurate but very stable — preferred for soft bodies, cloth, and large systems.