Как найти угол закрутки от углов Эйлера

РЕДАКТИРОВАТЬ: Я думаю, что это необходимо для дальнейшего уточнения, что я пытаюсь сделать:

У меня в Майе есть установка для установки предплечья с использованием проволочного деформера для управления поворотом. Деформатор проволоки находится сверху skinCluster. У запястного сустава есть дополнительный атрибут угла, называемый "поворот", который связан с родительским суставом, который находится в том же месте, что и запястье, но сохраняет ориентацию локтевого сустава. Атрибут twist также связан с атрибутом dropoffLocatorTwist[1] провода. При падении на 100 провод переворачивает предплечье до бесконечности, а суставы все еще представляют "позу" запястья и кисти. Чтобы компенсировать переворачивания из skinCluster, я добавил дубликат иерархии запястий и рук и связал поворот с поворотом x. Соединение worldInverseMatrix двойной иерархии с атрибутами skinClusters bindPreMatrix эффективно сводит на нет любое вращение суставов запястья / кисти вокруг оси локтевой кости.

Теперь я хочу продвинуть это дальше. Чтобы облегчить работу аниматоров, я хочу удалить дополнительный атрибут скручивания и интерполировать между всеми тремя значениями поворота эйлера самого соединения, чтобы сгенерировать значение скручивания. Предполагая, что аниматор устанавливает значения либо непосредственно в окне канала, либо просто относительно вращения запястья, эти значения могут легко превысить 1000 точек на дюйм (в градусах). Если поли сетка достаточно плотная, проволочный деформер может легко выполнить скручивание вдоль кривой до такой величины без каких-либо артефактов. Проблема заключается в том, как интерполировать вращения Эйлера, чтобы получить одно значение угла, точно представляющее как позу, так и поворот. Я попытался интерполировать касательную и матрицу запястья путем умножения каждого значения Эйлера на произведение точки касательной к поворотам Эйлера, сопровождающим вектор строки в матрице, но это не работает полностью:

твист =rx*(касательная точка row1 матрицы)+ry*(касательная точка row2 матрицы)+rz*(касательная точка row3 матрицы)

В частности, он не любит вращений вокруг оси Y. Может кто-нибудь сказать мне, почему это так и как правильно разложить поворот Эйлера на угол поворота, не ограничивая поворот на -pi <-> pi?

ПРЕДЫДУЩАЯ СПРАВКА:

Я использую деформацию проволоки Maya (кривая) и хочу найти значение скручивания вдоль тангенса проволоки, основанное на эйлеровом вращении соединения. Соединения в Maya на самом деле представляют собой матрицы преобразования, но они составлены таким образом, что пользователь может ввести максимально возможное значение с плавающей запятой в качестве значения степени для любого компонента вращения Эйлера. Я хочу взять эти значения Эйлера (x y z) и объединить их таким образом, чтобы в результате получился поворот оси на угол, где ось - это первая строка родительской матрицы (или касательная к проводу), и угол является значением несвязанного скручивания вокруг этой оси, допускающим неограниченное скручивание сетки без переворотов. Проблема в том, что я не могу найти способ интерполировать значения x, y и z, чтобы результирующий угол представлял только поворот и ничего больше. Проще говоря, я хочу найти значение вращения 'x' для вращения Эйлера, где ось X была повернута и, таким образом, теперь представлена ​​как 'y', 'z' или что-то промежуточное между всеми тремя компонентами., Есть ли способ сделать это без потери значения x меньшим, но эквивалентным значением (например, 270 == 90, но мы хотим 270)?

2 ответа

Это нетривиальная проблема по нескольким причинам.

Во-первых, Eulerization of the matrix может привести к множеству правильных решений, которые не будут правильно интерполироваться (если вам когда-либо приходилось использовать пустой Euler Filter в редакторе графиков Maya, вы понимаете, о чем я). Существует множество комбинаций Эйлера, которые дают заданную кватернионную или ротационную матрицу. Это означает, что трудно создать детерминированное решение, которое охватывает все возможности.

Во-вторых, касательная вдоль сплайна является вектором, но вы не можете превратить вектор в матрицу без хотя бы одного другого вектора, чтобы придать пряности решение. Если вы знакомы с Maya Spline IK и сложностями поиска достойной системы отсчета для управления поворотом, вы увидите здесь те же проблемы.

В-третьих, и это наиболее важно для этой цели: поворот не может быть выражен как вращение в трехмерном пространстве - это относительное вращение в неевклидовом пространстве исходной кривой, которое не соответствует согласованной матрице мирового пространства.

Если вы хотите работать со скручиваниями, вам нужно создать преобразование системы отсчета для любой точки кривой, которую вы хотите выбрать, и вам нужно предоставить какую-то дополнительную информацию, чтобы начать ее. Поскольку твист является относительным, вам нужно указать начальную точку для измерения твиста. Вы заметите, что все нативные инструменты Maya для работы вдоль кривых (траектории движения, сплайн IK) делают это.

