💡 Довідник · Фізичні рушії
📅 Березень 2026 ⏱ Довідник 🎯 Фізика реального часу

Формули ігрової фізики — шпаргалка

Усі ключові рівняння для побудови фізичних рушіїв реального часу: імпульс-імпульс тіла, обробка зіткнень із тертям, системи пружина-демпфер, динаміка твердих тіл, тензори інерції для поширених форм та порівняння методів числового інтегрування.

1. Кінематика та закони Ньютона

Другий закон Ньютона (поступальний):
F = m·a     a = F/m

Другий закон Ньютона (обертальний):
τ = I·α     α = I⁻¹·τ

Кінематичне інтегрування (на крок часу dt):
v += a·dt
x += v·dt

Кінетична енергія:
KE_trans = ½·m·v²
KE_rot = ½·ω·I·ω

Імпульс:
p = m·v    (лінійний)
L = I·ω    (момент імпульсу)
Символ Значення Одиниця SI
m маса кг
F сила Н = кг·м/с²
a прискорення м/с²
v швидкість м/с
x позиція м
τ момент сили Н·м
I тензор моменту інерції кг·м²
α кутове прискорення рад/с²
ω кутова швидкість рад/с

2. Імпульс та обробка зіткнень

Коли два тверді тіла стикаються в точці контакту P, ми прикладаємо імпульс J уздовж нормалі контакту n̂.

Відносна швидкість у точці контакту:
v_rel = (v_A + ω_A × r_A) − (v_B + ω_B × r_B)
v_n = dot(v_rel, n̂) (нормальна складова, від'ємна = зближення)

Величина імпульсу (без тертя):
j = −(1 + e) · v_n / K

Ефективна маса 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̂)

Оновлення швидкості:
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 = коефіцієнт відновлення (0 = абсолютно непружне, 1 = пружне)
Пара матеріалів e (приблизно)
Сталь по сталі 0.55–0.75
Гумовий м'яч об підлогу 0.75–0.85
Супер-м'яч 0.90–0.95
Глина по глині 0 (пластичний удар)
Скло по склу 0.95
М'яч для гольфу 0.68
Баскетбольний м'яч 0.70–0.75
function resolveCollision(bodyA, bodyB, contact) {
  const n = contact.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; // розходяться — пропустити
  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. Тертя та контактні сили

Кулонівське тертя:
|f_t| ≤ μ · |f_n|

Якщо ковзає:   f_t = −μ_k · |f_n| · t̂   (кінетичне тертя)
Якщо не ковзає: |f_t| ≤ μ_s · |f_n|   (конус статичного тертя)

μ_s ≈ 1.2–1.4 × μ_k  (статичне завжди трохи більше)

Тертя на основі імпульсу (дотичний імпульс):
v_t = v_rel − dot(v_rel, n̂)·n̂  (дотична відносна швидкість)
j_t = −dot(v_t, t̂) / K_t  (дотичний імпульс)
Обмеження: |j_t| ≤ μ·|j_n|   (конус тертя)
Пара матеріалів μ_s (статичне) μ_k (кінетичне)
Сталь по сталі (суха) 0.74 0.57
Сталь по сталі (змащена) 0.15 0.09
Гума по бетону (суха) 0.8 0.75
Дерево по дереву 0.4 0.2
Лід по льоду 0.03 0.02
Тефлон по тефлону 0.04 0.04
Спрощене ігрове тертя: Більшість ігрових рушіїв використовують єдиний коефіцієнт тертя і застосовують friction_impulse = clamp(j_t, -μ·j_n, +μ·j_n). Щоб розрізнити статичне/кінетичне, перевірте, чи перевищує швидкість дотичного ковзання малий поріг (наприклад, 0.01 м/с).

4. Системи пружина-демпфер

Закон Гука (лінійна пружина):
F_spring = −k · (x − x_rest)

Демпфер (в'язкий):
F_damper = −c · v

Пружина-демпфер разом:
F = −k·Δx − c·v

Критичне демпфування:
c_critical = 2·√(k·m)

Коефіцієнт демпфування:
ζ = c / (2·√(k·m))
ζ < 1: недодемпфоване (коливається)
ζ = 1: критично демпфоване (найшвидше повернення, без коливань)
ζ > 1: передемпфоване (повільне повернення)

Власна частота:
ω_n = √(k/m)  [рад/с]
f_n = ω_n / (2π)  [Гц]

Обертальна пружина (крутильна)

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

Та сама формула коефіцієнта демпфування: ζ = c_r / (2·√(k_r · I))
// Сила пружини-демпфера між двома з'єднаними тілами
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); // знакова швидкість уздовж пружини
  const force   = k * stretch + c * relVel;
  return dir.scale(force); // застосувати до A; для B змінити знак
}
Стабільність: Для явного інтегрування Ейлера пружина числово стабільна, коли k·dt² < 2·m. Якщо ваша пружина відскакує/«вибухає», або зменшіть k, або збільшіть масу, або перейдіть до напівнеявного Ейлера (спочатку оновіть швидкість, потім позицію з нової швидкості).

5. Динаміка твердих тіл

