3. Скоростные ограничения

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. Решение системы уравнений:

Теперь у нас есть два уравнения:

  1. $m_1 v_{1n} + m_2 v_{2n} = m_1 v’{1n} + m_2 v’{2n}$
  2. $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 как раз и решает эту проблему.

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