3. Скоростные ограничения
Интро
В предыдущих методах мы решали ограничения с помощью манипуляций позиций и поворотов тел. Он отлично работает для симуляции мягких тел, волос, тканей и прочего. Наиболее успещный метод среди позиционных – XPBD. Но у него есть недостаток: он дает несовсем правильные скорости тел. Для того чтобы получить скорости мы делали много вещей – вычисляли скорость из старой позиции и исправленной. Дополнительно пытались учесть трение и отталкивание.
Поэтому умные ребята придумали другой способ разрешать ограничения.
Основная идея такая: Давайте посмотрим как бы мы разрешали коллизии для шариков. Мы бы просто выставили скорость шарика так, чтобы при столкновении мы получали отражение.
Решение столкновения шариков
1. Дано:
- Массы сфер: $m_1$ и $m_2$
- Скорости сфер до столкновения: $\vec{v_1}$ и $\vec{v_2}$
- Радиусы сфер: $r_1$ и $r_2$
- Коэффициент упругости $e$, где $e = 1$ для абсолютно упругого столкновения и $e < 1$ для частично упругого.
- Положение центров сфер до удара: $\vec{r_1}$ и $\vec{r_2}$
2. Расчёт нормальной составляющей скорости:
Сначала находим нормальный вектор столкновения, который направлен вдоль линии, соединяющей центры двух сфер:
\begin{equation} \hat{n} = \frac{\vec{r_2} - \vec{r_1}}{|\vec{r_2} - \vec{r_1}|} \end{equation}
Касательный вектор $\hat{t}$ будет перпендикулярен $\hat{n}$, но для нас важна только нормальная составляющая при упругом столкновении.
3. Проекция скоростей на нормальный вектор:
Теперь проектируем скорости сфер на нормальный вектор:
\begin{equation} \begin{split} &v*{1n} = \vec{v_1} \cdot \hat{n} \ &v*{2n} = \vec{v_2} \cdot \hat{n} \end{split} \end{equation}
Эти проекции — скорости сфер вдоль линии столкновения.
4. Закон сохранения импульса:
При упругом столкновении сохраняется и импульс, и кинетическая энергия. Для нормальных составляющих скоростей:
\begin{equation} m1 v{1n} + m2 v{2n} = m1 v’{1n} + m2 v’{2n} \end{equation}
где $v’{1n}$ и $v’{2n}$ — нормальные компоненты скоростей после удара.
5. Закон коэффициента упругости:
Коэффициент упругости $e$ описывает, насколько изменится относительная скорость сфер после удара по сравнению с до удара:
\begin{equation} e = \frac{v’{2n} - v’{1n}}{v*{1n} - v*{2n}} \end{equation}
Для абсолютно упругого удара, где $e = 1$, это становится:
\begin{equation} v’{2n} - v’{1n} = v*{1n} - v*{2n} \end{equation}
6. Решение системы уравнений:
Теперь у нас есть два уравнения:
- $m_1 v_{1n} + m_2 v_{2n} = m_1 v’{1n} + m_2 v’{2n}$
- $v’{2n} - v’{1n} = v_{1n} - v_{2n}$
Решив их, получаем нормальные компоненты скоростей после удара:
\begin{equation} \begin{split} &v’{1n} = \frac{(m_1 - e m_2) v{1n} + (1 + e) m2 v{2n}}{m1 + m_2} \ &v’{2n} = \frac{(m2 - e m_1) v{2n} + (1 + e) m1 v{1n}}{m_1 + m_2} \end{split} \end{equation}
7. Скорости после удара:
После того как мы нашли нормальные составляющие скоростей $v’{1n}$ и $v’{2n}$, можем вычислить итоговые скорости сфер:
\begin{equation} \begin{split} &\vec{v’1} = \vec{v_1} + (v’{1n} - v*{1n}) \hat{n} \ &\vec{v’_2} = \vec{v_2} + (v’*{2n} - v_{2n}) \hat{n} \end{split} \end{equation}
Теперь у нас есть итоговые скорости сфер после столкновения.
Выглядит круто. Теперь нужно придумать, как это обобщить на произвольные ограничения.
Вот у нас есть какое-то ограничение зависящее от позиции
$$ C(x) = 0 $$
Если продифференцировать это ограничение по времени, то получим скорость точки в направлении ограничения.
$$ \dot{C}(x) = \frac{dC}{dx} \cdot \dot{x} $$
Теперь мы можем использовать это уравнение для того чтобы изменить скорость точки так, чтобы она удовлетворяла ограничению. Если мы в каждый момент времени будет выставлять скорость точки правильным образом, то оригинальное ограничение будет удовлетворено.
Пример
Рассмотрим ситуацию, когда обычный кубик падает на пол и касается одной точкой пола.