Создать матрицу довольно просто. получить нормализованный вектор для касательной кривой, а другой - для "восходящего вектора". Вектор повышения - это то, что вы должны определить по соглашению - вот почему все инструменты Maya, которые работают с касательными геометрии кривой, требуют, чтобы вы выбрали или предоставили один. Если ваша кривая лежит более или менее на плоскости XZ, вы можете использовать вектор вверх. Если он более или менее вертикальный, вы можете использовать X или Z. Однако вы получите его, вам нужен этот нормализованный вектор. Ваш "боковой" вектор, локальная ось z вашей конечной матрицы, является перекрестным произведением касательного вектора и бокового вектора. Теперь замените исходный вектор вверх на вектор пересечения касательных и боковых векторов (иначе ваша матрица будет срезана). Наконец, вам нужно положение в мировом пространстве точки на кривой, где вы получили свою касательную.

Теперь соберите свою матрицу так:

tangent.x  tangent.y  tangent.z  0
up.x       up.y       up.z       0
side.x     side.y     side.z     0 
pos.x      pos.y      pos.z      1

Это создает матрицу в точке выборки, где локальный x направлен вдоль касательной кривой, а локальный y более или менее направлен на исходный вектор вверх. В контексте этой матрицы ось скручивания является локальным вращением X. Управлять поворотом проще, создав два преобразования: родительский элемент, который использует эту матрицу для предоставления системы отсчета, и дочерний элемент, который заблокирован по Y и Z и вращается только по X. Числа Эйлера из матрицы касательных кадров не будут значение твиста - в этом контексте твит - это абсолютно относительное понятие, которое не может быть выражено в одной матрице!

Честно говоря, для такого рода вещей может быть легче решить с помощью встроенных инструментов. Я бы поэкспериментировал с использованием траектории движения, чтобы ограничить эталонное преобразование (соединение или локатор) кривой: Анимация> Траектории движения> Присоединить к траектории движения. Это будет делать то, что вы спрашиваете по умолчанию, ваша ось X будет касательной кривой, а Y будет на весь мир. Вы можете просто привязать второе соединение к первому (локально обнулено), и его локальный X будет осью скручивания, и вы можете просто заблокировать две другие оси и использовать это значение.

В зависимости от формы вашей кривой, вы можете столкнуться с двумя различными наборами проблем. Если ваш верхний вектор слишком близок к направлению кривой, решение нестабильно. Вы можете исправить это, выбрав другой вектор "вверх" - для вертикально ориентированной кривой вы можете использовать мир Z вместо мира Y. Однако, если кривая повторяется во всех трех измерениях, математически полного решения не существует.

Вторая стратегия заключается в использовании вытянутой геометрии для обеспечения вектора "вверх". Если вы выдавливаете отрезок линии вдоль вашей исходной кривой, образуя ленту с исходной кривой в качестве изопармы V=0, то в любой точке вдоль кривой вы можете использовать изопарм U в качестве вектора вверх. Таким образом, вы можете увидеть и при необходимости скорректировать поворот по кривой, чтобы избежать переворотов и колебаний - которые в противном случае будут довольно распространены в этой ситуации. Вы можете захватить векторы с поверхности, используя команду pointOnSurface. Пока история для вашего выдавливания включена, вы можете редактировать или анимировать исходную кривую, и это решение все еще работает.

Обновить

В ответ на дополнительную информацию ОП:

1) Я бы не слишком беспокоился об очень больших поворотах. Как указывает Джуджа, это не имеет точного значения в реальном мире, который вам нужно моделировать - и на практике это понадобится только персонажам очень специального назначения. Биологический предел поворотов на запястье составляет менее +/- 90, а на плече - еще меньше. Мультипликационный персонаж мог бы пройти мимо этого - но, вероятно, только в контексте чего-то вроде закручивания резинки, а не универсальной оснастки.

2) Скручивание Эйлера является относительно ручным даже для трехосных соединений, если оно является первым членом Эйлера (т. Е. X в повороте XYZ). Если ваша рука была разложена без каких-либо дополнительных ориентиров суставов вдоль первой оси, вы могли бы измерить накопленный поворот, просто отслеживая первые вращения эйлера (т. Е. Для костей XYZ цепь представляет собой прямую длину суставов с нулевыми поворотами, расположенными вдоль локального X). В этой конфигурации легко добавить заглушки, чтобы противодействовать повороту с помощью простых выражений или математики на основе узлов. Вы можете распределить поворот скручивания по нескольким костям, чтобы все было гладко (хотя при современной шкуре с двойным кватернионом это не проблема, и двух или трех костей вокруг плеча и запястья, вероятно, достаточно). Поскольку кости - это окурки, им не нужно выполнять сложную 3d-математику, чтобы выяснить скручивание: например, кость в бицепсе, которая распространяет скручивание от плеча, просто вращает что-то вроде (-5 * x) по сравнению с х вращение плеча. Вы снимаете кожу с костей тупика, а не с костей основной линии, поэтому вы получаете YZ-повороты основной кости, но модулированный X-образный стержень.