Подання стану:
Позиція: x ∈ ℝ³
Орієнтація: q ∈ SO(3) (бажано кватерніон)
Лінійний імпульс: p = m·v
Момент імпульсу: L = I_world · ω

Тензор інерції у світовому просторі:
I_world = R · I_body · R^T
(R = матриця обертання з кватерніона)

Рівняння руху:
dx/dt = v = p/m
dp/dt = F_ext
dq/dt = ½ · Q(ω) · q  (похідна кватерніона)
dL/dt = τ_ext
ω = I_world⁻¹ · L

Сила від коріолісового члена кутової швидкості (обертова система):
Зауваження: ω × (ω × r) — доцентрова, ω × v — коріолісова — потрібні лише в обертових системах відліку.

Інтегрування кватерніонів

Похідна кватерніона за кутовою швидкістю ω:
dq/dt = ½ · [0, ω] ⊗ q

Інтегрування (явний Ейлер, мале dt):
q += ½ · [0, ω] ⊗ q · dt
q = normalize(q)  <-- ВАЖЛИВО: перенормовуйте на кожному кроці
function integrateRigidBody(body, dt) {
  // Оновити лінійний стан
  body.vel.addScaledVector(body.force,  body.invMass  * dt);
  body.pos.addScaledVector(body.vel,    dt);
  // Оновити кутовий стан
  body.angVel.addScaledVector(body.torque, body.invInertiaWorld * dt); // спрощений скаляр
  // Інтегрувати кватерніон
  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();
  // Скинути сили
  body.force.set(0,0,0);
  body.torque.set(0,0,0);
}

6. Довідник тензорів інерції

Усі тензори діагональні у власному просторі тіла (вирівняні з осями симетрії). R = радіус, L = довжина, a/b/c = піврозміри.

Суцільна куля (маса m, радіус R)

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

Порожниста сфера (тонка оболонка)

I = (2/3)mR² для всіх осей

Суцільний циліндр (вісь уздовж z, радіус R, висота H)

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

Суцільний паралелепіпед (піврозміри a, b, c уздовж x, y, z)

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

Суцільний конус (радіус R, висота H, вершина вгорі, основа центрована)

I_xx = I_yy = m(3R²/20 + 3H²/80)  (відносно центроїда, H/4 від основи)
I_zz = 3mR²/10

Тонкий стрижень (довжина L, вісь уздовж z)

I_xx = I_yy = mL²/12  (відносно центра)
I_zz ≈ 0
Теорема Гюйгенса-Штейнера (паралельних осей): Щоб зсунути тензор інерції від центроїда до точки, зміщеної на 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. Числове інтегрування

Метод Порядок Енергія Випадок застосування
Явний Ейлер 1-й Набирає енергію Прості демо, нестабільний для жорстких пружин
Напівнеявний Ейлер 1-й (симплектичний) Зберігає (майже) Тверді тіла, типовий для фізичних рушіїв
Верле 2-й Добре зберігає Системи частинок, тканина, молекулярна динаміка
Velocity Verlet 2-й Добре зберігає Стандарт для MD і фізичних рушіїв
«Чехарда» (Leapfrog) 2-й Симплектичний Гравітація N тіл, орбітальна механіка
RK4 4-й Трохи дисипативний Точні траєкторії, мале dt
Напівнеявний Ейлер (бажаний для ігор):
v(t+dt) = v(t) + a(t)·dt
x(t+dt) = x(t) + v(t+dt)·dt  <-- використовує нову швидкість

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

«Чехарда»:
v(t+½dt) = v(t−½dt) + a(t)·dt
x(t+dt) = x(t) + v(t+½dt)·dt

8. Сили обмежень та з'єднання

Обмеження зменшують ступені свободи, прикладаючи коригувальні імпульси на кожному кроці часу. Якобіан обмеження J відображає похибку обмеження на узагальнені сили.

Обмеження відстані (стрижень):
C = |x_A − x_B| − L = 0  (позиційна похибка)
Ċ = dot((x_A−x_B)/|…|, v_A − v_B) = 0  (похибка швидкості)

Стабілізація Баумгарте (додає пропорційний член):
λ = −(Ċ + β/dt · C) / K
β ∈ [0,1] — стабілізація: зазвичай 0.1–0.3

Розділений імпульс (лише корекція позиції):
Відокремте імпульс корекції швидкості (впливає на швидкість) від
імпульсу корекції позиції (напряму зсуває позицію).
Уникає штучного впорскування енергії від корекції позиції.
Тип з'єднання Прибрані ступені свободи Еквівалент
Кульове (сферичне) 3 поступальні Плече, кульшовий суглоб
Шарнір 3 пост. + 2 обер. Дверна петля, лікоть
Повзун (призматичне) 3 пост. + 3 обер. − 1 Поршень, лінійний привід
Жорстке Усі 6 Зварювання, склеювання
Конус (кутове обмеження) Обмежує кутовий діапазон Хребет, обмеження плеча
Position Based Dynamics (PBD) — динаміка на основі позицій: Альтернатива обмеженням на основі імпульсів (застосовується в PhysX, Havok, Unity 2022+). Напряму проектує позиції для задоволення обмежень, потім виводить швидкості зі зміни позиції. Менш фізично точна, але дуже стабільна — бажана для м'яких тіл, тканини та великих систем.