ponimayka1
.pdfОчевидно, что атрибуты vx, vy, vz содержат теперь координаты вектора скорости, а атрибут velocity определяется как длина вектора скорости, то есть как величина скорости. Эти атрибуты вы можете использовать в дальнейшем.
Например, конус может удлиняться, двигаясь с большой скоростью - в соответствии с
общей теорией относительности...
Для этого достаточно дописать еще одну строчку в expression:
В дальнейшем вы можете использовать информацию о скорости и более интеллектуальным образом. Например, при движении с большой скоростью объект может изменять свой цвет или прозрачность. Вы также можете деформировать объект и задавать степень деформации в зависимости от скорости объекта. Такие интеллектуальные связи удобнее всего устанавливать с помощью операции Set Driven Key, о которой речь пойдет ниже.
Примечание. Чтобы добиться автоматического удлинения при разгоне и сплющивания при торможении, необходимо иметь информацию об ускорении объекта. Ускорение вы всегда можете вычислить как разницу между скоростью в текущем и предыдущем кадрах, пользуясь только что описанными выше принципами (см. сцену keyframeAcceleration.ma).
Поговорим теперь об ошибках. Когда конус останавливается, положение локатора совпадает с позицией конуса, и в этом случае конус пытается смотреть на локатор, находящийся у него в центре. Это приводит к тому, что конус просто разворачивается вдоль мировой оси X, так как констрейн не может вычислить необходимые вращения.
Чтобы избежать такой ситуации, надо, очевидно, проверить, не равна ли нулю скорость объекта, и если равна, то не надо ли производить обновления позиции локатора, оставляя его в последнем положении.
631
Сохраните сцену (keyframeVelocity.ma).
Подумайте о том, как еще можно использовать информацию о скорости.
Коленвал.
Преобразование типов движений с помощью expressions. Теорема Пифагора.
Разберем типичный пример совместного использования констрейнов и expressions. Ex pressions используются в данном случае для задания связи между объектами, не реализуемой с помощью констрейнов. А констрейны не только обеспечивают основные связи, но и служат источником информации об абсолютных координатах объектов, находящихся внутри иерархий. Пример и модель предоставлены Володей Забелиным.
Откройте файл-заготовку krivoship.ma.
В нем есть три элемента. Вращающийся вал с анимацией, штанга и поршень. Названия объектов достаточно красноречивы.
Обратите внимание, что длина штанги равняется примерно семи единицам. Наша задача состоит в том, чтобы перевести вращательное движение вала в поступательное вертикальное перемещение поршня.
Для начала закрепим один конец штанги на ручке вала. Проще всего это сделать с помощью локатора и Parent Constraint.
Создайте локатор, назовите его valLoc. |
|
|
|
|
|
|
||
Надо приподнять его на уровень |
вала |
(translateY=7) |
и «припарентить» |
к |
объекту |
val с |
||
помощью Parent Constraint: |
|
|
|
|
|
|
|
|
Выберите val, затем valLoc, выполните Constrain=>Parent Constraint). |
|
|
|
|||||
Теперь локатор вращается вместе с валом. |
|
|
|
|
|
|||
Внимание! |
Очень важно |
понимать одну |
существенную разницу |
между |
Par |
|||
ent Constraint |
и операцией |
Edit=>Parent. |
Внешне результат -припарентивания- |
|||||
совершенно одинаковый. Однако в |
случае |
применения констрейна |
в |
Channel |
Box |
632
для локатора будут высвечиваться абсолютные |
координаты |
объекта. |
В |
случае |
|||
обычного |
«припарентивания» эти координаты |
будут локальными |
(то |
есть |
|||
относительно вала как родительского объекта) |
и |
вообще |
не |
будут |
меняться, |
||
так как |
положение локатора относительно вала |
не |
изменяется |
в этом |
случае. |
Так как нам в дальнейшем понадобятся абсолютные координаты локатора для вычисления положения поршня, был использован Parent Constraint.
Теперь «прибьем» штангу к локатору.
Выберите локатор, затем штангу и выполните Constrain=>Point Constraint. Теперь штанга перемещается вместе с локатором, не вращаясь при этом.
Заставим штангу смотреть на поршень (то есть ему «в пивот»).
Выберите поршень, затем штангу и выполните Constrain=>Aim Constraint (с параметрами по умолчанию).
Штанга развернется в сторону поршня, однако не той локальной осью, которой нужно. Чтобы исправить положение, найдите в Channel Box атрибуты объекта shtanga_aimConstraint1 и задайте offsetZ=-90.
Теперь осталось согласовать вращение вала и перемещение поршня, чтобы между локатором и поршнем все время было одно и то же расстояние, равное длине штанги (в нашем случае ровно семи).
С помощью констрейнов сделать это ловко не удастся, и на помощь нам придет теорема Пифагора.
Рассмотрите прямоугольный треугольник, где гипотенузой (С) является штанга, одним катетом (А) будет расстояние от локатора до вертикальной оси Y, а вторым катетом (В) будет
633
расстояние от поршня до прямого угла.
Если мы найдем длину катета В, задача будет решена, так как это и есть искомое расстояние по вертикали от локатора до поршня, и нам останется написать expression, задающий связь между valLoc.translateY и porshen.translateY.
Длина гипотенузы С нам известна, это - 7. Длина катета А тоже, это valLoc.translateZ.
Как следует из теоремы Пифагора В2 = С2 - А2.
Создаем expression:
porshen.ty = valLoc.ty - sqrt(7*7 - valLoc.tz*valLoc.tz);
Здесь sqrt это функция, вычисляющая квадратный корень. Теперь вся конструкция исправно работает в анимации. Осталось, как обычно, навести блеск и поработать над возможными ошибками. Блеск заключается в том, что если вместо семерки вписать в expression значение атрибута scaleY для штанги
porshen.translateY = valLoc.ty - sqrt(shtanga.scaleY*shtanga.scaleY-valLoc.translateZ*valLoc. translateZ);
вы сможете после этого изменять длину штанги, и весь механизм будет перестраиваться под новые размеры, продолжая корректно отрабатывать анимацию.
Работа над ошибками заключается в следующем. Если сделать длину штанги достаточно короткой, возникнет ситуация, когда она станет меньше, чем радиус вала, и поэтому в какой-то момент выражение:
shtanga.scaleY*shtanga.scaleY-valLoc.translateZ*valLoc. translateZ
станет меньше нуля. Попытка вычислить квадратный корень из отрицательного выражения вызовет у MAYA приступ бешенства в виде серии сообщений об ошибках. Чтобы избежать такой ситуации, следует, очевидно, сделать проверку величины указанного выражения и в случае отрицательного значения (то есть когда штанга «отрывается от поршня») сделать высоту поршня (porshen.trans lateY) равным высоте локатора (valLoc.translateY).
634
Отредактируйте expression следующим образом:
Примечание. Попытка просто взять абсолютную величину подкоренного выражения с помощью функции abs приведет к менее удачной конструкции. Можете проверить сами.
Взрослые мальчики могут переписать expression в более компактном и «красивом» виде (правда, менее понятном):
Сохраните сцену (krivoshipFinal.ma).
Подумайте о связях между объектами, загляните в Hypergraph, проследите направление связей от вала к поршню.
Операция Set Driven Key. Формула произвольной гибкости
Представьте себе, что нужно сделать так, чтобы цвет и прозрачность объекта изменялись в зависимости от его размера. Примером может служить надуваемый воздушный шарик или же брюхо комарихи, набухающее и краснеющее по мере его заполнения.
Первое, что приходит на ум, это написать expression с формулой зависимости цвета от размера. Однако сразу возникает несколько проблем.
Во-первых, каналов цвета три и писать формулу придется для каждого в отдельности.
Во-вторых, значение цвета для каждого канала меняется от нуля до единицы. Конечно можно подобрать коэффициент зависимости между размером и цветом, чтобы цвет менялся примерно в нужном диапазоне. Однако как быть с границами диапазона? Хотелось бы иметь ограничение типа «цвет пропорционален размеру, но не может быть больше чем 0.9». С помощью expression это можно реализовать с помощью выражения типа:
В-третьих, для каждого канала цвета надо будет подбирать свои коэффициенты, причем вслепую. Соответствующий expression превратится в месиво цифр:
635
Говорить о наглядности и уж тем более об интерактивности, согласитесь, в данном случае не приходится.
Ну, ив-четвертых, как быть, если мы захотим, чтобы цвет менялся не прямо пропорционально размеру, а более сложным, нелинейным образом, типа: «медленно при малых значениях размера и быстро при больших»?
Приведенная ситуация - типичный пример, когда выбранное средство (expression) хоть и способно решить задачу, однако явно неэффективно и будет сильно тормозить производственный процесс.
Часто встречается ситуация, когда связь между атрибутами объектов описывается в терминах типа «если один объект находится в состоянии (положении, вращении и т.д.) А1, то второй объект должен быть в состоянии В1, а если первый объект будет в состоянии А2, то второй должен перейти в состоянии В2, и так далее». Такая связь плохо реализуется с помощью expres sions, но для ее описания идеально подходит операция Set Driven Key.
Идея технологии Driven Key заключается в следующем. Когда вы ставите обычные ключи на атрибуты объекта, возникает анимационная кривая, определяющая зависимость атрибута от времени. С помощью операции Set Driven Key можно ставить на атрибут ключи, определяющие зависимость этого атрибута не от времени, а от другого атрибута. Такие «особые» (driven) ключи также порождают анимационную кривую, у которой на горизонтальной оси в Graph Editor отображаются не кадры или секунды, а атрибуты управляющего объекта. В дереве зависимостей такая анимационная кривая располагается не между объектом и временем, а между управляемым и управляющим объектами.
Другими словами, можно сказать, что операция Set Driven Key позволяет определить не «прямую» связь между атрибутами (как в Connection Editor), а допускает задание произвольной зависимости между атрибутами, график которой определяется анимационной кривой.
Несмотря на использование термина «ключ» (Key), никакой зависимости от времени в ходе применения этой операции не возникает. Равно как и никакой анимации. Возникает лишь зависимость между атрибутами объектов, не более того. Я советую рассматривать ключи и анимационные кривые, созданные с помощью Set Driven Key, как своего рода expressions, связывающие атрибуты объектов.
Терминологический |
комментарий. |
Переводить команду |
Set |
Driven |
Key словами, |
||||||
вроде |
«установить |
управляемый |
ключ», я, как вы понимаете, не |
собираюсь. И |
|||||||
вообще не собираюсь как-либо «переводить» этот термин. |
Закоренелые мойщики, |
||||||||||
как нетрудно |
догадаться, употребляют |
прямолинейные |
выражения |
типа |
«этот |
||||||
сетап |
сделан |
дривен |
кеями» |
и |
прекрасно понимают друг друга. Я лишь |
упомяну |
|||||
о том, что |
driven |
в |
переводе с |
компьютерного означает |
«управляемый». |
Также |
|||||
замечу, |
что |
применительно |
к |
операции Set Driven Key, оперирующей |
такими |
||||||
терминами, |
как driver и |
driven, очень |
хорошо подходит понятийная |
связка |
|||||||
«ведущий-ведомый». |
|
|
|
|
|
|
|
|
|
Проделаем быстро простой пример, чтобы понять смысл операции Set Driven Key.
Интеллектуальный шлагбаум
Откройте файл drivenKey_start.ma. Если вам посчастливилось скачать эту книгу из Интернета, изготовьте цилиндрический паровоз и кубический шлагбаум. Рельсы носят декоративный характер.
636
Как известно, любой добропорядочный шлагбаум при приближении паровоза тут же опускается и перекрывает движение автомобилей по дороге. После удаления адской машины на безопасное расстояние шлагбаум автоматически поднимается и остается в таком положении, до следующего паровоза.
Зададим связь между положением паровоза и движением шлагбаума с помощью операции Set Driven Key.
Коль скоро управляемым будет шлагбаум, то есть на его атрибутах rotate будут «висеть» какие-то управляющие связи, надо выбрать его (объект bar), а затем выделить в Channel Box атрибут rotateX и в меню по правой кнопке выбрать Set Driven Key.
Откроется окно Set Driven Key, позволяющее задавать зависимость между управляющим объектом и выделенным атрибутом bar.rotateX.
Это окно напоминает отдаленно Connection Editor, только ориентированный вертикально. В нижней части отображаются атрибуты управляемого (или ведомого, driven) объекта. В верхней панели должен находиться управляющий (ведущий, driver) объект.
В нашем случае управляющим объектом будет parovoz, а управляющим атрибутом будет translateZ. Ведь положение шлагбаума должно зависеть от перемещения паровоза по оси Z. Чтобы загрузить паровоз в верхнюю Driver-панель, выберите его и нажмите кнопку Load Driver в окне Set Driven Key.
Теперь обязательно выберите атрибут translateZ в верхней панели, чтобы определить его как управляющий.
Не помешает удостовериться, что в нижней Driven-панели атрибут rotateX объекта bar также выбран.
637
Теперь начинается самое интересное.
Отведите паровоз на безопасное расстояние, то есть туда, где шлагбаум будет еще открыт. Откройте шлагбаум на адекватный, с вашей точки зрения, угол. Нажмите кнопку Key.
Внимание! В тот момент, когда вы нажали кнопку Key, вы создали связь-условие типа «если паровоз находится в таком-то месте, то шлагбаум должен быть
повернут на |
такой |
то |
угол». |
|
|
В терминах |
MAYA |
эта |
связь формулируется как «если атрибут parovoz.translate! |
||
равен -18, то атрибут |
bar.rotateX |
равен 80». К сожалению, |
никаких индикаторов |
||
или маркеров, свидетельствующих об этом, не появляется, |
так что вам надо |
||||
просто помнить о |
том, |
где и когда |
вы уже поставили Driven |
Key. |
Теперь передвиньте паровоз туда, где шлагбаум уже должен быть закрыт, а затем опустите шлагбаум. И снова нажмите кнопку Key.
Внимание! Сначала надо изменять управляющий объект, а затем управляемый. Это важно.
«Поелозьте» паровозом по рельсам. Шлагбаум должен в панике закрываться при приближении паровоза. -Поелозьте- также мышкой по временной линейке. Убедитесь, что никакой анимации нет и в помине. Все, что вы сделали, это установили связь между паровозом и шлагбаумом.
Примечание. Название кнопки Key катастрофически дезинформирует начинающих пользователей. Нажимая ее, они бессознательно ожидают появления анимации в сцене и с удивлением взирают на временную линейку, где не появляется ни одного ключа. С моей точки зрения более адекватным названием для кнопки было бы Set или Connect.
Поставим еще два driven-ключа.
В меню окна Set Driven Key есть пункт Keys=>Go to Next, позволяющий последовательно переходить в те положения, в которых были установлены связи-ключи. Это помогает не запутаться.
Заставьте паровоз проехать шлагбаум и остановите его в том месте, где осторожный шлагбаум должен начать подниматься.
Шлагбаум при этом трогать не надо: он ведь еще закрыт. Просто нажмите кнопку Key.
Совет. Шлагбаум или паровоз можно выбирать прямо в окне Set Driven Key. Это здорово экономит время и заодно помогает понять суть процесса.
638
Далее передвиньте паровоз еще дальше, затем откройте шлагбаум. Снова нажмите Key.
Теперь неистово подергайте за паровоз и убедитесь, что шлагбаум открывается и закрывается автоматически. Так, как будто бы работает некий expression, связывающий, перемещение паровоза и опускание-поднимание шлагбаума.
Так где же посмотреть на эти невидимые driven-ключи? Правильно, в Graph Editor.
А выбрать нужно при этом шлагбаум, ведь это на его атрибуте rotateX «висит» специальная анимационная кривая, отвечающая за связь с паровозом (в чем нетрудно убедиться, взглянув на цвет rotateX в Channel Box).
Откройте Graph Editor, нажмите «f».
Вы увидите анимационную кривую, определяющую зависимость вращения шлагбаума от перемещения паровоза. Обратите внимание: в правом нижнем углу обозначено не время, а перемещение паровоза (parovoz. translateZ).
Эту анимационную кривую можно редактировать любыми известными вам способами. Например, выберите ее и сделайте тангенсы всех ключей типа Spline: Tangents=>Spline.
Потаскайте паровоз и убедитесь, что шлагбаум стал «проваливаться», вместо того, чтобы оставаться закрытым. Форма анимационной кривой в середине красноречиво объясняет, почему так происходит. Чтобы обеспечить «мягкое» поднятие и опускание шлагбаума сделайте тангенсы «плоскими»: Tangents=>Flat.
Совет. |
Всегда помните |
о том, |
какого типа тангенсы создаются при создании |
|
ключей по умолчанию. |
Посмотреть |
или изменить этот тип можно в главном окне |
||
настроек |
Preferences, |
в |
категории |
Animation. |
639
Обратите внимание: driven-ключи не отображаются на временной линейке. Им просто негде там отображаться, ведь они не связаны ни с каким кадром.
Откройте Hypergraph и посмотрите, как устроены входящие связи для шлагбаума.
Анимационная кривая располагается в дереве зависимостей точно посередине между объектами parovoz и bar. Теперь вы можете ставить «традиционные» ключи на перемещение паровоза, производя анимацию его движения. Анимация шлагбаума при этом будет получаться автоматически. Сохраните сцену (drivenKey_final.ma).
Управление множеством атрибутов с помощью Set Driven Key. Борьба с комарами
Совершенно очевидно, что с помощью операции Set Driven Key можно заставить один управляющий атрибут влиять на множество управляемых. Нужно лишь произвести нужный выбор в окне Set Driven Key. Сделаем еще один пример.
Откройте новую сцену. Создайте две сплайновые сферы и превратите каждую в брюхо комара. Первую - в тонкое голодное брюхо, а вторую в набухшее сытое брюхо. Если вам лень таскать за точки, откройте файл komar_start.ma.
Сделаем морфинг тонкого брюха в толстое, имитируя, таким образом, процесс насыщения кровососущего паразита.
Сначала выберите большой живот, затем маленький и выполните операцию Deform=>Create Blend Shape.
Разыщите в Channel Box ноду blendShape1 и убедитесь, что если задать значение ее атрибута nurbsSphere2 равным единице, то худое брюхо превратиться в толстое.
Спрячьте или удалите второе, ненужное брюхо, а на оставшееся назначьте новый материал типа Phong (правая кнопка мыши=>Materials=>Assign New Material=>Phong).
640