Войти
ПрограммированиеСтатьиГрафика

Скелетная анимация и экспорт из Maya 4.0.

Автор:

Для начала договоримся о некоторых терминах и понятиях, чтобы потом не было путаницы.

Математика в скелетной анимации
Экспорт данных из Maya
Применение анимационной математики в экспорте
Использование в игре

Математика в скелетной анимации

Во-первых, умножения вектора и матрицы строятся как "матрица на вектор", то есть v'=M*v , где v' - результирующий вектор, v - исходный вектор, M - матрица.

Во-вторых, матрица преобразований представляет собой композицию матрицы вращения 3х3 и вектора перемещения 1х3. Все операции с ней проводятся отдельно по частям.

Изображение

R - матрица вращения 3х3
T - вектор перемещения 1х3

Это не законы для анимации, просто в начале работы оказалось необходимостью, чтобы вся математика строилась на этих принципах.

Скелет - набор joint'ов, связанных между собой по принципу "родитель"-"потомок", причем преобразования каждого joint'а заданы в системе координат "родительского" joint'а.

Joint - точка, вокруг которой происходит трансформация любых привязанных к ней объектов. Joint характеризуется положением в пространстве (3-мя координатами) относительно другого joint'а и направлением осей системы координат. Любые перемещения и повороты могут быть выполнены только относительно другого joint'а (иногда целесообразно добавить в скелет "мертвый" joint для упрощения перемещения всего скелета целиком). Каждому joint'у в соответствие  ставится матрица преобразований в мировой системе координат.

Изображение

Чтобы построить текущую матрицу преобразований для каждого joint'а, необходимо выполнить следующие операции:

построить матрицу текущего поворота

Cr=Pr*Rr
где Cr - текущая матрица поворота, Pr - "родительская" матрица поворота, Rr - матрица относительного поворота.

построить вектор текущего перемещения

Ct=Pt+Pr*Rt
где Ct - вектор текущего перемещения, Pt - "родительский" вектор перемещения, Pr - "родительская" матрица поворота, Rt - вектор относительного перемещения.

На рис. 1 joint "C" - это корневой joint скелета, состоящего из трех joint'ов - "A", "B" и "C". "Родительским" joint'ом для "B" будет joint "C", соответственно для "A" joint "B" будет "родительским". И тут возникает вопрос - а относительно чего задавать положение и перемещение joint'а "C"?  Ответ - относительно центра мировой системы координат. Часто возникают случаи, когда выгодно сделать центр мировой системы координат дополнительным, "мертвым", joint'ом - например, если объект двигается по земле, то достаточно передвигать центр "его" системы координат или вращать "его" систему координат не особо задумываясь, на какой высоте должен находиться корневой joint. Достаточно построить модель так, что ее ноги находятся на полу, а потом присоединить еще один элемент к корню скелета.

Итак, преобразование joint'а "C" известно (CCr - матрица поворота, CCt - вектор перемещения)

Для joint'а "B" известна матрица поворота относительно joint'а "C" - RBr, и вектор перемещения относительно joint'а "C" - RBt. Тогда текущие преобразования для joint'а "B" будут получены как:

матрица поворота
"родительская" матрица поворота умножается на матрицу относительного поворота, то есть

CBr=CCr*RBr

"Физически" мы получаем, что в мировой системе координат все точки, привязанные к joint'у "B" получат дополнительный поворот еще и вокруг joint'а "C".

вектор перемещения
"родительский" вектор перемещение прибавляется к повернутому относительно "родительского" joint'а  вектору относительного перемещения (много слов? :) )

CBt=CCt+CCr*RBt

"Физически" получается, что вектор относительного перемещения поворачивается вокруг "родительского" joint'а, а потом переноситься в точку, координатами которой является позиция "родительского" joint'а.