Ограничение на позицию кубика
$$ C(x) = x\cdot n - h > 0 $$
Где $n$ – нормаль к поверхности пола, $h$ – высота пола. Если продифференцировать это ограничение по времени, то получим скорость точки в направлении ограничения.
$$ \dot{C}(x) = n \cdot \dot{x} > 0 $$
Получается, очень простое требование: скорость точки касания должна быть направлена от пола. где $\dot{x}$ — скорость точки контакта.
Теперь, если у нас происходит удар, то в момент удара скорость в направлении ограничения должна испытывать скачок. Это скачок мы учитываем через импульс $J$, приложенный в точке контакта.
Обозначим:
$M$ — масса тела,
$\Delta{v_{cm}}$ - изменение скорости центра масс,
$\Delta{w_{cm}}$ - изменение угловой скорости,
$I$ — момент инерции тела в мировых координатах,
$r$ — вектор от центра масс до точки приложения импульса,
$J$ — импульс удара, который нужно найти.
Тогда закон сохранения импульса в точке контакта будет выглядеть так:
В общем случае (для твердого тела) импульс в точке изменяет: Линейную скорость центра масс и угловую скорость вокруг центра масс.
$$ \begin{align} M \cdot \Delta{v_{cm}} = J \\ I \cdot (\Delta{w_{cm}}) = r \times J \end{align} $$
Скорость точки контакта:
$$ \dot{x} = v_{cm} + w_{cm} \times r $$
Тогда изменение скорости точки контакта будет равно:
$$ \Delta{\dot{x}} = \Delta{v_{cm}} + \Delta{w_{cm}} \times r $$
Если подставить в это уравнение изменения скоростей центра масс, то получится:
$$ \Delta{\dot{x}} = \frac{1}{M} J + I^{-1} \cdot (r \times J) \times r $$
У нас получилось недоопределенное уравнение. Сейчас мы всего-то и требуем что бы скорость точки контакта была направлена от пола. Поэтому нужно добавить еще пару условий.
Первое условие – частично упругое столкновение. Нам известна скорость точки контакта до удара – $v^{-}$ Тогда мы можем записать: $$ n \cdot (v^{-} + \Delta{\dot{x}}) = -e \cdot n \cdot v^{-} $$ где $e$ – это коэффициент упругости. Если $e = 1$, то это абсолютно упругое столкновение, если $e < 1$, то частично упругое.
Если воспользоваться этим уравнением и тождеством смешанного произведения $a \cdot (b \times c) = b \cdot (c \times a)$, то получится: $$ m^{-1}(n\cdot J) + (n\times r) \cdot (I^{-1}(r\times J)) = -(1+e)n\cdot v^{-} $$
Второе условие – не делаем лишних движений. Это значит, что мы задаем импульс J вдоль нормали к поверхности. То есть, мы можем записать: $$ J = \lambda \cdot n $$ где $\lambda$ – это величина импульса, которую мы ищем. Если мы подставим это в уравнение, то получится:
$$ \begin{align} &\lambda = \frac{-(1+e) n \cdot v^{-}}{m^{-1} + (n \times r) \cdot (I^{-1} (r \times n))} \\ &J = \lambda \cdot n \end{align} $$
Пробуем:
Получилось очень хорошо. И здесь в отличии от XPBD скорости меняются сразу, а не через позицию. Поэтому у нас нет проблем с трением и отталкиванием.
Работаем дальше
Давайте посмотрим, что будет если куб будет падать плашмя на пол.
И не работает. Почему-то куб начинает вращаться.
Проблема вот в чем: Куб соприкасается двумя точками с полом.

Это незнание ограничений друг о друге приводит к множеству проблем. И нужно что-то придумать, чтобы это исправить. Метод Sequential Impulses как раз и решает эту проблему.
Такая же проблема появиться, если мы поставим несколько тел друг на друга с учетом гравитации. Мы ожидаем, что скорости на каждом шаге будут обнуляться. Но чтобы это произошло, верхнему телу нужно понять, что оно находится на нижнем, который тоже должен иметь нулевую скорость.