Основным недостатком этой схемы является то, что ваша поза связывания также не может быть вашей обнуленной позой: вам нужно, чтобы локальные оси вдоль цепи были непрерывными в "раскрученном" состоянии - что означает, что ваш 0,0,0 в плече это жесткая поза Т, выровненная с миром X, а не более расслабленная поза, которую вы получаете с большинством моделей. Аниматорам, как правило, не нравятся такие виды нулевых поз (и, конечно, если вы подходите к существующей модели, у вас нет выбора). Однако вы можете использовать dagPose для предоставления альтернативных нулевых поз, которые фактически обнуляются, но возвращают персонажа в нейтральное положение.

3D графика не реальность. Реальность действительно противна, когда дело доходит до математического моделирования. В данном конкретном случае сделано упрощение, заключающееся в том, что модели поверхности Maya и почти все 3D-приложения на самом деле ничего не вращают в конце. Посмотрите, поверхность либо полностью дискретизирована (полигоны, воксели), либо непрерывная поверхность упрощена как группа дискретных контрольных точек (сплайны). Приятно то, что им легко манипулировать, так как все - просто векторные движения, даже вращения. Правильно, в действительности не происходит ротации во всем процессе, в то время как некоторые узлы знают о ротации конечного результата после того, как все сказано, и узел отправил сообщение о том, что средство визуализации не имеет представления о том, что сделали узлы.

Это математически сложно определить

Итак, что вы спрашиваете, что-то вроде:

"Какова общая сумма вращения, спроецированного против одной оси?"

Вместо:

"Как правильно разложить эйлеровое вращение на угол поворота, не ограничивая поворот до -pi <-> pi?"

Последнее намного сложнее понять и плохо определить математически. Основной ответ на более поздний вопрос: вы не можете. Первая форма лучше определена, но все равно, что спрашивать, как далеко я прошел сегодня, зная, что я начал в своей постели и закончил день в своей постели. Причина в том, что вы не знаете, как я перешел между ними. Таким образом, реальным ответом на самом деле является интеграл по времени, который зависит от всех кадров раньше, иными словами, для решения этой проблемы вам необходима имитация. Вы должны сделать некоторые предположения и ограничения угла, которые помогут вам решить проблему.

Самым тривиальным было бы то, что вы заставляете одну ось просто всегда указывать вдоль направления поворота. Затем сделайте эту ось последним оцененным Эйлером (на самом деле Майя не использует углы Эйлера, а использует углы Тейта-Брайана). Теперь поворот можно легко принять за сумму этих отдельных каналов. Чтобы это работало жестко, ваш порядок вращения должен совпадать с вашим направлением, поэтому если он расположен вдоль оси x, то порядок вращения должен быть таким, который начинается с буквы x, например, xyz.

Вышеупомянутое работает в предположении, что другие углы фактически не вращаются на много оборотов. Конечно, для аниматора не имеет значения, полностью ли он корректен, пока он работает. И действительно вращение других осей произвольно, даже если вы не рассчитали скручивание, вызовет странные проблемы с интерполяцией.

Если этого недостаточно, это становится немного утомительно, так как мне нужно рисовать картинки. В основном проблема заключается в том, что угол Эйлера или Тейта-Брайана не является хорошей моделью для интерполяции вещей, просто указывает направление. Интерполяция колеблется так прямо, что это действительно странный беспорядок. У некоторых из них есть действительно не интуитивные угловые случаи.

Кластеры не могут решить эту проблему

Таким образом, каждая точка не может пройти более 360 градусов, чтобы вернуться к исходной точке. Поскольку точки связаны, кажется, что это возвращается к началу. Это правда, что используемый матричный расчет в конечном итоге имеет аналогичное ограничение, но не имеет значения, что движение точек является ограничивающим фактором, если вы посмотрите на отдельную точку. Теперь, если у вас есть цепочка точек, такая, что ни одна точка не "поворачивается" примерно на 45 градусов (чем меньше, тем лучше, чем больше точек, тем плавнее), то у вас нет проблем. Но все равно не получается. Зачем?

Кости перемещают позиции точек с взвешенными векторными перемещениями, которые называются кластерами, потому что перемещение каждой отдельной точки - это большая работа. Общий эффект заключается в том, что каждый совместный пролет может поворачиваться только на < 180 градусов. Это вызвано движением вектора. Опять не матрица, хотя, конечно, если бы векторное движение могло это сделать, матрица была бы ограничивающим фактором. Таким образом, кластеры не могут сделать это, но есть вещь, называемая двойной кватернионной интерполяцией, которая может использоваться вместо обычных кластеров. Что он делает, так это на самом деле хранит 2 приседания и интерполирует между ними. Это может решить весь 360-градусный срез в обоих направлениях с некоторой уловкой. Все еще довольно далеко от бесконечного поворота (при условии достаточного количества очков для поворота), конечно, лучше.

Двойная кват-интерполяция может сделать это, так что, возможно, вам следует использовать вместо этого двойную шкуру.

Другие вопросы по тегам