Простейшим примером такого скелета будет рука: joint "C" - плечо, joint "B" - локоть, joint "A" - запястье. Пример преобразований joint'ов и связанных с ними вычислений:
1.  Поднять вытянутую руку перед собой - это поворот корневого joint'а "C" (текущий). Относительные преобразования joint'ов "B" и "A" пока равны 0 (нет дополнительных поворотов и перемещений)
2.  Согнуть руку в локте - поворот joint'а "B" относительно joint'а "C". Теперь все точки, на которые оказывает влияние joint "B" получили дополнительный поворот - далее в наших расчетах необходимо учесть факт появления поворота "B" ОТНОСИТЕЛЬНО joint'а "A"
3.  Отвести руку в сторону - поворот joint'а "C". Однако у нас остался поворот joint'а "B" относительно joint'а "C"? Все правильно - рука осталась согнута в локте (если ее конечно перед этим не расправили :) и отведена в строну. Это и есть то, на что я потратил кучу слов.

Поворот - перемещение относительно некоторой оси без изменения расстояния до нее. Поворот будем задавать кватернионом (qx, qy, qz, qw), который строиться как

Изображение

где (x, y, z) - вектор направления оси, вокруг которой происходит вращение, j - угол вращения.

Собственно в данном случае это не так уж и важно, поскольку Maya может дать поворот и в виде матрицы и виде кватерниона, но может быть кто-то захочет построить какую-нибудь простую анимацию руками :)

Преимущество кватерниона перед матрицей поворотов в том, что не нужно задавать повороты joint'ов в каждом кадре, достаточно указать лишь ключевые кадры, а положение скелета в любой момент может быть вычислено как интерполяция между положениями joint'ов в них ("анимация по ключам").

По сути поворот никак не влияет на joint, единственно на чем можно заметить его отражение - система координат joint'а, которая будет поворачиваться относительно системы координат родительского joint'а или, после вычисления всех преобразований, относительно мировой системы координат.

Может показаться непонятным, что в разговоре о joint'ах я говорил о матрицах, а сейчас предлагаю использовать кватернионы. К сожалению, я не знаю как можно применить поворот представленный кватернионом к вершине, однако известно, как представить кватернион в виде матрицы.

Итак, задан кватернион (x, y, z, w), матрица поворота строиться следующим образом

Изображение

Кожа - набор вершин меша, для которых определена степень влияния всех joint'ов - веса вершины по отношению к joint'ам, сумма которых должна равняться 1.

При вычислении координат точек кожи будем пользоваться формулой

Изображение

, где
n - число joint'ов, влияющих на вершину
Ci - текущая матрица преобразований для i-ого joint'а
V'i - координаты вершины в системе координат i-ого joint'а, вычисляются как V'=B-1*V, где
V - координаты вершины в мировой системе координат
B - матрица преобразований joint'а в мировой системе координат в момент первой привязки - "bind pose",
B-1 означает обратную матрицу. В идеале эта матрица содержит только перемещения, но для дизайнеров удобно настраивать оси системы координат некоторых joint'ов как-то по другому, поэтому можно запросто ожидать появления в ней еще и поворотов.

Это преобразование выполняется только один раз - при экспорте скелета, в дальнейшем понадобиться только информация о том какой joint, на какие вершины и как влияет.

Изображение

Что же получается "физически"?

Пусть есть вершина V, привязанная к joint'ам "A", "B" и "C" (рис. 2). Предположим в какой-то момент произошла анимация как на рис. 3. Если мы попытаемся вычислить координаты вершины используя текущую матрицу преобразований каждого joint'а, то окажется что у нас уже не одна, а три вершины! - VA, VB, VC. Возникает вопрос - а какую из них выбрать? Вот тут и пригодятся веса V'=VA*aA+VB*aB+VC*aC- по сути выражение  есть не что иное, как интерполяция по трем точкам, при этом чем больше вес (степень влияния joint'а) тем ближе к соответствующему joint'у будет расположена точка. Именно так и получается растяжение или сжатие полигонов - одна вершина сильнее привязана к одной группе joint'ов, остальные - к другой.

Страницы: 1 2 3 4 Следующая »

#Maya, #анимация, #скелетная анимация, #экспорт

6 марта 2003 (Обновление: 23 сен. 2009)

Комментарии [1]