Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ponimayka1

.pdf
Скачиваний:
131
Добавлен:
07.06.2015
Размер:
37.11 Mб
Скачать

Чтобы не писать каждый раз сумму масштабов цилиндров (вместо двойки), я запомнил ее

впеременную $scale и подставил ее вместо двойки. Теперь перемещение цилиндров согласуется

сих размером.

Немного «почистим» сцену.

Наши цилиндры должны перемещаться только по вертикали и могут менять размер. Потому выберите оба цилиндра, выделите в Channel Box все атрибуты, кроме translateY и

scaleXYZ, и сначала заблокируйте их (Lock Selected), а затем спрячьте от греха подальше, то есть удалите из Channel Box (Hide Selected).

Посмотрим, как можно быстро добавить несколько звеньев в наш телескоп и при этом затратить минимум энергии на создание и редактирование новых expressions.

Сначала выделите все уже отлаженные команды в Expression Editor и скопируйте их в буфер обмена (Ctrl-c).

Выберите цилиндр р2 и сдублируйте его с помощью операции Edit=>Duplicate. Появится новый цилиндр с именем рЗ.

Откройте Expression Editor и нажмите кнопку New Expression. Вставьте скопированный текст (Ctrl-v) в поле Expressions: .

Теперь его надо исправить так, чтобы он устанавливал зависимость третьего цилиндра от второго. То есть имя р2 надо исправить на рЗ, а имя р1 - на р2.

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

Теперь цилиндры двигаются как система вложенных поршней, и управляющим является первый цилиндр. Если такая модель вас устраивает, сохраните файл (telescope_v1 .ma) и далее можете ограничиться только чтением.

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

Выберите в Expression Editor по очереди оба expressions и исправьте их текст следующим образом:

Теперь второй логический оператор проверяет, не опустился ли верхний цилиндр ниже

621

нижнего, и если да, то «прицепляет» нижний к верхнему.

Сохраните сцену (telescope_v2.ma).

Если вам захочется покрутить антенну или прикрепить ее к радиоприемнику, то, очевидно, лучше всего объединить цилиндры в группу и ориентировать группу «хитрым» способом.

Выберите все три цилиндра, сгруппируйте их: Edit=>Group. Перетащите пивот группы в основание нижнего цилиндра.

Чтобы ловко вращать антенну за конец или основание, воспользуемся констрейнами. Выберите сначала локатор, затем только что созданную группу и выполните Constrain=>Aim

Constraint.

Если параметры этой операции были заданы по умолчанию, цилиндры «лягут» на бок. Чтобы направить их на локатор, найдите в Channel Box атрибуты объекта group1_aimConstraint1 и задайте offsetZ= -90.

Подробнее про использование констрейнов читайте в соответствующем разделе.

Теперь вы можете ориентировать условную антенну, перемещая локатор и группу друг относительно друга, а также вытягивать ее или сжимать, передвигая верхний цилиндр.

Сохраните сцену (telescope_final.ma).

Напоследок замечу, что в данном примере expressions предназначены для задания связи между объектами, которую можно описать следующими словами: «если объекты расположены так, то делать одно действие, а если эдак, то делать другое, в противном же случае - ничего не делать!». Реализовать такую зависимость другими средствами (констрейнами, Set Driven Key) было бы очень и очень непросто, особенно логику типа «в противном же случае ничего не делать». Поэтому перед выбором подходящих средств для определения связей между объектами всегда стоит хорошенько подумать о логике этих связей и, быть может, даже сначала описать эти связи «человеческим» языком или в виде блок-схемы.

622

Общие принципы создания и использования expressions

После такого подробного и пошагового разбора примеров я хочу немного ускорить темп и поговорить об общих принципах написания и применения expressions.

Прежде всего, следует постоянно помнить о том, что expressions - это объекты (точнее, ноды), хранящиеся вместе со сценой. Вы всегда можете увидеть их в Hypergraph и там же «распутать» или исследовать их связи с другими объектами.

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

Если говорить о циклических движениях, в их основе лежат, как правило, триногометрические функции sin() и cos(), зависящие от времени. Случайными перемещениями «заведуют» функции rand() и noise(). Примерами циклических движений могут служить различные спиралевидные траектории, колебания вокруг некоторой точки, размахивание крыльями, руками и другими конечностями, мигание маяка и прочее. Примеров хаотических перемещений так много, что перечислять их нет особого смысла, а диапазон примеров простирается от движения камеры

