
Глава 3
Матричная математика
Вся 3D анимация создана в среде, являющейся математической моделью реальности. Эта модель не очень точна, но, как и Матрица, она подчиняется правилам. И хотя их нельзя обойти или нарушить, из них точно можно извлечь выгоду.
Этот раздел – не букварь по 3D. Подразумевается, что читатель уже имеет некоторое знакомство с трехмерными системами координат и размещением точек в трехмерном пространстве. В этой главе мы собираемся рассмотреть некоторые математические основы, которые управляют 3D анимацией и и ведут к созданию Компьютерной Мультпликации (Computer Graphics Imaging – CGI).
Точки и векторы
Точки и вершины похожи, но все же очень отличаются. Все они представлены в трехмерном пространстве тремя числами. С точками все довольно просто: они показывают положение в пространсве. Примеры точек – контрольные вершины и вершины полигональных плоскостей.
Вектор – это совсем другой зверь. Хотя он тоже представлен тремя числами, это не положение в пространстве, а направление и расстояние. Каждое из трех чисел означает сдвиг по трем главным осям. Векторы часто изображаются исходящими из некоторой точки, но у них нет начала. Вектор можно сравнить с удаленным светом в компьютерной графике: его лучи характеризуются только направлением и яркостью.
В Maya векторы используются в нескольких областях. Нормали поверхности – являются векторами, и ограничители нормалей используют их для орентации объекта. С этой же целью векторы используются с целевым ограничителем для вычисления ориентации объекта (UpVector). В Инверсной Кинематике в Maya для управления поведением ИК-манипуляторов применяются полярные векторы (pole vectors).
Некоторые векторные операции
Векторы обладают несколькими интересными свойствами, которые можно использовать в некоторых специфических операциях. Одна из них – скалярное произведение. Оно очень полезно для определения направления двух векторов. Скалярное произведение двух векторов положительно, если они сонаправлены, отрицательно, если они направлены противоположно друг другу, и равно нулю, если они перпендикулярны.
Откройте файл dotProduct.ma с Web-сайта http://www.courseptr.com/downloads. Вы должны увидеть куб и две сплайновые кривые образующие стрелки.
Выделите vector2 и поверните его по оси Y (рис. 3.1). Вы заметите, что размер куба меняется. Скалярное произведение этих двух векторов определяет размер куба.
Установите атрибут rotate второго вектора на 90. Куб исчезнет. Когда два вектора перпендикулярны, их скалярное произведение равно нулю.
Установите атрибут rotate на 180. Куб появится вновь. Но если вы выделите куб и проверите его масштаб, вы увидите, что он равен -1. Когда два вектора направлены в противоположные стороны, их скалярное произведение отрцательно.
Вы можете свободно вращать векторы и изучать их влияние на куб.
@Рис. 3.1. Изменение направления векторов определяет размер куба через скалярное произведение
В этой сцене для получения скалярного произведения используется узел vectorProduct . Открыв Outliner, вы увидите два локатора, один из которых приходится дочерним другому. Если вы откроете окно Hypergraph и отобразите входящие и исходящие соединения, то увидите, как создана сеть. Параметр локаторов WorldPosition (глобальная позиция) выведен в промежуточный узел plusMinusAverage. Вычитание одного локатора из другого создает вектор. Результат вычитания передается в узел vectorProduct. Учитывая сущность векторов, помните, что перемещение векторов не имеет значения, важно лишь их направление.
Векторное произведение – еще одна операция над векторами – базирующаяся на полярном векторе и up-векторе целевого ограничителя. Векторное произведение двух векторов дает вектор, перпендикулярный исходным. Чтобы увидеть пример векторного произведения, откройте файл chapter03/crossProduct.ma. Вы увидите три стрелки. Повернув любую из двух, вы увидите, что стрела в центре переворачивается, по мере изменения двух других векторов. Центральная стрелка прикреплена целевым ограничителем к узлу, атрибуты перемещения которого соединены с узлом vectorProduct, установленным на векторное произведение. В следующем упражнении исследуются свойства полярного вектора.
Откройте файл crossProduct.ma с Web-сайта http://www.courseptr.com/downloads. Вы увидите три стрелки.
Выберите кривую vector2 под узлом crossProduct. Поверните ее по оси Y. Вы должны увидеть как стрела в центре перескакивает с направления вверх на направление вниз. Эта стрела соединена целевым ограничителем с локатором, который преобразует векторное произведение.
Установите атрибут rotateY кривой «vector2» на 60,0. Вы должны увидеть, что указатель центральной стрелки направлен точно вверх.
Выделите узел crossProduct и перемещайте его как угодно. Вы должны увидеть, что центральная стрелка всегда указывает в направлении, перпендикулярном другим двум стрелкам (рис. 3.2)
@Рис. 3.2. Векторное произведение направляет средний вектор перпендикулярно двум другим.
Векторное произведение имеет исключительное свойство: оно всегда имеет значение перпендикулярное двум другим векторам. В этом примере вектор векторного произведения мечется между двумя направлениями, но оба они перпендикулярны исходным векторам. Однако если два вектора постоянны, относительное положение векторного произведения не изменяется.
Матрицы
Вы не можете изучать основы 3D достаточно долго, не затрагивая матрицы. Матрица – это математическая основа, которая делает 3D возможным вообще. Она управляет размещением всех объектов в трехмерной сцене для анимации и рендеринга. Хотя непосредственно в Maya матрицы не редактируются, умение их использовать весьма полезно для понимания того, как Maya оперирует трехмерными объектами.
Матрица – это фабрика 3D. Это то, что обеспечивает точкам расположение, необходимое для рендеринга. Каждая геометрическая вершина в Maya перед рендерингом обрабатывается матрицей. Создание компьютерной анимации заключается в манипуляциях с матрицей для создания движения. Когда объекты размещены в иерархиях, именно матрицы делают возможным предсказуемое манипулирование ими. На самом деле, матрицы делают возможным существование иерархий.
Матрицы составлены из 16 чисел, расставленных в четыре ряда и 4 столбца. Эти числа несут всю информацию, которая необходима Maya для перемещения, вращения, масштабирования трансформы. Для этого Maya берет данные входных атрибутов объектов из редактора каналов и создает ряд матриц. Одну, например, для описания перемещения объекта, другую – для описания вращения. Любая информация об объекте представлена в виде матрицы, а затем они сводятся вместе. В результате получается матрица объекта. В то время как у трансформы объекта появляется shape-узел, все вершины геометрии сводятся в матрице объекта, чтобы занять свою конечную позицию во вьюпорте. Существует множество меньших матриц, вовлеченных в этот процесс, но окончательный результат – это один набор из 16 чисел.
Рассмотреть матрицы с другой стороны можно с помощью системы координат. Всякий раз, когда объект группируется с трансформой другого объекта родительскими отношениями, он размещается в системе координат родительского объекта, поэтому при построении иерархий вы создаете множественные системы координат.
Следующее упражнение предназначено для точной иллюстрации влияния матрицы на точки в трехмерном пространстве.
Начните новую сцену.
Создайте пустую группу. Назовите ее “matrixGroup”.
Создайте локатор и переименуйте его в “testPoint”.
Выделив локатор, отройте Attribute Editor и создайте три атрибута типа float: “offsetX”, “offsetY” и “offsetZ”.
Откройте Hypershade. В разделе Utility-node создайте узел vectorProduct. Переименуйте его в matrixVP.
Соединяя информацию матрицы, проще устанавливать соединения через Connection Editor. Выходные каналы матрицы не отображаются в Hypershade и Hypergraph. Откройте Connection Editor и загрузите matrixGroup на левую панель, а matrixVP – на правую. Убедитесь, что способ соединения установлен на from→to.
Соедините атрибут matrix узла matrixGroup с атрибутом matrix узла matrixVP.
Установите атрибут operation узла matrixVP на Point Matrix Product (Точечное матричное произведение).
Выделите локатор testPoint и загрузите его на левую панель. Соедините атрибут offsetX с атрибутом input1X узла matrixVP. То же самое проделайте с атрибутами offsetY и input1Y, offsetZ и input1Z. Установите значение атрибута offsetZ на 5.
Нажмите на кнопку Mapping (Отображение) и переключите ее на tofrom (кот). Соедините атрибут output узла matrixVP с атрибутом translate локатора testPoint.
Установите параметр offsetZ локатора testPoint на 2,5.
Выделите узел matrixGroup. Вращайте его как угодно. Обратите внимание, как локатор поддерживает постоянный сдвиг от узла (рис. 3.3). Вы можете свободно поэкспериментировать со значениями параметров “offsetX”, “offsetY”, и “offsetZ”.
@Рис. 3.2. Отображение результата размножения матриц на перемещение локатора
С помощью атрибутов offset вы можете перемещать локатор. Если вы выделите узел matrixGroup и станете вращать его, то положение локатора будет меняться, оставаясь в соответствии с пространственным положением узла matrixGroup. Именно так матрицы используются для управления точками. Вы заметите, что локатор не вращается и не масштабирутся относительно узла matrixGroup. Так и должно быть, потому что вершины или управляющие точки, составляющие геометрию, не имеют ни направления, ни размера. Все манипуляции с трехмерными объектами осуществляются через изменение их пространственного положения с помощью матриц.
Объекты в пространстве
Чтобы показать возможности матриц, используем их в следующем упражнении для создания собственного инструмента привязки. Хорошая привязка объекта – один из самых необходимых компонентов инструментария риггера. Довольно часто Вам понадобится выровнять (align) два объекта в рабочем пространстве. Инструмент выравнивания (Align tool) в Maya не берет в расчет вращение и размер. Один из способов обойти это ограничение создание временной точки и направленных ограничителей.
Чтобы получить доступ к матричной информации, можно воспользоваться командой xform.
Начните с новой сцены.
Откройте Script Editor (Редактор сценариев).
Введите следующие команды. При этом не нажимайте клавишу Enter на цифровой клавиатуре, а вводите их как единый кусок кода.
global proc snap()
{
string $sel[] = ` ls -sl`;
float $t[] = `xform -q -t $sel[0]`;
xform -ws -t $t[0] $t[1] $t[2] $sel[1];
float $rl[] = `xform -q -ro $sel[0]`;
xform -ro $rl[0] $rl[1] $rl[2] $sel[1];
}
Введя скрипт, с помощью команды File Save Selected (Файл Сохранить выделенное) сохраните его как snap.mel.
Создайте во вьюпорте локатор. Перемещайте и вращайте его так, чтобы он оказался в положении, далеком от первоначального.
Создайте примитив – полигональный куб.
Выделите локатор и затем с помощью клавиши Shift выделите куб.
В командной строке введите команду snap и нажмите Enter (рис. 3.4).
@Рис. 3.4. Выполнение команды привязки
Вы увидите, что куб размещается в соответствии с расположением и ориентацией локатора. Параметры куба не ограничены, как если бы его атрибуты были вручную привязаны к атрибутам локатора. В сценарии вы заметите, что команда xform требует 16 аргументов из массива $sM float. Это и есть числа, составляющие матрицу.
Команда xform – лучший друг сборщика персонажей. Атрибуты объекта – не очень точный способ размещения его в пространстве. Команда же xform даст вам предельно точную информацию о перемещении объекта, потому что она непосредственно обращается к матричной информации. Учтите, что если локатор является дочерним объектом другого узла, то атрибуты его перемещения могут быть равны нулю, в то время как его родительский узел как угодно перемещается в среде. В результате куб может переместиться на 0 0 0, хотя реальное положение локатора в пространстве будет другим.
Центры объекта
При построении матрицы перемещений Maya перемножает числа других матриц. Среди них – матрицы центра вращения (rotate pivot) и центра масштабирования объекта (scale pivot). Они позволяют пользователю контролировать и анимировать центральные точки атрибутов вращения и масштабирования узла. Когда вы позиционируете объект в Maya, то центр перемещения объекта также является его центром вращения. Центр масштабирования – отдельный центр, являющийся главным элементом операции изменения масштаба объекта. Это позволяет создавать сложное поведение узла. При использовании инструмента Move пользователь может нажать на клавишу Insert, чтобы войти в режим редактирования центра, в таком случае будет перемещаться именно центр вращения.
Центр вращения также регулируется всякий раз, когда объект перемещается из первоначального положения, и применяется инструмент Freeze Transforms (Заморозить перемещения). Атрибуты перемещения объекта обнуляются, но объект все еще может вращаться вокруг своего первоначального центра. Это из-за сдвига центра.
Центры вращения, в своей сущности, значительно влияют на сценарий привязки. Если вы попытаетесь привязать два объекта с разными точками вращения, то увидите, что они выравниваются именно по точкам вращения. Применив точечный ограничитель, вы получили бы другой результат. Рассмотрим обновление сценария привязки под вычисление различных точек вращения.
Первое, что нужно добавить в старый сценарий привязки – получение данных о центрах вращения обоих объектов. Команда xform имеет метку -rp, которая может быть использована для получения данных о центрах вращения.
float $rp1[] = `xform –q –rp $sel[0]`;
float $rp2[] = `xform –q –rp $sel[1]`;
Нужно будет определить центры вращения обоих узлов. Центр вращения первого объекта прибавится к его перемещению, а второй будет вычтен. Эти модификации проявятся в команде, устанавливающей перемещение второго узла.
xform –ws –t ($t[0]+$rp1[0]-$rp2[0]) ($t[1]+$rp1[1]-$rp2[1]) ($t[2]+$rp1[2]-$rp2[2]) $sel[1];
Чтобы увидеть работу нового сценария, откройте файл snap3.mb с Web-сайта http://www.courseptr.com/downloads. В сцене два куба. Выделив их, вы заметите, что перемещение обоих равно нулю, но они находятся в различных местах. Выделив их и создав точечный ограничитель, вы увидите, что два куба теперь будут привязаны к одной локации. Если вы запустите сценарий snap.mel, то никаких изменений не произойдет: ни один куб не сдвинется.
Выделите кубы и запустите новый сценарий. Вы увидите, что оба куба выровнялись так, как надо.
Эта новая привязка уже больше похожа на то, чего вы хотите добиться. Также она не опирается на какие-либо соединения, поэтому она может быть использована для размещения узлов с входящими соединениями от анимационной кривой.
Локатор
Всестороннее обсуждение использования матриц в Maya должно высветить некоторые уникальные свойства локатора. Локатор – это трансформа с shape-узлом, которая создает маленький крестик. Большинство shape-узлов в Maya перенимают пространственную ориентацию от матрицы своей трансформы: вы можете запросить расположение вершины с помощью команды xform, но это не управляемый соединением метод реального времени. Однако, локатор, имеет живое соединение с действительным пространственным расположением своего shape-узла – точки в пространстве, где пересекаются три линии, составляющие его изображение.
Это очень полезное свойство локатора, потому что позволяет создавать такие системы риггинга, где вы всегда можете напрямую получать доступ к пространственному расположению локатора, не создавая вторичный узел для его точечного ограничения. Это может сэкономить силы при построении системы, использующей пространственное расположение локатора для вычисления расстояния. В предыдущих примерах с операциями над векторами данные положения локатора использовались для вычисления векторов. Собственно говоря, shape-узел пространственного расположения локатора – это то, благодаря чему функционирует узел измерения (dimension node), который измеряет расстояние между двумя точками пространства.
Узел dagPose
Одна из самых интересных и наименее известных функций в Maya – dagPose. DagPose – это узел, записывающий матрицы узла или иерархию узлов и сохраняющий их для дальнейшего использования. DagPose – это узел, который Maya использует для хранения позы первичной привязки (bind pose) персонажа, когда кожа прикреплена. DagPose может быть действительно полезным инструментом для определенных операций моделирования, но у него есть важные ограничения:
dagPose не может восстанавливать матрицу объекта с входящими соединениями каналов перемещения, вращения или масштабирования.
команда dagPose не хранит данные о видимости или других индивидуальных атрибутах. Она хранит только матрицы объектов.
Эти ограничения кажутся весьма серьезными, но у dagPose есть и преимущества. Одно из них заключается в быстроте и точности. Другое – в том, что dagPose записывается в файл, и не нуждается в дополнительных внешних хранилищах или в написании посторонних скриптов . Узел DagPose может быть особенно полезным для создания дополнительных поз скелетов с целью улучшения отладки деформаций.
Откройте файл dagPose.ma. Вы можете найти его на http://www.courseptr.com/downloads. Вы должны увидеть персонаж PigGoblin среднего разрешения.
Пара узлов dagPose уже сохранены для этого персонажа. В командной строке введите следующее:
dagPose –restore stride;
Вы должны увидеть изменение позы персонажа. Чтобы увидеть другой dagPose, введите следующее:
dagPose –restore spreadEagle;
Поза персонажа теперь должна повторять показанную на рисунке (рис. 3.5).
Теперь давайте восстановим первичную позу привязки персонажа. В меню Skin (Кожа) выберите пункт Go to Bind Pose (Перейти к первичной позе привязки), чтобы вернуть персонаж к его первичной позе привязки.
Затем мы сохраним dagPose. Выделите сочленения персонажа и разместите их в позу прыжка (рис. 3.6).
@Рис. 3.5. DagPose восстановил позу spreadEagle
Когда поза Вас устроит, выделите узел pgDeform. В командной строке введите следующее:
dagPose –s –n jumpPose;
Вы увидите, как фигура становится в позу, как на рисунке (рис. 3.6).
Чтобы проверить сохраненную позу, с помощью пункта меню Skin Go to Bind Pose верните персонажу первоначальную позу. Затем в командной строке введите следующее:
dagPose –r jumpPose;
Вы должны увидеть, что персонаж вернулся в созданную вами позу.
Как упоминалось ранее, первичная поза привязки прошедшего скиннинг персонажа – это его dagPose. Это полезно знать, потому что часто при работе с персонажем, к которому прикреплены несколько кожных кластеров (skin cluster), первичная поза привязки может быть утерянна. Если такое произошло, то команда Skin Go to Bind Pose не вернет персонаж в первоначальную позу скиннинга. В этом случае для восстановления скелета иногда можно применять команду dagPose. Восстанавливая первичную позу привязки вручную с помощью команды dagPose, лучше придерживаться следующего синтаксиса:
dagPose –restore –global -bindPose;
@Рис. 3.6. Поза прыжка
Нет необходимости что-то выделять, чтобы восстановить dagPose. Как вы могли заметить, команды относящиеся к dagPose одновременно работают с целыми иерархиями. Вы можете сохранить dagPose выделенных объектов, вставив метку -sl во время сохранения первичной позы привязки.
Как видите, dagPose – очень полезный инструмент для настройки деформаций на простом скелете. Он упрощает проверку деформаций и хранение на будущее данных о положении объектов. Так как объекты dagPose являются узлами, то они для простоты доступа сохраняются в сценах Maya.