Глава 8
Пропсы и интерактивные аксессуары.
С пропсами $$Под «пропсами» подразумеваются некие аксессуары и предметы взаимодействия, такие как оружие, стаканы, фонарики и т.д. – прим ред. $$ дело обстояло нелегко с самого появления 3D анимации. Иерархическая природа трехмерной анимации не давала просто брать и устанавливать объекты в персонажах. По мере совершенствования анимационного программного обеспечения появились разнообразные инструменты, упрощающие управление пропсами. Разработка ограничителей позволила объектам выходить за пределы иерархии. Но теперь, с появлением новых инструментов, появились и новые вопросы. Как организовать пропсы наилучшим образом?
Прежде чем заняться пропсами, важно сделать кое-какую подготовку и задать некоторые вопросы. В случае с пропсом нужно в первую очередь определить его статус, то есть узнать, является ли он неотъемлемой частью персонажа. Если вы настраиваете такой персонаж, как Hellboy, который всегда держит необычное оружие, то пропс всегда должен быть со сборкой, и, вероятно, он будет настроен для постоянного взаимодействия с персонажем. Другие пропсы могут взаимодействовать с ним на протяжении нескольких сцен, например, когда он пьет из банки с газировкой, а потом ставит ее на место.
Простое переключение ограничителя пропса
Как персонажный риггер, вы не раз попадете в такие ситуации, когда будет необходимо закрепить один объект между двумя другими и сделать так, чтобы он мог легко переключаться от одного к другому. В случае с пропсами всё это можно легко настроить в один прием, также как основное управление самим персонажем. Система ограничителей и узлов в Maya как раз приспособлена под переключения объекта между двумя локациями через переключение ограничителя. В этом разделе рассказывается о создании такой переключающей системы использующей ограничители в Maya. В следующих разделах мы рассмотрим переключение ограничителя между множественными локациями.
Для начала давайте обратимся к настройке системы ограничителя, которая может легко переключаться между двумя целями:
Откройте файл reverseConstraint_start.ma (рис. 8.1). Его можно найти на http://www.courseptr.com/downloads. Вы увидите простую кисть, цилиндр и контроллер глобального пространства в виде кривой NURBS. Идея заключается в том, что цилиндр prop будет настроен на смешивание местоположения между кистью и кривой NURBS, которая действует как контроллер.
@Рис. 8.1. Сцена reverseConstraint_start.ma
Выделите цилиндр. Он должен быть расположен в точке отсчета. Нажмите Ctrl+g, чтобы сгруппировать его. Назовите новый узел prop_pivot. Этот узел будет служить в качестве узла сдвига: он может быть анимирован и будет задействован, если аниматору понадобится внести корректировки в пропс.
Врезка. Обратите внимание, что геометрия пропса сгруппирована под узлом prop_pivot. Это позволяет довольно легко заменить её в любое время. Этот небольшой объект можно заменить группой объектов, и текущая точка опоры этой группы не имеет значения, главное разместить ее лишь опираясь на узел prop_pivot.
Нажмите Ctrl+g, чтобы снова сгруппировать узел prop_pivot. Переименуйте этот новый узел в prop_attach. К этому узлу и будет применен ограничитель. Иерархия должна совпадать с той, что на рисунке 8.2.
@Рис. 8.2. Иерархия, управляющая геометрией пропса
Теперь пора установить местоположение пропса на кисти. Создайте пустую группу с помощью меню Create → Empty Group (Создать → Пустая группа), или просто нажмите Ctrl+g, ничего не выделяя. Назовите новую группу prop_wrist_null.
Выделите сочленение wrist. Это то сочленение, к которому будет прикреплен пропс. Так как объект будет находиться в ладони персонажа, нужно, чтобы он двигался всякий раз, когда двигается узел, отвечающий за деформацию кисти. Удерживая Shift, выделите узел prop_wrist_null, затем создайте точечный ограничитель и ориентационный ограничитель.
Создайте локатор и назовите его prop_wrist_attach. С выделенным локатором выделите, удерживая Shift, узел prop_wrist_null и нажмите p, чтобы создать между ними родительскую связь.
В Channel Box установите перемещения и вращения узла prop_wrist_attach на 0.
Врезка. Обратите внимание, что целевой объект этого ограничителя не связан с ИК-контроллером кисти. Очень вероятно, что в анимации ИК контроллеры могут не использоваться, и поэтому не соответствовать деформациям персонажа. Чтобы свести затруднения к минимуму, всегда прикрепляйте пропсы к трансформам, деформирующим геометрию.
С помощью меню Create → Empty Group создайте новый нулевой узел. Переименуйте его в prop_wrist_offset и подчините локатору prop_wrist_attach. Установите его перемещения и вращения на 0.
Через меню File → Import импортируйте файл nurbSplineCube.ma с http://www.courseptr.com/downloads. Переименуйте узел curve1 в prop_ctrl.
Теперь создайте еще одну пустую группу и переименуйте ее в prop_ctrl_offset. Это будет узел, к которому прикрепляется собранный prop на NURBS контроллере. С выделенным узлом prop_ctrl_offset выделите, удерживая Shift, кривую NURBS prop_ctrl и нажмите p, чтобы создать родительскую связь. Установите перемещения и вращения узла prop_ctrl_offset на 0. Когда вы закончите, Outliner должен выглядеть как на рисунке 8.3.
@Рис. 8.3. Иерархия для присоединения пропса к ладони и глобальный контроллер пропса
Когда ничего еще не выделено, выделите узлы ctrl_prop_offset, ctrl_wrist_offset и, наконец, prop_attach. Создайте точечный ограничитель и ориентационный ограничитель с помощью меню Constaint $$ Меню “Constrain” можно найти предварительно выбрав Animation-расположение главного меню - прим ред. $$.
Теперь пора сделать управляющий атрибут пропса. Размещение этого атрибута – вопрос, который должен быть согласован риггером и аниматором. В нашем случае контроллер будет размещен на NURBS кривой.
Выделите NURBS кривую prop_ctrl. Нажмите Ctrl-a, чтобы вызвать Attribute Editor. Создайте атрибут под названием toHand с минимальным значением 0.0 и максимальным 1.0. Этот атрибут будет управлять переключением пропса.
Откройте окно Hypershade. Выделите кривую prop_ctrl и узлы prop_attach и отобразите их входящие и исходящие соединения. Вы должны увидеть узлы и ограничители в окне Hypershade.
В разделе General Utilities пункта Create создайте реверсный узел. Переменуйте его в prop_reverse.
С помощью правой кнопки мыши соедините атрибут prop_ctrl.toHand с атрибутом inputX реверсного узла, как показано на рисунке 8.4.
@Рис. 8.4. Соединение атрибута prop_ctrl.toHand с узлом prop_reverse
Соедините атрибут prop_ctrl.toHand с атрибутом prop_wrist_offsetW1 узлов точечного и orient-ограничителей.
Соедините атрибут outputX реверсного узла с атрибутом prop_ctrl_offsetW0 узлов точечного и orient-ограничителей.
Установите атрибут prop_ctrl.toHand на 1. Обратите внимание на то, что пропс направлен в центр геометрии запястья. Выделите узел prop_wrist_attach и переместите его так, чтобы пропс лежал на ладони. Когда вы будете довольны размещением, примените к локатору Freeze Transforms,чтобы эта позиция стала положением покоя (рис. 8.5).
@Рис. 8.5. Завершенная система реверсного ограничителя.
Врезка. Когда вы размещаете локатор prop_wrist_attach, убедитесь, что вы настроили атрибут prop_ctrl.toHand, чтобы увидеть, как пропс смешивает движения к руке и от нее. Во многих случаях вращение локатора таково, что пропс при перемещении будет описывать дугу в 360º, а это обычно нежелательно, так как мешает гладкому переходу от контроллера пропса к кисти. Это можно исправить, повернув локатор prop_wrist_offset так, чтобы добиться более приемлемого положения. Обычно поворот этого узла на 180º по оси Z решает проблему. Возможно, придется немного поэкспериментировать, чтобы найти наилучшее сочетание. Если локатор нельзя изменить, чтобы сохранить выровненное положение, то попробуйте изменить поворот узла ctrl_prop_offset, смягчая переход.
Теперь ограничитель готов. Изменив значение атрибута to.Hand, вы получите смешивание перемещения пропса между его контроллером и локатором присоединения на ладони. Обратите внимание на то, что весь пропс располагается вне иерархии, управляющей деформацией, так как не было подчинений ни к одному из сочленений. Это удобно, потому что так систему пропса можно удалить когда угодно, никак не повлияв на деформации. Пропс можно сгруппировать под узлом, что упростит процесс его размещения и редактирования.
Также нужно обратить внимание на то, как пропс перемещается между своими локациями. С orientConstraint пропс может неудачно перевернуться при настройке весов. Когда вращения определены, Maya преобразовывает их из Эйлеровых в кватернионы, чтобы вычислить вращения. Результат преобразовывается обратно в Эйлерово вращение. Недостаток этого заключается в том, что кватернионовый решатель иногда берет альтернативный набор значений Эйлерова вращения как искомый объект. Чтобы решить эту проблему, выделите orientConstraint и установите его атрибут interpType на shortest. Это должно исключить нежелательные перевороты, пока две цели ограничителей вращаются с учетом друг друга.
Возможно, вы также заметили, что вам действительно не нужны дополнительные узлы сдвига под локатором и пропсом. Узлы сдвига – дополнительный слой гибкости, который, возможно, никогда вам и не понадобится. Они занимают некоторое количество памяти и некоторую вычислительную мощность, но их потолок довольно низок, и, с точки зрения предосторожности, обычно лучше ошибиться. Если бы в этой сцене были сотни пропсов, думаю - был бы смысл избавиться от дополнительных слоев.
Система одноручного пропса.
Итак, простой реверсный ограничитель хорошо работает с пропсами, имеющими только две локации, но от некоторых пропсов требуется более сложное поведение. В этой книге мы работали над фэнтэзийным персонажем, так что давайте продолжим и дадим ему оружие. Наш воображаемый режиссер решил, что персонажу нужен грозный нож, чтобы кромсать врагов. Мы взглянули на раскадровку эпизодов, где персонаж использует нож, и решили, что нож должен помещаться только в правую руку персонажа и в ножны на поясе. Однако, предугадывая требования проекта, мы добавим способность ножа свободно находиться в глобальном пространстве. Правило риггинга – не перегружать сборку, но в нашем случае все эти операции не потребует особых затрат, и сделать так, чтобы нож был свободен, довольно просто.
Теперь, когда мы знаем, что должен делать пропс, нужно обратить внимание на его геометрию и на руку, которая должна его держать. Тут все довольно очевидно: у ножа есть рукоятка, а у персонажа – руки, хорошо приспособленные для хватания. Кисть персонажа будет удобно охватывать рукоятку, так что особой подгонки не потребуется.
Техника, которую мы используем для управления пропсом, будет включать в себя присоединение его ограничителями к разным узлам. В Maya есть родительские ограничители (parent constraints), которые позволяют динамически подчинять объекты, что очень полезно для быстрой и легкой настройки пропса. Однако в случае с этим пропсом, который будет использоваться очень интенсивно, родительские ограничители имеют несколько побочных эффектов. Во-первых, при переключении от одного контроллера к другому нет гарантии в сохранении местоположения пропса. Чтобы обеспечить в производстве постоянство персонажа, который будет использоваться многими аниматорами, вероятность несовпадения должна быть сведена к минимуму.
Откройте файл knife_start.ma. Он есть на http://www.courseptr.com/downloads.
Импортируйте файл knife.ma с того же Web-сайта. Вы увидите геометрию ножа и ножен в сцене Maya. В Outliner должен быть показан новый узел под названием knife. Если вы рассмотрите группу ножа, то увидите, что она содержит два узла, составляющие геометрию ножа. Нож появится в точке начала отсчета (рис. 8.6).
@Рис. 8.6. Импортированная геометрия ножа
Создайте пустую группу и назовите ее sheath_geo_offset.
Выделив узел sheath_geo_offset, выделите также sheath_geo, удерживая клавишу Shift. Создайте pointConstraint и orientConstraint.
С помощью инструмента Move разместите sheath_geo_offset так, чтобы геометрия ножен размещалась сразу за торсом персонажа. Разместив, не запускайте Freeze Transforms: это действие установит ориентацию ножен неверно.
Через меню File импортируйте nurbsSplineCube.ma. Это кривая NURBS, которую вы примените для управления ножнами. Этот файл вы найдете на уже упоминавшемся Web-сайте.
Выделите только что импортированную curve1 и переименуйте ее в sheath_ctrl.
Выделите узел sheath_geo_offset и затем, удерживая клавишу Shift, выделите sheath_ctrl. Создайте pointConstraint и orientConstraint, чтобы выровнять sheath_ctrl с геометрией. Удалите ограничители и примените инструмент Move, чтобы разместить кривую sheath_ctrl соотносительно с ножнами, как на рисунке 8.7.
@Рис. 8.7. Размещение управляющей кривой ножен
Создайте новую пустую группу. Переименуйте ее в sheath_ctrl_Zero.
Выделите узел bn_hips и, удерживая клавишу Shift, выделите группу sheath_ctrl_Zero. Создайте pointConstraint и orientConstraint
С помощью меню Window → General Editors → Channel Control (Окно → Общие редакторы → Управление каналами) отобразите окно Channel Control. Переместите атрибуты перемещения, вращения, масштабирования и видимости узла sheath_ctrl_Zero в графу unkeyable.
Выделите sheath_ctrl и, удерживая клавишу Shift, выделите sheath_ctrl_Zero. Нажмите p, чтобы создать родительскую связь.
Примените Freeze Transformations к узлу sheath_ctrl.
Выделите узел sheath_geo_offset и, удерживая клавишу Shift, выделите узел sheath_ctrl. Нажмите p, чтобы родительскую связь.
Врезка. Задача узла sheath_geo_offset – сдвинуть вращения геометрии ножен, поэтому он не должен находиться в положении покоя – в точке 0 0 0. Узел sheath_ctrl должен быть в положении покоя, но команда Freeze Transformations заморозит перемещения во всей иерархии, в том числе и те, которые будут влиять на вращение геометрии с учетом узла sheath_geo_offset. Следовательно, исправления во вращении нужно делать после заморозки трансформаций узла sheath_ctrl.
Выделите узел sheath_geo_offset. Выделите каналы в Channel Control и заблокируйте их с помощью меню правой кнопки мыши.
Создайте пустую группу и переименуйте ее в knife_geo_ofset.
Выделите узел knife_geo_ofset, а затем выделите геометрию knife_geo. Создайте pointConstraint и orientConstraint. В идеале геометрия ножа должна быть обнулена с учетом точки начала отсчета, так чтобы при создании ограничителя геометрия не перемещалась.
Врезка. Единственная задача этого узла – выступать в качестве цели ограничителя геометрии: если геометрия была заменена, то она может быть прикреплена к этому узлу, а узел можно передвинуть, если нужно.
Выделив узел knife_geo_ofset, нажмите Ctrl+g, чтобы создать новую группу. Переименуйте эту группу в knife_pivot.
Снова импортируйте файл nurbsSplineCube.ma. Переименуйте импортированный узел curve1 в knife_ctrl.
Для правильного выделения разместите с помощью инструментов Move, Rotate и Scale кривую knife_ctrl в таком месте, которое хорошо соотносится с геометрией ножа (рис. 8.8).
@Рис. 8.8. Размещение управляющей кривой ножа
Врезка. В этом разделе значительная часть работы над пропсами сосредоточена вокруг точки начала отсчета. Чтобы облегчить эту работу, переключите видимость слоя персонажа и спрячьте сочленения в меню Show (Показать), которое находится на панели моделирования.
Выделив knife_ctrl, с помощью меню Modify → Freeze Transformations обнулите управляющий элемент.
Выделите узел knife_pivot и кривую knife_ctrl, удерживая клавишу Shift. Нажмите клавишу p, чтобы создать между ними родительскую связь.
Выделив узел knife_ctrl, нажмите Ctrl+g, чтобы снова его сгруппировать. Переименуйте получившуюся трансформу в knife_ctrl_Zero.
Теперь пора построить систему ограничителей. Создайте пустую группу и переименуйте ее в knife_handR.
Выделив узел knife_handR, нажмите g, чтобы сгруппировать его. Переименуйте новую группу в knife_handR_attach. У вас должно быть две пустых группы в простой иерархии.
Дублируйте эту иерархию и переименуйте верхний узел в knife_sheath_attach, а нижний – в knife_sheath.
Еще раз дублируйте иерархию и переименуйте верхний узел в knife_world_attach, а нижний – в knife_world.
На этом этапе у вас должно быть три иерархии из пустых групп, как на рис. 8.9. Обратите внимание, что в названиях всех этих узлов есть префикс knife_. Если бы вам понадобился больше, чем один проп, то это предупредило бы появление множества узлов с названиями world или handR. В Outliner нажмите [+] после каждой группы, чтобы развернуть иерархии. Удерживая клавишу Ctrl, выделите узлы handR, sheath, world и knife_ctrl_Zero в этом порядке. С помощью команд Constrain → Point и Constrain → Orient создайте точечный ограничитель и ориентационных ограничитель.
@Рис. 8.9. Иерархии пропса
В Outliner нажмите [+] после узла knife_ctrl_Zero, чтобы показать его иерархию. Выделите узел knife_ctrl_Zero_orientConstraint1 и установите его Interp Type на shortest в Channel Box или Attribute Editor. Это предотвратит нежелательные перевороты при переключении между объектами.
Выделите узел ctrl_knife. Откройте Attribute Editor и создайте три новых атрибута под названиями handR, sheath и world. Атрибуты должны быть типа float, и их минимальное и максимальное значения должны быть установлены на 0 и 1. Значение атрибутов по умолчанию должно быть 0, кроме атрибута sheath, который нужно установить на 1: это будет положение пропса по умолчанию.
Врезка. Какое положение установить по умолчанию – это решать техническому режиссеру и аниматорам. Всегда полезно определить подходящее положение по умолчанию, так как это предотвращает ситуацию, когда пропс при распространении файла находится в нежелательном положении. Например, если по умолчанию нож был установлен на world, то всякий раз, когда файл требовался для новой анимации, нужно было вручную устанавливать пропс на sheath и handR. Это еще одна деталь, которую нужно принять во внимание.
Следующий шаг лучше всего осуществляется в Hypergraph. В Outliner выделите, удерживая клавишу Ctrl, узлы knife_ctrl_Zero, knife_ctrl_Zero_pointConstraint1и knife_ctrl_Zero_orientConstraint1. В окне Hypergraph отобразите с помощью кнопки pod racer входящие и исходящие соединения. Через контекстное меню правой кнопки мыши соедините атрибут knife_ctrl_Zero.handR с атрибутом handRW0 узла knife_ctrl_Zero_pointConstraint1. Повторите эту операцию для соединения атрибута knife_ctrl_Zero.handR с атрибутом handRW0 узла knife_ctrl_Zero_orientConstraint1 (рис. 8.10).
@Рис. 8.10. Соединение knife_ctrl_Zero с ограничителями
Врезка. Порядок, в котором вы выделяете объекты ограничителей, влияет на название атрибута, управляющего весом ограничителя. Имя первого целевого узла при создании узла ограничителя должно иметь суффикс W0. Имя второго объекта будет с суффиксом W1, третьего – с W2, и так далее. При настройке и управлении множеством объектов ограничителей важно давать им осмысленные названия, потому что это может быть единственным способом проследить за ними при управлении весами.
Повторите эти операции с другими атрибутами узла knife_ctrl_Zero. Соедините атрибут sheath этого узла c атрибутами sheathW1 точечного и ориентационного ограничителей. Также соедините атрибут world с атрибутом worldW1 узлов ограничителей.
На этом этапе вы сможете контролировать, к какому объекту направляется нож, настроив значения узла knife_ctrl_Zero. Хорошо бы спрятать атрибуты, заново заданные ограничителями. Примените команду Window → General Editors → Channel Control, чтобы открыть окно Channel Control. Подсветите атрибуты перемещения, вращения и масштабирования (и видимости, если хотите) и переместите их в колонку non-keyable, нажав кнопку Move в нижней части окна.
Теперь пора подобрать локации пропса. Выделите knife_ctrl_Zero и установите все значения, кроме sheath, на 0. Установите значение sheath на 1. Нож должен находиться рядом с точкой начала отсчета, там, где находятся пустые узлы.
Выделите узел sheath_ctrl и, удерживая Ctrl, выделите узел knife_sheath_attach. Создайте точечный ограничитель и ограничитель ориентации. Нож должен двигаться по направлению к ножнам, но размещены они не точно.
Выделите узел sheath и с помощью инструментов Move и Rotate разместите нож так, чтобы лезвие было в ножнах и казалось, что оно надежно спрятано (рис. 8.11).
Врезка. Не замораживайте перемещения узла sheath: помните, что это не контроллер. Это узел сдвига (offset node), и его не нужно обнулять.
@Рис. 8.11. Размещение цели ограничителя ножа
Когда он придет в правильное положение, выделите все каналы в Channel Box и заблокируйте их с помощью контекстного меню. Через меню Window → General Editors → Channel Control откройте окно Channel Control. Выделите keyable-каналы узла sheath и переместите их в колонку unkeyable, нажав на кнопку Move.
Выделите узел knife_ctrl_Zero и установите все атрибуты, кроме handR, на 1.
Выделите сочленение hand_R и, удерживая Ctrl, выделите в Outliner узел handR_attach. Создайте точечный и ориентационный ограничители .
Выделите узел handR и, воспользовавшись инструментами Move и Rotate, разместите нож так, чтобы его рукоятка вкладывалась в ладонь воина (рис. 8.12).
@Рис. 8.12. Размещение ножа по отношению к кисти
Убедитесь в том, что нож плавно перемещается из ножен в руку. Даже при interpType ориентационного ограничителя, установленном на shortest, если есть существенное различие в ориентации узлов sheath и handR, то пропс все еще может вращаться не так, как нужно.
Следующие пункты раскроют процесс очищения объектов ограничителей для создания гладкого смешивания:
Придайте персонажу такую позу, как будто он вытаскивает нож из ножен. Так как это не формальная сборка персонажа, то для придания нужной позы вы можете вращать непосредственно сочленения. В качестве примера вы можете использовать рисунок 8.13.
@Рис. 8.13. Придание персонажу позы для совершенствования перемещения ножа из ножен в руку
Когда персонаж будет находиться в нужном положении, выделите узел knife_ctrl_Zero. Установите канал sheath на 1, а остальные каналы – на 0. Убедитесь, что временной ползунок на нуле и нажмите s, чтобы сохранить ключевой кадр.
Переместите временной ползунок на кадр 10 и установите атрибут handR на 1, а остальные – на 0. Сохраните еще один ключевой кадр.
Теперь подвигайте временной ползунок назад и вперед между кадрами 0 и 10. Если все идет хорошо, то вы должны увидеть плавное перемещение. Если что-то не так, посмотрите, по какой оси происходит скручивание. Пусть это будет ось Y. Выделите узел handR и поверните его на 180º по оси Y. Например, если узел handR отклонен на 35º, попробуйте повернуть его до 215º (180+35). Подвигайте временной ползунок назад и вперед, чтобы проверить результат.
Теперь, когда ориентация установлена, удалите ключевые кадры узла knife_ctrl_Zero. Потом заблокируйте каналы узла handR. Работайте в окне Channels Control, чтобы заблокировать у каналов возможность создания ключевых кадров. Выделите узлы world_attach, sheath_attach, handR_attach, sheath_ctrl_Zero и knife_ctrl_Zero. Нажмите клавишу g, чтобы сгруппировать их вместе. Назовите группу knife_rig.
Теперь пропс настроен. При анимации весов пропс будет сдвигаться от кисти к ножнам в глобальном пространстве. Этот сдвиг сконструирован с целью использования в анимации, для имитации настоящего перемещения пропса от одного объекта к другому.
Облегчение перемещения
Итак, пропс настроен для переключения, но сделать все это довольно тяжело. Эй, они наняли тебя, чтобы аниматорам не приходилось отслеживать все эти нули и единицы, так?
Но все-таки было бы здорово, если бы вы автоматизировали переключение пропса так, чтобы при переключении на кисть вам не приходилось бы вручную устанавливать все остальные атрибуты на ноль, особенно учитывая то, что в любой анимированной сцене, возможно, придется остановить движение пропса на полпути между ножнами и кистью. Было бы удобно настроить систему, в которой установка одного объекта на on переключала бы остальные объекты на off.
Одно из решений – сделать так, чтобы целочисленное значение управляло весами ограничителей через Set Driven Key. Значением может быть атрибут типа enum, добавленный в knife_ctrl_Zero. Недостаток здесь в анимации. Пусть цели ножен присвоено значение, скажем, 0, а цели кисти – 1, а глобальная цель представлена значением 2. В анимации перемещение от ножен, или нуля, к глобальному пространству, или двойке, должно будет произойти через положение 1 – кисть.
Обходным путём будет являться создание интерфейса, который будет автоматически устанавливать атрибуты пропса. Если веса целей являются единственными объектами с возможностью установки ключевых кадров, мы можем просто установить все атрибуты (кроме нужным нам целей) на ноль. Наличие в Maya некоторых инструментов делает возможным создание такой операции.
В следующем упражнении мы настроим мягкую, автоматизированную систему пропса.
Продолжайте предыдущее упражнение или отройте файл /chapter08/scenes/knife/knife_part2.ma.
Выделите узел knife_ctrl_Zero.
В следующей части вы будете использовать Script Editor, так что убедитесь, что он открыт. Через меню Edit → Clear All (Редактировать → Очистить все) очистите историю и все входящие соединения.
В Channel Box установите атрибут handR на 1. Остальные целевые атрибуты (sheath и world) установите на 0. Эти команды должны отразиться в Script Editor следующим образом:
setAttr “knife_ctrl_Zero.handR” 1;
setAttr “knife_ctrl_Zero.sheath” 0;
setAttr “knife_ctrl_Zero.world” 2;
select –r knife_ctrl;
Команда выделения в скрипте не обязательна, так как узел knife_ctrl, вероятно, не будет активно участвовать в анимации. Решения должны быть приняты аниматорами, совместно с персонажными риггерами.
Теперь нам нужно создать несколько скриптовых узлов для оперирования управляющими атрибутами ножа.
Выделите команды в поле истории и скопируйте их в буфер обмена, нажав Ctrl+c.
Через меню Window → Animation Editors → Expression Editor (Окно → Редакторы анимации → Редактор выражений) откройте Expression Editor. С помощью меню Select Filter → By Script Node Name переключите редактор на редактирование узлов со сценарием.
В поле Script Node Name введите toHandR. В поле Script вставьте команды, которые вы скопировали из Script Editor. Script Editor должен выглядеть как на рисунке 8.14.
@Рис. 8.14. Создание скриптового узла toHand
Держа окно Script Node открытым, выделите узел knife_ctrl_Zero. Измените значения узлов handR, sheath и world на 1. Нажмите кнопку Test Script, чтобы проверить работу команд.
Нажмите кнопку Create, чтобы создать Скриптовый Узел. Его имя должно добавиться в список.
Создайте локатор и назовите его hand_switcher. Нажмите на клавишу g, чтобы группировать локатор и назовите получившийся узел hand_switcher_Node.
Выделите сочленение hand_R и затем, удерживая клавишу Shift, выделите hand_switcher_Node. Создайте точечный ограничитель.
Выделите локатор hand_switcher и используя инструмент Move, сдвиньте его от сочленения запястья.
В командной строке введите следующее: buttonManip “scriptNode -executeBefore toHandR” “ hand_switcher ”.
В Expression Editor скопируйте команды из скриптового узла toHandR, выделив их и нажав Ctrl+c.
Нажмите кнопку New Script Node (Новый скриптовый узел), чтобы очистить настройки в Expression Editor.
Вставьте команды в поле Script, нажав Ctrl+v.
Измените значения в выражениях с командой setAttr, чтобы установить атрибут knife_ctrl_Zero.sheath на 1, а остальные – на 0, так же, как в следующем коде:
setAttr “knife_ctrl_Zero.handR” 0;
setAttr “knife_ctrl_Zero.sheath” 1;
setAttr “knife_ctrl_Zero.world” 0;
select –r sheath_ctrl;
И снова, автоматическое выделение узла sheath_ctrl необязательно.
В поле Script Node Name введите toSheath.
Нажмите кнопку Create, чтобы создать новый скриптовый узел. Он должен называться toSheath (рис. 8.15).
@Рис. 8.15. Создание скриптового узла toSheath
В среде моделирования создайте локатор и назовите его sheath_switcher.Сгруппируйте этот узел, нажав на g, и переименуйте его в sheath_switcher_node.
Выделите узел sheath и, удерживая клавишу Shift, sheath_switcher_node. Создайте точечный ограничитель.
Переместите локатор sheath_switcher, немного отодвинув его от тела.
В командной строке введите следующую команду: buttonManip “scriptNode -executeBefore toSheath” “sheath_switcher_node”.
Выделите узел sheath_ctrl и, удерживая клавишу Shift, sheath_switcher_node. Создайте pointConstraint с помощью меню Constrain → Point.
Выделите узел sheath_switcher и разместите его так, чтобы он находился вне геометрии (рис. 8.16).
@Рис. 8.16. Создание скриптового узла toWorld
Снова обратитесь к Expression Editor и нажмите на кнопку New Script Node. В поле Script Node Name введите toWorld.
На панели Script введите следующие команды:
setAttr “knife_ctrl_Zero.handR” 0;
setAttr “knife_ctrl_Zero.sheath” 0;
setAttr “knife_ctrl_Zero.world” 1;
select –r world_attach;
При переключении на глобальное пространство глобальный узел, возможно, следует выделить, просто потому, что ему, скорее всего, потребуется регулировка.
В среде моделирования создайте локатор и назовите его toWorld_switcher.
В командной строке введите следующую команду: buttonManip “scriptNode -executeBefore toSheath” “toHandR1”.
Выделите в Outliner узлы worldSwitcher_Node, sheath_switcher_Node и ctrl_switcher_Node, а также узлы манипуляторов. Наконец, выделите, удерживая Ctrl, узел knifeRig и нажмите p, чтобы подчинить ему остальные .
Команда buttonManip создает сферу, которая, если щелкнуть по ней, выполняет команду первого аргумента. Второй аргумент – это трансформа, с которой сфера перемещается. Скриптовый узел содержит команды для установления весов ограничителя. При изменении значений атрибута эти изменения записываются через установление ключевых кадров узла knife_ctrl_Zero.
Команды buttonManip выполняются наилучшим образом, если они связаны с трансформой. Когда трансформа двигается, buttonManip следует за ней. Здесь есть один недостаток: сфера, являющаяся кнопкой, не может быть отмасштабирована, и всегда держит один размер в окнах вьюпорта.
Важно знать причину использования buttonManips. В Maya можно применить reverseNode и создать простой контроллер переменного веса. Когда один вес равен 0, другой – 1, и наоборот (для получения дополнительной информации обратитесь к разделу reverseNode главы 1). Однако балансирование между тремя и более весами усложняет задачу. Можно наложить реверсные узлы и multiply-узлы, чтобы они управляли более чем двумя целями, но вы все равно придете к множеству атрибутов, которые нужно установить на 0 или 1. Решение с buttonManip и скриптовым контролем упрощает управление: вы можете установить столько контролирующих скриптов, сколько нужно для данного количества целей. Обычно мы работаем со включенной функцией автоключей. Если это не ваш стиль, можете добавить в контролирующие скрипты команду setKeyframe, чтобы ключевой кадр сохранялся при переключении целей .
Эта ситуация чуть более управляема. Вместо постоянного соединения scriptNode вручную устанавливает атрибуты, как если бы они были установлены в Channel Box.
Наведение блеска
Когда базовая система пропса для ножа в основном настроена, еще несколько штрихов сделают ее чище. В то время как buttonManips очень полезная штука, нам всё же нужно немного освободить экран. Для этого персонажа нож – скорее, вспомогательный пропс, поэтому имеет смысл скрыть контроллеры, чтобы упростить работу аниматора. Основной контроллер пропса ножа – узел knife_ctrl_Zero, так что он будет управлять еще и видимостью контроллеров пропса.
Следующие шаги иллюстрируют, как настроить управление видимостью buttonManips:
Откройте Outliner.
Выделите узел knife_ctrl_Zero и откройте Attribute Editor. С помощью пункта меню Add Attribute добавьте логический атрибут под названием knifeSwitchControls.
Откройте Connection Editor. На левую панель загрузите узел knife_ctrl_Zero. На правую – узел knifeRig. Проверьте, что кнопка в центре установлена на from→to.
Соедините атрибут knife_ctrl_Zero.knifeSwitchControls с атрибутом видимости узла knifeRig (рис. 8.17).
@Рис. 8.17. Добавление управления видимостью переключения ножа
Теперь аниматор может контролировать видимость контроллеров, не обращаясь к Outliner. Так как knife_ctrl_Zero – корневой узел пропса, то логично установить в нем особые атрибуты, влияющие на функционирование контроллеров. Также обратите внимание на то, что атрибут knifeSwitchControls имеет возможность установки ключевых кадров. На самом деле так не должно быть, но иначе он не отображался бы в Channel Box. Каждое производство своеобразно, но для нас предпочтительно, чтобы простота доступа перевешивала раздражения от невизуализирумых контроллеров, анимируемых на включение и выключение.
Теперь пропс настроен, но допустим, что персонаж собирается положить нож на стол. При переключении с правой руки на глобальное пространство возникает неестественный сдвиг. Его можно скорректировать «на глаз» или с помощью временных ограничителей, но, возможно, выгоднее встроить эту функцию в саму систему пропса. Для этого мы должны будем применить скрипт, разработанный с использованием некоторого материала из главы 3: скрипт под названием snapArgs. SnapArgs принимает в качестве входных данных имена двух узлов и привязывает второй узел к первому, что очень похоже на ограничитель. Однако постоянного соединения нет, так как сценарий лишь устанавливает значения атрибута.
Поведение, которое мы хотим установить, таково: всякий раз, когда модель переключается с руки или ножен на мировое пространство, узел глобального пространства должен выравниваться по положению и ориентации узла текущего присоединения. Все данные положения и вращения ножа предоставляются узлом knife_ctrl_Zero. Это та трансформа, которая присоединяется к узлам handR, sheath и world. Если узел worldCtrlWorld перемещается в положение узла handR, когда пропс переключен не на руку, то пропс не сдвинется и перемещение будет плавным. Чтобы оно было плавным, действуйте следующим образом:
Врезка. Важно помнить, какие трансформы влияют на пропс. Чтобы этот процесс происходил плавно, вращения и перемещения узла ctrlKnife должны быть обнулены.
Выделите узел knife_ctrl_Zero и откройте Attribute Editor.
Примените команду меню Attributes → Add Attribute, чтобы добавить логический атрибут под названием worldAutoSnap.
С помощью меню Window → Animation Editors → Expression Editor откройте окно Expression Editor.
Примените команду Select Filter → By Script Node Name, чтобы переключить редактор в режим редактирования скриптового узла.
Выделите узел toWorld на панели Script Node.
В окне сценария перед любой из команд setAttr добавьте следующие строки (рис. 8.18):
if(`getAttr knife_ctrl_Zero.worldAutoSnap`)
{
select –r knife_ctrl_Zero knife_ctrlWorld;
snap();
}
@Рис. 8.18. Добавление команды привязки в узел со скриптом toWorld
Первая строка проверяет, нужно ли привязать узел глобального пространства к положению пропса, когда происходит переключение. Чтобы совершить привязку, во второй строке используется MEL-команда snap из третьей главы. Копия команды привязки есть на Web-сайте http://www.courseptr.com/downloads.
Нажмите на кнопку Edit, чтобы внести изменения в скриптовый узел.
Выделите узел knife_ctrl_Zero и установите атрибут worldAutoSnap на on.
Теперь, если вы щелкнете по buttonManip руки или ножен, пропс будет двигаться. Если щелкнете по buttonManip глобального пространства, то его контроллер привяжется к положению активного в настоящий момент пропса. Он действительно привязывается в текущее положение узла knife_ctrl_Zero до того, как меняет веса в ограничителе.
Двуручные пропсы
Итак, одноручный пропс довольно прост. Теперь мы рассмотрим двуручный. Здесь возникают новые вопросы. Как пропс будет управляться? Будет ли он управлять движением рук? Как руки будут управлять им?
Многие аниматоры предпочитают применять решения прямой кинематики, там, где это только возможно. Помните об этом, при конструировании пропса разумно связывать его главное действие с его основной рукой. Другую руку можно прикрепить ограничителем к точке на пропсе. Это простое решение хорошо работает, пока не возникает необходимости в переключении рук пропса.
Давайте посмотрим, как одарить нашего персонажа дубинкой:
Скачайте файл staff_start.ma с http://www.courseptr.com/downloads.
С помощью команды File → Import импортируйте файл /chapter_8/scenes/staff_start.ma. У точки начала отсчета вы увидите аксессуар персонажа.
Создайте пустую группу и переименуйте ее в staff_geo_offset.
Выделите узел staff_geo_offset и, удерживая Shift, узел staffGeo. Через меню Constrain создайте pointConstraint и orientConstraint.
В меню File выберите Import и импортируйте nurbSplineCube.mb. Переименуйте объект curve1 в staff_ctrl.
Выделите узел staff_geo_offset и, удерживая Shift, кривую staff_ctrl. Нажмите p, чтобы создать между ними родительскую связь.
Выделите узел staffCtrl и сгруппируйте его, нажав Ctrl+g. Переименуйте группу в staff_hand_L_attach.
Импортируйте еще одну управляющую кривую. Переименуйте узел curve1 в staff_hand_L_ctrl. Прикрепленный к дубинке, он будет управлять левой рукой.
Выделите узел staff_hand_L_attach. Удерживая Shift, выделите узел staff_hand_L_ctrl. Нажмите p, чтобы создать родительскую связь.
Выделите staff_hand_L_ctrl и подчините его узлу staff_ctrl.
@Рис. 8.19. Импортирование двуручного пропса персонажа
Выделите узел staff_hand_L_ctrl. Используя инструмент Move, сдвиньте его вниз по рукоятке копья. Не обязательно ставить его именно в этой точке, мы просто подготавливаем иерархию. Когда вы закончите, два контроллера должны располагаться на дубинке так, как показано на рис. 8.20.
@Рис. 8.20. Создание управляющей геометрии аксессуара
Теперь займемся созданием узлов прикрепления (attachment nodes). Сначала создайте пустую группу и переименуйте ее в staff_r_hand_offset. Сгруппируйте этот узел и переименуйте его в staff_r_hand_offset_attach.
Выделите bn_hand_node. Удерживая Shift, выделите узел staff_r_hand_attach. Создайте точечный и ориентационный ограничители.
Создайте пустую группу и назовите ее staff_world_offset. Сгруппируйте этот узел и назовите получившуюся группу staff_world_space.
Выделите узлы staff_r_hand_offset, staff_world_offset и staff. Создайте точечный и ориентационный ограничители.
Выделите узел staff_ctrl и откройте Attribute Editor. Через меню Add Attributes создайте атрибут под названием toWorld с минимальным значением 0.0, максимальным 1.0 и 0 по умолчанию.
Откройте Hypergraph. Выделите узлы staff_ctrl и staff. Отобразите входящие и исходящие соединения.
Соедините атрибут staff_ctrl.toWorld с атрибутом sWorldW2 узла staff_pointConstraint1 и еще раз с таким же атрибутом узла staff_orientConstraint1.
Откройте Hypershade, в закладке Create выберите Maya Utilities (Утилиты Maya) и создайте реверсный узел. Переименуйте его в staff_reverse.
В Hypergraph или Hypershade выделите реверсный узел и узел staff_ctrl. Отобразите соединения.
Соедините атрибут toWorld узла staff_ctrl с атрибутом inputX узла staff_reverse, как показано на рис. 8.21.
@Рис. 8.21. Соединение узла staff_ctrl
Соедините атрибут staff_reverse.outputX с атрибутами r_HandW1 узлов staff_pointConstraint1и staff_orientConstraint1.
Копье должно быть выровнено по узлу r_Hand правой руки. Выделите этот узел и примените инструменты Move и Rotate, чтобы правильно разместить копье. Нужно определить ее место так, чтобы это выглядело естественно.
Этой настройки будет достаточно для вещей, предназначенных для одной руки, таких, как трость, например. Мы собираемся сделать так, чтобы левая рука pigGoblin тоже захватывала копье, придавая ощущение большей интерактивности. Так же мы хотим настроить левую руку так, чтобы было смешивание обычных анимационных контроллеров сборки и контроллеров, расположенных на копье. Это значит, что точка прикрепления левой руки к дубинке будет снабжена объектами точечного и ориентационного ограничителей.
Придайте фигуре такую позу, чтобы контакт копья и левой руки выглядел наиболее натурально. Вы можете воспользоваться этой возможностью, чтобы заново разместить staff_ctrl рядом с точкой прикрепления. Если вы так поступите, то не забудьте заморозить трансформации, чтобы установить положение покоя. Сверьтесь с рис. 8.22.
@Рис. 8.22. Регулировка положения узла staff_ctrl.
Теперь пора сделать первую цель для оружия. Выделите узел ctrl_wrist_ori_local. Если у вас возникли трудности с его нахождением, введите его название в строке быстрого выделения или введите в командной строке select -r staff_hand_L_ctrl.
Выделив узел, нажмите Ctrl+d, чтобы дублировать его. Переименуйте узел в ctrl_wrist_ori_Staff_L.
Оставьте этот узел выделенным и, удерживая Ctrl, выделите узел staff_hand_L_attach. Нажмите клавишу p, чтобы создать родительскую связь.
Выделите узел ctrl_wrist_ori_Staff_L и, удерживая Shift, узел ctrl_wrist_Zero_L. Через меню Constrain → Orient Constraint установите дублированный узел как новую цель ориентации.
Выделите узел ctrl_wrist_L|xtraAttrs. В Attribute Editor примените пункт меню Add Attribute для создания нового атрибута под названием weapon. Назначьте ему минимальное значение 0.0, максимальное 1.0. Значение по умолчанию должно равняться 0.0.
Атрибут оружия будет управлять смешиванием между контроллерами левой руки и копья. С помощью utility-узлов он будет прицепляться к различным ограничителям, управляющим ориентацией руки. В Hypershade создайте реверсный узел. Переименуйте его в staff_orient_reverse.
Следующие действия лучше всего выполнять в окнах Hypergraph или Hypershade. Соедините атрибут ctrl_wrist_L|xtraAttrs.staff с атрибутом ctrl_wrist_Zero_L_orientConstraint1.ctrl_wrist_ori_Staff_LW2. Это установит вес цели оружия на 1.
Соедините атрибут ctrl_wrist_L|xtraAttrs.staff с атрибутом staff_reverse.inputX.
В Hypershade создайте узел multiplyDivide. Переименуйте его в staff_constraint_dampen. Этот узел будет использоваться для изменения значений первоначальных целей руки на 0. Когда атрибут ctrl_wrist_L|xtraAttrs.staff установлен на 1, оба других веса – целей глобальной и локальной ориентации – будут умножены на 0, и станут равны нулю.
Соедините атрибут staff_reverse.outputX с атрибутами staff_constraint_dampen.input2X и staff_constraint_dampen.input2Y (рис. 8.23).
@Рис. 8.23. Соединение узла staff_orient_reverse с multiplyDivide‑узлом staff_constraint_dampen
Соедините атрибут ctrl_wrist_L|xtraAttrs.wristFollow с атрибутом staff_constraint_dampen.input1X.
Соедините атрибут reverse5.output с атрибутом staff_constraint_dampen.input2Y. Это управление локальным и глобальным весами ориентации запястья.
Соедините атрибут staff_constraint_dampen.outputX с атрибутом ctrl_wrist_Zero_L_orientConstraint1.ctrl_wrist_ori_Local_LW0.
Соедините атрибут staff_constraint_dampen.outputX с атрибутом ctrl_wrist_Zero_L_orientConstraint1.ctrl_wrist_ori_World_LW1.
На этом этапе значения ограничителя ориентации на месте. Теперь пора создать переназначение перемещения. Выделите узел aux_blend_L и дублируйте его. Переименуйте узел в aux_blend_staff_L.
Выделив узел aux_blend_staff_L, выделите также, удерживая Shift, узел staff_hand_L_attach. Нажмите на клавишу p, чтобы создать родительскую связь.
Выделите узел aux_blend_staff_L. Удерживая Shift, выделите aux_blend_L. С помощью меню Constrain → Point Constraint установите aux_blend_staff_L в качестве цели точечного ограничителя.
Создайте реверсный узел и переименуйте его в staff_point_reverse.
Соедините атрибут ctrl_wrist_L|xtraAttrs.staff с атрибутом aux_blend_L_pointConstraint1.aux_blend:staff_LW1.
Соедините атрибут ctrl_wrist_L|xtraAttrs.staff с атрибутом staff_point_reverse.inputX.
Соедините атрибут staff_point_reverse.outputX с атрибутом aux_blend_L_pointConstraint1.ctrl_arm_LW0.
Теперь настройка смешивания завершена. Персонаж должен выглядеть так, как на рис. 8.24. Когда атрибут ctrl_wrist_L|xtraAttrs.staff установлен на 1, другие веса точечного и ориентационного ограничителей умножаются на 0, и их значение становится равным нулю.
@Рис. 8.24. Законченный пропс
Создавая цели для левой руки, обратите внимание на то, проще будет продублировать и переподчинить цель, особенно если в качестве цели вы используете сочленение. Сочленения с их собственной ориентацией выравнивать нелегко. Вы также заметите, что пропс не должен находиться в положении покоя для того, чтобы его можно было использовать как цель. В сущности, к настройке двуручного пропса нужно отнестись внимательно именно потому, что его нельзя настроить в обычном положении покоя. Можно обеспечить сохранность позы покоя, установив всем контроллерам ключевой кадр в нулевом кадре анимации и работая с позой в другом кадре.