в трясущихся руках взволнованного оператора до моргания глаз растроганного режиссера. Затухание амплитуды колебаний или хаотических движений задается обычно с помощью

эспоненциальной функции, зависящей от времени, типа ехр(-0.01*time). Однако можно просто делить нужную величину на текущее время ($amp/(time*10+0.0001)) и тогда она будет линейно убывать по мере проигрывания анимации. Не забывайте про деление на ноль в этом случае.

Примечание. Классики анимации советуют делать сначала линейное затухание, а потом - экспоненциальное.

Среди expressions, предназначенных для задания связи между разными объектами, трудно выделить какие-то определенные типы. Могу лишь заметить, что знание теоремы Пифагора и основ тригонометрии совершенно необходимо для написания такого рода expressions, так как задача перевода вращений в перемещения и обратно встречается в этом случае очень часто. Примерами могут служить зависимость вращения колеса от его перемещения, различные формулы для программирования циклов походки (walk cycles), преобразующие поступательное движение туловища персонажа в циклические перемещения его ног.

Очень часто для эффективного использования expressions приходится добавлять к объектам дополнительные атрибуты и сохранять в них вспомогательную или промежуточную информацию, например, о состоянии объекта в предыдущем кадре или расстоянии от него до определенной точки. Помните о том, что expressions выполняются в каждом кадре и такая информация помогает задавать дополнительные свойства атрибута например, скорость. (Пример использования скорости объекта для его ориентации будет приведен ниже.)

Узнать значение нужного атрибута в любом кадре можно с помощью функции getAttr с флагом -time. Например:

Однако использовать функции getAttr и setAttr в expressions крайне нежелательно. (Об этом еще скажу позже.) Для создания «отстающей» или «догоняющей» анимации лучше всего подойдет использование клипов (см. раздел, касающийся нелинейной анимации). Для объектов, анимированных с помощью динамики, такой трюк, однако, не пройдет, так как MAYA не «знает» (точнее, не «запоминает»), где будет или где был объект некоторое время назад (в этом случае может помочь кэширование).

Expression нередко используются совместно с констрейнами для «сборки» анимированных конструкций. Дело в том, что некоторые свойства - например, ориентацию в сторону цели - удобно

623

задавать с помощью констрейнов, а взаимодействие объектов можно определять через expres­ sions. Помните только о том, что expression и констрейны не должны воздействовать на одни и те же каналы (если только вы намеренно не смешиваете два типа анимации).

Также следите за тем, чтобы не возникали циклические зависимости - например, первый объект «прибит» ко второму с помощью Point Constraint и в то же время влияет на перемещения второго посредством expression типа:

object2.tx=-1.5*object1.ty;

Если вы на свой страх и риск создаете объекты прямо в expressions с помощью MEL-команд (или, совсем потеряв совесть, удаляете объекты), надо понимать, что при возвращении в первый кадр никто за вас не будет делать Undo: ведь это не динамика с ее начальным положением системы. В этом случае, вы можете сделать нужные действия в первом кадре с помощью конструкции if(frame==1), например:

if (frame==1) { delete "myObject*"; $counter=0;}

Примечание. Про разницу между «»» и «==» можно прочитать в главе про MEL.

Объекты, анимированные с помощью expressions, не имеют, очевидно, никаких анимационных кривых. Однако вы всегда можете превратить процедурную анимацию в анимацию по ключам с помощью операции Edit=>Keys=>Bake Simulations. Это может, например, понадобится для экспорта сцены в другие пакеты или движки, ничего не знающие про механизм expressions. Операция Bake Simulations предназначена не только для преобразования динамической симуляции в анимационные кривые, а может использоваться для перевода любого типа анимации в анимацию по ключам.

Примечание.

Для написания

эффективных expressions вам придется открыть

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

примитивной

тригонометрии,

простейшей алгебре

и элементарной

арифметике.

В

идеале

термины

«квадратный корень» или «длина

вектора»

не должны валить

вас с ног.

К

сожалению, я не видел на русском языке книги «Высшая математика

для чайников», а ведь она могла бы быть крайне

полезна для не поступающих в

вузы.

 

 

 

 

 

 

 

Крайне

полезным

может

быть и

прочтение раздела документации

«Useful

Functions» в

рубрике MEL and Expressions.

