Быстрая инверсная кинематика в 2D
Часто бывает необходимо сделать процедурную анимацию для цепочки сочлененных сегментов, когда координаты узлов не известны, а есть только набор правил, которым эта цепочка должна следовать (длина сегментов, углы поворота и т.п). На помощь приходит инверсная кинематика.
Задачей инверсной (обратной) кинематики является поиск такого набора позиций сочленений (решения), который обеспечил бы непротиворечивое размещение всей связанной цепочки сегментов на основе ограничений. Базовые ограничения обычно следующие:
- “Цель” - точка в пространстве, к которой должна “тянуться” цепочка концом своего последнего сегмента, “подтягивая” за собой все остальные сегменты. Пример - предмет, к которому мы можем подтягивать кисть руки, а за ней и всю остальную руку.
- Длины сегментов - обычно считается, что сегменты являются жесткими связями, имеющими фиксированную длину.
- Углы поворота - каждый сегмент может быть ограничен в углах вращения вокруг оси сочленения, причем как по часовой, так и против часовой стрелки на разные значения. Пример - голень ноги человека может сгибаться назад почти на 90 градусов, а вперед - не может.
Все ограничения применяются одновременно и решение считается верным только тогда, когда все правила выполнены и нет противоречий.
Существует несколько способов находить решения, большинство из них либо тяжелы в расчетах, либо дают приближенное итеративное решение - за один цикл выполняется корректировка позиций каждого сегмента на выполнение условий ограничений, а потом это повторяется N-раз. Обычно это недостаточно быстро работает на большом количестве цепочек и требуется что-то более быстрое, пусть и менее стабильное в плане плавности переходов между пограничными условиями. Одним из таких подходов является FABRIK - Forward And Backward Reaching Inverse Kinematics, “инверсной кинематики методом прямого и обратного следования”.
Пакет Leopotam.Ik
предоставляет механизм решения инверсной кинематики для цепочки сегментов в 2D пространстве с учетом длин сегментов и ограничений на их вращение. Например, нам в unity
необходимо симулировать “щупальце”, тянущуюся к нужной точке:
1 | public class IkSolver : MonoBehaviour { |
В результате получим следующее поведение:
Подключим ограничение на углы вращения:
1 | void Update () { |
В результате поведение изменится на следующее:
Актуальные версии пакетов доступны в закрытом discord-сервере для vk/boosty-подписчиков.