Кроме того, вам не избежать прочтения главы в этой книге, посвященной языку MEL. По крайней мере, если вы хотите знать основы синтаксиса и понять, наконец, зачем нужно ставить все эти дурацкие кавычки.

Далее, я приведу еще немного примеров для иллюстрации разных типов expres­ sions, упомянутых выше. Я также буду предполагать, что Expression Editor уже освоен вами в совершенстве.

Циклические движения. Устаканивание с помощью expressions

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

Циклические движения описываются обычно с помощью функций sin() и cos(), задающих перемещения по двум любым координатам. Например, создайте полигональный куб и сделайте для него простой expression:

pCube1.tx = sin(time);

624

После этого куб начнет перемещаться в плоскости XY по окружности единичного радиуса. Чтобы увеличить радиус, следует просто домножить каждую функцию на свой коэффициент. В теории колебаний он называется амплитудой.

Если амплитуды колебаний по каждой координате разные, получится эллипс, а не окружность. Кроме амплитуды, существует еще частота колебаний, определяемая коэффициентом, на который умножается время.

Если частота колебаний по каждой координате разная, окружность превратится в различные «циклоиды» и вместо периодической траектории вы получите довольно экзотические колебания.

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

«Классический» способ состоит в использовании экспоненциальной функции с отрицательным аргументом

Более интуитивно понятный способ заключается в делении амплитуды на величину, пропорциональную времени, чтобы добиться линейного убывания амплитуды с временем.

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

Заметьте, что координата Z остается совершенно свободной. Вы можете задать спиралевидное движение, заставив ее равномерно увеличиваться. Это можно сделать с помощью двух ключей или же дописать в expression еще одну строку

Теперь вернемся к тарелке на столе.

В новой сцене создайте полигональный цилиндр.

Сожмите его по вертикали до состояния «тарелки» и приподнимите немного (translateY=0.5).

625

Теперь поверните цилиндр на 30 градусов вокруг оси Z. Его край коснется «земли».

Тут пытливые умы сообразят, что радиус цилиндра равен единице и что угол в тридцать градусов был взят не с потолка, а в результате сакральных вычислений, заключающихся в следующем: если радиус цилиндра (равный единице) это гипотенуза прямоугольноготреугольника, а положение его центра по вертикали катет (равный 0,5), то угол напротив этого катета должен быть равен 30 градусов, ибо синус от 30 градусов равен в точности 0,5.

Давайте напишем expression, который будет вычислять угол поворота тарелки в зависимости от высоты, так, чтобы она всегда касалась «земли».

Откройте Expression Editor и создайте новый expression:

Загадочная функция asind - это арксинус (функция, обратная синусу), возвращающий значение в градусах (буква d на конце это от degree).

Теперь, если вы будете таскать тарелку вверх-вниз, она всегда будет касаться одним краем земли.

Теперь попробуем закрутить тарелку.

Оказывается циклические выражения, упомянутые выше, применимы не только к перемещениям, но и к любым другим атрибутам. Чтобы заставить, например, циклически поворачиваться нашу тарелку, можно просто написать формулу:

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

Сейчас тарелка весело вращается вокруг вертикальной оси, наклоняясь на 30 градусов. Для угла наклона у нас уже есть формула, осталось подставить ее вместо числа 30. Используем для этого переменную:

Теперь тарелка вращается под нужным углом в зависимости от высоты ее центра (не задирайте пока тарелку выше единицы).

626

Число 5 в формулах задает частоту колебаний. Эта частота должна возрастать по мере того, как тарелка опускается на «землю», а у самой земли тарелка должна неистово дребезжать.

Зададим формулу для вычисления частоты колебаний в зависимости от высоты центра тарелки, то есть от значения атрибута translateY.

Теперь, если высота центра близка к единице, то тарелка вращается с прежней частотой, приблизительно равной 5, а если опускать тарелку, то ее вращение стремительно ускоряется. Это можно увидеть, и не запуская анимацию, а лишь «таская» тарелку вверх или вниз. Добавление числа 0.01 необходимо для того, чтобы избежать деления на ноль, когда центр тарелки вдруг опустится на «землю».

В принципе expression готов. Для того, чтобы анимировать «устаканивание» тарелки, вам достаточно поставить ключи на атрибут translateY. Это даст вам возможность уложить ее на землю именно так, как, по-вашему, должны вести себя фотореалистические тарелки. Она может подниматься и опускаться столько раз, сколько вам нужно. Если вы до того прониклись революционными идеями процедурной анимации, что не можете более ставить ключи, можете дописать в expression дополнительную строчку для анимации translateY, например

Однако тогда вам придется дополнительно останавливать вконец обезумевшую тарелку. Наведем некоторый блеск и подготовим тарелку к дальнейшей анимации. «Блеск»

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

Во-первых, функция арксинус не может принимать в качестве аргумента значения больше единицы (ведь синус в мирное время больше единицы не бывает).

Поэтому надо проверить значение translateY и принять меры.

Во-вторых, если значение translateY равно нулю, это означает, что тарелка полностью «легла» на землю. По существующей формуле частота колебаний ($speed) будет равна 500. Однако, к счастью, значение амплитуды $аmр, вычисляемой через арксинус, будет в этом случае равно нулю.

627

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

В-четвертых, число 5.0 следует вывести наружу в виде атрибута объекта, для того, чтобы можно было вручную задавать замедление или ускорение вращения.

Выберите цилиндр, добавьте к нему атрибут speed:

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

горизонтальные смещения центра цилиндра - для пущей реалистичности:

Коэффициент 100.0 также можно вывести наружу в виде атрибута объекта.

Наиболее пытливые умы могут придумать формулу вращения вокруг оси Y, чтобы обеспечить «непроскальзывание» (хотя реальная тарелка как раз активно проскальзывает). Не забудьте только

поменять порядок вращений в Attribute Editor на Rotate Order="yxz". Сохраните сцену (plate.ma).

628

Если вы хотите еще немного поиграть с тарелкой, поставьте ключи на атрибут translateY:

После этого, с помощью операции EditPolygons=>Extrude, превратите тарелку в другой вид посуды, например, в рюмку или бутылку. Вся анимация «устаканивания» будет успешно унаследована новой формой.

Сохраните сцену (plateFinal.ma). И попытайтесь отказаться от навязчивых мыслей о дальнейших усовершенствованиях.

Скорость объекта. Использование expressions для ориентации объекта по направлению движения. Работа с динамическими атрибутами

Если перемещение объекта анимировано по ключам, никакой информации о скорости объекта у нас нет. Мы можем лишь узнать позицию объекта в каждом кадре. С помощью ex­ pressions можно вычислить скорость, ускорение и другие «динамические» свойства объекта, анимированного «традиционным» способом. Эти свойства можно затем использовать, например, для автоматического разворота объекта «носом» по направлению движения (то есть необходимо только проанимировать положение объекта по ключам, а вращение будет получаться автоматически).

Создайте полигональный конус.

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

Добавьте к конусу три динамических атрибута (Modify=>Add Attribute), назовите их oldX, oldY, oldZ.

Создайте довольно примитивный expression:

Пока этот expression абсолютно бесполезен, ибо просто копирует текущее положение конуса в дополнительные атрибуты в каждом кадре. Однако если мы допишем некоторые формулы

629

перед этими строками, то сможем использовать «старую» позицию конуса перед тем, как она обновится.

Создайте локатор.

Допишите в expression еще три строчки:

Как следует из этих незамысловатых формул, локатор будет всегда отставать от конуса ровно на один кадр.

«Подергайте» за конус, чтобы в этом убедиться.

Поставьте несколько ключей на перемещение конуса, задав «быстрые» и «медленные» участки. Теперь можно воспользоваться тем фактом, что направление скорости - это вектор идущий от локатора в центр конуса.

Таким образом, если мы заставим конус «смотреть» на локатор, он будет всегда ориентирован «по скорости», то есть поворачиваться по направлению движения. Проще всего это сделать с помощью Aim Constraint.

Выберите локатор, затем конус и выполните Constrain=>Aim Constraint с параметрами по умолчанию. Чтобы конус повернулся «макушкой» от локатора, задайте в Channel Box для объекта pCone1_aimConstraint1 значение offsetZ=90. Опять «подергайте» за конус и убедитесь, что он теперь поворачивается макушкой по ходу движения.

Задача решена. Осталось, как обычно, навести блеск.

Теперь вы можете как угодно ставить ключи на перемещения конуса - вращения при этом будут получаться автоматически, и вам не нужно будет дополнительно разворачивать объект и ставить ключи на атрибуты rotate.

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

Добавьте к конусу еще четыре атрибута: vx, vy, vz и velocity. Допишите в expression еще несколько строк:

630

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]