Академический Документы
Профессиональный Документы
Культура Документы
В двух книгах
Книга вторая
Цыпцын Сергей.
П 75 Понимая MAYA
ISBN 978-5-902976-03-5
Эта книга не о том, "как" сделать красиво и не от том, как освоить программу за 21
день. Эта книга о понимании принципов, по которым работает MAYA.
Автор, выпускник мехмата МГУ, соединил академический научный подход и легкий
стиль изложения. Среди прикладной литературы, посвященной компьютерным
программам, эта книга является совершенно уникальной, так как призывает читателя
вникнуть в саму суть построения программы и понять логику использования ее
инструментов.
Автор является официальным российским "проповедником" MAYA, а также
единственным в России сертифицированным инструктором компании Autodesk по
этому пакету.
Материал построен на основе семилетнего цикла лекций, прочитанных автором,
и является предельно субъективным и неформальным. В подготовке книги автору
помогали лучшие специалисты отечественной индустрии компьютерной графики.
ISBN 978-5-902976-03-5
© Цыпцын Сергей, 2007
® 0 0 0 "Арт Хаус медиа", 2007
Содержание
Книга 2
Глава 7 Персонажная анимация .718
Настройка персонажей 719
Использование готовых решений 720
«Мануальная терапия». Кости и суставы. Построение скелета 721
Вправление суставов.
Кошмары с локальными осями.
Автоматическая и ручная настройка ориентации 724
Степени свободы и неволи 726
Издевательство над костями. Удобные локаторы 728
Кинематика - инверсная и прямая 729
Свойства IK-манипуляторов 731
Алгоритмы вычисления инверсной кинематики.
Типы IK-манипуляторов. IK Solvers 732
Алгоритм Rotation Plane Solver 732
Алгоритм Single Chain Solver 735
Алгоритм Two Bone Solver 735
Алгоритм Multi Chain Solver 735
Анимация длинных цепочек 738
Атрибуты суставов, корректирующие поведение инверсной кинематики ... ....739
Joint Rotation Limit Damping - мягкое торможениие 741
Прямая и инверсная кинематика. Дело вкуса. Свобода воли 741
Смешивание прямой и инверсной кинематики. История вопроса 742
Смешивание прямой и инверсной кинематики - современный подход 743
Операция Set IK/FKKey. Анимация переключения кинематик 743
Переключение и смешивание FK и IK 744
Операция Connect IK/FK 745
IK Spline Solver - анимация хвостов, усов и щупалец 746
Борьба с перекручиваниями - IK Spline Handle 748
Практический пример настройки персонажа: сетап крыла 750
Настройка модели крыла 751
Строение крыла 755
Кожа да кости 756
Перья 756
Построение крыла 757
Построение «шаблона» будущего скелета 758
Построение скелета 760
76
Оперение крыла 763
Управление крылом 764
Управление задней кромкой 766
Перенос анимации. Навешивание ярлыков.
Animation Retargeting. Joint Labelling 777
Полнотельная кинематика: Full Body IK 786
Подготовка скелета к использованию Full Body IK 787
Создание системы управления Full Body IK 789
Пиннинг, или прикалывание 791
Анимация с помощью эффекторов.
Внутреннее устройство Full Body IK 792
Проблемы синхронизации. Немного о грустном 799
Двойной пивот. Secondary Controller 800
Жесткий контакт с землей 801
Некоторые комментарии к системе Full Body IK 803
Нелинейна анимация Non-linear Animation 805
Обобщенный «Персонаж». Character Set 806
Подперсонажи - SubCharacters 808
Позы и клипы 809
Работа с Trax Editor 810
Создание и редактирование клипов 811
Изнанка клипов 812
Абсолютные и относительные клипы и каналы 815
Склеивание и смешивание клипов 818
Немного тонкостей, или еще раз об абсолютных клипах 820
Редактирование анимационных кривых для клипа 823
Временная активизация ключей 825
Корректирующая анимация. Ключи поверх клипов 826
Монтаж анимации 827
Слияние и запекание клипов 828
Деформация времени. Retiming 828
Вес клипов 829
Некоторые комментарии на нелинейную тему 830
Практические замечания относительно нелинейной анимации 831
Клипы 832
Absolute и Relative 832
Blend 833
Motion Wrap 834
Time Warp 834
Нестандартное использование клипов.
Движение по пути, или Macro Driven Key 835
Некоренные переходы между клипами 836
«Шкурный вопрос»: скининг персонажей 837
Создание скининга 838
Методы мягкого и жесткого скининга 839
Нормализация весов 842
Нода skinCluster и tweak 843
Поза привязки: Bind Pose 843
Редактирование скининга. Paint Skin Weights Tool 844
Объекты влияния: Influences 847
Назначение и использование объектов влияния.
Некоторые анатомические и философские аспекты
мышечных деформаций 851
Копирование весов 852
Сохранив и восстановление весов 852
Изучение чужих персонажей 853
Практические замечания по скинингу персонажей 855
Дополнительные кости и раскладывание вращения на сгиб
и скручивание для корректного скининга 858
Глава 8 M E L , и л и MAYA E m b e d d e d Language 864
Про что эта глава 865
Что такое MEL? 865
Есть скрипт! 867
MEL-ресурсы 867
Освоение MEL. Как все начинается 868
MAYA API 868
Не для программистов. Как примерно все происходит 870
Немного MEL-команд. Работа с документацией 871
Структура MEL-команд 871
Особенности работы в Script Editor 872
Применение MEL для работы со списком выделенных объектов 873
Переменные и типы данных 875
Массивы 877
Полный путь к объекту или атрибуту 878
Работа с циклом. Перебор объектов в списке 879
Скобки и кавычки 881
Комментарии 882
Добавление вращения 882
Создание Noise Deformer 884
Граница применимости MEL 887
Процедурное моделирование 887
Важное замечание про округления и забытые точки 890
Проверка существования объекта. Условные переходы 891
Использование различных функций 892
Invalid redeclaration и область видимости переменных 897
Скрипты и expressions. Различия и сходства 898
Нетрадиционные выражения.
Выращивание объектов в анимации 899
Интерактивность построения кривых 902
Построение траекторий и хвостов 903
Поджигание хвоста 905
Пример использования MEL для решения проблем.
Интерактивный рендеринг нужного количества кадров 906
Программирование интерфейсов пользователя на MEL 908
Работа с кнопками 915
Объявление и вызов процедур 918
Разница между объявлением и выполнением 919
Работа с файлами. Чтение и запись 919
Спецсимволы. Косые и обратные черты. Кавычки в кавычках 922
Чтение данных из файла 924
Оформление скрипта в виде процедуры. Вызов его с диска 925
Порядок вызова и расположение пользовательских
и стандартных скриптов. Что происходит при вызове MEL-команды 928
Как запускать скрипты, скачанные из Интернета 929
Что такое Source Script 929
Script Node, или expression по вызову 930
Интерфейс для рисования процедурных кривых 934
Режимы команд построения элементов интерфейса 936
Имена элементов интерфейса 937
Работа с меню. Минимизация всех открытых окон 940
Как заставить MAYA выполнять команды при загрузке 943
Немногое хакерстве, или моя MAYA 944
О глобальных переменных 945
Создание интерфейса с помощью веб-браузера.
Радикально альтернативный подход 946
Все, что вы хотели узнать про MEL 947
Некоторые практические советы 947
История. Я опять не хочу в Париж 949
Глава 9 Paint Effects .954
Рисовальные эффекты 955
Рекомендации по освоению Paint Effects 955
Классовая принадлежность Paint Effects 956
Применения Paint Effects 956
Природа Paint Effects. Штрихи 958
Природа Paint Effects. Кисти 959
Смешивание кистей 961
Последняя кисть. Template Brush 962
Атрибуты кисти 962
Два ключевых типа кистей. Tubes 963
Размер кисти 964
Природа кистей. Спрайты. Визуализация штрихов 964
Природа кистей. Рендеринг. Композитинг. Постэффекты 965
Работа с обычными штрихами. Рендеринг кривых 965
Сохранение собственных кистей 970
Работа с кистями растительного и животного происхождения 971
Рисование по поверхности 971
Редактирование атрибутов кисти 972
Конвертация Paint Effects в полигоны 972
Настройка ширины 974
Выращивание конечностей. Работа с атрибутами кисти 976
Направление роста и ориентация по пути 976
Анимация листьев-конечностей 978
Визуализация и текстурирование 979
Методы рендеринга Paint Effects 980
Тектстурирование листьев-конечностей 981
Шипы и мохнатые лапы 982
Усы, цветы и прочие отростки 982
Размножение муравьев 983
Улучшение анимации 985
Изменение индивидуальных атрибутов вдоль пути 986
Тени 987
Природа кистей. Тени 988
Анимация кистей и штрихов 988
Ручная деформация штрихов Paint Effects 989
Встроенные пружины 992
Ручная анимация. Модификаторы 995
Анимация роста и старения 996
Искусственное размножение 998
Авторисование 999
Некоторые замечания по поводу рендеринга 999
Туман, глубина и прозрачные объекты 1000
Оптимизация просчета и интерактивной работы 1001
История 1002
Глава 10 Динамическая симуляция 1004
Динамика твердых тел 1007
Колбасинг 1007
Законы динамики 1009
Закон динамики 1 1010
Закон динамики 2 1011
Закон динамики 3 1011
Закон динамики 4 1012
Закон динамики 5 1012
Концепция твердости тел 1013
Свойства твердых тел 1015
Анимация активности твердых тел 1016
Закон динамики 6 1016
Катание шаров 1017
Избавление от динамики. Выпекание ключей 1023
Свойства полей 1025
Игра «Место под солнцем» 1025
Конструктивные констрейны для твердых тел 1028
Подвесной таран 1028
Твердые сабдивы 1031
Просчет ненужных столкновений 1033
Искусство бить посуду 1033
Секретные атрибуты и слежение за ударами 1036
Уловки и трюки при работе с динамикой 1040
Поведение, а не траектория 1040
Твердые тела всегда остаются твердыми 1041
Соблюдайте скоростной режим 1041
Используйте альтернативную динамику 1041
Почаще испекайтесь 1041
Глава 11 Динамика частиц 1044
Применения систем частиц 1045
Особенности работы с частицами 1045
Природа частиц 1046
Столкновения с препятствиями 1051
Испускание частиц с поверхностей и кривых 1052
Свойства и атрибуты частиц 1053
Продолжительность жизни и курение сигарет 1059
Время жизни и возраст частиц 1067
Массивные атрибуты (Per Particle Array Attributes) 1067
Индивидуальные динамические атрибуты 1068
Вопрос приоритетов 1070
Работа с индивидуальными атрибутами 1070
Component Editor 1070
Как обсыпать объект частицами? 1071
Обнуление скоростей. Начальное состояние 1072
Использование текстуры Ramp для управления частицами 1074
Particle Expressions - от порядка к хаосу и обратно 1078
Создание, выполнение и виды Particle Expressions 1081
Ода функции rand 1085
До и после динамики 1086
Работа со скоростью и ускорением 1087
Goal, или воля к победе 1090
Интерактивное взаимодействие с динамикой:
Interactive Playback 1093
Многоцелевые частицы 1094
goalU и goalV, или как уложить частицы точно на поверхность 1095
Концепция мягких тел 1098
Фальшивый занавес 1102
Как надуть модель? 1108
Инстансирование. Подстановка объектов в частицы 1112
Множественная подстановка 1120
Сжатие и растяжение динамики 1125
Ускорение/торможение падения твердых тел 1125
Замораживание частиц - остановка динамического времени 1128
Кэширование частиц 1141
Визуализация частиц 1143
Аппаратный дымок 1144
Аппаратный дымок нового типа 1147
Софтверный дым 1148
ParticleSamplerlnfo - переносчик информации 1150
Железный рендер 1152
Практические советы и ухищрения 1153
Прежде всего, некоторые советы: что и чем делать 1153
Работа со спрайтами 1153
Работа с мультистриками 1154
Особенности работы с motion blur 1154
Длинная история 1155
Глава 12 MAYA Fluids 1160
Область применения MAYA Fluids 1161
Типы флюидов 1162
Контейнеры и внутреннее устройство флюидов 1162
Размер и разрешение контейнера 1164
Содержимое и начинка контейнера 1165
Типы контейнеров и распределение свойств внутри них 1166
Заполнение контейнера 1167
Начальное состояние 1169
Примеры для изучения 1169
Заполнение контейнера раскрашиванием 1171
Как опустошить контейнер 1173
Динамическая анимация флюидов 1174
Так почему же все плывет вверх? 1175
Взаимодействие флюидов с «нормальной» динамикой 1177
Кэширование флюидов 1179
Визуализация флюидов. Поверхности 1181
Пресеты. Контейнер сыра 1189
Конвертирование в полигоны 1189
Визуализация объемных флюидов 1189
Практические советы по работе с контейнерами 1195
Оптимизация визуализации 1196
Флюиды как текстуры 1197
Акватория MAYA 1199
Визуальные свойства поверхности воды 1201
Рыбалка на озере 1202
Буйки и поплавки 1204
Внутреннее устройство океана 1205
Интерактивная визуализация морской поверхности 1206
Динамическая анимация морской поверхности 1208
Визуализация акватории 1209
Основной прием при работе с морской поверхностью 1210
История насыщенного контейнера 1210
Глава 13 Меховая глава 1214
Меховые применения MAYA Fur и отличия от MAYA Hair 1215
Устройство MAYA Fur 1216
Меховой вывод: мех - это большая процедурная текстура 1216
Подготовка модели к покрытию мехом 1217
Причесывание и редактирование меховых свойств 1219
Настройка формы и внешнего вида меха 1226
Главный метод изучения свойств меха 1228
Причесывание кистями несуществующего атрибута Direction 1228
Освещение меха 1232
Еще немного про визуализацию или взрослый мех 1236
Меховые проблемы 1238
Практические рекомендации по оптимизации просчета меха 1239
Использование Mental Ray для просчета меха 1240
Немного про Renderman 1241
Анимациямеха 1242
Глава 14 Волосатый симулятор 1254
Применения MAYA Hair 1255
Рекомендации по освоению MAYA Hair 1256
Закон динамики 1 1257
Закон динамики 2 1257
Закон динамики 3 1257
Закон динамики 4 1257
Закон динамики 5 1257
Неформальный закон динамики 1257
Архитектура и устройство MAYA Hair 1257
Создание системы волос 1258
Типы визуализации волос 1258
Требования к поверхности для создания волос 1259
Система волос и ее свойства 1263
Взаимодействиесостандартными полями 1265
Редактирование длины волос 1266
Сохранение начального положения 1267
Долгий разговор о коллизиях и взаимодействии с поверхностям 1268
Индивидуальные свойства волос 1273
Творческий выбор 1274
Изменение индивидуальной гибкости кривых 1275
Стартовые кривые: Start Curves 1276
Отображение стартовых кривых 1276
Редактирование начальной формы 1277
Три типа кривых при работе с системой волос 1282
Система констрейнов для динамических кривых 1282
Атрибуты констрейнов 1289
Симуляция столкновений с помощью констрейнов 1288
Выбор поверхностей и оптимизация столкновений 1289
Визуализация системы волос 1290
Различные способы визуализации системы волос 1290
Непосредственный рендерингкривых 1291
Стандартная визуализация с помощью Paint Effects 1292
Форма системы волос. Химзавивка 1294
Цвет волос. Мелирование и прочие глупости 1296
Волосы и текстуры цвета 1297
Визуализация волос с помощью кистей Paint Effects 1298
Традиционное применение MAYA Hair 1302
Создание волос 1302
Практическое создание прически 1303
Стрижка, укладывание и прическа 1306
Пассивные кривые. Увеличение густоты прически 1311
Визуализация. Настройка формы волос 1312
Визуализация. Настройка освещения 1314
Глобальное удлинение 1316
Практические методы увеличения визуальной густоты волос
и экономии вычислительного времени 1318
Заплетание косичек 1319
Рендеринг волос с помощью mental ray 1321
Работа с кэшированием 1322
Динамические кривые как самостоятельные объекты 1322
Разрезание веревки 1323
Наследование цвета волос с текстуры 1326
Универсальный совет для работы с волосами 1330
Аэродинамическая история 1330
Глава 15 Рендеринг 1333
Renderman 1338
Сношения с внешними рендерерами или присовокупление к Renderman'y 1339
Зачем? 1339
MAYA + внешние рендереры = ? 1342
MAYA + Renderman = хорошо 1344
Ужасная история в поезде 1351
RAT, или Рендерим Визуально 1352
MTOR 1352
Alfred 1354
Alfserver 1355
It 1355
SLIM 1357
Irma 1360
prman, или Закапываемся 1360
prman.exe 1361
Другие RIB'ы 1365
shader.exe 1365
txmake.exe 1369
Надпись 1370
Могучая кучка 1372
Альтернативы? 1375
Какие рендереры? 1376
Gelato 1377
Jot 1383
GRUNT 1387
Spore 1388
Renderman - альтернативы RAT 1389
Альтернативные интерфейсы для MTOR 1390
Альтернативные Renderman-совместимые рендереры 1391
Экспорт из MAYA в RIB-MEL 1391
Экспорт из MAYA в RIB-не MEL 1391
MayaMan 1391
Liquid 1395
ShaderMan 1396
ShadingRate 1404
PixelSamples 1407
LOD 1409
Архивы и Замороженные Архивы 1410
Разговаривающие и адаптивные шейдеры 1411
Только то, что видно (или «Стыдно - когда видно») 1411
По слоям 1412
Мантра про raytracing 1417
Собственное все 1418
Для любознательных - пример из жизни 1419
Думайте о неожиданном 1420
И под конец нашего списка 1422
К вопросу о благодарностях 1426
Персонажная анимация
Настройка персонажей
Вначале я по инерции хотел назвать главу «Персонажная анимация», но потом понял, что
про анимацию в этой главе не будет ни слова. Ну, если только чуть-чуть и то чисто теоретически.
Как правило, когда речь идет о технических аспектах персонажной анимации или о возможностях
MAYA в этой области, имеется в виду создание, настройка и подготовка объекта к анимации. Это
чисто техническая работа и к анимации (в классическом понимании этого слова) она не имеет
никакого отношения. Такой работе и посвящен целиком материал этой главы. Поэтому все
процессы связанные с созданием, тестированием и подготовкой персонажа я буду обобщенно
называть настройкой персонажа.
Тут самое время уточнить, что такое персонаж. Как я уже упоминал, персонажем может
быть абсолютно любая группа объектов, не обязательно представляющая живой или еле живой
объект. Это может быть паровоз, дерево, телефон или фонарь. Однако в этой главе речь пойдет
об тех персонажах, для анимации которых используется скелет. Коль скоро задача анимации
живых существ выделилась в отдельный класс спецэффектов, для нее сформировался целый ряд
технологических решений, которые и будут описаны в этой главе.
Передохнув после выламывания рук персонажу в процессе настройки весов, вам захочется
обеспечить модель дополнительными деформациями, основным примером которых служат
сокращения мышц в различных местах поверхности. Мышечные деформации должны работать
автоматически, например, при сгибе локтя или колена, поэтому на помощь к вам придут сонмы
деформеров и, конечно, операция Set Driven Key, обеспечивающая плавное включение деформаций
в зависимости от поворота костей или других атрибутов. Set Driven Key позволит вам реализовать
всевозможные автоматизации и зависимости поведения одних частей модели от других. Здесь же
на помощь придут интеллектуальные expressions и бесхитростные констрейны.
После этого вам следует подвергнут персонажа пыткам, выворачивая ему конечности
и задавая всевозможные допустимые значения управляющих атрибутов, чтобы убедиться, что
персонаж к бою, то есть к анимации, готов.
Первый состоит в том, чтобы найти знакомого сетапщика и уговорить его вам помочь.
Поверьте, это будет быстрее всего, при условии, что сетапщик хорош и нежаден.
Примечание. Пока я писал, что компания Alias успела приобрести компанию Kay¬
dara, компания Autodesk успела приобрести компанию Alias. He думаю, что к
моменту выхода книги появится что-то типа Character Studio for MAYA (китайские
наработки не в счет), однако дело, похоже, все-таки реально идет к этому.
В состав Bonus Pack for MAYA входит также довольно древний, но полезный (для изучения)
скрипт Skeleton Works, позволяющий строить скелеты не только человекообразных обезьян, но и
разных животных, а также некоторых типов насекомых.
В принципе, это очень неплохая идея - использовать уже однажды кем-то созданного
и настроенного скелета (может быть, даже вами самими). Оставляя за бортом коммерческие
аспекты и борьбу с непомерными амбициями, могу сказать: это - очень продуктивный путь.
Как правило, в профессиональных студиях используется скелет, уже однажды созданный и
настроенный гениальным техническим директором. Хочу заострить ваше внимание лишь на одной
проблеме. Готовый скелет придется «втискивать» во все ваши настоящие и будущие модели, так
как не модель подгоняется под скелет, а наоборот. Не все готовые решения позволяют делать это
безболезненно, а кости как объекты, ох, как не любят операцию масштабирования. Поэтому одним
из критериев отбора того или иного готового скелета должна быть его «втискиваемость» в любую
модель без болезненных последствий.
Но для всех тех, чья гордость или любознательность не позволяют использовать чужие
скелеты в процессе настройки персонажа, предназначен дальнейший материал этой главы.
Коль скоро это наверняка будут очень сильно мотивированные или невероятно технически
подготовленные читатели, я позволю себе изложение в лаконичной и стремительной манере.
Опять же повторю: про собственно анимацию дальше не будет ни слова. Кроме того, настройка
персонажей - это огромная, довольно занудная и крайне рыхлая тема, заслуживающая, без всякого
сомнения, отдельной книги. В соответствии с названием этого издания, я сосредоточусь на
понимании принципов работы инструментов для работы с персонажами, для того, чтобы вы могли
их адекватно использовать и комбинировать. Вы не найдете здесь большого количества готовых
примеров на все случаи жизни или инструкций по настройке персонажа «от и до». Персонажи
бывают, мягко говоря, разные и перечислять все возможные случаи - задача неблагодарная.
Совет. Чтобы развернуть и увидеть всю цепочку костей в Outliner, следует нажать
на микроплюс, удерживая клавишу Shift.
Вы можете выбрать любой сустав (так и тянет писать «любую кость») и с помощью операции
Skeleton=>Reroot Skeleton превратить его в «корневой сустав», то есть в Root Joint. Вся структура
иерархии скелетона, естественно, изменится.
Коль скоро скелет - это обычная иерархия из объектов, то вы можете объединять два скелета
или, наоборот, разрывать скелет на части с помощью операций Edit=>Parent и Edit=>Unparent.
Поэкспериментируйте самостоятельно и обратите внимание, как появляются и исчезают
соединительные кости между суставами. Существуют также две альтернативные операции - Con¬
nect Joint и Disconnect Joint, позволяющие добавлять дополнительные соединительные кости или
удалять их.
Как видите, в построении скелетов нет ничего сложного, однако веселая жизнь начинается
сразу после того, как скелет построен. Выясняется, чтоу каждой кости (то есть сустава) чрезвычайно
богатый внутренний мир, то есть масса собственных атрибутов.
Так как в обоих случая повороты суставов равны нулю (в чем нетрудно убедиться, взглянув
на Channel Box или Attribute Editor), ориентация суставов определяется локальными вращательными
осями (Local Rotation Axes). Чтобы увидеть локальные оси для всех суставов скелета, следует
выполнить следующие действия.
Напуганные малодушные пользователи могут робко спросить, а для чего вся эта возня
с локальными осями, если мы все равно навесим инверсную кинематику, которая и будет
дергать персонажа за руки-ноги, получая вращения автоматически. В принципе, до тех пор,
пока вы используете такую кинематику, вам может быть совершенно все равно, каким образом
ориентированы оси. Однако весьма трудно обойтись одной инверсной кинематикой для анимации
всего персонажа, и ко многим частям персонажа придется применять прямую кинематику, то
есть вращать суставы вручную. Вот тут-то вы и запляшете, когда кости начнут вращаться вокруг
странных осей...
Общий принцип ориентации осей таков: сделайте так, чтобы суставы было удобно
анимировать напрямую или чтобы ими было удобно управлять с помощью других объектов
(Set Driven Key и пр.). Если оси развернуты произвольно, покрутить их и добиться корректного
результата трудно, а порой невозможно. При этом совершенно не важно, какая ось «первая», а
какая «вторая» - важна ориентация этих осей относительно сустава.
Атрибут Radius используется только для изменения визуального размера сустава на экране.
Кстати, в Option Box инструмента Joint Tool вы можете задать зависимость радиуса от длины кости.
Это сравнительно свежее нововведение, а раньше все персонажи в MAYA имели огромные лапы-
руки, так как абсолютный размер суставов для пальцев и колен был одинаков.
Эта команда создаст еще одну копию (Instance) полигонального «шейпа» и «припарентит»
его к кости.
Теперь кость приняла нужный вид. Осталось только сдвинуть вершины полигона в нужное место.
Теперь нужно не запутаться, что есть что. Главное - это запомнить, что многие ноды в MAYA
происходят от ноды transform, а разобраться в этом поможет документация. В начале описания
каждой ноды всегда имеется ссылка на «родителькую» ноду (не путать с «родительским» объектом
в сцене). А у каждой ноды происходящей от transform ноды, наследуется возможность иметь
«шейпы».
Для тех, кому по душе подобные локаторы, Мишей Бажуткиным был написан скрип multi-
Curve. mel, позволяющий создавать такие локаторы автоматически из нескольких кривых. Создайте
несколько кривых, и сделайте им Freeze Transformation, если у них «ненулевой транформ».
Выделите их и выполните команду multiCurve, которая создаст из них один объект.
Специально для таких случаев, когда конечности персонажа должны что-то брать или на
что-то опираться (например, ногами о землю), был придуман алгоритм инверсной кинематики.
В окне front нарисуйте цепочку из трех костей (четырех суставов) с помощью Joint Tool.
Затем возьмите в руки инструмент 5keleton=>IK Handle Tool и, читая Help Line, щелкните в
первый сустав, а затем в третий.
Enter нажимать не надо, MAYA сама разберется с тем, когда выйти из контекста.
В нашем случает интерес представляют два раздела. Первый из них, IK Handle Attributes,
задает поведение и внешний вид объекта IK Handle. По умолчанию IK-манипулятор как бы привязан
резинкой к концевому суставу, и когда вы оттягиваете его слишком далеко, а затем отпускаете,
он мгновенно возвращается к своему суставу. Это поведение можно отменить, выключив атрибут
Snap Enable.
Чтобы не выбирать каждый раз IK Handle и не переключаться в Show Manipulator Tool, было
бы разумно закрепить конец этого вектора на каком-нибудь объекте, например локаторе. Именно
для этих целей и существует Pole Vector Constraint.
Однако вас может поджидать еще одна проблема. Это flipping, или внезапный разворот
суставов внутри кинематической цепочки. Если IK Handle, локатор и верхний сустав находятся в
одной вертикальной плоскости и вы будете перемещать IK Handle наверх, рано или поздно согнутая
конечность перевернется.
Чтобы лучше понять принцип его действия, давайте абстрагируемся от самой MAYA и
представим себе структуру костей в виде дерева, с гибким стволом и ветвями. A IK Handles этого
солвера, в виде резинок, которые с привязаны к разным ветвям и одновременно тянут ветви в
разные стороны. Причем у каждой из них может быть своя упругость. Поэтому форма, в которую
согнут это деревце наши резинки, зависит от совокупности действия разных сил. Вот примерно так
же работает и ikMCsolver.
Только в отличие от дерева, конечно же, кости не гнутся, а вращаются у своего основания.
А сила натяжения каждого IK Handle задается атрибутом weight.
Очень важно помнить, что солвер во время своих расчетов учитывает все IK Handles с
одним номером приоритета (атрибут priority).
Создайте цепочку из двух костей (трех joints) и создайте два IK Handles, от первого сустава
до второго и от первого до третьего.
Так как Multi Chain Solver солвер не создается автоматически при создании костей, нужно
выполнить команду: createNode ikMCsolver.
Затем с помощью Attribute Editor у обоих IK Handles нужно выбрать тип солвера "ikMC-
solverl" в закладке IK Solver.
Такая система может напоминать работу ikRPsolver с одним IK Handle и Pole Vector, но все
же есть два отличия.
Первое, что бросается сразу в глаза - позиция последнего сустава зависит от удаленности
первого IK Handle со слабым весом. Чем дальше он удаляется от костей, особенно в противоположную
сторону от другого IK Handle, тем больше удаляется последний сустав от своей конечной цели, а
именно позиции второго IK Handle.
А второе отличие состоит в том, что солвер, перед тем как сделать новый расчет углов,
не возвращает кости в Preferred Angle (углы предпочтения). Другими словами, он делает расчет,
исходя из текущих на данный момент углов. Это означает, что даже вернув все IК Handle в исходную
позицию, мы не получим исходные углы костей. Чем больше мы дергаем наши IK Handles, тем
больше «накручиваем» углы на костях. Очень забавно, но совсем не практично.
Из этого можно сделать вывод, что использовать ikMCsolver желательно только как
вспомогательную систему. Например, с его помощью мы можем вычислить позиции суставов, к
которым с помощью Point Constraint можно прикрепить IK Handles других солверов.
От слов к делу! Рассмотрим пример применения ikMCsolver для сетапа из трех костей.
Многие сталкивались на практике с тем, что самая предсказуемая и легко управляемая система
состоит только из двух костей. Недаром в 7-ой версии MAYA разработчики добавили ikSpringSolver,
который облегчает работу с тремя и более длинными цепочками костей. Но в нашем примере нам
поможет только ikMCsolver.
Задача у нас следующая: требуется рассчитать позицию трех костей - двух коленей и таза
персонажа, который стоит на коленях. При этом, чтобы имелась возможность управлять наклоном
таза из стороны в сторону и вверх-вниз, а также поворотами влево-вправо. Колени же при этом
должны оставаться в тех местах, где находятся соответствующие локаторы.
С нем содержится пример с тремя костями. Здесь вы не увидите никаких коленей и тем
более таза. Проявите свое воображение и представьте себе, что два локатора (синий и красный)
на плоскости задают позицию коленей, а зеленый, соответственно, таза.
Все IK handles в сцене скрыты, и для того чтобы увидеть их, вам придется открыть Outliner
и установить их атрибуты visibility в значение 1.
Первые два IK Handle прикреплены к зеленому верхнему локатору таза обычной операцией
parent (можно использовать и Parent Constraint). Они имеют единичный вес (weight = 1), и
расстояние между ними соответствует длине второй кости.
Третий IK Handle прикреплен с помощью Point Constraint к синему локатору левого колена
и имеет большой вес (weight = 1000).
Как вы уже, видимо, догадались, третий IK Handle самый главный в этой цепочке. Он
обеспечивает достижение последним суставом позиции синего локатора.
Первые два IK Handles задают позу цепочки. В какую сторону смещается локатор таза,
туда и стремятся согнуться кости, насколько это возможно. При этом поведение и поза костей
полностью под контролем аниматора.
Конечно же, этот солвер не безгрешен. Точнее, не абсолютно точен в своих вычислениях.
Чтобы свести к минимуму его промахи, приходиться устанавливать его атрибут tolerance на очень
малое значение, например = 0,0000001. В противном случае возможно мелкое дрожание костей при
воспроизведении анимации. К сожалению, повышение точности солвера может снизить скорость
воспроизведении анимации.
Ну, и напоследок - еще об одной особенности этого солвера. Если значение атрибута веса
главного IK Handle примерно в десять раз больше вспомогательных, то распрямление цепочки
костей будет происходить не резко, как у остальных солверов, а мягко. Конечно, при этом
последний сустав не будет полностью достигать IK-цели. Это замечательное свойство может быть
с успехом использовано для реалистичного сетапа человека и животных, особенно четвероногих,
где так важна пластичность в движениях.
Однако если вам совсем приспичило создать прямую цепочку, а затем согнуть ее, вы
можете подсказать кинематике, в какую сторону должны сгибаться кости при перемещении IK
Handle. Для этой подсказки используется атрибут Preferred Angle.
Удалите IK Handle, выберите второй сустав, откройте Attribute Editor и введите значение
Preferred Angle Y=10.
Это означает, что предпочтительный угол для сгибания сустава определяет положительное
вращение вокруг оси Y (в данном случае абсолютная величина угла значения не имеет).
Снова навесьте IK Handle и подергайте его. Теперь кости будут сгибаться в нужном направлении.
Заметьте, что даже если кости немного согнуты перед навеской кинематики, с
помощью Preferred Angle вы может указать предпочтительное направление сгибания костей при
перемещении IK Handle.
Тем не менее, два этих вида кинематики делят между собой возможные способы анимации
скелетов. Казалось бы, области применения каждой из них довольно четко очерчены, однако
существуют некоторые нюансы. Прямая кинематика отлично подходит для анимации свободных
движений конечностей и других частей скелета (рук, шеи, челюстей). Если же конечности
ограничены какой-либо связью (ноги упираются в землю, руки на стол, лицо в тарелку), то
очевидны плюсы использования инверсной кинематики.
Теперь вы можете по очереди выбирать в Outliner два Orient Constrain, и меняя атрибуты,
отвечающие за веса первой и третьей руки, делать так, что вторая рука будет прилипать то к
первой, то к третьей конечности.
Теперь создайте один сустав, чуть повыше плеча.
Выберите первую, затем третью руку, а потом новый сустав.
Выполните Edit=>Parent.
Выберите самый верхний сустав и добавьте к нему новый атрибут (name=fkik, min/max=0/1,
default=0.5).
Теперь откройте окно Set Driven Key.
Загрузите наверх верхний сустав, а вниз оба констрейна типа Orient.
Теперь вам осталось навесить IK Handle на одну из управляющих рук, например, на третью.
Затем вы можете шевелить, то бишь, анимировать то первую руку (прямой кинематикой), то третью
руку (инверсной кинематикой) и переключать среднюю руку между ними, анимируя в нужный
момент атрибут fkik. Очевидно, что поверхность модели должна быть привязана к средней руке.
Это, конечно, очень примитивный пример, однако он демонстрирует основной принцип
переключения от одного типа движения к другому с помощью старых добрых констрейнов и
вездесущей технологии Set Driven Key. Несмотря на некоторую громоздкость, этот подход дает
абсолютно предсказуемый результат и отлично проверен временем.
Однако для пользователей, измученных сражениями с окном Set Driven Key и поиском
потерянных ключей, не так давно появилась возможность плавно переключаться от прямой к
инверсной кинематике, не создавая шестируких самураев.
Таким образом, имеется один атрибут, переключающий управление над всеми костями
цепочки с инверсной кинематики на прямую и обратно.
В принципе этого достаточно для педантичных пользователей, так как остается только
аккуратно расставить ключи на нужные атрибуты (это, прежде всего, translate для IK Handle и
rotate для всех суставов плюс ключи для ikBlend). Но где вы видели таких пользователей среди
трехмерщиков? Поэтому, чтобы не ввергать этих детей анархии в полный хаос, был сделан
специальный пункт меню: Animate=>IK/FK Keys=>Set IK/FK Key.
Перейдите в следующий кадр. Так как с этого момента должна начинаться территория
прямой кинематики, инверсную следует сразу выключить: установите ikBlend=0 и тут же поставьте
на него (и только на него!) ключ. (В этот момент документация советует выполнить Set IK/FK Key,
однако это поставит дополнительные ключи на вращения суставов, и вы получите ключевой кадр
идентичный предыдущему, то есть «замирание».)
В последнем кадре, где используется прямая кинематика, выберите IK Handle (он должен
«приехать» на место вместе с вращением костей), убедитесь, что атрибут ikBlend равен нулю и
выполните операцию Set IK/FK Key. Затем перейдите в следующий кадр, задайте ikBlend=0 и тут же
поставьте на него (опять, только на него) ключ, переключившись, таким образом, на инверсную
кинематику.
Вроде все выглядит просто, однако есть ряд не очень положительных моментов.
Вы можете заметить, что операция Set IK/FK Key ставит ключи на все анимируемые атрибуты
IK Handle. Ключи, таким образом, плодятся в большом количестве. Однако вам нужно лишь
переключить значение атрибута ikBlend в соседних кадрах и не забыть зафиксировать положение
скелета в момент этого переключения. Поэтому вы можете вовсе не использовать операцию Set
IK/FK Key, а ставить все ключи вручную на перемещения IK Handle, вращения суставов и, конечно,
на атрибут ikBlend.
Если вы хотите «врезаться» в уже существующую инверсную кинематику с «куском»
прямой кинематики, сначала поставьте ключи на атрибуты IK Handle и ikBlend на границах этого
диапазона. Внутри этого диапазона выключите инверсную кинематику (ikBlend=0), не забудьте
поставить ключ на ikBlend и анимируйте на здоровье суставы вручную.
Переключение и смешивание FK и IK
Вы могли также заметить, что до сих пор речь шла только о переключении видов кинематики,
то есть о мгновенном переходе в соседних кадрах от одного типа управления к другому. В этом
случае все работает достаточно предсказуемо.
Несложно проверить, что если значение атрибута ikBlend будет равно, например, 0.5, на
кинематическую цепочку будут усредненно влиять и перемещения IK Handle и вращения суставов.
Поэтому если ключевые кадры, в которых атрибут ikBlend принимает значения 0 и 1, не будут
Однако скелет движется совсем не так, как можно предсказать. И заставить его
переходить от инверсной кинематики к прямой адекватными методами невозможно. Поэтому
все, что я могу посоветовать - это использовать смешивание разных типов кинематики с большой
осторожностью.
Что касается данной сцены, остается применить только «метод тыка». Так как анимационной
кривой для вращения главного сустава не существует, применить эйлеровскую фильтрацию или
сменить тип интерполяции не представляется возможным. Остается лишь безнадежно обратиться
к порядку вращений. Выберите основной сустав и в Attribute Editor установите для него Rotate
Order=xzy. Убедитесь, что остальные варианты тоже существенно улучшают ситуацию. Попробуйте
объяснить происходящее.
Коль скоро хвост или щупальце или даже позвоночник напоминают собой кривую, то и
управлять такой многосуставной цепочкой было бы удобно с помощью обычной кривой. Для этого
в MAYA есть совершенно замечательный инструмент.
Теперь выберите инструмент Skeleton=>IK Spline Handle Tool и привычно щелкните в первый
и последний сустав хвоста. Возникнет совершенно предсказуемый IK Handle. Однако при попытке
его подергать или повращать наиболее нетерпеливые получат обескураживающее сообщение:
Если вы будете гнуть эту кривую, форма хвоста будет соответственно изменяться. Кроме
того, если выбрать сам IK Handle, можно обнаружить на нем массу полезных атрибутов.
Это прежде всего Offset, позволяющий «протягивать» суставы вдоль кривой. Атрибут Roll
поворачивает все суставы вокруг кривой, а атрибут Twist позволяет спирально «скручивать» все
суставы от конца к началу.
Кроме того, по умолчанию вы не можете «оторвать» первый сустав от кривой (не говоря уж
об остальных). Однако выключив атрибут Root On Curve, вы сможете это сделать, получив таким
образом более «ручное» управление положением всей цепочки вдоль кривой (атрибут Offset при
этом игнорируется).
Если хвост или позвоночник из чего-то «растут», то есть имеют родительский сустав или
объект, то включенная по умолчанию галка Auto Parent Curve, поместит вновь созданную кривую на
тот же уровень иерархии, чтобы хвост и управляющая кривая двигались за «родителем» вместе.
Однако глядя на то, как ловко перемещается вдоль кривой вся цепочка при изменении атрибута Off
set, вы с большой долей вероятности захотите заняться дрессировкой пресмыкающихся, заставляя
их ползать вдоль заранее созданной кривой. Для этого вам надо снять галку Auto Create Curve и
MAYA дополнительно попросит вас выбрать кривую после щелкания в первый и последний сустав
цепочки. Этот вид анимации принципиально отличается от деформации хвостов и позвоночников
и требует в основном пристального слежения за ориентацией суставов.
В Option Box инструмента IK Spline Handle Tool выключите галки Root on Curve и Auto Cre
ate Curve и включите галку Auto Create Root Axis. Это позволит вам использовать собственную
кривую и дополнительно создать пустой родительский объект для первого сустава. Создав IK Han
dle, следует выбрать этот вспомогательный объект (он наверняка будет называться transform"!),
затем выбрать кривую и запустить этот пустой объект по пути: Animate=>Motion Paths=>Attach to
Motion Path.
В заключение скажу, что при использовании IK Spline Handle, особенно внутри сложных
иерархий, вы можете случайно «припарентить» кривую к первому суставу, который находится
внутри цепочки, управляемой этой же кривой. Возникнет цикл в дереве зависимостей (подробнее
о таких циклах читайте в главе про изнанку), так как кривая управляет суставом, а сустав является
родителем для кривой. Следите внимательно, чтобы кривая находилась в иерархии никак не ниже
первого сустава.
На этом пути нас ожидает несколько неприятных сюрпризов. Во-первых, такое крыло
поддается правдоподобным деформациям в очень ограниченных масштабах, и то преимущественно
в направлении «вверх-вниз».
Вторая «засада» крыло слишком тонкое. Как только мы начнем вручную редактировать
влияние костей на поверхность (веса прискиненных точек), так неизбежно столкнемся с тем, что
после редактирования веса точек верхней части поверхности будут отличаться от весов нижней
части, а значит при вертикальном «сложении» поверхности будут деформироваться немного по-
разному и, как следствие, проникать одна сквозь другую.
Если теперь по этим отрезкам построить NURBS-поверхность (loft), «не убивая» историю
(history), при манипуляциях с костями поведение построенной поверхности будет ближе к
поведению крыла (конечно, такое крыло еще не слишком соответствует динамике настоящего
крыла пернатых представителей фауны и больше напоминает махолет, но все же...)
Вы, может, спросите: зачем? А дело в том, что Wrap-деформер позволит нам избежать
самопересечения геометрии исходного крыла при деформациях, как по ширине, так и по
толщине.
Более того, подобной конструкции крыла можно добавить несколько большую степень
правдоподобности за счет согласованных между собой вращений базовых отрезков как вправо-
влево, так и вверх-вниз. Первое позволит нам проэмулировать «растопыривание» крыльев (хотя
Конечно, не надо вращать базовые отрезки независимо друг от друга, нужно согласовать
их вращение. Проще всего это сделать, «посадив» эти самые отрезки с помощью Driven Key на
дополнительные управляющие атрибуты.
Описанная выше технология в принцие позволит получить более или менее правдоподобное
движение крыльев птицы, «парящей где-то вдалеке», однако не является безусловно
окончательным, полным и просто хорошим решением для крыла.
Отмечу, например, что достаточно непросто будет получить гладкие деформации в районе
соединения крыла (управляемого Wrap-деформацией) и тушки тела (прискиненного к основному
скелету).
Подводя итоги, можно сказать, что на пути косвенного (indirect) скиннинга вдумчивого
конструктора ждет немало подводных камней на пути к успеху. Обиднее всего, что успех, в
принципе, может быть только относительным.
Собственно, вся эта длительная преамбула нужна была лишь для того, чтобы отбросить
любые попытки неофитов решить задачу сетапа крыла «лихим кавалерийским наскоком».
Итак, главный принцип прост и очевиден: чем полнее в конструкции майского персонажа
будут отражены законы (физические, математические, биомеханические), управляющие
поведением прототипа, тем более реалистичным будет выглядеть результат.
И еще пару слов перед тем, как мы подвергнем вивисекции наше пернатое несчастье.
Сетап - лишь подготовительный, хотя и очень важный этап. Наша основная цель - это все-
таки дальнейшая анимация создаваемой конструкции, и полученный результат должен быть не
только функционален, но и удобен для дальнейшей работы. Поэтому великомученик-«сетапер»
вынужден балансировать между двумя противоречивыми условиями - ведь нужны максимальная
гибкость и минимальное число управляющих элементов.
Вполе возможно, что дойдя до этого места, вдумчивый читатель воскликнет : «А можно
еще латисы (Lattice) использовать! И нелинейные деформеры! И кластеры!» Можно. Более того,
обязательно пробуйте приходящие вам в голову идеи: ведь все, что вы читаете в книжке - лишь
изложение чужого опыта, а нужен собственный опыт, и он набирается только и исключительно путем
проб и ошибок, синяков и садин. Вполне возможно, что ваши собственные идеи окажутся более
плодотворными, чем изложенные выше или ниже. Так что экспериментируем, экспериментируем,
потом отдохнем и еще раз поэкспериментируем.
Строение крыла
Итак, крыло. Анатомическая конструкция крыла птицы близка к конструкции руки, однако
есть и ряд серьезных отличий. В соответствии с анатомическим строением разобьем процесс
сетапа крыла на два этапа: первый - кости и кожа, второй - перья.
Перья
Главная сложность перья. У настоящего крыла перья расположены в несколько
перекрывающих друг друга слоев (как на иллюстрации ниже).
Это и создает идеальный аэродинамический профиль. Но мы, для наших целей, рассмотрим
несколько более простую модель. Для нас важно, что перья вдоль крыла можно разбить на
несколько групп соответственно перья «плеча», «предплечья» и «кисти» в зависимости от того,
где именно перо крепится к коже. (Я не знаю правильных терминов, поэтому нижнюю часть пера
буду называть «основанием», верхнюю «кончиком». Желающие могут легко найти правильные
термины в соответствующих книгах о птицах.)
Основания перьев достаточно жестко закреплены возле костей, и каждое перо, на первый
взгляд, может двигаться как угодно вокруг точки крепления. Но это только на первый взгляд.
Перья взаимодействуют друг с другом так, что импульсы, которые получает основание пера,
«гасятся», усредняются влиянием соседних перьев, и в результате вся перьевая масса ведет
себя согласованно. Линия «кончиков» перьев (задняя кромка) оказывается сглаженной и, хотя и
зависит от линии оснований, но живет в основном по своим собственным законам.
Во-вторых, перо эластично и гнется вверх-вниз при маховых движениях крыльев, «кончик»
же пера в своем движении по вертикали несколько отстает от «основания».
Построение крыла
Предварительный совет. Когда мы создаем цепочку костей с помощью Joint Tool,
локальная система координат внутри каждой кости по умолчанию располагается
очень удобно для дальнейшей работы. Ось X - вдоль кости, ось Y - перпендикулярно
X и в плоскости, образованной данной и следующей за ней костью, а ось 1,
естественно, перпендикулярна осям X и Y.
Кривая curve1 (NURBS-кривая первого порядка) - это шаблон для костей «тушки» тела,
curve2 - это кривая (NURBS-кривая 2-го или 3-го порядка), определяющая заднюю кромку (они обе
в файле wing01.ma).
Будем строить упрощенную модель крыла - всего по 3 пера на каждый сустав (итого 9
перьев), ведь для понимания процесса такого количества будет достаточно, а большее количество
перьев лишь загромоздит конструкцию, не внеся в нее ничего принципиально нового.
Для каждого пера мы будем строить отдельную цепочку костей. Построим «направляющие»
для этих перьевых «цепочек».
Построим отрезок вдоль оси X, начало которого в начале координат. Заметим, что пивот
его по построению находится в начале, и локальная ось X направлена вдоль этого отрезка.
Сделаем 8 копий этого отрезка (всего должно получиться 9 отрезков - по числу перьев). Назовем
их, например, C1, С2, СЗ....С9.
Теперь сориентируем наши отрезки так, чтобы они пересекались с кривой curve2,
определяющей заднюю кромку крыла.
Для этого создадим девять локаторов, назвав их, например, L1, L2...L9, и с помощью того
же Geometry Constraint (или с помощью утилитки pointOnCurvelnfo) «нанижем» локаторы подряд
на кривую curve2 задней кромки крыла, как бусинки на нитку.
С помощью Aim Constraint сориентируем отрезок С1, направив его на локатор L1. Затем С2
аналогично направим на L2, СЗ на L3 и так далее.
Построение скелета
Включив привязку к точкам (snap to point), строим первую цепочку сочленений вдоль
кpивой curve1.
Теперь займемся скелетными цепочками для перьев. Для каждого пера мы построим
индивидуальный скелет из трех суставов, чтобы можно было реализовать как скручивающие
деформации, так и деформации «на изгиб».
Используя привязку к кривой (snap to curve) вдоль первого отрезка «перьевого шаблона»
С1, построим цепочку из трех костей (четырех сочленений), как показано на рисунке. Первые два
сочленения расположим близко друг к другу, а третье сочленение будет делить нашу цепочку
примерно пополам (это место «сгиба» пера). Самое первое сочленение - «не рабочее», оно нам
Теперь нам нужно удалить первые кости в каждой из перьевых цепочек и то, что
останется, «припарентить» к костям передней кромки крыла. Поскольку лень - великий движитель
общественного прогресса, то сэкономим немного сил, выполнив эти действия не в три (Unparent=
>Delete=>Parent), а в два этапа.
Сначала припарентим кости а1, а2, аЗ к первой фронтальной кости frontLeft1; а4, а5, а6
- ko второй frontLeft2; и, наконец, а7, а8, а9 - к третьей frontLeft3.
Итак, первый, самый простой этап завершен: скелет построен и вспомогательные кривые
нам больше не нужны - их можно удалить, хотя лучше, все же, проявить осторожность и просто
спрятать (Hide). Самое время передохнуть, сохранить файл (файл wing07.ma) и расширить
сознание чашкой ароматного чая с пряником. Далее перейдем к основной задаче - приданию
нашему скелету функциональности.
Наличие перьев на нашем скелете поможет нам лучше понимать процесс сетапа, поскольку
на узких квадратных костях скелета трудно будет разглядеть результаты нашей деятельности, а
на плоских широких «перьях» результаты сгиба и скручивания выглядят более убедительно (файл
wing08.ma).
Для реализации этого управления создадим локатор , который назовем, например, IPoleV-
ectorControl.
Поместим его в место соединения первой и второй кости передней кромки крыла, используя
все ту же привязку к точке (snap to point).
Выполним Freeze Transformation для этого локатора, чтобы обнулить значения атрибутов
translateX, translateY и translateZ.
Затем воспользуемся констрейном типа Pole Vector для ориентации направления сгиба IK
Handle передней кромки крыла (файл wing11.ma).
Теперь самое время создать контрольный элемент, управляющий работой крыла. Часто
для этой цели используют кривую, но можно обойтись и просто локатором.
Итак, используя функцию привязки к точке (snap to point), выстроим цепочку костей вдоль
задней кромки крыла, переименовав сочленения соответственно в backJ, backJ_1, ..., backJ9?
(файл wins13.ma).
Однако при «нацеливании» нужно позаботиться о том, чтобы плоскость пера была
сориентирована вдоль костей передней кромки.
Для а1, а2, аЗ целевым объектом для Up Vector будет frontLeft2, для а4, а5, а6 frontLeft3,
а для а7, а8 и а9 - frontLeft4, соответственно.
После того, как все девять «перьевых» костей а1, ..., а9 будут сориентированы указанным
образом, можно подвигать управляющий локатор крыла IWingControl, чтобы убедиться, что теперь
перья работают «почти правильно»: они ориентируются на звенья «заднекромочной» цепочки
костей, при этом плоскости перьев ориентируются вдоль костей передней кромки крыла (файл
wing14.ma).
Итак, командой createNode создаем ноду plusMinusAverage (по умолчанию она получит имя
plusMinusAverage1) и не забудем установить операцию Substract.
На входы этой ноды подаем координаты двух локаторов: на первый вход - координаты
«конца» (локатора orientL1), а на второй вход координаты «начала» (локатора orientL0).
createNode plusMinusAverage;
connectAttr -f orientL1.translate plusMinusAverage1.input3D[0];
connectAttr -f orientL0.translate plusMinusAverage1.input3D[1];
Теперь осталось с помощью Aim Constrait направить кость b1 на backJ_1, выбрав в качестве
Aim Vector направление продольной локальной оси X (вектор <<1,0,0>>), в качестве Up Vector
направление локальной оси Z (вектор <<0,0,1>>), то есть World Up =«Vector», и в качестве World
Up Vector результат вычитания координат локаторов, то есть выход ноды plusMinusAverage1.
Для этого на всю «заднекромочную» цепочку костей навесим IК Spline Handle, постаравшись
минимизировать число контрольных точек сплайновой кривой (их должно получиться всего четыре,
и этого вполне хватит для реализации задуманного нами управления).
Руководствуемся при этом общим правилом - чем ближе «к телу», тем вес меньше.
Свяжем в Connection Editor этот атрибут с масштабированием вдоль локальной оси X кости BackJ:
Однако, как мы видим, при изменении атрибута wide масштабируется только кость
BackJ, а все дочерние кости «заднекромочной» цепочки остаются неизменными. Дело в том, что
у каждой кости есть специальный атрибут Segment Scale Compensate, который отвечает за то,
чтобы дочерние кости не наследовали масштабирование своих родителей, который по умолчанию
установлен в значение True.
Отожмем галку у атрибута Segment Scale Compensate для всех звеньев «заднекромочной»
цепочки и отметим, что теперь при изменении атрибута wide контрольного локатора крыла все
перья «растопыриваются» согласованно:
При wide=1.3:
И наконец, крыло птицы достаточно эластично, и при маховых движениях задняя кромка
гнется, отставая в своем движении от передней кромки крыла. Причем чем дальше от тела, тем
такие изгибы больше (файл wing21.ma).
Дело в том, что реально Aim Constraint для костей b# влияет только на вращение кости
вдоль локальной продольной оси (оси X), а вращения по остальным осям остаются нулевыми,
поскольку и кости b# и кости а# направлены на одни и те же объекты. Различия только в Up
векторах. Поэтому у дочерних (по отношению к звеньям а#) костей b# вращения по осям Y и Z
всегда будут нулевые, а значит, эти атрибуты вращения можно освободить от влияния Aim Con
straint без ущерба для общей функциональности. Что мы и сделаем.
Далее, чтобы управлять изгибом крыла, нам, естественно, понадобится еще один
дополнительный атрибут на контрольном локаторе (назовем его bend), который мы создадим
точно так же, как создавали атрибут wide, например, MEL-командой:
Поскольку есть естественное желание, чтобы изгибом всего крыла управлял один атрибут,
вы не можете напрямую связать новоявленный атрибут bend с углом поворота костей b# - кости
должны по-разному реагировать на одно и то же значение атрибута bend, а именно: чем дальше от
тела, тем поворот кости больше. Поэтому связь между атрибутом bend и углами поворота костей
мы осуществим с помощью технологии Set Driven Key.
Ну, и наконец последний, завершающий штрих - изменение Infinity для всех Driven Key
кривых открываем Graph Editor, выделив предварительно кости b#, и для всех обнаруженных
кривых изменяем значении параметра Pre- и Post Infinity с Constant на Linear (файл wing25.ma).
Ну вот и все. Основные идеи сетапа крыла изложены. Вам осталось только переварить
все прочитанное. Естественно, то крыло, которое мы построили, весьма далеко от совершенства.
Реальность, как всегда, намного сложнее. И вам придется самостоятельно изменять конструкцию,
в зависимости от конкретной задачи, но, тем не менее, надеюсь, что некое понимание устройства
крыла у вас все-таки появилось...
Рано или поздно перед вами встанет задача переноса анимации с одного персонажа
на другой. Хочу сразу обозначить разницу между переносом анимации (Animation Mapping) и
переносом движений (Animation Retargeting). В первом случае вы переносите с одного объекта
(или персонажа) на другой именно анимацию, то есть анимационные кривые (в виде клипов)
будут перенесены с атрибутов одного персонажа на атрибуты другого. Эта технология реализуется
средствами нелинейной анимации и будет описана позже. Она полностью прозрачна и бесхитростна
и к тому же не привязана только к скелетам.
Сразу оговорюсь, что эта технология хорошо подходит для человекообразных обезьян,
однако для четвероногих друзей, насекомых и прочих паразитов вы можете применять ее на свой
страх и риск. Еще раз напомню: она служит для переноса движения только между скелетами.
Метки имеют фиксированные имена, для того, чтобы названия суставов на разных скелетах
были унифицированы. Вы можете задавать метки для суставов либо через Attribute Editor, либо
через специальное меню Skeleton=>Retargeting=>Joint Labelling, что гораздо быстрее.
После того, как вы зададите метки, необходимо задать нейтральные позы для обоих
скелетов с помощью операции Skeleton=>Retargeting=>Set Neutral Pose. He путайте эти позы, с
позами возникающими автоматически при скининге (Bind Pose). Совершенно необязательно
распинать скелет, ставя его в Т-позу, при задании нейтральной позы. Наоборот, вы должны
придать обоим персонажам независимые позы, от которых будет «отсчитываться» и сравниваться
анимация. Если один персонаж это обезьяна, ее нейтральная поза наверняка будет включать в
себя согнутую спину, опущенные руки, вытянутую шею. Если вы переносите движение с обезьяны
на бравого солдата Швейка, то для него нейтральной позой может быть стойка «Смирно!».
После задания поз можно задать параметры и выполнить ключевую операцию Skeleton=>Re
targeting=>Retarget Skeleton. К этому моменту вы обязательно должны пометить один из суставов
как Root на каждом скелете. Сначала надо выбрать исходный скелет за этот сустав, затем целевой
скелет за него же и выполнить вышеуказанную операцию.
Еще немного замечаний, перед тем, как дать практический пример. Для тех суставов, чьи
метки не заданы или установлены в опцию «None», перенос движения не производится вообще.
Для остальных суставов происходит не только сравнивание имен меток, но и анализ взаимного
расположения суставов. Кроме того, для суставов, обозначенных как руки и ноги, производится
дополнительный анализ их поведения и обеспечивается сохранение некоторых характерных
особенностей движения, таких, как прилегание ног к земле. Все это делает возможным перенос
Можете использовать свой любимый персонаж, однако если это пятирукий мутант, лучше
все-таки открыть файл retargetStart.ma.
В этом файле два персонажа, Бивис и его дружок. Бивис имеет небольшую анимацию,
которую мы собираемся перенести на его приятеля.
Сначала надо расставить метки на суставах. Эту рутинную работу лучше проводить на
обоих скелетах одновременно, чтобы гарантировать синхронизацию названий. Но вы можете
проделать это для каждого отморозка отдельно. Я буду просто указывать: «выберите такой-то
сустав и пометьте его как Neck», имея в виду, что вы выбираете сустав либо на обоих скелетах,
либо на одном.
Совет. Перед процессом расставления меток очень полезно «оторвать» меню Skel
eton=>Retargeting=>Joint Labelling, чтобы просто не сойти с ума.
Выберите самый верхний сустав - Root Joint. У Бивиса это сустав Bivis, у напарника - ButtHead
Теперь в меню Joint Labelling выполните Label Root.
Дальше выберите левую ногу (LeftUpLeg), выполните Label Leg.
Чтобы отличать одну ногу от другой, обозначьте ее как левую - Label Left.
Теперь выберите правую ногу (RightUpLeg), выполните Label Leg, обозначьте как Label
Right. Выберите место, откуда растут руки (руки, а не ноги!) (Collarbone_Root), и выполните La
bel Collar. Выберите левое плечо (LeftArm), выполните Label Arm. Стоп! Вот тут сюрприз, за счет
издержек «интеллектуальности». MAYA честно пометила выбранный сустав как Shoulder и быстро
разметила три нижележащих сустава как Elbow (локоть), Hand (рука, кисть) и Finger (палец). При
этом она совершенно не учла (да и откуда ей знать), что между локтем и кистью, был вставлен
дополнительный сустав для продольного поворота кисти.
Выберите дополнительный сустав, ошибочно помеченный как Hand, и выполните Label None.
Затем выберите концевой сустав, помеченный как Finger, и выполните Label Hand.
Выберите правое плечо (Right Arm). Для того, чтобы не исправлять ошибочную разметку,
сразу пометьте его как Label Shoulder и Label Right.
Выберите сустав Head, отвечающий за голову и пометьте его как Label Head.
Выберите сустав Neck, отвечающий за шею и пометьте его как Label Neck. Обратите
внимание, что шея имеет разное количество суставов на первом и втором скелете.
Закончив этот адский процесс для обоих персонажей, сохраните сцену и передохните. Еще
раз проверьте, все ли метки на месте. Если вы не смогли выдержать до самого конца, откройте
сцену retargetLabelled.ma.
Для этого надо сначала выбрать исходный скелет за сустав, помеченный как Root, а затем
выбрать за такой же сустав второй (целевой) скелет, на который будет переноситься движение. В
нашем случае надо выбрать сначала Bivis, а затем ButtHead.
Если вашего второго персонажа сильно «перекрячило» или согнуло вниз, нажимайте Undo
и проверяйте разметку суставов. В крайнем случае возьмите готовый файл retargetLabelled.ma,
там метки расставлены корректно.
Вопрос в том, как вернуть все обратно и заново ориентировать оси. Малодушные (и
самые разумные пользователи) просто заново загрузят сохраненный файл retargetLabelled.ma.
Однако мы легких путей не ищем, а потому убьем всю анимацию второго персонажа и вернемся в
Это означает, что данная операция не может быть использована для суставов с ненулевыми
вращениями. Чтобы обойти это ограничение, а заодно вычистить все вращения и получить
«стерильный» скелет, откройте Option Box операции Modify=>Freeze Transformation и включите
галку Joint Orient, а затем нажмите кнопку Freeze Transform.
Теперь можно повторить попытку переноса движения. Выберите первый и второй скелеты.
Выполните Skeleton=>Retargeting=>Set Neutral Pose (ведь мы основательно «прочистили» второй
скелет), а затем Skeleton=>Retargeting=>Retarget Skeleton.
Поэтому в Option Box операции Retarget Skeleton для вычисления движения нижних
конечностей (Lower Body) по умолчанию используется опция Scaled Foot Placement, обеспечивающая
то, что расстояние от бедер до ступней (Hip to Foot) будет пропорционально сохраняться на втором
скелете (вы можете сами определить, какое расстояние использовать для сохранения пропорций
в движении ног, задав значение параметра Lower Body Scale).
Если персонаж выполняет какие-то специфические движения ногами, например прыгает
по камням через ручей, необходимо, чтобы ноги попадали в конкретные места (абсолютные
позиции). В этом случае можно использовать опцию Absolute Foot Placement.
Если руки не закреплены, для переноса движения верхних конечностей (Upper Body) лучше
использовать опцию Joint Rotations Only. Если же руки опираются на что-то или совсем уж сильно
отличаются по размеру для обоих скелетов, можно воспользоваться опцией Scaled Hand Place
ment. Если персонаж что-то держит в руках, лучше использовать вариант Maintain Hand Distance,
сохраняющий пропорции в расстоянии от рук до туловища.
На этом можно закончить разговор о мануальной терапии, то есть о скелетах и суставах, и
перейти к дерматологической теме - скинингу.
В седьмой версии MAYA появился еще один вид инверсной кинематики. Этот способ
управления персонажем появился в результате покупки компанией Alias компании Kaydara,
имевшей наиболее продвинутые, на тот момент, решения в области инверсной кинематики,
нелинейной анимации и управления скелетом.
Этот вид управления персонажем, возможно, придется по вкусу если не большинству,
то значительному количеству майских пользователей, измученно навешивающих сонмы IK-
манипуляторов и управляющих локаторов на своих иезуитски-сложных персонажей.
Впрочем, лучше сразу несколько раз увидеть, чем один раз услышать или прочитать.
Откройте новую сцену и выполните 5keleton=>Full Body IK=>Get FBIK Example.
Из открывшегося окна Visor с парой примеров перетащите и бросьте средней кнопкой
мыши человекоподобного персонажа прямо в панель камеры.
Внешне это выглядит так: вы создали скелет и просите MAYA создать для него систему
управления человекообразным или четырехлапым персонажем (эти варианты указываются в Op
tion Box операции Add Full Body IK). Однако MAYA ничего не знает про то, где, по вашему мнению,
у персонажа находится голова, а где хвост, где руки, а где ноги. MAYA видит ваш скелет как
сборище костей с именами j o i n t 1 , joint2..., как-то соединенных между собой. Поэтому самым
главным условием успешного создания системы управления Full Body IK является корректное
поименование частей тела вашего скелета. После того, как разные кости будут иметь строго
определенные имена, MAYA сможет создать нужные манипуляторы для рук, ног, головы и других
частей тела. Любые неточности в названиях костей будут приводить к ошибкам и некорректной
работе системы Full Body IK.
2. Можно создать для суставов метки (labels), рассмотренные выше в разделе про перенос
анимации. Эти метки, создаваемые через меню Skeleton=>Joint Labelling=>Add FBIK Labels,
позволяют дать суставам «дополнительные» и строго фиксированные имена.
Далее, я буду говорить про «имена» или «названия» суставов, имея в виду, что это могут
быть как реальные имена, так и метки.
Прежде всего это базовые суставы. Для успешного создания системы управления Full Body
IK необходимо дать названия некоторому базовому набору суставов (и, как следствие, создать
его). Если базовые суставы не будут иметь нужные названия, система Full Body IK просто не будет
создана.
Базовые суставы называются в MAYA так: Hips (pelvis or root, копчик или основание
позвоночника), Spine (позвонки), Head (top of neck, голова), UpLeg (бедра), Leg (knees, колени),
Foot (ankles, ступни), Arm (shoulders, плечи), ForeArm (elbows, локти), and Hand (wrists, запястья).
В скобках приведены «человеческие» названия для суставов.
Следует заметить, что если вы назвали сустав каким-то «своим» образом (например,
«tail» или «хвост» или «joint4096»), этот сустав не будет управляться системой Full Body IK и,
как следствие, просто не будет вращаться при работе с манипуляторами. Тоже самое касается
«непоименованных» суставов, имеющих метки «None». Такие суставы система Full Body IK просто
игнорирует.
Если вам не лень, откройте файл fbikLabelled.ma, выберите скелет за самый верхний
сустав ButtHead и откройте Option Box операции Add Full Body IK.
Убедитесь, что выбран метод идентификации суставов по меткам (Identify Joints=By Label)
и коль скоро скелет явно прямоходящий, то надо выбрать Posture=Biped.
Выберите левое колено и пометьте его с помощью Skeleton=>Joint Labelling=>Add FBIK La
bel как Knee и затем как Left.
Это означает, что при создании системы Full Body IK существуют дополнительные требования
к ориентации и расположению скелета и отдельных его частей.
В случае, если ваш персонаж еще не встал на две ноги и продолжает бегать на четырех
лапах, требования будут следующие:
Подергав за некоторые из них, например, за локоть, вы можете заметить, что работают они
похоже на обычные IK Handle, то есть могут даже отрываться от своего сустава, если перемещения
слишком велики. Однако сдвинув немного соседний манипулятор, вы увидите, что оторвавшийся
эффектор прилипает обратно к суставу.
Вы также можете заметить, что некоторые эффекторы ведут себя по разному. Мало того,
что они имеют разную форму (кубики, шарики), они еще и по-разному реагируют на перемещения
соседних частей тела. Некоторые остаются на месте, а некоторые послушно следуют за скелетом.
Об этом стоит поговорить подробнее.
На этом можно было бы и закончить. Однако одна деталь не даст пытливым умам спокойно
спать - почему для постановки ключей на FBIK-скелет нужна специальная операция, да еще и со
своими параметрами.
Действительно, для того, чтобы ставить ключи на персонаж с Full Body IK нельзя
использовать ни операцию Set Key, ни функцию Auto Key. Для этого существует специальная
операция Animate=>Set Full Body IK Key.
Прежде, чем говорить о ее параметрах, я бы хотел остановиться подробнее на внутреннем
устройстве системы Full Body IK.
Прежде всего замечу, что кроме скелета и набора эффекторов в сцене присутствует еще
один, невидимый скелет, называемый FK Skeleton. Как следует из названия, он хранит в себе
информацию о прямой кинематике, то есть о вращениях костей основного скелета.
Основной скелет (тот, который виден на экране) называется в майской терминологии input
skeleton. Я буду продолжать называть его основным, подчеркивая, что именно он используется
Когда вы ставите ключ (точнее, ключи) на ваш персонаж (или его часть, об этом позже) с
помощью операции Set Full Body IK Keys, то все ключи ставятся, во-первых, на эффекторы, а во-
вторых, на суставы вспомогательного FK-скелета. На суставы основного скелета никаких ключей
на ставится!
Еще раз повторюсь: на основном скелете никаких ключей не появляется, все ключи
создаются для набора эффекторов и вспомогательного FK-скелета.
Если вы уже в первом кадре, откройте Option Box операции Animate=>Set Full Body IK Keys
и установите параметры по умолчанию
Проиграйте анимацию, а затем встаньте в пятый кадр и посмотрите поближе на локти или
на колени. Вы можете заметить, что основной и вспомогательный скелеты не совпадают между
собой.
Параметр Reach keying mode отвечает за «тип» устанавливаемых ключей в данном кадре.
Если выбран тип IK Key, то кости, управляемые выбранным эффектором, будут двигаться после
этого ключа вслед за решением инверсной кинематики, а если выбран тип FK Key, то эти кости
будут следовать за FK-скелетом.
Грубое правило постановки и выбора типа ключей такое: после задания позы и перед
установкой ключа следует выбрать те эффекторы, чьи суставы должны оставаться на месте и
после этого поставить ключ типа IK Key. Это гарантирует, что между соседними ключами нужные
суставы не будут проскальзывать или дрожать. (Заметьте, я пока ничего не говорю про параметр
Keying Mode, полагая, что он установлен в Аll.)
Технически вся эта чехарда с типами ключей устроена следующим образом. У каждого
эффектора есть два атрибута: Reach Translation и Reach Rotation, на которые документация (и
я в дальнейшем) часто ссылается как на один атрибут Reach. Так вот, когда этот (эти) атрибут
равен единице, то кости (суставы), управляемые этим эффектором, строго следуют за инверсной
кинематикой, определяемой положением этого эффектора (это практический полный аналог
атрибута ikBlend для обычных IK Handle). Если атрибут Reach равен нулю, то кости, управляемые
им, начинают следовать правилам прямой кинематики, игнорируя положение эффектора и
двигаясь вслед за FK-скелетом.
По умолчанию, у вновь созданного Full Body IK персонажа атрибуты Reach равны единице
для рук (HandEff), ног (FootEff) и бедер (HipEff), (для handEff атрибут Reach Rotate равен нулю),
так как эти части тела обычно управляются с помощью эффекторов, то есть с помощью инверсной
кинематики. Для остальных эффекторов атрибут Reach равен нулю, так как, например, голову или
шею проще анимировать прямой кинематикой.
Еще раз уточню, что атрибут Reach определяет, как будут двигаться кости (соответствующие
эффектору) между ключевыми кадрами. Если, например Reach будет равен 0.5, то между
ключевыми кадрами кости основного скелета будут где-то посередине между решением инверсной
кинематики и FK-скелетом.
Так вот, когда вы выбираете эффектор(ы) и ставите на него ключ типа IK Key, то для него
(них) атрибут Reach устанавливается в единицу и на него (них) ставится ключ - с тангенсом типа
Stepped Next. Это происходит только для выбранных эффекторов - и не верьте документации,
утверждающей, что «all other effectors' Reach values are set to 0»! Атрибуты Reach для остальных
невыбранных эффекторов остаются нетронутыми.
Если же вы ставите на выбранные эффекторы ключ типа FK Key, то для них атрибут
Reach устанавливается в ноль и на него ставится ключ {с тангенсом типа Stepped). Это опять же
происходит только для выбранных эффекторов.
Примечание. Тангенс типа Stepped Next определяет, что если в данном кадре
Таким образом, если за ключом типа IK Key следует ключ типа FK Key, то кости выбранного
эффектора начинают работать в режиме прямой кинематики сразу же после первого IК-ключа.
Если за ключом типа FK Key следует ключ типа IK Key, то кости выбранного эффектора продолжают
работать в режиме прямой кинематики вплоть до достижения этого IK-ключа. Это удобно, так
как позволяет фиксировать и отрывать конечности в нужный момент времени, не заботясь о
дополнительных ключах в соседних кадрах.
Параметр Keying Mode=All определяет, что в дополнение к ключам на атрибут Reach для
выбранных эффекторов, ставятся ключи на перемещения и вращения всех эффекторов и на
перемещения, вращения и масштаб всех суставов FK-скелета. Существует возможность также
ставить эти ключи только на определенные части тела (Keying Mode=Body Part), относящиеся к
выбранным эффекторам. То есть для выбранного эффектора ключи ставятся только на некоторый
набор эффекторов и костей FK-скелета, относящихся к текущей части тела.
Еще раз повторюсь, что параметр Keying Mode определяет, на какие эффекторы будут
ставиться ключи на перемещение и вращение (и масштаб для FK-скелета). Он не никак не влияет
на постановку ключей на атрибут Reach, производимую только для выбранных эффекторов в
соответствии со значением Reach Keying Mode.
Выберите оба эффектора для ног и поставьте ключ типа IK Key (при этом Keing Mode=AU).
Перейдите в двадцатый кадр и снова поставьте такой же ключ (пользуясь Option Box операции Set
Full Body IK Keys).
Перейдите в десятый кадр, выберите центральный эффектор для бедер, опустите его
вниз, посадив персонаж пониже, затем снова выберите оба эффектора для ног и опять поставьте
ключ типа IK Key.
Перейдите в тридцатый кадр и снова посадите персонажа, снова не забудьте выбрать оба
эффектора для ног, но в этом случае поставьте ключ типа FK Key.
В этом случае вы увидите, что ноги персонажа проваливаются под землю между двадцатым
и тридцатым кадром. Последите за изменением атрибутов Reach для эффекторов ног, перемещаясь
от кадра к кадру. После двадцатого кадра Reach становится равным нулю и это означает, что
суставы, управляемые эффекторами ног двигаются по законам прямой кинематики, то есть вслед
за FK-скелетом (который вы всегда можете включить для отображения на экране).
Примечание. Забегая немного вперед, могу добавить, что при создания системы
Full Body IK дополнительно создается персонаж (character) и некоторое количество
«подперсонажей» (subcharacters) для каждой части тела. Эти объекты нелинейной
анимации создаются для хранения и манипулирования ключами, поставленными на
эффекторы и суставы. Вы можете заметить, что при выборе любого эффектора
на таймлайне появляется соответствующий ему subcharacter.
Это происходит вследствие того, что в меню Skeleton=>Full Body IK по умолчанию включена
опция Body Part Autoload.
Примечание. Имейте в виду один неприятный глюк. После того как вы загрузите
или создадите скелет с Full Body IK, при выделении любого объекта отключается
активный Character Set. Это от того, что происходит автоматическое
переключение Character Set для нового Full Body IK, но при этом нарушается выбор
обычных сетов. Для того, чтобы можно было работать с обычными сетами,
нужно отключить меню "Body Part Autoload".
Очевидно, что удалив или сдвинув эти ключи вы успешно рассинхронизируете инверсную и
прямую кинематику (рассинхронизируете в ключевых кадрах, в промежуточных кадрах кинематики
и так рассинхронизированы). Эффекторы будут двигаться по-своему, а FK-скелет - по-своему.
Поэтому постарайтесь держаться подальше от Graph Editor. Если вам уж очень невтерпеж, можете
открыть его, посмотреть на кривые, вздохнуть и закрыть его - от греха подальше. Самые смелые
могут поменять тип тангенсов, не трогая позиции ключей.
С помощью этого меню выбранные на TimeLine ключи удаляются как с эффекторов, так и
с суставов FK-скелета, обеспечивая необходимую синхронизацию.
Во-вторых, вы должны помнить, что если включена опция Body Part Autoload, то на Time-
Line отображаются ключи не только для выбранного эффектора, но и для всех эффекторов и
суставов, входящих в соответствующую часть тела. Это может иногда служить причиной путаницы
и появления «лишних» ключей.
В-третьих, если опция Body Part Autoload выключена и вы ставите ключи на выбранные
эффекторы с помощью Keying Mode=Selected (или с помощью правой кнопки мыши и меню Key
Selected), на TimeLine появляются ключи только для выбранного эффектора. Следовательно, если
вы начнете их редактировать на TimeLine, то быстро нарушите вышеупомянутую синхронизацию.
Помните об этом и следите за тем, какие ключи отображаются на TimeLine в каждый момент
времени.
Снова выберите эффектор для левой ступни (LeftFootEff) и выполните Add Secondary Con
troller.
Новый эффектор оттащите вперед и вниз на место сгиба пальцев, уменьшите его, если
надо, а затем выполните Skeleton=>Full Body IK=>Activate Secondary Effector.
Теперь вы можете вращать ступню сразу за три пивота. При анимации не забудьте выбирать
нужный эффектор и ставить на него ключи типа IK Key, чтобы избегать проскальзывания в точке
вращения (дополнительные эффекторы также имеют атрибуты Reach и на них распространяются
принципы выбора Reach Keying Mode).
Удобнее работать с атрибутами для контакта в Attribute Editor, так как там они появляются
уже сгруппированными по разделам для работы с отдельными видами контактов с землей: для
рук, для ног, для пальцев.
Снова перемещайте персонаж вверх и вниз, убедитесь, что ноги успешно упираются в
землю.
Если вам нужна дополнительная индивидуальная плоскость контакта для любого эффектора,
вы можете создать ее, просто выбрав нужный эффектор, и выполнить операцию Skeleton=>Full
Body IK=>Add Contact Plane.
Таким образом, нода hikHandle отвечает за настройку поведения всей системы Full
Body IK для выбранного персонажа. Далее вам остается вооружиться описанием этой ноды из
документации, терпением и, если надо, словарем и разобраться с атрибутами данной ноды. Скажу
лишь, что если некоторые атрибуты заблокированы, то в разделе Pull надо включить опцию Expert
Mode для совсем уж взрослых мальчиков, чтобы получить доступ ко всем секретным атрибутам.
Во-вторых, вся система достаточно сложна и громоздка для аниматоров. Всегда существует
большая вероятность того, что стоит что-нибудь забыть переключить или недоглядеть, и FBIK
поведет себя непредсказуемым образом. Например, можно сильно потянуть одну конечность так,
что фиксация остальных с поверхностью земли будет неполной, и если после этого поставить
ключи, то при прохождении через этот кадр, будет "дребезг" в позиции ступней.
Пытливые умы, конечно, обнаружили, что при создании системы Full Body IK в сцене
появляются новые сущности (не путать с существами). Их можно обнаружить в Outliner или
Channel Box в виде объекта fbikCharacter и множества подобъектов, чьи названия начинаются
с подчеркивания, типа _Legs. Все это так называемые Characters, относящиеся к понятиям и
технологиям нелинейной анимации. К этим понятиям мы сейчас и перейдем. Те кому не терпится
перейти к дерматологической тематике и заняться скинингом, могут проскочить эту тему и перейти
к «шкурному» вопросу.
Дело в том, что основной инструмент нелинейной анимации в MAYA называется Trax Edi
tor (сокращение от Tracks). Благодаря гибкости русского языка и неоднозначности трактовки
большинства словоформ, использующих корень «трах», название этого инструмента приобрело на
традиционном майском жаргоне дополнительное очарование.
Рано или поздно вам (или кому-то еще) захочется объединить все необходимые атрибуты
для анимации конкретного персонажа в некоторый набор атрибутов, и далее иметь дело только
с этим набором, с облегчением забыв о том, каким объектам эти атрибуты принадлежат. Таким
образом, мы выходим на понятие обобщенного «Персонажа», представляющего из себя набор
атрибутов от различных объектов. Таким образом, мы поднимаемся с уровня «объекты-атрибуты»,
на следующий уровень абстракции, используя вполне человеческое и нетехническое понятие
«Персонаж», как набор атрибутов, собранных вместе и необходимых для управления и анимации
любой системой объектов. Такой «Персонаж» - уже не объект, а некое абстрактное понятие,
имеющее, впрочем, вполне конкретную реализацию в MAYA.
Выберите все шесть кластеров, а затем в Channel Box выберите все атрибуты translate.
Откройте Option Box операции Character=>Create Character Set.
Назовите персонажа Grass и установите lnclude=From Channel Box.
Нажмите кнопку Create Character Set и поглядите в Outliner. Там появится новая сущность
Таким образом, вы имеете набор атрибутов для анимации под названием Grass. Этот набор
можно дополнять или изменять с помощью операций Add to Character/Remove From Character. Для
этого достаточно выбрать нужные атрибуты в Channel Box.
«Но позвольте!» - воскликнут пытливые умы. «Ведь у операции Add to Character Set
отсутствует Option Box. Откуда тогда MAYA узнала о том, в какой набор character надо добавить
новый атрибут? Ведь таких наборов в сцене может быть много.»
Ответ следующий: MAYA добавила атрибут в текущий character. Если посмотреть в правую
часть Timeline, можно заметить небольшой элемент интерфейса для выбора текущего character в
сцене.
Примечание. Если текущий character не выбран (None), ключи ставятся, как обычно,
на выбранный объект.
Таким образом, вам не надо даже заботиться о выборе объектов и следует только помнить,
какой character является текущим. Это устрашающе экономит время аниматора.
Подперсонажи - SubCharacters
В травинкой все более-менее просто, однако у некоторых персонажей бывают руки и даже,
что удивительно, ноги. И часто бывает нужно поставить ключи только на атрибуты объектов,
управляющих ногами или руками, и не хочется ставить ключи на все атрибуты, входящие в char
acter.
Откройте Option Box операции Create Subcharacter Set и установите Subcharacter Set
Attributes=From Channel Box.
Теперь вы можете добавлять новые атрибуты либо в основной character Grass, либо в
subcharacter Top, в зависимости от того, какой из них является текущим.
Если текущим является «верхний» или «основной» персонаж (character), то при выполнении
операции Set Key ключи ставятся на все атрибуты этого персонажа и все атрибуты всех его
подперсонажей (subcharacters). Если текущим является какой-нибудь подперсонаж (subcharacter),
то ключи ставятся на все его атрибуты и атрибуты входящих в него «подподперсонажей» (subchar
acters).
Позы и клипы
Продолжим философские рассуждения. Коль скоро весьма удобно рассматривать
обобщенный «Персонаж» как список атрибутов, то вполне «по-человечески» будет назвать «Позой»
зафиксированный набор значений этих атрибутов. В самом деле, одной позе соответствует вполне
конкретный набор значений атрибутов, а другой позе - другой набор значений.
Теперь мысленно возьмем две позы и представим движение персонажа из одной позы в
другую. Адекватно будет назвать такое движение (кусок анимации) как «Клип». Таким образом,
Подумайте также о том, что клипы можно смешивать, усреднять, накладывать поверх друг
друга, получая новые типы движений.
Вместо того, чтобы предлагать вашему вниманию тщательно отлаженный учебный пример
и набор безупречно работающих инструкций, я хочу использовать максимально сырой материал,
чтобы воспроизвести «глюки» и «косяки», с которыми вы можете столкнуться.
В сцене уже есть character под названием duck. И даже присутствует некоторая анимация,
сделанная с помощью постановки ключей на все атрибуты персонажа. Утка совершает один цикл
плавательных движений.
Выберите character duck в Outliner и выполните в меню Trax Editor операцию List=> Load
Selected Character. Появится синяя полоска duck, под которой пока нет ни одного клипа.
Примечание. Можно включить в меню Trax Editor опцию List=>Auto Load Selected
Character.
Итак, коль скоро персонаж уже имеет некоторую анимацию, создадим из этой анимации
клип. Выполните в меню Trax Editor операцию Create=>Clip с параметрами по умолчанию.
Клип можно растягивать-сжимать за правый (левый) нижний угол. При этом вся анимация
За верхние углы клип можно только тримировать, то есть ограничивать его область
действия, не меняя темпа анимации. Естественно, что расширять область действия за исходные
границы нельзя: за границами исходного клипа ведь ничего нет.
Примечание. Если два раза щелкнуть по цифрам в углах клипа, то можно вбивать
значения вручную прямо «на клипе».
Пытливые умы, пропитанные идеологией MAYA наверняка заподозрят, что в результате этих
операций меняются атрибуты некоторого объекта и будут, безусловно, правы. Клип это объект
сцены со своими атрибутами, что прекрасно видно в Attribute Editor.
Для этого надо нажать Shift и вновь потаскать клип за углы. Форма курсора поможет
сообразить, за что отвечают разные углы.
Задайте в Attribute Editor значение Post Cycle=2. Это вызовет повторение клипа еще два раза.
Никто не мешает вам после этого, менять Scale для клипа, циклы будут также масштабироваться.
Атрибут Hold отвечает за удержание последнего кадра клипа в виде «стоп-кадра» в течение нужного
количества времени. Если после клипа нет других клипов, это, очевидно, не имеет смысла.
Прежде, чем говорить о других операциях с клипом и уж тем более с несколькими клипами,
я бы хотел поговорить, о «природе» клипов и их внутреннем устройстве.
Изнанка клипов
Любители экстремального монтажа знают, что есть два вида видео-материала: исходный
материал (полученный захватом с камеры и лежащий на диске в определенном месте) и рабочий
материал, представленный на временной линейке монтажной программы. Все манипуляции
(склейки, переходы, подрезки) производятся над рабочим материалом, а исходный материал, как
лежал одним куском (несколькими кусками) на диске, так и лежит, и никто его, как правило, не
трогает.
Точно также анимационный клип в MAYA состоит из двух частей. Первый часть - это
исходный клип (source clip), невидимый в Trax Editor, а вторая часть - регулярный(нормальный)
клип (regular clip), который как раз и лежит в рабочей области Trax Editor.
Примечание. После создания клипа все ключи, по умолчанию, будут удалены с Time-
Line и «перейдут» в исходный клип. А персонаж готов к постановке новых ключей
и созданию новых клипов.
Один исходный клип может иметь много регулярных копий. Если вы копируете регулярный
клип с помощью операции Duplicate (из меню Trax Editor), то по умолчанию создается новый
регулярный клип, у которого тот же самый «исходник». Если вы удаляете регулярный клип из
Trax Editor, то с исходным клипом ничего не происходит, он остается жив-здоров. Вы всего лишь
удаляете его копию.
Итак, регулярные клипы вы видите и редактируете вТгах Editor. А где искать исходные клипы?
Для них определены специальные закладки в окне Visor, куда можно попасть непосредственно из
Trax Editor с помощью меню File=>Visor...
В закладке Character Clips находятся все исходные клипы, соответствующие существующим
персонажам. Есть еще закладка Unused Clips, куда попадают «бесхозные» клипы, например, при
импорте их из внешних файлов.
Вы можете перетащить clip1Source средней кнопкой мыши из Visor или Outliner и бросить
его на свободное место в Trax Editor. После этого вы немедленно получите еще одну копию
исходного клипа в виде регулярного клипа в Trax Editor.
Удалите полученный таким образом клип из Trax Editor, при этом исходный клип останется
неизменным (правда, может изменить при этом свое имя).
Следует, однако, постоянно помнить, что у каждого регулярного клипа есть «исходник».
Например, при выполнении операций Edit=>Trim Before/After, просто происходит изменение
атрибутов Source Start/End для регулярного клипа. А вот операция Split, разделяющая один
регулярный клип на два клипа, порождает два новых регулярных клипа и, по умолчанию, оставляет
один исходный клип. (Не пытайтесь «засплитить» зацикленный клип, это невозможно. Установите
сначала Post Cycle=0.) Однако в Option Box операции Split вы можете выбрать опцию Delete Original
Source, после чего будут возникать два новых регулярных клипа и два новых исходных клипа.
Примечание. В Option Box операции Create=>Clip входит опция Put Clip in Visor Only/
Put Clip in Trax Editor and Visor. Она как раз и определяет, создавать ли только
исходный клип, помещаемый в Visor, или также создавать регулярный клип и
показывать его в Trax Editor.
Импортирование клипов
Судя по тому, что клип самостоятельный объект сцены, его наверняка можно
экспортировать в виде отдельного файла и позже импортировать обратно, имея, таким образом,
библиотеку клипов, не привязанных к конкретной сцене. Вопрос о том, как «приклеить» клип,
созданный для слона, к персонажу типа «моська», я оставлю на попозже, я предположу, что вы
в состоянии поставить ключи на супер-утку и создать еще пару клипов. Более того, вы наверняка
способны выбрать эти клипы и экспортировать их на диск с помощью операции File=>Export Clip.
А вот о том, как эти клипы импортировать обратно, следует поговорить подробнее.
Выберите duck в Outliner или на TimeLine (это важно) и выполните File=>lmport Clip to
Character. Выберите в папке Clips файла run.ma и нажмите Import.
В Trax Editor появится новый клип с бегущей уткой. В зависимости от того, в каком кадре
вы находились, он появится либо после первого клипа, либо над ним. Оттащите его так, чтобы он
был слева от первого «плывущего» клипа.
Очевидно также и то, что на работу данного клипа каким-то образом влияет, клип
находящийся перед ним. Вопрос в том, каким образом?
Однако часто бывает так, что очередное движение должно начинаться с учетом последней
позы персонажа. Например, вы сделали в начале координат клип, отвечающий за прыжок вперед,
а затем клип, отвечающий за прыжок на месте, и теперь, расположив клипы друг за другом, вы,
естественно ожидаете, что после первого прыжка, персонаж подпрыгнет на месте приземления,
однако в случае, если второй клип будет абсолютным, то второй прыжок будет происходит в
начале координат, где был создан клип, то есть персонаж, прыгнув вперед, тут же сместится назад
и там скакнет на месте. Так что в этом случае хотелось бы сделать клип «относительным» (rela
tive), чтобы к анимации клипа добавлялась еще последняя поза предыдущего клипа. Более строго
говоря, для «относительного» клипа к значениям анимационных кривых добавляются последние
значения анимированных атрибутов из предыдущего клипа.
Выберите второй («бегущий») клип и нажмите правую кнопку мыши над ним. Появится
основное рабочее меню для работы с клипами. В нем собраны основные операции из меню Тгах
Editor, применимые к клипам.
Однако не произойдет ровным счетом ничего. На самом деле должен появиться At
tribute Editor для выбранного клипа, который и так открыт. Таким образом MAYA говорит вам
(довольно ненавязчиво, надо сказать), что в Attribute Editor надо открыть раздел Channel Offsets и
отредактировать там свойства анимационных каналов.
Откройте в Attribute Editor раздел Channel Offsets и поглядите, как MAYA расставила
свойства Absolute/Relative для импортированного клипа.
Примечание. Здесь следует заметить, что ноль скоро при экспорте клипа в
отдельный файл, сохраняется только «исходный» клип, то информация об
атрибутах Channel Offset просто теряется (эти атрибуты есть только у
регулярных клипов, у исходных они отсутствуют, проверьте сами). Поэтому при
импорте клипа (равно как и при его создании) MAYA проявляет некий «интеллект»
при расстановке свойств Absolute/Relative для нового регулярного клипа.
В данном случае проблема заключается в том, что к перемещениям лап утки, добавляются
их позиции из первого клипа.
Если «надвинуть» второй клип на первый (попутно возникнет вторая монтажная дорожка),
то возникнет эффект «суммирования» клипов, когда значения соответстующих каналов просто
суммируются и возникает просто «двойная» анимация. Для корректировки анимации это, может
быть, и хорошо, однако сейчас задача состоит в том, чтобы сделать мягкий переход от одного
клипа к другому.
Отодвиньте второй клип правее, затем выберите первый клип, нажмите Shift и выберите
второй клип.
Теперь происходит плавный переход из одной позы в другую, точно также как между
ключевыми кадрами. В зависимости от расположения клипов, этот переход автоматически
подстраивается под расстояние между клипами.
Выберите в Trax Editor зеленую стрелку, чтобы посмотреть на этот переход повнимательнее.
Это тоже отдельный объект. Как и у любого объекта, у перехода обнаруживаются некоторые
атрибуты в Attribute Editor.
Поэтому для переходов между клипами по умолчанию значение Rotation Blend установлено
как Quaternion Short, что означает максимально короткую траекторию вращающихся объектов в
пространстве при переходе от позы к позе. Про остальные значения просто пока забудьте.
Еще раз повторюсь, что когда вы вручную контролируете вращение объекта и ставите на него
ключи, наблюдая за значениями вращений, то вы примерно чувствуете, как он будет двигаться.
Однако работая с позами и клипами, вы как правило, не уточняете, какие именно значения для
вращений многочисленных суставов установлены в конце одного клипа, а какие в конце другого.
Сейчас утка, закончив плыть, делает искусственное переходное движение лапами между
плаванием и бегом, а затем начинает бежать. Однако хотелось бы, чтобы утка начинала бежать
еще в воде, постепенно переходя от плавания к бегу. То есть хочется получит не переходный
взмах, а смешанное движение, включающее в себя и плавание и бег.
Для этого передвиньте второй клип под первый, расположив его «внахлест».
Установите для второго клипа в Attribute Editor значение Post Cycle=4 и сохраните сцену
как duckNLAClip3.ma
После того как вы удлинили второй клип, можете сделать область пересечения клипов
длиннее, переход по-прежнему будет работать.
Выбрать второй клип (это важно), нажать над ним правую кнопку мыши и выполнить Enable
Clip, сняв соответствующий флажок и заблокировав тем самым работу второго клипа.
Все правильно, ведь соответствующие каналы клипа имеют свойство absolute, то есть
каждый цикл выполняется независимо от предыдущего цикла.
Проведите эксперимент. Нажмите в Attribute Editor кнопку All Relative в разделе Channels
Offsets.
Теперь крыло утки не будет возвращаться назад при переходе от 25-го к 26-му кадру,
а будет начинать новый цикл из текущего положения. Казалось бы, что все неплохо, однако
прокрутите анимацию до пятисотого кадра и посмотрите на «распнутую» утку.
Так как положения крыльев не совпадали в первом и последнем кадре клипа, а каждый
цикл начинался с последнего положения, то постепенно накопилось смещение, обусловленное
этим несовпадением.
Если вашей первой мыслью будет исправить это несовпадение и поставить ключи так,
чтобы конец и начало клипа совпадали, то это не очень хорошая мысль. Чтобы движение было
по-настоящему зацикленным, нужно чтобы в последний кадр отличался от первого на «один шаг
цикла», иначе при зацикливании, будут возникать два одинаковых кадра, стоящих рядом, и это
будет давать небольшую паузу в движении, хорошо различимую глазом.
Если клип выбран, нажмите правую кнопку мыши над ним, и выполните переключение
Relative Clip, сняв флажок и сделав тем самым клип абсолютным.
Проверьте, что все каналы клипа в разделе Channels Offset стали абсолютными, и утка
теперь не растопыривает крылья.
А теперь нажмите правую кнопку мыши над клипом, и снова выполните переключение
Relative Clip, включив флажок и сделав тем самым клип «относительным». И сразу загляните
в Attribute Editor. Посмотрите в Channels Offset, где творится некоторая чехарда: все каналы
вращений остались абсолютными, а остальные каналы стали относительными. Это в понимании
MAYA называется «относительным» клипом.
Нажмите BAttribute Editor кнопку Restore Defaults (и не забудьте посмотреть, что произойдет
с каналами), чтобы вернуться к исходной ситуации.
Все, что нужно сделать - это выбрать клип и открыть Graph Editor.
Выберите первый клип и выполните в Trax Editor операцию View=>Graph Anim Curves
Это всего лишь откроет Graph Editor для выбранного клипа.
Пытливые умы могут тут же задаться вопросами если регулярный клип является копией
исходного, то чьи анимационные кривые мы видим в Graph Editor? Являются ли они копией других
кривых или существуют в одном экземпляре?
Ответ следующий - для каждого исходного клипа существует один экземпляр анимационных
кривых. Все регулярные клипы, созданные на основе этого исходного клипа, используют эти же
кривые, никаких копий кривых не создается.
Если вы сдвинете или сожмете (отредактировав Scale) регулярный clip1, то в Graph Editor
для него анимационные кривые также сдвинутся или сожмутся (надо только «обновить» Graph
Editor, выбрав что-нибудь, а затем снова выбрав clipl). В то же время анимационные кривые для
исходного клипа clipl Source останутся неизменными.
Однако, все это одни и те же анимационные кривые, просто для регулярных клипов они
показываются в Graph Editor с учетом положения и масштаба клипов, а для исходных клипов они
всегда отображаются в исходном масштабе и с нулевого кадра.
Если вы «испортили» c l i p l , верните его на место (Start Frame=1, Scale=1) и снова покажите
его анимационные кривые.
Выберите в левой панели Graph Editor каналы с именами типа shoulder, отвечающие за
движение крыла.
Очевидно, что крыло начинает двигаться с пятого кадра, вызывая некоторую паузу в начале
клипа. Отредактируем это.
Теперь утка шевелит крыльями без пауз. Повторюсь: начала и концы кривых для
зацикленного клипа не должны совпадать, иначе это вызовет паузу длиной в один кадр на границе
циклов.
Ничего не произошло. Однако если выбрать в Outliner персонаж Duck, вы увидите, что на
TimeLine появились исходные ключи для первого клипа. А клип стал сиреневым, что означает,
что его ключи временно «активизированы» и что после редактирования анимации надо не забыть
вернуть клип в нормальное состояние.
Занеся руку над клавишей «s», посмотрите в правую часть TimeLine. Похоже там, в поле
выбора текущего персонажа, стоит No Character Set.
Перед постановкой ключей на любые части тела, обязательно сделайте персонаж текущим!!
Иначе позднее вы можете очень сильно запутаться в ключах и позах.
Выберите клип и деактивизируйте ключи, выполнив снова Modify=> Activate /Deactivate Keys.
Убедитесь, что ключи не активизированы, то есть что клип имеет здоровый светло-синий
цвет и персонаж duck не имеет ключей на TimeLine.
Посмотрим, что будет, если мы начнем ставить ключи поверх клипа, не активируя ключи
Встаньте в первый кадр. Убедитесь, что на TimeLine текущим персонажем является duck.
Нажмите клавишу «s», ставя ключ на уже имеющуюся позу.
Если утка вдруг резко «улетела» из кадра, не пугайтесь: это «шутки» нелинейной анимации.
Просто сместитесь в любой кадр и вернитесь обратно в первый.
Встаньте в двадцать пятый кадр. И снова поставьте ключ клавишей «s».
Теперь встаньте в тринадцатый кадр.
Выберите сустав root и опустите утку немного вниз.
Поставьте ключ и проиграйте анимацию. Утка должна притонуть и всплыть в течение клипа.
Таким образом, вы создали еще один слой анимации, отвечающий за вертикальное движение
утки. Чтобы зациклить это движение и синхронизировать его с остальной анимацией, создадим из
этих трех ключей клип.
Выполните в Trax Editor операцию Create Clip. Для созданного клипа (clip2), установите
Post Cycle=2. Теперь утка циклически покачивается на волнах.
Выберите клип fly, и в Attribute Editor установите для лап Channel Offsets=Absolute.
MAYA преобразует все выбранные клипы в один большой клип. Вы можете работать с ним
любыми доступными методами. Например, сжать его, чтобы утка двигалась быстрее, зациклить
или разрезать.
Дело в том, что при помощи атрибута Scale вы меняете темп всего клипа целиком. Однако
иногда возникают ситуации, когда нужно «подрулить» скорость выполнения только части клипа.
Например, сделать скорость посадки на воду чуть помедленнее или сделать так, чтобы утка
плыла, постепенно ускоряясь. Конечно, если у вас есть исходные клипы, это можно сделать для
каждого из них поотдельности, но зачастую бывает так, что анимацию надо «подогнать» целиком
под некоторый заданный темп или соответствующему безумному, утреннему замыслу режиссера.
Еще одной очевидной задачей являет разворачивание анимации вспять.
Вес клипов
Пытливые умы конечно давно приметили в Attribute Editor атрибут Weight и соседний с
ним атрибут Weight Style. Эти атрибуты отвечают за «интенсивность», или «громкость» клипа.
Попробуйте, например, в последнем примере установить для клипа Weight=0.1, и вы увидите, что
утка станет шевелить конечностями в десять раз менее интенсивно.
Вы можете рассматривать клип как кубик, а атрибут Weight как высоту этого кубика, то есть
вертикальный размер его анимационных кривых. Уменьшая Weight вы «сжимаете» вертикально
анимационные кривые -то бишь уменьшаете «громкость» анимации. Атрибут Weight Style
определяет, где находится pivot такого «сжатия»: на минимуме анимационных кривых или в нуле
(вариант Absolute From Start означает, что относительно нуля сжимаются только «абсолютные»
каналы). Конечно, можно не только сжимать (глушить), но и растягивать клипы, получая эффекты
преувеличения анимации. (Вам наверняка понравится вариант Weight=0.1, Weight Style=From
Zero)
Поза выделена в Trax Editor как отдельный объект, однако вы можете рассматривать ее
как клип длиною в один кадр и работать с нею при помощи тех же самых инструментов. Одним из
применений именно поз может быть создание персонажа для атрибутов Blend Shapes и дальнейшее
выстраивание мимики в виде набора поз. Имейте в виду, что созданная поза появляется только в
Visor и ее надо вытаскивать оттуда в Trax Editor вручную.
Если вы импортируете в сцену звуковой файл, то сразу увидите его в Trax Editor. Сразу
скажу, что со звуковыми клипами в Trax Editor нельзя делать ничего вообще. Только двигать
вправо-влево. Как могут заметить пытливые умы, это даже не настоящие клипы, а просто ноды типа
audio, видимые в Trax Editor. При расположении звуковых клипов друг под другом, проигрываться
будет только верхний клип, его и можно услышать. Чтобы услышать другие звуковые клипы,
присутствующие в Trax Editor, надо обязательно включить в контекстном меню на TimeLine опцию
Use Trax Sounds. Кроме того, надо не забыть в общих установках для анимации установить Playback
Speed=Realtime.
Рано или поздно (лучше поздно) перед вами встанет задача переноса анимации с одного
персонажа на другого. Технически это делается обычно следующим образом: в сцене должны
быть два персонажа, и хотя бы на одном из них должна быть анимация в виде клипов. Вы
выбираете нужный клип с одного персонажа и выполняете в Trax Editor операцию Edit=>Copy.
Заглянув в Option Box команды Paste, вы можете увидеть несколько способов (Paste Method), с
помощью которых MAYA может «приделать» анимационные кривые от одного персонажа к другому.
В тех случаях, когда персонажи идентичны, вполне может подойти метод определения нужных
атрибутов по имени или по структуре иерархии. Однако, в тех случаях, когда нет уверенности
в том, что абсолютно все атрибуты двух персонажей имеют идентичные имена и совпадающие
С тех пор, как в MAYA появилось понятие Персонажа (Character Set), многие сетапщики и
аниматоры с большим энтузиазмом восприняли эту технологию и стали создавать эти Character
Set еще до стадии анимации, как бы «укомплектовывая» его по полной программе различными
«примочками». Но потом появились проблемы - на деле оказалось не все так радужно и красиво.
Тем не менее, эта технология заслуживает большого внимания. И зная подводные камни, можно
извлечь из нее много полезного.
Обратите внимание на то, что, начиная с версии 6.0, в MAYA был значительно изменен
механизм работы клипов и самого Trax Editor. Эти изменения настолько значительны, что некоторые
сцены, сделанные в версии MAYA 5.0 с использованием клипов, могут некорректно открываться в
старших версиях MAYA.
Клипы
Клип в MAYA - это, по сути, контейнер, содержащий какое-либо движение. Поза - это тоже
клип, только без движения. Аниматор может превратить обычные ключи в клип, и наоборот, клип
в ключи. Но помимо этого, в клипе есть дополнительные параметры, которые помогают аниматору
оперировать ими. Например, с какого кадра он будет воспроизводиться в сцене (Start Frame).
Также у него есть и другие, не менее важные, хотя, на первый взгляд, незаметные атрибуты.
Например, атрибуты Source Start и Source End, показывающие, с какого и по какой именно кадр
будет воспроизводиться анимация из анимационных кривых, содержащихся в клипе. Именно они
определяют базовую длину клипа.
При этом хочется обратить внимание на тот факт, что операция Merge изменяет исходные
анимационные кривые клипов. Появляются ключи в каждом кадре клипа, как и при операции Bake
Channel в Graph Editor. И в анимационных кривых, входящих в этот клип, имеются дополнительные
ключи в тех кадрах, где исходный клип был разрезан операцией Split. Эти ключи стоят рядом с
оригинальными ключами, повремени примерно на одну десятую долю секунды. Иногда имеет смысл
их «подчищать». Автоматически это можно сделать операцией Bake Simulation (Edit=>Keys=>Bake
Simulation), после того, как клип был активирован (меню Trax Editor: Modify => Activate /Deactivate
Keys).
Если клип удалить, после того как он был активирован, анимация никуда не пропадет,
она останется на персонаже. Character Set, который использовался для операций с клипами,
тоже можно удалить без потери анимации, если, конечно, в Trax Editor на нем нет больше других
клипов.
Absolute и Relative
В отличие от клипов, с которыми многие имели дело в программах для видеомонтажа,
в MAYA клипы содержат информацию о движении объектов в пространстве. И это значит, что
при склейке разных клипов могут появиться вопросы типа: как быть, если движение в клипах
происходило в разных местах сцены, а хочется, чтобы вместо однокадрового скачка, движение
органично продолжилось с последней позы первого клипа? Для этого в клип были введены
дополнительные параметры Absolute и Relative, которые частично помогают решить эту проблему.
Absolute - режим, при котором значение ключа внутри клипа трактуется как абсолютное, то есть
В MAYA 6.5 этот подход стал более продвинутым, в результате того, что разработчики
сделали возможным устанавливать этот параметр не только на весь клип, но и на каждый его
канал по отдельности. Теперь во многих случаях нет необходимости прибегать к Subcharacter Set,
чтобы более тонко регулировать эти правила для каналов. Для того, чтобы облегчить работу по
настройке этих параметров в разных, но однотипных клипах, в меню Тгах появилось функция Сору
Channel Offset, которая позволяет быстро скопировать установки первого выбранного клипа на все
последующие.
Blend
Начиная с версии MAYA6.0, значительно расширились возможности функции Blend, которая
стала позволять делать не только плавные переходы между концом и началом двух клипов, а
также микшировать их движения с нужным количеством кадров, просто подставляя их один под
другой. Это сделало Тгах Editor достаточно мощным редактором нелинейной анимации, и во многих
случаях уже нет такой острой необходимости прибегать к услугам других пакетов, таких как Motion
Builder. К сожалению, до сих пор в MAYA нет штатного инструмента для автоматической подгонки
двух аналогичных поз из разных клипов, перед тем, как сделать Blend между ними. Частично эту
проблему могут решить инструмент Redirect, технология Motion Wrap, а также собственноручно
написанные скрипты.
Например, стало очень просто создавать цикл походки на основе данных Motion Capture.
Для этого нужно поместить анимацию походки в клип, выбрать ключевую позу, с которой будет
начинаться и заканчиваться цикл, но так, чтобы в походке она появлялась хотя бы три раза, то
есть персонаж сделал бы четыре шага. Можно и больше, если позволяют записанные данные.
Основная идея - сделать линейный Blend в течение двух шагов так, чтобы в начале и в конце этого
мы «пришли» к одной и той же позе.
Подрежем в первый клип так, чтобы в нем остались третий и четвертый шаг, а в другом - первый
и второй шаги (Edit=>Trim Before и Trim After).
Подставим в Тгах Editor один клип под другой и, выделив оба клипа, сделаем Blend (Edit=>Blend).
Очень важно, чтобы Blend был линейным. Если он будет другого типа, то персонаж «поплывет», то
есть его таз не будет стабилизирован относительно одной точки, как на беговой дорожке. Также
важно, чтобы все каналы нижнего клипа были в режиме Absolute.
Для этого нужно выделить клип, зайти в Attribute Editor и в закладке Channel Offset нажать
кнопку All Absolute. Если все сделано правильно, мы получим зацикленное движение. Если у вас
получатся какие-либо скачки в позах, при возращении в первый кадр, значит, вы где-то ошиблись
в кадрах при подрезании клипов. Чтобы проверить это, убедитесь, что цифры в верхнем левом
углу верхнего клипа и в верхнем правом углу нижнего клипа совпадают.
Для того, чтобы персонаж не проскальзывал на одном месте, а двигался вперед, можно
использовать технологию Motion Wrap.
Основное применение эта технология находит во время правки данных с Motion Capture,
микшировании клипов (например, для создания циклов походки), а также при создании новых
вариантов ранее анимированного движения. Полученную анимацию можно также превратить в клип
и получить новое движение. Клипы, расположенные в Trax Editor один под другим, автоматически
складываются в режиме Add.
Кстати, необязательно редактировать все сразу: эти клипы можно создавать для разных
частей персонажа или делать их по смыслу, как разные дубли, чтобы при показе режиссеру можно
было быстро выбрать самый лучший вариант.
Основное правило при создании Motion Wrap анимации - это предварительно поставить два
ключа: в кадре, с которого начинается правка, и там, где она заканчивается. Главное - чтобы в
этих кадрах позы персонажа устраивали аниматора. Если все было сделано правильно, значения
этих ключей должны быть нулевыми, если, конечно, вы не преследуете других целей, таких,
как общее смещение анимации (offset) . Тангенсы этих крайних ключей лучше делать типа Flat,
чтобы Motion Wrap был незаметен для зрителя. Далее аниматор ставит ключи в нужных кадрах,
поправляя позы персонажа, там, где считает это целесообразным.
В этом случае нужно быть внимательным, чтобы во время работы с Motion Wrap режим
Auto Key не был включен, то есть все изменения в позах вы должны подтверждать («ключевать»)
стандартным образом, нажимая клавишу «s» (Set Key).
Time Warp
Те, кто работал в программах для композитинга, часто пользуются функцией Time Remap
ping, чтобы нелинейно управлять скоростью воспроизведения видеоклипов. Очень здорово, что
для клипов в MAYA имеются такие же возможности, только под названием Time Warp. Для клипа
создается дополнительная кривая, которая показывает, в процентном соотношении к общей длине
клипа, какой именно кадр этого клипа должен быть воспроизведен. При включении этого режима
изначально кривая в Graph Editor представляет собой линейный график (два ключа от 0 до 100
по двум осям). Далее аниматор, редактируя ее, может по своему усмотрению изменять скорость
воспроизведения на различных участках клипа. Только будьте внимательны: пересчет позы
персонажа не интерактивен, то есть после очередной правки Time Warp кривой, нужно подвигать
мышью по Time Line, чтобы проанализировать происходящее. Конечно, это не всегда удобно и
не интерактивно. Но самое интересное то, что такую кривую необязательно создавать в MAYA, a
можно импортировать из программы композитинга, например из программы After Effects .
Проверьте это следующим образом. Поставьте значение атрибута клипа Source End на много
больше, чем там было, и проиграйте анимацию. Если все сделано правильно, при прохождении
кадра, где раньше клип заканчивался, не должно быть никаких скачков. Если таковые имеются,
значит это неправильный цикл. Также для «чистоты» воспроизведения желательно сделать всем
кривым вращения операцию Euler Filter, чтобы при попадании в межкадровое пространство не
было никаких «глюков» с вращением.
Еще одно условие - персонаж должен «шевелиться» на одном месте. И у него должен
иметься такой локатор (или группа), двигая который, мы могли бы передвигать его по сцене.
На этом локаторе создадим дополнительный атрибут (тип Float) для управления фазой
движения цикла.
Свяжем его (в Connection Editor ) с атрибутами клипа - Source Start и Source End. В этот
момент клип в Trax Editor должен сократиться до одного кадра. Это нормально, за исключением
того, что теперь стало трудней искать его там и выделять.
Проверим работу нового атрибута (кстати, я его назвал phase), изменяя его значения -
персонаж должен зашевелиться.
Теперь добавим на контрольный локатор еще один атрибут (path, тоже типа Float) для
преобразования пройденного расстояния персонажем в текущую фазу цикла. Преобразование
можно делать простым выражением (expression) типа: phase = path / 1.15. Можете также
использовать Set Driven Key, особенно если эта зависимость нелинейная.
Данную технику можно использовать также для анимации толпы. Мой коллега, программист
Дмитрий Робустов, для нужд нашей студии написал плагин, который, используя фазы клипа
персонажа, меняет позу персонажа уже во время рендеринга в RenderMan. Это позволяет
существенно оптимизировать процесс передачи данных на рендер и ускорить сам процесс просчета
толпы. Но замечу: это только один из многочисленных вариантов технологий анимации толпы. Как
правило, в каждой студии, он чем-то отличается от других.
Для того, чтобы «помочь» пользователям в таких ситуациях корректно перенести клип
на Character Set, в MAYA существует несколько режимов вставки клипов: по имени атрибута, по
порядку, по имени ноды и «карте» (Character Map) персонажа. Последний режим разработан
специально для тех случаев, когда названия атрибутов, между которыми происходит копирование
анимации, различны. То есть теоретически можно обмениваться анимацией между персонажами
разного типа. Недостаток этого режима - необходимость создавать так называемую «карту»,
в которой просто расписаны соответствия между атрибутами двух персонажей. Что-то типа:
«человек.левая_рука -> птица.левое_крыло» (пишу на русском, чтобы было понятнее).
Для персонажей, у которых таких атрибутов (каналов) может быть больше сотни,
составление подобной карты может превратиться в рутину. Остальные режимы вставки клипа на
Character Set в вышеописанных ситуациях дают «сбои».
Для того, чтобы помочь себе и каждый раз не мучиться с подобными проблемами, я стал
создавать, помимо персонажа, еще и Quick Select Set, куда входили все объекты, участвующие в
анимации. И перед тем, как создавать Character Set, я выделял эти объекты в алфавитном порядке
с помощью написанного скрипта, пользуясь информацией ранее созданного Quick Select Set. Дело
в том, что стандартный способ выделения, вызываемый из меню Edit=>Quick Select Sets, дает
разный порядок выделения в разных сценах, и это также создает проблему с переносом клипов.
Переменная SquickSelectSet содержит имя нужного Quick Select Set. A MEL-команда sort
производит сортировку объектов этого сета в алфавитном порядке. После того, как ваши Character
Sets будут созданы по этой схеме, вы можете переносить клипы в режиме «по порядку атрибутов»
(By Attribute Order) в окне Paste Clip Options (меню Trax Editor, Edit=>Paste). Единственное, чего
не может предусмотреть этот способ, так это изменений в самом Quick Select Set или в атрибутах
объектов, входящих в него.
Для начала мы просто сделаем операцию Merge в Trax Editor, выделив два нужных клипа.
Затем вызовем меню правой кнопкой мыши на полученном клипе, активируем его ключи, выбрав
В ранних версиях MAYA можно было делать операцию Merge только для участка с переходом
между клипами, созданного операцией Blend. К сожалению, теперь этот фокус не проходит, а
после операции Merge оригинальные ключи в полученном клипе «засоряются» дополнительными,
как после операции Bake Channel.
Как вариант, можно активировать ключи клипа с движением, и после этого поставить в
позу персонаж в нужном кадре, используя возможности окна Visor, вызвать меню правой кнопкой
мыши на позе - Apply Pose. Когда персонаж встанет в эту позу, ее можно «закрепить» ключами и
проделать операцию Euler Filter. Есть и другие способы, поэтому каждый из вас может найти свой
путь, «субъективно оптимальный» в каждом конкретном случае.
Кроме того, к непрямому скинингу можно отнести механизм Influence Objects (или, как
говорят майщики, «инфлюенсы», то есть влияющие объекты). Когда, в дополнение к скинингу,
на поверхность модели могут также влиять своей формой дополнительные объекты. Именно так
делаются мышечные деформации. К этому мы еще вернемся. А сейчас, чтобы «потрогать руками»
скининг, сделайте простое упражнение.
Создание скининга
Откройте файл skinLeg.ma. В нем содержится часть тела и кусочек скелета.
Выберите поверхность и верхний сустав Leg.
Выполните Skin=>Bind Skin=>Smooth Bind.
Выберите группу LGroup (для этого есть специальный «хендл») и пошевелите ногой. Как
видите, нога гнется с помощью костей (можете также выбирать подгруппы внутри LGroup и вращать
соответствующие части ноги).
Для корректировки этих проблем существует множество «подпорок» типа флексоров (Flex
ors) и разных ухищрений. Конечно, веса вершин, на которые влияет та или иная кость, можно
редактировать и сами вершины можно переносить «от одной кости к другой» с помощью Edit Mem
bership Tool, однако тот факт, что каждая вершина может находиться под влиянием только одной
кости, является самым существенным ограничением технологии Rigid Bind. Возможно этот метод
может быть эффективен в том случае, когда к костям привязывают не поверхности, а решетки
Lattice, так как редактирование весов небольшого количества вершин решетки не будет сложной
задачей. Однако на этой оптимистической ноте я и закончу с методом Rigid Bind.
Разумно предположить, что чем дальше кость от данной вершины, тем меньше эта кость на
нее влияет. Разумно также предположить, что рассчитывать влияние всех костей на все вершины
довольно долго, поэтому проще ограничить число костей, одновременно влияющих на каждую
вершину некоторым числом: например, 5.
Обратите внимание на то, что веса остальных костей, хотя и маленькие, но ненулевые,
то есть существует влияние пяточной кости на место сгиба под коленкой! Это побочный эффект
«интеллектуальности» метода Smooth Bind. Конечно, при выполнении операции Smooth Bind
можно подобрать параметр Dropoff Rate, влияющий на то, как далеко может влиять кость на
близлежащие вершины, однако застраховаться от появления маленьких весов (влияния пятки на
колено) заранее невозможно. Для «вычищения» таких маленьких зловредных весов была даже
придумана специальная операция Skin=>Edit Smooth Skin=>Prune Small Weights (prune=урезать),
удаляющая все веса меньше указанного в Option Box со всех вершин поверхности (или только с
выбранных вершин).
Примечание. Как вы уже заметили, в этом разделе я все время говорю «кости»
и очень редко «суставы». Дело в том, что в процессе привязки принимаются во
внимание именно «кости», то есть прямые линии между соседними суставами.
Расстояние до вершин рассчитывается до ближайшей кости (линии), а не до
ближайшего сустава (точки). Помните, однако, что с точки зрения объектов в
сцене «кости» и «суставы» - одно и то же. Я также буду все время перемешивать
термины «привязка», «привязывать» и «скининг», «прискинить». Все это одно и
то же.
Параметр Bind Method вам вряд ли придется когда-нибудь менять. Значение по умолчанию
Closest In Hierarchy задает, что в процессе привязки будет учитываться положение каждой кости
в иерархии скелета. К примеру, несмотря на то, что кость левой пятки расположена очень близко
к поверхности правой пятки, она не будет влиять на нее после привязки, так как находится очень
далеко в иерархии скелета от кости правой пятки, которая является ближайшей к поверхности
правой пятки. Аналогично, если рука в момент привязки окажется около бедра, кости руки не
будут влиять на бедро, так как в иерархии скелета они находятся далеко от костей бедра. Значение
Closest Distance определяет игнорирование иерархии скелета и задает привязку только на основе
пространственной близости костей к вершинам.
Поэкспериментируйте с параметром Dropoff Rate. Задайте его равным 0.1 и нажмите Apply. Теперь
выберите несколько вершин под коленом и откройте Component Editor.
Очевидно, что при маленьком Dropoff Rate (степени затухания) влияние каждой кости
слабо убывает по мере удаления от этой кости, поэтому веса костей распространяются среди
точек довольно равномерно и на каждую точку влияют одновременно пять костей. Для ноги это
довольно плохая ситуация, в чем можно убедиться, попытавшись согнуть ногу.
Опция Keep History может быть полезна, если вы хотите отвязать кости, не удаляя,
однако, информацию о весах (еще точнее, не удаляя ноду skinCluster). Это имеет смысл, когда вы
хотите добавить пару костей с скелету и привязать его обратно к поверхности с сохранением уже
настроенных весов.
Теперь, очевидно, только две ближайшие кости влияют на выбранные вершины. Веса
остальных костей равны нулю, так как мы задали высокую степень затухания влияния в завимости
от расстояния между вершиной и костью.
В случае ноги этот вариант явно предпочтительнее, кроме того форма сгиба стала более
«резкой», поэтому имеет смысл увеличивать Dropoff Rate для «острогнущихся» конечностей.
Кроме того, очевидно, что в большинстве случаев хватит влияния только двух костей
на ближайшие точки, а остальные кости могут только вносить путаницу. Поэтому имеет смысл
задавать в Option Box значение Max lnfluences=2. Если понадобится, позже вы можете добавить
влияние дополнительных костей на нужные участки поверхности, редактируя скининг. Для этого
надо либо заранее выключить галку Maintain Max Influences в Option Box, либо позже снять ее
в Attribute Editor для ноды skinCluster, чтобы MAYA не пыталась ограничивать влияние только
фиксированным количеством костей.
Педантичные умы могут отвязать кости и, задав Max lnfluences=2, привязать их обратно, а
далее убедиться, что на любые вершины влияют только две кости.
Нормализация весов
Как хорошо видно в Component Editor в колонке Total, MAYA удерживает равным единице
суммарный вес костей, влияющих на каждую вершину. Если вы вручную (или в результате раскраски
весов) увеличите для какой-нибудь вершины вес одной кости, веса остальных автоматически
уменьшатся (в соответствии с расстоянием до этих костей).
// To disable IK, constraints, and expressions, you can use the Modify->DisableNodes menu.
Во-первых, это «ручная сборка», то есть Component Editor, где вы можете бодро вбивать
значения весов в клеточки для костей.
Ну, и, наконец, в-четвертых, это инструмент Paint Skin Weights Tool, позволяющих красить
поверхность модели весами выбранных костей. О нем и пойдет речь сейчас.
Я думаю, многие аналитические умы, едва речь пошла о весах, сразу задумались о
возможности рисовать этими весами вдоль поверхности. Действительно инструмент Paint Skin
Weights Tool подобен всем остальным «рисовальным» инструментам. Его отличительная особенность
- необходимость сначала указать кость, а затем рисовать карту влияния именно этой кости.
Итак, откройте все же уже поднадоевший вам файл skinL.eg.ma и привяжите поверхность
к скелету со следующими параметрами: Maxlnfluences=2, Dropoff Rate=5, Maintain Max
lnfluences=On.
Согните ногу в колене. Так как мы задали довольно высокий Dropoff Rate, то граница
влияния соседних костей довольно «резкая» под коленкой.
He забудьте открыть Tool Settings для этого инструмента и нажать в нем кнопку Reset Tool.
В разделе Influence находится список костей, влияющих на выбранную поверхность. Щелкая по
названиям костей, вы можете видеть области их влияния.
Чтобы немного примять верхнюю часть икры, мы не будем уменьшать влияние кости Left_
Knee, а будем увеличивать влияние вышестоящей кости LeftJHip.
Если вы хотите уменьшать текущее значение веса, задавайте Paint Operation=Scale, a Val-
ue=0.95. Если нужно совсем избавиться от влияния кости на некоторый участок (это часто случается
в области подмышек), то следует установить Paint Operation=Replace, Value=0 и покрасить этот
участок в черный цвет.
Как было указано выше, MAYA постоянно нормализует веса (приводит суммарный вес к
единице). Поэтому выбрав кость влияния и крася участок поверхности, вы должны понимать, что
черно-белая карта для другой кости в этот момент тоже изменяется и что этот процесс происходит
вслепую (вы ведь можете только догадываться, как он меняется).
Иногда бывает нужно «заморозить» или зафиксировать раскраску весов для выбранной
кости. Для этого предназначена кнопка Toggle Hold Weights On Selected. Нажав ее, вы гарантируете,
что черно-белая карта весов для выбранной кости не будет изменяться при покраске областей
влияния соседних костей.
Фиксируя карту влияния какой-нибудь кости с помощью кнопки Toggle Hold Weights On
Selected, следует, однако, помнить, что тем самым вы накладываете ограничение на изменение
области влияния для других костей. Если на раскрашиваемую область влияют три кости, то
заморозив карту весов для одной из них, вы будете перераспределять веса между оставшимися
двумя.
В нашем случае, когда на область в районе колена влияют только две кости, фиксирование
карты для одной из них ведет к автоматической блокировке изменения карты другой.
В самом деле, выберите в списке Influence кость Left_Hip и нажмите кнопку Hold Weights
On Selected.
Теперь выберите в списке кость Left_Knee и попробуйте покрасить белым цветом (Paint
Operation=Replace, a Value=1) область выше колена.
Вы, однако, можете без проблем красить в данном случае область в районе ахиллесова
сустава. Там веса распределяются между костями Left_Knee и Left_Ankle.
Совет. Часто бывает удобнее прямо на экране, а не в списке выбрать кости, чье
влияние хочется покрасить. Для этого надо просто нажать над нужной костью
правую кнопку мыши и выбрать в контекстном меню Paint Weights.
Идея следующая: вы берете поверхность, кривую или локатор и назначаете ее как объект
влияния («инфлюенс») для уже прискиненной поверхности. После этого все перемещения и даже
деформации объекта влияния будут влиять на модель. Внешне это ничем не отличается от Wrap
Deformer, с тем исключением, что после этого можно красить веса влияния не только костей, но и
назначенного объекта влияния.
Выбрав сферу, выберите также сустав LeftJHip и выполните операцию Edit=>Parent, чтобы
сфера «прикрепилась» к бедру и двигалась вместе с ним.
Выберите в окошке Set Driven Key ноду blendShapel и установите в Attribute Editor для нее
Muscle1=1.
Выберите поверхность ноги, а затем мышцу (порядок важен) и откройте Option Box операции
Skin=>Edit Smooth Skin=>Add Influence.
Галка Use Geometry по умолчанию включена и означает, что добавляемая к скинингу мышца
будет влиять на поверхность ноги не только своими трансформациями, но и деформациями, то
есть изменениями формы.
Опция Lock Weight может быть полезна в том случае, если вы долго мучились с настройкой
скининга и теперь не хотите потерять тщательно нарисованные области влияния всех костей. Надо
понимать, что добавляя объект влияния, мы «втискиваем» его в уже имеющееся распределение
весов. Если нажать галку Lock Weights, то новый инфлюенс будет добавлен с нулевым влиянием, и
его веса будут заморожены, до тех пор пока вы не отожмете кнопку Toggle Hold Weights On Selected
в инструменте Paint Skin Weights Tool.
Сфера добавилась как объект влияния, в чем можно убедиться, выбрав ее и обнаружив у
Однако никакого влияния она, похоже, не оказывает. Впрочем, если сферу немного
помасштабировать, станет ясно, что влияние все-таки есть, но только вследствие трансформаций
- а вот деформации, вызванные сгибанием ноги, не оказывают никакого влияния. В чем же дело,
ведь мы специально оставили галку Use Geometry включенной?!
Оказывается, надо включить еще одну, секретную галку.
Разыщите в Attribute Editor закладку skinClusterl и включите там опцию Use Components.
После этого все объекты влияния будут передавать поверхности также свои деформации.
Кроме того, объекты влияния могут быть использованы не только для «вспучивания»
поверхности в нужных местах. Используя кривые как инфлюенсы, вы можете делать складки кожи
или подобие крупных морщин.
Для этих целей существует специальная операция Skin=>Edit Smooth Skin=>Mirror Skin
Weights. Она позволяет скопировать веса вершин с одной стороны поверхности на другую. Если
«кожа» персонажа состоит из нескольких поверхностей, копирование может быть произведено
с одной поверхности на другую, надо их выбрать в нужном порядке. Можно также симметрично
скопировать веса только выбранных вершин.
Следует понимать, что зеркальное копирование весов производится без всякого анализа
топологии поверхности: MAYA просто ищет в пространстве точки, симметричные относительно
выбранной в Option Box плоскости, и копирует их веса в выбранном направлении. Однако анализ
топологии скелета все же производится. Поэтому перед зеркальным копированием вы должны
позаботиться о том, чтобы ваш персонаж находился в симметричной позе и чтобы его скелет тоже
был симметричен относительно нужных плоскостей.
Но если можно скопировать веса с одной части персонажа на другую, то можно и копировать
их между персонажами. Для этого есть операция Skin=>Edit Smooth Skin=> Copy Skin Weights.
Очевидно, что эта операция будет хорошо работать только для весьма похожих персонажей.
Копирование весов позволяет экономить массу времени при настройке скининга. Многие
энтузиасты и технические директора пишут собственные скрипты для копирования, перемещения,
сохранения и восстановления весов вершин.
Настройка скининга дело еще более индивидуальное. Кому-то нравятся объекты влияния,
кто-то предпочитает Sculp Deformer для мышц, а кто-то все делает с помощью tweaks и Blend
Shapes.
Вокруг тролля расставлены пять хэндлов (один напротив пуза), чтобы удобнее было
выбирать нужные кости для тестирования скининга. Так как вся кинематическая «обвязка» с
тролля снята, гнуть его следует с помощью прямой кинематики, то есть вращая кости.
Погните тролля за руки (или за лапы?). Обратите внимание, что к костям прикреплены все
пять поверхностей из группы geometry.
В районе бицепсов находятся инфлюенсы - сферы, размер которых меняется через Set
Driven Key в зависимости от сгиба в локтях.
В пузе также находится сфера в качестве инфлюенса, она удерживает форму пуза при
сгибах в позвоночнике.
Вопрос о том, как крепятся кольца на груди и спине, не касается скинига, поэтому вы
можете исследовать его самостоятельно, это довольно остроумное решение.
Выберите поверхность тела (body_osnova) и выполните операцию Export Skin Weights. MAYA
попросит вас ввести имя нового файла. Задайте, например, skinBody и нажмите кнопку Export.
Появится предупреждение о том, что на диск будут записаны 99 текстур. Лучше будет
согласиться, после чего все эти текстуры довольно неторопливо запишутся на диск.
Теперь вы можете выбрать поверхность тела и выполнить операцию Reset Weights to De
fault, чтобы вернуться к скинингу по умолчанию. Это займет некоторое время.
Повращайте плечи и убедитесь, что скининг «сильно изменился». После этого попробуйте
с помощью инструмента Paint Skin Weights Tool настроить веса. В какой-то момент вам наверняка
захочется взглянуть на оригинальные веса. Вы можете это сделать, импортировав их обратно.
Если вы решите полностью отодрать персонаж от скелета, в Option Box операции Detach
Skin выберите опцию Bake History, чтобы оставить все поверхности в текущем положении. Не
забудьте перед этим встать в Bind Pose и выбрать все поверхности из группы geometry.
2. Тогда, для того, чтобы привязать модель к костям, вы можете выделять кости через
меню Edit => Quick Select Set => bindSet, а затем выбирать поверхность. При этом в окне Option Box
для операции Smooth Bind нужно установить значение Bind to=Selected Joints. Как следствие, нет
необходимости включать параметр Remove Unused Influences. К тому же, из-за того, что некоторые
3. Не спешите раскрашивать веса костей после того, как вы совершили привязку операцией
Smooth Bind. На данном этапе имеет смысл сделать несколько тестов, которые вам ответят на
вопросы о том, правильно ли расставлены позиции суставов, и оптимальны ли были параметры
операции Smooth Bind. Ведь от того, насколько хорошо они были изначально подобраны для
вашей модели, в дальнейшем зависит количество часов, проведенных вами перед компьютером.
В своей работе я за основу тестов, как правило, беру пальцы рук персонажа, потому что их кости
самые маленькие. И подгоняя значение параметра Dropoff Rate (в окне Smooth Bind Options), я
смотрю, как при сгибании этих костей между ними распределяются веса. Чем меньше значение
Dropoff Rate, тем шире зона совместного влияния соседних костей, и в результате - неправильный
сгиб поверхности. Практика показывает, что проще изначально сделать границы влияния костей
контрастными (с помощью большого Dropoff Rate), а потом, если необходимо, сделать операцию
Smooth в Paint Skin Weights Tool. To же самое касается параметра Max Influences, которому для
базовой привязки, как правило, лучше давать значение 2, чтобы в области суставов смешивались
веса только двух костей. Более сложные взаимодействия костей (от трех и выше) лучше делать
вручную, раскрашивая их в Paint Skin Weights Tool. Исключением могут быть персонажи с длинными
цепочками костей, такие, как змеи, рыбы и другие твари с длинными шеями и хвостами.
5. Если в процессе скининга, у вас появится необходимость добавить еще одну кость,
используйте операцию Skin=>Edit Smooth Skin=>Add Influence. В окне Option Box для операции Add
Influence выставьте Use Geometry=Off, Lock Weights = On, a Default Weight = 0. Это необходимо
для того, чтобы веса других костей не пострадали после добавления новой кости. Тоже самое
касается геометрического «инфлюенса», только в этом случае нужно включить опцию Use Geome
try. Параметр Dropoff и Polygon Smoothness можно настраивать после того, как вы добавили объект
в скин-деформер. Для того, чтобы после такого добавления начать редактировать скининг, нужно
вызвать Paint Skin Weights Tool и в списке костей найти добавленную кость или инфлюенс-объект
(как правило, если список отсортирован по принципу «By Hierarchy», этот объект будет в конце
списка и в конце его имени будет в скобках пометка Hold). Затем, выделив его в списке, нажать на
кнопку Toggle Hold Weights On Selected, находящуюся под списком костей. Это снимет блокировку
весов выбранной кости или объекта, и можно будет их редактировать. Будьте внимательны, когда
вы добавляете геометрический инфлюенс-объект, не забудьте включить параметр Use Components
в атрибутах скин-деформера (skinCluster). Если он будет выключен, то, как бы вы ни «колбасили»
форму инфлюенс-объекта, вы не увидите никакой реакции со стороны деформера. Деформер
будет реагировать только на трансформации инфлюенса.
6. Как правило, после того как вы уже имеете прискиненную поверхность, нужно
отредактировать веса костей и, может быть, инфлюенса. И это можно сделать не только в Paint
Skin Weights Tool. Если выделить кость, участвующую в скининге, и открыть Attribute Editor, то там
можно увидеть внизу новую закладку Smooth Skin Parameters.
7. А для того, чтобы добавить в скининг не одну, а сразу несколько костей, я использую
другой способ. Хитрость этого метода в том, что он использует одну уникальную способность
скин-деформера - временно отключаться, оставаясь при этом в истории объекта. Для этого все
новые кости надо добавить в наш ранее созданный bindSet. Затем надо выбрать прискиненную
поверхность и выполнить Skin=>Detach Skin с параметром History = Keep History (для того, чтобы
не потерять скин-деформер (skinCluster) с уже отредактироваными весами - это тот самый,
волшебный параметр, котрый был заявлен еще в документации к MAYA версии 4.5, а заработал
лишь в версии 5.0). Затем выбираем Edit=>Quick Select Sets=>bindSet, поверхность и Skin=>Bind
Skin=>Smooth Bind, с тем же параметром Bind to=Selected Joints. Тогда мы получим поверхность,
которая будет прискинена и к «старым» и «новым» костям. Причем новые кости «приедут» в наш
скининг с нулевыми весами, а веса «старых» костей не пострадают после этой операции.
8. Для того, чтобы было удобно настраивать веса скининга и одновременно тестировать
его, рекомендую использовать следующий прием. Поставьте ключи в нулевом кадре на все ваши
контрольные объекты, управляющие персонажем, и тем самым зафиксируейте базовую позу
персонажа. В последующих кадрах вы выставляете своего персонажа в другие позы, при которых
удобно проверять работу скининга, например, когда согнуты рука и нога, повернуты голова и шея.
И в процессе рисования весов вы просто двигаете мышью по Timeline между ключевыми позами,
не выходя из инструмента Paint Skin Weights Tool. Попробуйте, это действительно удобно!
10. Для чего нужны режимы Add и Scale при редактировании весов в Paint Skin Weights Tool?
Add прибавляет данное значение (Value) к имеющемуся весу выбранной кости, a Scale умножает
на него. Внимательные умы могут заметить, что, добавляя и умножая вес, можно легко выйти за
единичный или нулевой (максимальный и минимальный) диапазоны. Но так как есть параметр-
ограничитель Min/Max Value, можно не боятся этого и использовать эти режимы совместно с
режимом Replace. Есть случай, когда имеет смысл на время выйти из нормального (от 0 до 1)
диапазона. Правда, это уже относится к cluster-деформеру. Бывают в практике случаи, когда нужно
инвертировать вес кластера, то есть то, что было 0, превратить в 1, а то, что было 1 - в 0. В этом
случае можно обойтись средствами Paint Attributes Tool. Для начала мы установим значения Min
Value=-1 и Value= - 1 , выставим режим Scale и нажмем кнопку Flood. Эта операция умножит все веса
кластера на - 1 . Не пугайтесь того, что поверхность стала вся черной, это не от того, что все веса
обнулились, а от того, что они перешли в диапазон от -1 до 0. Вторичное нажатие на Flood может
вернуть веса в исходное значение. (А для пытливых умов в закладке Display имеется возможность
Error: Skin on jointX was bound at a different pose. Go to the bindPose to attach new skins.
Эта операция невозможна, потому что скелет должен находиться в той же позе, что при
предыдущей привязке. Дело в том, что MAYA во время операции Smooth Bind создает ноду bind
Pose для того, чтобы запомнить и сохранить позу привязки (Bind Pose), и в дальнейшем, при
повторении операции привязки, она проверяет текущую позу на соответствие уже запомненной.
Поэтому необходимо возвратить скелет в уже существующую позу для привязки. Если у вас не
была сохранена эта поза (в виде ключей на управляющих объектах или в виде позы в Visor), можно
воспользоваться командой Skin=>Go to Bind Pose. Но иногда MAYA «упирается» и отказывается это
сделать! Я не буду останавливаться на вопросе «почему?», а лучше расскажу, как поступить в этом
случае. Есть в MAYA MEL-команда dagPose, которая поможет нам сделать «reset» bind-позы, то есть
сделать Bind Pose из текущей позы. В некоторых случаях это даже нужно делать. Например, когда
вы привязываете тело к скелету в позе «звезды» (так лучше делать для облегчения настроек всех
сгибов), а обувь в позе, когда ноги стоят на «земле», носками вперед. Перед тем, как запустить
команду, нужно выбрать все те кости, для которых она будет выполняться. А вот, собственно, ее
формат:
Обратите внимание на то, что имя bindPose-ноды (в конце команды) может меняться: bindPose2,
bindPose3 и т.д. Это происходит потому, что MAYA создает новую bindPose-ноду всякий раз, когда
вы привязываете геометрию к разным скелетным «цепочкам», или в случае изменения в уже
существующей цепочке, например, при добавлении новых костей в имеющийся скелет.
В этом примере вращение двух костей aim_joint и twist J o i n t будет согласовано с вращением
Для того, чтобы повернуть кость aim_joint без учета twist-вращения, так чтобы ее
направление совпало с направлением кости b a l l j o i n t , мы воспользуемся Aim Constraint. В качестве
«цели» выступит сустав targetjoint.
Итак, выделяем targetjoint и aim_joint и вызываем Option Box операции Constraints=> Aim
из раздела Animation.
Так как у нас кости были построены вдоль оси Y, в параметрах указываем Aim Vector = 0, 1,
О и Up Vector = 0, 0, 1. Если вы ошиблись со значениями параметров при создании Constraint - не
страшно, их можно всегда исправить после, с помощью Attribute Editor.
Переключите порядок вращения в кости t w i s t j o i n t с XYZ на XZY, если хотите, чтобы twist-
угол рассчитывался в «человеческих» единицах (в диапазоне от -180 до 180 градусов). Порядок
вращения нужно выбирать таким, чтобы ось, по которой, собственно, будет происходить вращение,
Например, для MAYA, угол по оси Y, равный значению 272 и 88 - одно и тоже, только вот
первая цифра, уж поверьте, никак не понравится ни одному сетапщику в мире. Если не изменить
порядок вращения кости, при переходе через значение -90 градусов, может возникнуть «щелчок» в
прискиненной геометрии, если этот угол был использован в сетапе для вычисления twist-поворота
и последующих деформаций.
Неизбежны щелчки только при повороте более 180 градусов. Но на это можно не обращать
внимание, так как у нас нет ни одного сустава, который бы вращался столь сильно.
Посмотрите на рисунки. Как видите, даже цифры при сложении поворотов двух костей
отличаются от значений исходной ball j o i n t . Хотя ориентация конечных костей идентична! Можете
легко проверить это, прицепив в первом кадре к balLjoint и twist_joint два одинаковых куба и
проиграв анимацию.
В заключение хочется добавить, что для разделения сложных вращений можно, при
желании, воспользоваться вместо Aim и Orient Constraint работой ikSCsolver. Пытливые умы в
качестве разминки могут проделать эту работу сами.
Анимация 861
MEL
или MAYA Embedded Language
Заранее предупреждаю: эстетствующие умы, имеющие аллергию на слова
«программирование» и «скрипты», могут с отвращением и ужасом пропустить эту главу без ущерба
для дальнейшего чтения. В последующих главах я не буду злоупотреблять многостраничными
скриптами, отсылая читателя к этой главе. Так что решение спрятаться от MEL лежит целиком на
вашей личной совести. Могу сказать лишь одно: если избегать MEL во всех его проявлениях, то
рано или поздно это скажется на производительности и эффективности вашей работы. Кроме того
вы лишаете себя возможности небрежно блеснуть перед коллегами модной фразой типа «я это
делаю полностью процедурно, с помощью MEL».
В принципе, можно обходиться без знания и использования MEL в своей работе, особенно
если ваши служебные или домашние обязанности сводятся к выдаче двух минут анимации в день
или моделированию заданного количества элементов интерьера. Но подумайте о том, что рано
или поздно вам это сильно надоест, и в этот момент знание MEL может вам сильно пригодиться в
поиске новой работы или смене характера 3D-деятельности.
Во-первых, для этого есть специальные, неплохие книжки (например, «MAYA: полное
руководство по программированию» Дэвида Гоулда; текст там дельный, перевод - на совести
издательства).
В-третьих, я просто собираюсь порассуждать здесь на тему о том, как бы я (или кто-то
другой, более скромный) осваивал язык MEL, только-только познакомившись с MAYA. На примере
таких рассуждений я намереваюсь описать логику использования и основные правила работы с
MEL, но уж никак не полный синтаксис этого языка и все существующие в нем функции.
Боюсь, правда, что вам не удастся использовать эту главу как справочное пособие по MEL.
Ее можно лишь прочитать с начала до конца (опуская наиболее жуткие, не лезущие в голову вещи)
и попытаться вникнуть в суть использования MEL. Ведь, как вы сами знаете, наилучшее справочное
пособие - в документации.
Во-первых, вся интерфейсная часть MAYA - ее, так сказать, витрина - написана на MEL
и поэтому может быть дополнена новыми меню, окнами, кнопками. Соответственно, интерфейс
MAYA может быть улучшен, изменен или обезображен до неузнаваемости. Вы можете писать свои
окошки для выполнения вами же запрограммированных действий или встраиваться в стандартные
меню MAYA, чувствуя себя агрессивным хакером. MEL позволяет делать и то и другое.
Анимация 865
с выравниванием и привязкой объектов друг к другу (snap & align). Мои друзья, только что
перешедшие с другого пакета на MAYA, были в шоке от такой аскетичности и горестно молили
о помощи. Запрограммировать выравнивание объектов было делом нехитрым, а вот в качестве
интерфейса для написанного скрипта я сделал копию окошка из другого пакета, повторяющую все
кнопочки и педальки соответствующего инструмента.
Во-вторых, наиболее часто MEL используется для создания коротких «макросов», то есть
запоминания последовательности действий для последующего многократного воспроизведения
ее. Эту последовательность действий гордо называют скриптом (а не «макро») и назначают обычно
на горячую клавишу или на кнопку на полке. В отличие от макро в других программах, эти скрипты
для MAYA обычно подвергаются активному редактированию, их передают по наследству, а иногда
даже продают, за небольшие деньги.
В-четвертых, если некоторая функция или алгоритм в MAYA отсутствует, его можно
запрограммировать на MEL и действительно получить то самое расширение функциональности
MAYA, о котором так часто говорят рекламные листовки. Примером может служить анимация
аттрактора Лоренца с помощью expression или паровоз с квадратными колесами (www. zabelin.
ru).
В-девятых, MEL- это любимое развлечение (а нетолько рабочий инструмент) всех технических
директоров. Можно даже сказать: для них это основное средство творческого самовыражения (и
в самом деле, нужно ведь давать возможность посамовыражаться и техдиректорам, а не только
эстетам-художникам или заносчивым аниматорам).
В-десятых, список применений MEL можно продолжать еще очень долго, начиная с задач
обслуживания рендеринга и заканчивая запуском «Фотошопа» из-под MAYA.
Есть скрипт!
Как представители других конфессий часто ссылаются на наличие у них плагинов
с различной дополнительной функциональностью, так и майские пользователи с завидной
регулярностью произносят сакральную фразу: «Есть такой скрипт!», отвечая на вопрос, а есть ли
в MAYA та или иная операция.
Действительно, MAYA представляет из себя центральное приложение, обросшее массой
дополнительных скриптов.
Дело в том, что в отличие от плагинов, требующих, во-первых, времени, во-вторых,
квалификации, в-третьих, сильной мотивации (как правило, коммерческой или производственной)
для их написания, скрипты могут быть написаны молниеносно, в том числе для решения
сиюминутной задачи, о которой можно забыть после ее решения.
Соответственно, задачи, которые решаются с помощью скриптов, могут быть как весьма
универсальные, так и узкоспециализированные, интересующие довольно ограниченный круг
пользователей. Поэтому, как правило, можно найти скрипты-решения практически на все (в том
числе, довольно экзотические) случаи жизни.
Такая архитектура и такое положение дел, с моей точки зрения - довольно удачный
компромисс между мощностью, гибкостью и удобством программы. Ведь если включить в MAYA все
это огромное количество довольно полезных (и бесплатных) скриптов, написанных пользователями
за несколько лет существования MAYA, этой программой просто невозможно будет пользоваться
- из-за обилия мелких, узконаправленных функций и операций, в которых может потеряться
основная логика пакета.
Поэтому если вам вдруг не хватает какой-то возможности в MAYA, с большой долей
вероятности уже существует скрипт, решающий вашу проблему. Первым делом надо залезть в
Интернет в поисках такого решения, а еще лучше - позвонить приятелям, которые наверняка уже
разыскали и скачали его.
MEL-ресурсы
Наиболее удачное, опять же с моей точки зрения, хранилище скриптов для MAYA,
содержащее категоризацию по функциональности, находится на сайте www.highend3d.com.
Также не стоит забывать про сайт производителя MAYA: www.alias.com.
Один из лучших ресурсов с точки зрения обучения и понимания MEL создал уважаемый
человеком по имени Brian Ewert. Его сайт (http://www.ewertb.com/) содержит не только примеры
полезных скриптов, но и подробный список вопросов и ответов, касающихся наиболее часто
возникающих проблем при работе с MEL. Кроме того, если у вас возник вопрос типа: «А как бы мне
сделать вот это на MEL?», вы наверняка найдет ответ на его отличном англоязычном сайте.
Некоторое количество ссылок на полезные ресурсы, касающиеся MEL-программирования,
Суть этой моей сентенции такова: MEL - вполне «человеческий» язык программирования.
Даешь старый добрый процедурный подход!
MAYA API
Есть спецтип vector, как вариант массива из трех float, над которым определены векторные
операции. Типы описывать не обязательно. Как обычно, объявление по первому присваиванию
служит источником неприятностей.
Контрольные конструкции - типа {}, if-else, for, while, break, switch, continue и другие - такие же,
как в С.
Есть также операции работы с файлами типа fopen, fread, fwrite, fprint, хорошо работающие
с текстовыми данными.
setAttr("pCube1.tx", 10);
можно написать
Например, вместо
int $х = size($array);
можно написать
Вместо
string $control =
удобнее написать:
string $control =
attrFieldSliderGrp -I "magnitude" -min 0 -max 1 -w 400';
Такой стиль вызова команд иногда называется императивным - в противовес традиционному
функциональному.
Убедитесь в том, что MAYA напечатала в верхней части Script Editor команду:
sphere -p 0 0 0 -ах 0 1 0 -ssw 0 -esw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 8 -nsp 4 -ch 1;
Теперь представьте себе, что MAYA состоит из двух частей. Первая часть - это интерфейс,
то есть окно MAYA, которое вы наблюдаете каждый день, со всеми его менюшками, окошками и
кнопками.
Вторая часть, ядро MAYA, скрывается позади интерфейса, и если вам еще не исполнилось
семи лет, представьте себе, что оно (ядро) сидит в системном блоке, а интерфейс - в мониторе
компьютера.
Когда пользователь своими непрямыми руками что-то делает через интерфейс (например,
двигает сферу за манипулятор Move Tool) происходит примерно такая цепочка действий:
Интерфейс MAYA преобразует судорожные движения рук пользователя в команду move с нужными
параметрами и передает эту MEL-команду ядру MAYA. Ядро MAYA «ловит» эту команду, пересчитывает
матрицы трансформаций, запоминает новое положение сферы и «кричит» интерфейсу MAYA:
«Готово! Перерисуй экран!». Интерфейс просто обновляет экран в соответствии с новым
move -r 0 4.539716 0 ;
Интерфейс ее и отсылает ядру, чтобы оно реально передвинуло сферу в новое положение,
посчитало все, что нужно, и сообщило, где теперь сфера находится - чтобы именно там интерфейс
ее и нарисовал.
Вывод первый. Все, что делается через интерфейс MAYA, можно повторить с помощью MEL-
команд.
Вывод второй. В помощью MEL-команд можно сделать гораздо больше, чем через интерфейс
MAYA. Надо только их знать.
Совет. Сохраните любую сцену, как файл с расширением .та и откройте его в
любом текстовом редакторе. Вы увидите, что MAYA сохраняет собственные сцены
как последовательность MEL-команд, выполнение которых приводит к созданию
сцены. Такая открытость и возможность в любой момент выполнять любые
MEL-команды делает MAYA абсолютно открытой и драматически расширяемой
системой.
Вы можете без труда разыскать там вышеупомянутую команду move, прочесть описание
того, что она делает, и увидеть список параметров-флагов, которые модифицируют действие
команды.
Структура MEL-команд
Следует сразу оговориться, что условно язык MEL состоит как бы из двух частей.
Первая - это конструкции языка программирования типа if-else, for, while, break, switch,
continue, такие, что позволяют складывать числа, организовывать циклы, условные переходы и
управлять последовательностью выполнения команд.
Вторая огромная часть - это собственно сами MEL-команды, которые выполняют конкретные
действия в MAYA, а не только складывают и умножают числа.
Основные конструкции языка я разберу чуть позже, а сейчас остановлюсь на внешнем виде
MEL-команд.
move -r 0 5.6 0;
Если имя объекта не указано, команда применяется к выбранным объектам (если она, конечно,
работает с объектами).
sphere -р 0 0 0 -ах 0 1 0 -ssw 0 -esw 360 -r 1 -d 3 -ut 0 -tol 0.01 -s 8 -nsp 4 -ch 1;
Имена флагов могут быть длинные и короткие (по аналогии с атрибутами объектов), чтобы
ленивые программисты могли печатать меньше символов. Использование длинных имен флагов не
изменяет действия команды, это улучшает читабельность программ, но зато увеличивает расход
энергии программиста.
sphere -pivot 0 0 0 -axis 0 1 0 -startSweep 0 -endSweep 360 -radius 1 -degree 3 -useTolerance 0 -toler
ance 0.01 -sections 8 -spans 4 -constructionHistory 1;
sphere;
то возникнет сфера, лежащая на боку, так как значение флага -axis по умолчанию равно 1 0 0.
Именно это значение будет использовано, если флаг -axis не указан явно в команде.
Впрочем, если слова «флаги» или «аргументы» начинают вас пугать, перейдем к
практическому примеру, на котором разберем, как можно случайным образом изменять свойства
(то есть атрибуты) большого количества выделенных объектов с помощью MEL.
Я настойчиво советую выполнять любые команды, всегда выделяя их в нижней части Script
Editor и нажимая серую клавишу Enter, чтобы команды не пропадали из окна.
Совет. Если в нижней панели Script Editor трижды щелкнуть по тексту, строка
выделится целиком.
Совет. Те, кто не хочет сломать глаза на микроскопическом шрифте Script Editor,
могут нажать Ctrl и покрутить колесо мыши в нижней панели.
Поднимите его на 0.5 по оси Y и опустите его пивот в начало координат, чтобы пивот лежал
на нижней грани куба.
Откройте Option Box операции Duplicate и сделайте девять копий куба со смещением на
единицу по оси X.
Выберите все объекты. Если мы хотим задать им случайный размер, то очевидно следует
пробежаться по списку выбранных объектов и задать различные значения для атрибута scaleY.
Как же получить список выбранных объектов? Для работы со списками объектов в сцене есть
команда Is.
Для справки. В среде Unix команда Is выполняет функции команды dir для Windows/DOS,
то есть выдает список файлов. Is - это аскетическое сокращение от list.
Если почитать документацию к команде Is, выяснится, что у нее есть масса флагов, позволяющих
выдавать списки объектов только определенного вида, в том числе только выбранные объекты.
Выполните команду Is -sl и убедитесь, что в верхней панели появился список только что выбранных
кубов.
Is -si;
Теперь надо этот список как-то «поймать», то есть сохранить для дальнейшей работы.
Выполните команду:
а затем команду
print $list;
и убедитесь, что команда print напечатает список выбранных объектов, сохраненный в переменной
Slist.
Точка с запятой в конце каждой команды обязательна, она отделяет одну команду от
другой. В принципе несколько команд можно писать в одной строке, разделяя их точкой с запятой
друг от друга, однако на первых порах я настоятельно советую писать в каждой строке одну
команду и не забывать про точку с запятой в конце строки. Пробелы можно ставить и в начале и
в середине строки «для красоты», они просто игнорируются. (Только не надо их вставлять внутри
имени команд или флагов!..)
Если хорошо понимаете, что такое переменные, и представляете себе, что они бывают
разных типов, пропускайте следующий раздел и переходите к работе с циклом («Работа с циклом.
Перебор объектов в списке»). Если же вы изрядно нервничаете и слова «переменная», а, тем
более, «массив», вас сильно пугают, переходите к следующему разделу.
Команды
объявляют переменные разных типов, то есть в памяти заводятся ячейки разного размера под
строку ($text) и под число ($х).
Кроме того, числа тоже делятся на два типа: целые и с плавающей точкой. Для хранения
целых чисел требуются ячейки меньшего размера, для остальных - большего.
Команды
$N=100;
$pi=3.1415926;
int $quantity;
float $expo;
string $text20;
объявляют переменные типа целое число, число с плавающей точкой и строка. Этим переменным
ничего не присвоено, они пока пустые, но готовые к использованию, под них выделены ячейки
памяти, но туда ничего не занесено.
int $quantity=10;
float $expo=1.56782;
string $text20= "Start of message";
Как вы уже догадались, напечатать значение переменной можно с помощью команды print.
Массивы
Какого же типа получается переменная, объявленная в результате команды
Если вы думаете, что это строка, причем очень длинная, то вы ошибаетесь. Хотя бы потому, что
команда
print $list;
Например, whatls "print"; выдает результат Command, заявляя о том, что print - это
встроенная команда. Выполните
whatls "$list";
Полученный результат
позволяет сделать вывод, что кроме простых переменных типа string, существуют составные
переменные типа string[], то есть массивы строк.
Обращаться к элементам такого массива можно по индексу, то есть по номеру внутри массива,
например
print $array[0];
print $list[21];
переменная $list неявно (по первому присваиванию) была объявлена как массив строк, и этот
массив был заполнен именами выбранных объектов.
Так как пытливые умы стараются не допускать неявного объявления типа переменных,
чтобы избежать путаницы, изменим эту команду следующим образом:
Вы должны понимать, что выражение $list[] может использоваться только при объявлении
переменной типа массив. Если последнюю команду разбить на объявление и на присваивание, это
будет выглядеть следующим образом.
string $list[];
$list = ' l s - s l ' ;
Обратите внимание, что во второй строке используется $list без скобок, так как массив строк
присваивается самой переменной.
Если вся эта жуткая теория про типы данных и переменных вас чудовищно устрашила,
не переживайте. Переходите к следующему разделу и воспринимайте только что описанную
команду как стандартное заклинание, которое позволяет получить и сохранить список выделенных
объектов.
Работа с объектами и атрибутами
Вам уже, наверное, осточертела навязчивая парадигма о том, что любой объект
представляет собой просто набор атрибутов, определяющих его свойства и качество жизни.
Однако я с маниакальным упорством буду возвращаться к ней снова и снова. На этот раз, чтобы
напомнить, что у любого атрибута есть, как правило, короткое и длинное имя, а вот полное имя
атрибута состоит из имени объекта и названия атрибута, например pCubel.tx или pCubel.trans-
lateX. Название атрибута всегда отделяется от имени объекта точкой, такая запись однозначно
определяет значение конкретного атрибута у конкретного объекта. Вы можете использовать как
короткие имена атрибутов, так и длинные, главное - не забывайте правильно писать маленькие и
большие буквы в именах объектов и атрибутов (MAYA чувствительна к регистру символов).
Очевидно, что при копировании групп MAYA оставляет без изменений «начинку» иерархии и
дает новое имя только самой верхней группе, в то время как объекты, входящие внутрь иерархии,
имеют одинаковые имена. Точно так же, как в разных папках на диске могут быть файлы с
одинаковыми именами.
select -r pCube1 ;
говорящее о том, что несколько объектов в сцене имеют одно и то же имя pCube1. Поэтому
обращаться к ним надо с использованием полных имен.
setAttr "pCubel.translateX" 3;
// Error: Not enough data was provided. The last 0 items will be skipped. //
setAttr "pCubel.translateY" 5 5 ;
Кстати, если объект не находится в иерархии, то его полное имя содержит просто одну
дополнительную вертикальную черту, обозначающую, что объект пригруппирован к мировому
пространству, например: | pTorus1. В общем случае эту черту можно не писать.
Чаще всего одинаковые имена возникают при дублировании групп (иерархий), и это
вполне разумно, когда у вас есть, например, набор персонажей, и у каждого из них конечности
называются одинаковыми, «человеческими» именами, типа «left_hand» или «right_foot». Однако
иногда хочется избежать появления одинаковых имен в сцене (например, для экспорта в другие
программы). Для этого в Option Box операции Duplicate существует галка Assign Unique Name to
Child Node.
Как правило, MAYA сама отслеживает формирование нужных имен и путей, в частности, при
работе с командой 'Is -sl', однако в некоторых случаях необходимо помнить о наличии одинаковых
имен объектов в сцене.
В данном случае нам понадобилась одна простая переменная типа string (строка) с именем
$item, чтобы «засовывать» в нее очередной элемент в списке в процессе перебора всех элементов
в цикле. Как видите, на MEL это звучит почти как на английском.
Фигурная скобка открывает тело цикла, то есть набор команд, которые будут выполняться
в цикле (их может быть хоть двести). Вторая скобка закрывает цикл и после нее могут идти
команды, уже не выполняющиеся в цикле. Такой интеллектуальный цикл сам посчитает, сколько
элементов в массиве $list, и выполнится ровно это число раз. Причем на каждом повторении цикла
в переменную $item будет попадать следующий элемент списка.
Если вы напечатали все символы правильно, MAYA напишет длинную строку, состоящую из
напечатанных друг за другом имен выбранных объектов:
pCubelpCube2pCube3pCube4pCube5pCube6pCube7pCube8pCube9pCube...
Однако MAYA не сможет понять запись $item.scaleY , так как реального геометрического
объекта с именем $item не существует. Но коль скоро мы знаем, что в переменной $item находится
строка, равная имени очередного объекта в списке, мы можем сконструировать строку типа
"pCube23.scaleY" следующим образом
$item + ".scaleY"
Пытливые умы наверняка догадаются, что операция суммирования для строк всего лишь
склеивает две строки в одну (другие операции для строк просто не определены).
Полученный цикл, являет собой пример очень часто встречающейся конструкции для
изменения атрибутов выбранных объектов. Постарайтесь вникнуть в смысл записи:
Она является образцом создания полного имени атрибута, включающего в себя имя объекта.
Функция rand(0,2) возвращает, в данном случае, значение от нуля до двух. (Дополнительные
скобки вокруг нее означают «посчитать выражение в скобках и выдать его наружу в виде числа».
Скобки и кавычки
Примечание. Те, кто имеют хоть небольшой опыт программирования или
увлекаются чтением чужих программ, без сомнения будут смущены наличием двух
способов вызывать функции-команды. На MEL можно вызвать функцию при помощи
традиционных скобок
$x=rand(1.1, 2.5);
Нет никаких рекомендаций по использованию того или иного стиля. Это дело вкуса, а
результат вызова команд будет идентичным. Дело в том, что довольно неудобно использовать
традиционные скобки для вызова чисто MEL-овских команд типа sphere с огромным количеством
флагов
sphere("-p", 0, 0, 0, "-ах", 0, 1, 0, "-ssw", 0, "-esw", 360, "-r", 1, " - d " , 3, "-s", 8, "-nsp", 4, "-ch",
1);
Однако, традиционные функции типа rand, noise или sin по привычке удобно вызывать с
помощью аргументов в скобках, поэтому я обычно смешиваю стили в своих программах. Если вы
Комментарии
Иногда удобно комментировать свои действия в самом скрипте. Для этого используются
комментарии. Как только MAYA встречает в какой-нибудь строке скрипта две косые черты «//»,
она игнорирует всё, что написано после них и до конца строки. Если две косые черты стоят в
начале строки, эта строка игнорируется, и вы можете писать в этой строке что угодно: полезные
замечания или всяческие глупости.
Добавление вращения
Если все кубы выбраны, вы всегда можете вернуть их в исходный размер просто задав в
Channel Box значение scaleY=1.
Добавьте пару строк в наш мощный скрипт для добавления случайных размеров по осям X и Z.
Теперь боковые размеры всех кубов случайным образом задаются в диапазоне от 0.3 до 0.8.
Добавим вращения нашим урбанистическим объектам. Вставьте еще одну строку в тело цикла:
Пустые строки вставлены здесь для удобства чтения, MAYA же их просто игнорирует.
Так как команда setAttr задает абсолютные значения атрибутов, пришлось использовать команду
move с флагом -r, чтобы задать смещение относительно текущей позиции объектов. Пытливые
умы, конечно, сразу заметят, что весь скрипт можно было бы переписать в более компактной и
даже более понятной форме:
Здесь сразу понятно, что с помощью команд move, rotate, scale трансформируется
очередной объект в списке, имя которого содержится в переменной $item. Но если бы я сразу
написал такой простой скрипт, как бы я тогда рассказал про составление имени произвольного
атрибута с помощью склеивания строк типа: ($item+".scaleY")?!
Кроме того, не для всех атрибутов есть команды типа move, и иногда нужно работать со
значением конкретного атрибута.
Можете выделить полученный скрипт и гордо перетащить его на полку. Для его дальнейшего
использования достаточно выделять объекты и нажимать на кнопку на полке.
Кроме того, запомните в уме и сохраните в текстовом файле конструкцию получения списка
выбранных объектов и циклический перебор их в цикле
Вы неоднократно еще будете использовать эти команды как шаблон для написания новых
скриптов, так как данная конструкция является совершенно стандартной и встречается в половине
программ, написанных пользователями MAYA.
В Script Editor отредактируйте предыдущий скрипт, убрав из него команды scale и rotate
(какой смысл вращать вершины?) и добавив перемещение по вертикали:
Выполните его, в надежде на то, что скрипт пробежит по списку выбранных вершин и
сдвинет каждую из них немного в случайном направлении.
Однако вершины сдвинутся как-то странно, целыми группами. Нажмите Undo. Выделите
снова часть вершин и загляните в Script Editor. Там должна появиться команда типа:
Если выделить и выполнить команду Is -si, она выдаст в точности этот же список и,
следовательно, наш цикл будет случайным образом двигать целые «кучки» вершин.
float $d=0.05;
string $list[] = 'Is -sl - f l ' ;
string $item;
for($item in $list)
[
move -r (rand(-$d,$d)) (rand(-$d,$d)) (rand(-$d,$d)) $item;
}
Таким образом, с минимальными исправлениями универсальный скрипт для работы
с выделенными объектами превращается в подобие noise deformer, и он модифицирует форму
объекта случайным образом. Этот скрипт будет работать с выделенными вершинами не только на
сплайновых поверхностях, но и на кривых, полигональных сетках и даже на решетках типа Lattice,
причем вы можете одновременно выбирать компоненты разных объектов и запускать скрипт на
выполнение.
Примечание. Флаг -fl никак не влияет на вид списка в случае, когда выбраны
объекты, а не компоненты, так что можете использовать его всегда, для
универсальности.
Если вы измените для сферы количество sections/spans до 50, то есть радикально увеличите
количество вершин, а затем выберете все вершины и запустите деформер-скрипт, его выполнение
займет ощутимое время.
Кроме того, если вы захотите написать полноценный деформер, так чтобы деформация
поверхности имела Construction History, то есть ноду, в которой можно задавать величину
деформации, вам никуда уже не деться от C++ и от MAYA API. С помощью скриптов нельзя задавать
операции, имеющие Construction History, можно лишь выполнить последовательность действий,
нажать Undo, изменить значения переменных и выполнить скрипт снова. Это принципиальный
момент.
Процедурное моделирование
Разберем далее, как можно использовать MEL-команды для моделирования, то есть для
построения геометрии с помощью формул. А заодно разберем еще одну конструкцию цикла и
применение условных переходов.
curve -р 0 0 0;
После этого в начале координат (в точке 0 0 0) возникнет кривая, состоящая из одной (!)
точки. Вы можете убедиться в этом, выбрав ее и исследовав в Attribute Editor.
Очевидно, что если выполнить команду:
curve -р 0 0 0 -р 0 1 0 -р 1 1 0 -р 1 0 0;
то возникнет сегмент кривой третьего порядка (значение флага d по умолчанию равно трем).
Однако идея состоит в том, чтобы поставив одну точку, добавлять к ней новые вершины в
цикле, добиваясь «выращивания» кривой по некоторой формуле.
Методом тыка попробуем выяснить, какие команды и флаги для этого нужны.
Коль скоро среди операций моделирования есть инструмент добавления точек к кривой, выберите
любую кривую, а затем выполните Edit Curves=>Add Points Tool.
Добавьте несколько точек к кривой, скашивая глаз на Script Editor и отслеживая, какие
команды появляются в нем при каждом новом щелчке.
curve -р 0 0 0 -n "myCurve";
curve -p 0 1 0 -a "myCurve";
curve -p 1 1 0 -a "myCurve";
curve -p 1 0 0 -a "myCurve";
Как видите, чтобы задать имя кривой, создаваемой первой командой, пришлось
воспользоваться флагом п, чтобы потом ссылаться на это имя при добавлении точек в следующих
командах.
Дело за малым: осталось вместо трех последних команд написать цикл, добавляющий
заданное количество вершин к первой точке.
curve -р 0 0 0 -n "myCurve";
int $i;
for($i=0; $i<100; $i=$i+1)
{
curve -p (rand(0,2)) (rand(0,2)) 0 -a "myCurve";
}
Возникнет хаотическая кривая, состоящая из ста и одной вершины. Напомню, что функция
rand возвращает новое случайное число при каждом вызове.
Перед началом выполнения счетчику цикла присваивается нулевое значение ($i=0), затем
проверяется условие цикла ($i<100), и если оно не выполняется, цикл прекращает исполняться.
В противном же случае выполняются команды из тела цикла. После каждого выполнения одного
оборота цикла, выполняется операция увеличения счетчика ($i=$i+1), затем снова проверяется
условие цикла ($i<100) и все продолжается до тех пор, пока условие цикла перестанет
выполняться.
Примечание для взрослых. Счетчик цикла не обязан быть целым. Условие цикла может
быть основано не только на значении счетчика, операции увеличения счетчика может не быть
вовсе или вместо нее может располагаться любая логическая операция.
Счетчик цикла изменяется в цикле от нуля до ста. Если его разделить на десять, то это
число очевидно будет изменяться от нуля до десяти.
curve -р 0 0 0 -n "myCurve";
int $i;
for($i=0; $i<100; $i=$i+1)
{
float $x=$i/10.0;
float $y=sin($i/10.0);
curve -p ($x) ($y) 0 -a "myCurve";
}
Теперь в цикле сто раз будут вычисляться новые значения для переменных $х и $у,
основанные на растущем счетчике цикла. Эти значения будут добавляться как координаты новой
вершины к кривой myCurve. В результате получается график функции синус (sin).
float $x=$i/10;
Несмотря на то, что переменная $х объявлена как float, она, очевидно, принимает в этом
случае только целые значения, то есть происходит неожиданное округление.
Дело в том, что выражение $x=$i/10 читается как «разделить целое число $i на целое
число 10». Поэтому результат деления тоже становится целым числом, то есть округляется и
только после этого «заталкивается» в переменную $х.
Выражение $x=$i/10.0 читается уже как «разделить целое число $i на число с плавающей
точкой 10.0». Поэтому результат деления в этом случае становится числом с плавающей точкой и
не округляется.
Первая строка содержит выражение if (...) {...}, логика выполнения которого следующая.
Набор команд в фигурных скобках исполняется только тогда, когда логическое выражение в
круглых скобках после if является истинным, то есть логически выполняется. В данном случае это
выражение звучит так: «равен ли единице результат, возвращаемый командой objExists».
Если «да, равен», то выполняется блок команд в фигурных скобках, если «нет, не равен», то
ничего не происходит, так как отсутствует оператор else, определяющий действия «в противном
случае».
Важное замечание. Двойное равно «==» - это не опечатка, это логическое «равно». Дело в
том, что по-русски одинаково звучат оба нижеследующих выражения: выражение $а=$b (то есть
«$а равно $b, значение $b присвоить переменной $а») и логическое выражение if($a==$b) («если
$а равно $b»). В английском языке в этих случаях употребляют разные слова: "assign" (присвоить)
и "equal"(paBHo), соответственно. На языке MEL это все обозначается как «=» (присвоить) и «==»
(равно ли?).
Опасность состоит в том, что если вы пропустите один знак «равно» в логическом выражении
и напишете где-нибудь if($i=1), то MAYA даже не выругается, а вместо этого присвоит единицу
переменной $i (чего вы вовсе не хотели) и выполнит все команды после if, так как посчитает
выражение ($i=1) истинным, то есть равным единице.
Напоминаю: в одной строке может быть сколько угодно команд; главное, чтобы они
корректно отделялись друг от друга точкой с запятой. Фигурные скобки могут располагаться в
любом месте строки и не требуют после себя точки с запятой. Дополнительные отступы в начале
строки также не влияют на выполнение команд, но радикально улучшают внешний вид программы,
позволяя визуально выделять наборы команд, принадлежащие циклам или блокам if.
Для взрослых. Хорошо осведомленные взрослые мальчики уже сообразили, что
«==1» можно не писать, так как результат, возвращаемый командой objExists равен нулю или
единице, а результат сравнения с единицей тоже равен нулю (нет) или единице (да). Совсем
недисциплинированные программисты знают также, что фигурные скобки можно не писать, если
в блоке находится только одна команда
Кроме того, существует довольно полезная команда flushUndo, позволяющая одним махом
очистить всю очередь Undo. Ее можно использовать не только в конце скриптов, но и после
многочасовой смены по моделированию чего-нибудь.
Теперь вы можете дать волю своим фантазиям и попытаться построить графики всех
известных вам функций (если таковые имеются). Те, кто с детства мечтал увидеть функцию noise,
могут быстро изменить всего одну строку и получить долгожданный график.
Для того, чтобы спираль была подлиннее, надо увеличить число точек до пятисот и
уменьшить ее скорость раскручивания по оси X.
Однако ленивые умы просто подсмотрят команду удаления первой точки в Script Editor и
вставят ее в конец скрипта.
int $NumPoints=500;
float $Amp=3.0, $Freq=2.0, $Density=10.0, $xSpeed=5.0;
Как заметили острозоркие программисты, скрипт сначала полностью выполняется, и только потом
обновляется экран. В качестве бонуса за терпение могу предложить команду refresh, принудительно
обновляющую экран. Если вставить ее в самый конец тела цикла, вы увидите «живое» построение
кривой (естественно, это увеличивает время работы скрипта).
refresh;
}
delete "myCurve.cv[0]";
Но чтобы построить все кривые на свете, следует пойти в книжный магазин и купить книжку:
Е.В. Шикин, М.М. Франк-Каменецкий «Кривые на плоскости и в пространстве». Там приведены
формулы для построения громадного количества кривых.
Совет. Лучше всего сохранять тексты из Script Editor, просто копируя их в буфер
обмена (Ctrl-c) и вставляя в любимый текстовый редактор. Если выполнить в
Script Editor пункт меню File=>Save Selected, текст сохранится в указанный вами
файл с «короткими» концами строк, то есть будет читаться, например, в Word-
Pad, тогда как в Notepad вы увидите «кашу» из склеенных строк.
Совет. Обязательно читайте сообщения об ошибках, которыми вас щедро угощает MAYA.
Я имею в виду вот что: надо не только горестно вздыхать, получив сообщение об ошибке, но и
пытаться понять (и если нужно, то со словарем!), чем Майя хочет порадовать вас на этот раз...
Есть, однако, одно сообщение, которое приводит многих начинающих MEL-маньяков в тупик. При
этом встречается оно довольно часто. Звучит оно так:
float $NumPoints;
// Error: float $NumPoints; //
// Error: Invalid redeclaration of variable "$NumPoints" as a different type. //
Лично меня такое поведение MAYA просто бесит. Причем, объявив переменную с
определенным именем, нельзя ее «очистить» или «освободить». Команда clear действует только
на массивы, да и очищает лишь их содержимое, не освобождая имя переменной для дальнейшего
использования. Чтобы как-то призвать MAYA к порядку, расскажу, как можно избежать этого
сообщения, работая в Script Editor.
Здесь следует упомянуть о таком понятии, как область видимости переменных. Пара
фигурных скобок {} называется блоком. Все переменные, объявленные внутри блока, видны
только внутри него. То есть объявив переменную внутри блока (например, в цикле) и попытавшись
обратиться к ней вне блока (вне цикла), вы либо получите сообщение о неведомой переменной,
либо MAYA молча заведет новую переменную, значение, которой никак не связано с переменной,
объявленной внутри блока. Более того, написав, например, такие команды:
p r i n t " - - - {";
{
int $a=10;
print $a;
print "} --- ";
}
int $a;
print $a;
вы получите два разных значения переменной с одинаковым именем:
--- {10} ---О
Дело в том, что при выходе за границы блока (за фигурные скобки) переменная «умирает»
и становится невидимой.
Блок не обязательно должен принадлежать циклу или условному оператору if. Его можно
открыть и закрыть в любом месте программы, используя фигурные скобки. Поэтому если, начав
писать команды в Script Editor, вы поставите в самом начале открывающую фигурную скобку «{«, а
в самом низу добавите закрывающую «}», то все команды в Script Editor окажутся внутри большого
блока и будут освобождаться каждый раз после выполнения этого блока (не забывайте только
выделять открывающую и закрывающую скобки, посылая команды на выполнение).
Прежде всего, скрипты - это просто куски текста, сохраняемые на полках или в текстовых
файлах и выполняемые по мере надобности.
Expressions - это объекты MAYA и, формально говоря - это ноды типа expression, являющиеся
полноправными участниками сцены и хранящие в себе текст на языке MEL в виде одного из своих
атрибутов.
Еще раз по поводу терминологии. Для избежания полной путаницы, употреблять термин
«выражение» я не буду. Никто никогда так не говорит в русскоязычной «майской» среде, а если вы
вдруг заявите, что заставили своего персонажа работать с помощью «выражений», окружающие
подумают в первую очередь о крепких выражениях. Устная майская традиция предполагает
употребление термина «экспрешен», обеспечивая стопроцентную однозначность трактовки. Я же
ограничусь непереведенным написанием «expression» (так же, как loft или trim), предполагая, что
произносить вы его будете, как положено, и все вас поймут при общении.
Теперь по поводу разницы в функциональности. Скрипт - это набор команд на языке MEL,
который выполняется по вашему требованию, то есть когда вы сами его запустите. Хранится он,
как правило, на диске в виде текстового файла и не является частью сцены (про ScriptNode -
отдельный разговор ниже).
Expression - это тоже набор команд. Но во-первых, эти команды хранятся в виде ноды и
являются частью сцены, то есть хранятся внутри нее. А во-вторых, эти команды выполняются
не по вашему желанию, а, грубо говоря, при смене номера кадра при анимации. Каждый раз
когда происходит переход к следующему кадру (или вы неловко ткнете мышкой в TimeLine),
выполняются все незаблокированные expressions, присутствующие в сцене. Также выполнение
expressions происходит с том случае, когда один из объектов, чьи атрибуты используются в expres
sion, изменяет значение своих атрибутов.
Таким образом, если вы проиграли двести кадров анимации, все expressions выполнятся
по двести раз. Поэтому expressions используются, как правило, не для интенсивных расчетов и
вычислений, а для задания логических связей между объектами (точнее говоря, между атрибутами
объектов).
$х = pSphere.tx;
Нетрадиционные выражения.
Выращивание объектов в анимации
Вернемся однако к построению процедурных кривых. И напишем довольно нетипичный
expression, который ничего не делает с атрибутами объектов, но выращивает кривую, наподобие
испускания частиц.
Пытливые умы наверняка заметили, что при построении кривой с помощью цикла
использовалась переменная $t, которая просто тихо и мирно увеличивалась в ходе выполнения
цикла, сильно напоминая увеличение времени (или номера кадра) в ходе анимации. В чей-нибудь
разгоряченный MEL-ом разум обязательно придет мысль использовать вместо цикла expression,
а вместо переменной $t системное время как увеличивающийся параметр. Дадим жизнь этой
пламенной мысли.
В абсолютно пустой сцене создайте новый expression. Вставьте в него упомянутый выше
скрипт для построения кривых в цикле (файл scripts.txt) и отредактируйте его, убрав команду и
скобки цикла (он теперь не нужен), удалив строку refresh и команду удаления первой точки. Код
этого expression должен выглядеть так:
int $NumPoints=500;
float $Amp=3.0, $Freq=2.0, $Density=10.0, $xSpeed=5.0;
float $t=time;
float $x=$t/$xSpeed;
float $y=$Amp * sin($t*$Freq);
float $z=$Amp * cos($t*$Freq);
if(frame==1)
{
if(objExists("myCurve")==1) { delete "myCurve"; }
curve -p ($x) ($y) ($z) -n "myCurve";
}
else
{
curve -p ($x) ($y) ($z) -a "myCurve";
}
Помните о том, expression выполняется в каждом кадре, поэтому никакой цикл нам больше
не нужен!
Тут следует провести аналогию с испусканием частиц, которые, как правило, исчезают при
возвращении в первый кадр. Точно так же, наша кривая должна исчезать или «обнуляться» при
перемотке назад в первый кадр.
if(frame==1)
{
if(objExists("myCurve")==1) { delete "myCurve"; }
curve -p ($x) ($y) ($z) -n "myCurve";
}
делается проверка, является ли кадр первым, и если да, то в нем производится удаление кривой
myCurve, если она уже существует, и она создается заново.
Блок
else
{
curve -p ($x) ($y) ($z) -a "myCurve";
}
говорит: в противном случае (то есть, если кадр не первый) во всех остальных кадрах надо
просто добавлять точку с координатами $х, $у, $z к уже созданной в первом кадре кривой.
Надо заметить, что начальный кадр диапазона анимации должен быть строго первым
(равным единице), чтобы expression успешно выполнял удаление в первом кадре. Если номер
начального кадра анимации равен 1.04 или 10, то expression не будет работать корректно.
Если expression заработал, можно сохранить сцену (curveBuilder.ma). Лучше всего сохранять
ее не в первом кадре, так как в начальный момент кривая myCurve состоит всего из одной точки
и в процессе сохранения теряет часть информации (установлено опытным путем). После открытия
сцены expression не может добавить точки к такой вырожденной кривой. Поэтому сохраняйте
сцену в кадре, где уже присутствует несколько сегментов кривой.
Однако, вернувшись в первый кадр, создатели трубок обнаружат, что Construction His
tory пропала и поверхность больше не обновляется. И это совершенно предсказуемо: ведь в
первом кадре происходит удаление кривой myCurve. Если бы можно было, не удаляя кривой, как-
нибудь ее «обнулять», это бы решило проблему сохранения Construction History. Хакерствующие
умы, покопавшись в описании к команде curve, наверняка уже обнаружили флаг -r (-replace),
позволяющий не добавлять, а заменять точки на существующей кривой. Поэтому в первом кадре
вместо команды удаления должна выполняться команда замены точек кривой. Выглядеть это
будет примерно так:
int $NumPoints=500;
float $Amp=3.0, $Freq=2.0, $Density=10.0, $xSpeed=5.0;
float $t=time;
float $x=$t/$xSpeed;
float $y=$Amp * sin($t*$Freq);
float $z=$Amp * cos($t*$Freq);
if(frame==1)
{
if(objExists("myCurve")==1)
{ curve -p ($x) ($y) ($z) -r "myCurve"; }
else
{ curve -p ($x) ($y) ($z) -n "myCurve"; }
}
else
{
curve -p ($x) ($y) ($z) -a "myCurve";
}
if(frame==1) // if (frame)
{
string $flag;
if(objExists("myCurve")==1) [ $flag="-r"; }
else { $flag="-n";}
int $NumPoints=500;
float $Amp=3.0, $Freq=2.0, $Density=10.0, $xSpeed=5.0;
$Amp=loc.amp;
float $t=time;
float $x=$t/$xSpeed;
float $y=$Amp * sin($t*$Freq);
float $z=$Amp * cos($t*$Freq);
Теперь амплитуда спирали будет равна значению атрибута loc.amp в каждом кадре.
Выберите локатор, откройте Attribute Editor, зайдите в раздел Extra Attributes. Запустите
анимацию и шевелите слайдер у атрибута amp прямо во время проигрывания.
float $x=ball.translateX;
float $y=ball.translateY;
float $z=ball.translateZ;
if(frame==1)
{
if (objExists("myCurve")==1)
{ curve -p ($x) ($y) ($z) -r "myCurve"; }
else
{ curve -p ($x) ($y) ($z) -n "myCurve"; }
}
else
{
curve -p ($x) ($y) ($z) -a "myCurve";
}
Если вы хотите, чтобы за объектом тянулся хвост определенной конечной длины, добавьте
в самый конец expression одну строчку:
}
if(frame>70) delete "myCurve.cv[0]";
Эта строка гарантирует «отрезание» первой точки у кривой в каждом кадре после
семидесятого.
Во-вторых, иногда Batch Render не может посчитать правильный результат, в то время как
в окне Render View все считается, как нужно. Примером может служить наш построитель кривых
или сцены, использующие expressions, которые создают новые объекты во время анимации. Если
запустить их на просчет с неначального кадра, то результат рендеринга с помощью Batch Render
будет непредсказуем.
Посмотрим, как можно быстро решить эту довольно экзотическую проблему с помощью
MEL. Коль скоро на MEL можно повторить все действия, производимые пользователем через
интерфейс, то наверняка несложно будет написать скрипт, выполняющий нужное количество раз
следующую последовательность действий:
Очевидно, что нужно просто «подглядеть», что какие команды MAYA использует для
выполнения вышеуказанных действий. Для этого нужно включить в меню Script Editor «шпионский»
режим отображения всех команд в ответ на действия пользователя: Script=>Echo All Commands.
Теперь просто выполняем нужные действия и определяем нужные команды.
Итак, рендерим картинку в окне: Render=>Render Current Frame. B Script Editor усматриваем
и запоминаем команду:
RenderlntoNewWindow;
Затем сохраняем картинку через меню окна Render View: File=>Save Image...
Задаем произвольное имя файла, например, renderTestl.iff.
Тип файла оставляем без изменения (Maya IFF), хотя можно задать и другие форматы
изображений.
renderWindowSavelmageCallback "renderView"
"С:/Documents and Settings/Administrator/My Documents/maya/projects/default/images/renderT-
estl.iff" "image";
После небольшого эксперимента можно убедиться, что если не писать в этой команде
полный путь к файлу, а ограничиться только его именем, картинка все равно будет сохраняться в
папке images текущего проекта:
И, наконец, нажав кнопку перехода в следующий кадр, находим в Script Editor команду
playButtonStepForward;
Теперь, используя сакральные знания о работе циклов, можно легко написать несложный
скрипт, который последовательно отрендерит в окне Render View несколько кадров (например,
десять, начиная с текущего) и сохранит их на диск в папку images текущего проекта.
int $i;
int $N=10;
string $fname="renderTest";
for($i=0; $i<$N;$i++)
{
Renderl ntoNewWindow;
renderWindowSavelmageCallback "renderView" ( $fname + $i + ".iff" ) "image";
playButtonStepForward;
}
Самое «сложное» здесь - составить имя файла с номером, равным счетчику цикла, чтобы
все картинки сохранялись со своими уникальными именами.
Запустив этот недлинный скрипт, вы должны увидеть, как, начиная с текущего кадра,
в окне Render View просчитаются десять картинок, а анимация последовательно сдвинется на
десять кадров. После этого в папке images вы можете обнаружить новые изображения.
int $i;
int $N=10;
string $fname="renderTest";
for($i=0; $i<$N;$i++)
{
RenderlntoNewWindow;
renderWindowSavelmageCallback "renderView" ( $fname + $i + ".iff" ) "image";
currentTime ("currentTime -q +1);;
}
currentTime ('currentTime -q' - $N);
string $cmd = "fcheck -n 0 "+($N-1)+ " 1 "+ ( $fname + "@.iff" );
system($cmd);
Те же, кто хотят делать свои дела на MEL не только быстро, но и красиво, наверняка
жаждут написать к своим мощным алгоритмам еще и изысканный интерфейс. Тем более, что
многие слышали, что интерфейс самой AAAYA, все ее окошки, менюшки, списки и кнопки написаны
также на MEL, поэтому созданные пользователем элементы интерфейса будут «родными» для
MAYA, как по визуальному стилю, так и по логике использования.
Сцена называется dropPreset.ma и состоит из системы частиц и двух полей типа Radial,
испускаемых из самих частиц и к тому влияющих на частицы. (Те, кто потерял файл или диск,
могут просто создать систему частиц и два любых поля.)
window;
showWindow;
Чтобы добавить какие-нибудь элементы интерфейса в окно, надо задать, каким образом
они будут располагаться в нем: в столбец, в строку, в виде таблицы или еще как-нибудь. Способ
расположения элементов в окне называется Layout и определяется соответствующей командой:
window;
columnLayout;
attrFieldSliderGrp -at pushField.mag;
showWindow;
Удалите окно (нажав на крестик) и добавьте еще пару строк в Script Editor
window;
columnLayout;
attrFieldSliderGrp -at pushField.mag;
attrFieldSliderGrp -at pushField.att;
attrFieldSliderGrp -at pushField.max;
showWindow;
Как видите, логика достаточно прозрачная, надо лишь правильно указать полное имя
атрибута. Короткое или длинное, не имеет разницы.
Пытливейшие умы успеют быстро метнуться в описание команды window и найти там флаг
-t (-title), позволяющий задать заголовок окна вместо стандартного windowN.
Если скопировать и добавить еще три команды, создающие поля для трех атрибутов
другого поля, встанет вопрос о том, как различать атрибуты разных полей в окне. (Не забудьте
отредактировать min/max для magnitude второго поля.)
Можно также пытаться с помощью флага -I изменять подписи у полей со слайдерами, однако
наблюдательные умы наверняка заметят, что в Attribute Editor есть очень удобные открывающиеся
Закройте окно. В Script Editor уберите строки с разделительной линией и текстом и добавьте
еще пару строк в начале скрипта:
Однако нам нужно сделать два раздела, по одному для каждого поля. Следовательно,
Представьте себе, что окно это рамка (window), куда вы вставляете лист картона (column-
Layout), чтобы на нем что-нибудь написать или прикрепить.
На этот лист вы крепите еще две рамки (frameLayout), в которые вставлены свои листы картона
(columnLayout), на которых друг под другом закреплены таблички attrFieldSliderGrp.
Команда setPatent ..; осуществляет переход на предыдущий уровень. Две точки «..»
используются по аналогии с командой cd операционный системы, когда набрав в командной строке
Windows или Unix «cd ..», вы попадаете в предыдущий (родительский) каталог.
Таким образом первая команда setPatent ..; перемещает нас (готовых клеить новые
элементы в окно) на уровень frameLayout, а вторая команда setPatent..; переводит нас на уровень
основного columnLayout, на котором мы снова создаем второй frameLayout и т.д.
В принципе у всех элементов интерфейса есть уникальные имена, задать которые можно,
просто добавив название в конец команд, создающей элемент. Зная имя элемента (например, имя
для columnLayout), можно использовать команду setPatent с конкретным именем, чтобы сразу
перейти на нужный уровень (снова сравните с командой cd).
Однако взрослые мальчики так обычно не пишут, потому что теряется последовательность
программы, а внезапные переходы сразу на конкретный уровень напоминают команду goto,
запрещенную уже во всех цивилизованных странах.
setParent..;
setParent..;
напоминает вложенные блоки, где вместо фигурных скобок используются команды setParent.
Как видите, для удаления элементов интерфейса существует команда deleteUI, для которой
достаточно указать имя элемента. Называть собственные элементы я предпочитаю большими
буквами, чтобы гарантированно не перепутать их со стандартными, используемыми MAYA. Команда
window -ex DROP_WINDOW вернет единицу, если окно с таким именем существует. Кавычки по-
прежнему нужны, чтобы получить возвращаемое значение и сравнить его с единицей.
Работа с кнопками
Добавьте в окно еще один раздел для работы с атрибутом conserve у системы частиц.
После окончания этого раздела (то есть после двух команд setParent..;) добавьте четыре кнопки
командой button с флагом - I , задающим надпись на кнопке.
showWindow DROP_WINDOW;
Как видите, дизайн нижней части окна оставляет желать лучшего. Если с шириной
кнопок все более-менее понятно (флаг -w), то для расположения их в одну строку проще всего
воспользоваться схемой расположения gridLayout, которая расставляет элементы в виде таблицы
с заданным количеством столбцов.
showWindow DROP_WINDOW;
Названия флагов команды gridLayout говорят сами за себя. Чтобы кнопка выполняла
какое-нибудь действие, необходимо привязать к ней команду (или набор команд). Это делается
с помощью флага -с, поэтому пытливые умы быстро сообразят, что для того, чтобы закрыть окно
кнопкой Close, надо добавить к соответствующей команде button строку, содержащую команду
удаления окна.
В строке, идущей за флагом -с, может содержаться несколько команд, разделенных точкой
с запятой. Однако если команд будет слишком много, будет неудобно писать такую длинную
строку. В этом случае удобнее объединить набор команд в процедуру и вызвать ее по имени при
нажатии кнопки.
Добавьте к кнопке Reset вызов некоторой команды resetAll, а в самый низ скрипта добавьте
следующие строки:
Выделив и выполнив весь скрипт, вы теперь можете смело «портить» значения всех
атрибутов в окне, а затем нажать кнопку Reset и убедиться, что все атрибуты вернулись к исходным
значениям.
Запоздалый совет. Чтобы не набивать вручную семь команд setAttr можно просто забить
значения атрибутов в нашем окне, а потом посмотреть, что MAYA написала в Script Editor.
Конструкция
Вызов объявленной процедуры (или команды, что пока одно и тоже) производится так же,
как и для остальных команд - выделением ее имени и выполнением.
Можете убедиться в этом сами, выделив слово resetAll в Script Editor и нажав нужный Enter.
MAYA каждый раз будет ругаться на попытку вызова команд resetAll, например, по нажатию
кнопки
Каждый раз когда MAYA встречает незнакомую ей команду, она в первую очередь проверяет
таблицу объявленных пользователем процедур и если имя команды там отсутствует, MAYA начинает,
как правило, ругаться.
Еще раз повторюсь, что процедура - удобный способ объединить большой набор команд в
один блок, для того, чтобы вызывать его потом неоднократно. И прежде, чем вызвать процедуру,
она должна быть обязательно объявлена. Чтобы изменить действие процедуры, достаточно ее
отредактировать и переобъявить.
Обратите внимание, что косые черты в имени папки - прямые, как в Unix, а не обратные,
как в Windows. Это важно.
Команда fopen открывает файл с указанным в качестве первого аргумента именем. Второй
аргумент («w») определяет, что файл открывается для записи, то есть что все его содержимое
при открытии стирается. Причем команда fopen возвращает уникальный номер только что
открытого файла, на который будут ссылаться все дальнейшие команды чтения-записи в файл.
Для любопытствующих умов замечу, что операционная система работает не с текстовыми именами
файлов, а с их номерами (каналами), поэтому при открытии файла для работы ему присваивается
уникальный номер, возвращаемый командой fopen.
Представляйте себе мысленно открытие файла в скрипте как открытие нового документа
в MS Word или Notepad.
Если на экран значения переменных можно вывести командой print, то в файл их можно
напечатать командой fprint
Если наша кнопка Save отработала без ошибок, то есть выдала список файлов, в котором
вы указали файл для записи и нажали Open, можете открыть указанный вами файл и обнаружить,
что MAYA напечатала туда все значения атрибутов друг за другом, в одну строку, как в общем-то и
следовало ожидать.
3942-6450.9
Осталось напечатать после каждого значения «перевод каретки», то есть перейти на следующую
строку в файле. Это можно сделать, напечатав специальный невидимый символ, обозначаемый
как «\п», который просто переводит курсор на следующую строку (когда работаете с командой
print, представляйте, что печатаете на клавиатуре, и когда нужно нажать Enter, используете
выражение print «\n»). Чтобы не добавлять дополнительную команду frpint «\n», просто прибавим
этот спецсимвол к печатаемому значению атрибута. В результате получится строка, состоящая из
цифр и спецсимвола, которая будет печататься в файл.
Объяснение сути этой проблемы, честно говоря, совершенно не касаемо MAYA, а относится
к операционной системе Windows (и DOS). Приведу лишь решение проблемы. При записи в файл
для перевода строки надо добавлять два спецсимвола «\r\n», то есть вот так:
Любители компактного кода быстро сообразят, что можно выкинуть одно присвоение и
запихнуть команду getAttr прямо внутрь команды fprint.
Как вы уже знаете, спецсимвол «\n», встречающийся внутри строки, переводит печать на
новую строку:
Если вам надо поместить внутрь строки символ двойной кавычки, это тоже делается через
обратную косую черту перед знаком кавычки, ведь просто поставив кавычку внутри строки, вы
просто закончите строку и получите сообщение об ошибке. Таким образом «V», тоже является
Пытливые умы наверняка догадаются, что для того, чтобы напечатать или запихнуть внутрь
строки обратную косую черту, надо перед ней поставить еще одну обратную косую черту, иначе
MAYA будет пытаться трактовать символ, следующий за одиночной косой чертой, как спецсимвол.
Двойная обратная косая черта трактуется как одиночная.
Если после обратной косой черты стоит любой другой символ, кроме n, r, t, \ или ", то он
не трактуется как спецсимвол и печатается без изменений, а косая черта при этом опускается.
print "c:\temp\fromPC\disk8\NewFolder\system\network\driveC\docs";
с: empfromPCdisk8NewFoldersystemetworkdriveCdocs
Текст любой команды может располагаться хоть на пяти строках, лишь бы в конце была точка
с запятой. Однако если вы присваиваете строке длинное значение и хотите расположить команду
присваивания на нескольких строках, перенос тела строки на новую строчку осуществляется также
при помощи обратной косой черты.
Процедуру saveAll придется разбить на две процедуры, так как fileBrowserDialog требует
объявления дополнительной процедуры, которая вызывается при нажатии на кнопку в окне
файлового диалога. Выглядеть это будет так:
button -I "Save" -w 94
-с "fileBrowserDialog -m 1 -fc \"saveAttr\" -an \"Save_Attr\" -ft \"text\";";
fclose $fileNumber;
}
Обратите внимание, что в аргументах команды fopen необходимо указать параметр "г",
определяющий, что файл открывается только на чтение и что его содержимое изменяться не
будет.
в правой части происходит чтение строки из файла, которая преобразуется в число оператором
присваивания «=», так как слева от него стоит переменная типа float.
Команда fgetline читает строку из файла, номер которого указан в качестве аргумента,
и переводит курсор на следующую строку, так что следующий вызов fgetline будет читать новую
строку.
Для взрослых. Проверить достижение конца файла можно командой eof , а возвратиться к
его началу командой rewind.
Любители запихать все в одну строку могут скомпрессировать наш код в следующую
процедуру:
Держать такое огромное количество строк в Script Editor, естественно, неудобно. Можно,
конечно, выделить весь нужный текст в Script Editor и забросить его на полку (shelf) одним
движением мыши. Однако мы поступим более традиционным способом. Оформим весь наш скрипт,
рисующий окно, в виде процедуры и будем вызывать его по имени этой процедуры.
showWindow DROP_WINDOW;
} // end of dropAttrWindow procedure
//////////////////////////////////////////////////////////
global proc resetAll()
{
setAttr "pushField.magnitude" 39;
setAttr "pushField.attenuation" 4;
setAttr "pushField.maxDistance" 2;
setAttr "pullField. magnitude" -6;
setAttr "pullField.attenuation" 4;
setAttr "pullField.maxDistance" 5;
setAttr "dropShape.conserve" 0.9;
}
//////////////////////////////////////////////////////////
global proc saveAll()
{
string $fileName = 'fileDialog -dm "c:/temp/" ';
int $fileNumber = 'fopen $fileName "w" ';
fprint $fileNumber ('getAttr "pushField.magnitude" '+"\r\n");
fprint $fileNumber ('getAttr "pushField.attenuation" "+"\r\n");
fprint $fileNumber ("getAttr "pushField.maxDistance" '+"\r\n");
fprint $fileNumber ('getAttr "pullField.magnitude" '+"\r\n");
fprint $fileNumber ('getAttr "pullField.attenuation" '+"\r\n");
fprint $fileNumber ('getAttr "pullField.maxDistance" '+"\r\n");
fprint $fileNumber ('getAttr "dropShape.conserve" '+"\r\n");
fclose $fileNumber;
}
//////////////////////////////////////////////////////////
global proc loadAll()
{
string $fileName = 'fileDialog -dm "c:/temp/" ';
Если теперь выделить и выполнить приведенный выше код, то ничего, очевидно, на экране
не появится. Произойдет лишь объявление четырех процедур, после чего MAYA будет знать об их
существовании и при попытке их вызвать будет бодро их выполнять. А вызвать любую процедуру
можно по имени. Теперь достаточно набрать в Script Editor строку dropAttrWindow, выделить ее и
выполнить, как тут же на экране появится окно с атрибутами.
Однако, как заметят проницательные умы, это будет работать пока мы не выйдем из MAYA.
Если зайти в MAYA заново, на попытку вызвать команду dropAttrWindow вы получите сообщение об
ошибке:
dropAttrWindow;
// Error: Cannot find procedure "dropAttrWindow". //
Для того, чтобы все заработало, надо снова провести объявление процедур, то есть
загрузить в Script Editor предварительно сохраненный код, описывающий все процедуры, и
выполнить его.
Однако вы, наверное, слышали, что если сохранить текст скрипта в определенном месте
с определенным именем, он будет доступен для MAYA всегда. По крайней мере, так поступают с
файлами скриптов, скачанными из Интернета.
Если вы сделали все корректно, можете выйти из MAYA, затем зайти обратно, открыть
файл с частицами (dropPreset.ma) и выполнить в Script Editor команду dropAttrWindow. При этом
появится до боли знакомое окно с атрибутами.
Сейчас я хочу остановиться более подробно на том, что происходит, когда вы вызываете
на выполнение какую-нибудь команду.
Итак, вы, предположим, открыли MAYA, набрали в Script Editor некоторую команду
(например, dropAttrWindow) и попытались ее выполнить.
i
И если объявление процедуры с таким именем будет найдено в памяти, эта процедура будет
немедленно выполнена.
2. Если процедура с таким именем до сих пор не была объявлена, MAYA проверяет, не
является ли эта команда стандартной майской командой типа print или Is. Если да, то понятно, что
происходит.
6. Если его не обнаруживается и там, тогда MAYA радостно ругается о том, что не может
найти процедуру с указанным именем.
Иногда выполняемая команда требует аргументов при запуске, например «superscript 1»,
и в этом случае либо выдается подсказка (если скрипт грамотно написан), либо надо открывать
текст скрипта и искать там описание процедуры global proc superScript( . . . ), и разбираться, как
она устроена, и что ей требуется указать в качестве входных аргументов.
Чтобы загрузить изменения, только что сделанные в файле, не перезапуская MAYA, надо
принудительно выполнить скрипт из файла. Эта операция называется Source Script и находится в
меню File окна Script Editor. Все команды из указанного фала просто выполняются, поэтому если в
файле находятся только объявления процедур, они обновляются в памяти, а если набор команд,
то эти команды выполняются.
Более того, хочется, чтобы такой скрипт выполнялся каждый раз при открытии сцены и мы
имели бы, например, интерфейс для работы с атрибутами объектов.
Чтобы сохранить набор команд вместе со сценой, надо создать объект типа Script Node.
Это делается при помощи Expression Editor.
В текстовое поле следует просто вписать набор команд и нажать кнопку Create.
При этом писать следует именно скрипт, а не expression. To есть фамильярности типа
$x=pCube1.tx недопустимы.
dropAttrWindow;
Поэтому проще и удобнее скопировать в поле Script: все содержимое файла dropAttrWin
dow.mel и дополнить его в конце вызовом команды dropAttrWindow:
showWindow DROP_WINDOW;
}
//////////////////////////////////////////////////////////
global proc resetAll()
{
setAttr "pushField.magnitude" 39;
setAttr "pushField.attenuation" 4;
setAttr "pushField.maxDistance" 2;
setAttr "pullField.magnitude" -6;
setAttr "pullField.attenuation" 4;
setAttr "pullField.maxDistance" 5;
setAttr "dropShape.conserve" 0.9;
}
//////////////////////////////////////////////////////////
global proc saveAll()
{
string $fileName = 'fileDialog -dm "c:/temp/" ';
int $fileNumber = 'fopen $fileName "w" ';
fprint $fileNumber (getAttr "pushField.magnitude" '+"\r\n");
fprint $fileNumber ('getAttr "pushField.attenuation" '+"\r\n");
После этого следует немедленно нажать кнопку Create и получить новый объект типа Script
Node с именем scriptl.
Осталось решить, когда созданный объект Script Node будет выполняться. Пока он просто
сохранился в недрах сцены и выполняется только по нашему требованию при нажатии на кнопку
Test Script. В отличие от expressions, он не будет выполняться при смене кадра, если только мы
его об этом не попросим.
Чтобы задать, когда созданный объект-скрипт будет выполняться, выберите в списке Ex
ecute On: пункт GUI Open/Close.
Это означает, что скрипт будет выполняться каждый раз при открытии (или закрытии)
сцены в MAYA.
Остальные пункты в списке Execute On: позволяют выполнять Script Node при открытии
сцены не только в интерфейсе MAYA, но и при постановке на рендеринг. Опция Time Changed
превращает такой скрипт в банальный expression, выполняющийся каждый раз при смене кадра.
Сейчас нужно обязательно сохранить сцену, ведь мы создали новый объект!
Естественно, что скрипты, сохраняемые со сценой, должны, как правило, иметь дело
с содержанием сцены: рисовать интерфейс для работы с объектами, проверять глобальные
установки, удалять или создавать кэш-файлы, вставать в первый кадр и прочее.
Если вы уже устали от рисования окошек, пропускайте этот раздел и двигайтесь в сторону
изменения стандартных майских скриптов. А я бы хотел остановиться на вопросе создания окошек,
содержащих не слайдеры, связанные с атрибутами объектов, а просто числовые поля, значения
которых можно использовать для последующих построений или вычислений.
Напомню, что вначале главы нами был написан скрипт, рисующий спираль или другую
процедурную кривую по заданной формуле.
int $NumPoints=500;
float $Amp=3.0, $Freq=2.0, $Density=10.0, $x$peed=5.0;
Немного улучшим построитель кривых, а заодно оформим его в виде процедуры, чтобы
его можно было вызывать одной командой, тем более, что мы собираемся создать окно с большой
красивой кнопкой для построения кривой.
Первые строки не требуют комментариев, это просто построение окна, уже рассмотренное
выше.
Команды intSliderGrp и floatSliderGrp создают в окне группу из текстовой метки, слайдера и
числового поля, не привязанного ни к какому атрибуту. Кроме того, эти команды имеют секретный
флаг field, который должен быть явным образом установлен в единицу, иначе числовое поле
будет спрятанным и на экране появится только слайдер с надписью.
У этих команд есть очевидный флаг value, позволяющий установить или прочитать
значение поля. В режиме создания через этот флаг задаются значения, задаваемые при появлении
окна. Две кнопки внизу окна ничем не отличаются от изученных ранее. Очевидно, что первая из
них вызывает команду-процедуру построения кривой curveBuilder.
Для того, чтобы сделать это, следует поговорить о трех режимах для команд построения
элементов интерфейса.
Для элементов интерфейса нет команды типа getAttrUI или getFlagUI, все гораздо проще
(а может, сложнее).
Для того, чтобы получить значение флага (определяющего, например, ширину кнопки),
надо после команды, используемой для создания кнопки, добавить флаг -q (-quiery). После чего
указать флаг, значение которого мы хотим получить (например, -w) и, естественно, имя элемента
интерфейса. Команда получения ширины кнопки выглядит примерно так:
Совершенно очевидно, что надо позаботиться при создании некоторых элементов, чтобы
у них были конкретные названия. Это можно сделать в режиме создания, просто добавив в самом
конце команды имя элемента.
Если вышеприведенные команды создают окно без ошибок, то дело за малым - переделать
незначительно процедуру построения кривой. Очевидно, что надо просто прочитать значения
числовых полей из окна и «засунуть» их в нужные переменные.
Чтобы прочитать значения числовых полей, надо обратиться к ним с помощью тех же
команд, что использовались при их создании, только с флагом -q, при этом запрашивать надо
значение флага -value, содержащего числовое значение.
Посмотрим, как можно также обновлять свойства элементов в окне. Я напомню, что скрипты
подобного типа довольно активно поедают память, особенно если у вас задана бесконечная
очередь Undo. Чтобы контролировать расход памяти, добавим еще одно числовое поле, которое
будет содержать количество свободной памяти и будет обновляться после каждого построения
кривой. Команда, с помощью которой можно узнать у MAYA, сколько, по ее мнению, еще есть
свободной памяти, называется memory.
Добавим также кнопку, которая будет очищать очередь Undo, это банальная задача, надо
только не забыть увеличить количество столбцов до трех в gridLayout.
Дополнительно добавим в окно галку, которая будет включать обновление экрана во время
построения кривой. Галка добавляется командой checkBox, однако лучше использовать команду
checkBoxGrp, так как она располагает метку слева от галки и лучше вписывается в дизайн нашего
окна. Кроме того, она позволяет создавать до четырех галок одновременно, поэтому для задания
значения галки (то есть для включения/выключения) надо использовать флаг -valuel, а не -value.
В цикле для построения кривой должна быть проверка типа:
Так как внезапно обнаружилось, что команда memory возвращает массив чисел, то
пришлось создать маленькую процедуру updateMemoryField, которая берет первый элемент этого
массива и обновляет текстовое поле, содержащее количество свободной памяти. Эту процедуру
удобно вызывать сразу после построения кривой, а также после нажатия кнопки Flush Undo.
Теперь, очевидно, следует сохранить получившийся скрипт как текстовый файл под
названием curveBuilder.mel и вызывать его командой curveBuilder.
Созданная кривая имеет третью степень по умолчанию, так как флаг d был опущен при
добавлении первой точки к кривой.
Еще более взрослые мальчики обнаружат, что у сплайновых кривых есть удивительный
атрибут .nurbsCurve, содержащий полное описание самой кривой в виде набора данных (см.
документацию к команде setAttr). В атрибут можно «запихать» все описание кривой одной
командой setAttr, и тем самым мгновенно построить (или перестроить) кривую целиком.
Поставим простую задачу: в майском меню Window последние пункты отвечают за работу с
открытыми окнами, но среди них нет команды, позволяющей быстро минимизировать все открытые
окна. А такая потребность возникает довольно часто. Напишем сначала такую процедуру, а потом
добавим ее в основное меню MAYA.
Если вы помните, мы удаляли элементы интерфейса командой deleteUI, это наводит нас
на мысль, что существуют и другие полезные команды с суффиксом UI для работы с окнами и их
элементами.
Точно так же, как для получения списка объектов в сцене существует команда Is, так и
для работы со списками существующих окон, меню и других элементов интерфейса есть команда
IsUI.
Ее надо использовать с одним из необходимых флагов. Например, для получения созданных
в MAYA окон нужно выполнить:
IsUI -wnd;
// Result: AEWindow CURVE_BUILDER CommandWindow MayaWindow //
Дальше можно пустить в ход уже отлаженную выше технологию для работы со списком
объектов в цикле. Необходимо перебрать список и минимизировать все окна, кроме основного
окна MAYA. Минимизировать любое окно можно, просто установив его «минимизированность» в
единицу, то есть изменив значение флага -iconify (такой флаг есть у команды window).
string $it;
string $windows[] = 'IsUI -windows';
for ($it in $windows)
{
if ($it != "MayaWindow")
{
window -e -iconify 1 $it;
Откройте побольше окон и выполните эти содержательные строки - все окна слетятся в
нижнюю часть экрана.
string $it;
for ($it in 'IsUI -wnd') if ($it != "MayaWindow") window -e -i 1 $it;
Для того, чтобы ловко вызывать написанные строки, оформим их в виде процедуры minAll-
Win и сохраним в файле minAllWin.mel на диске в пользовательской папке scripts, где этот файл
будет виден для MAYA как скрипт.
Теперь можно минимизировать все окна простой командой minAllWin. На мои предложения
повесить эту команду на горячую клавишу или на кнопку на полке, настоящие MEL-маньяки с
негодованием возопят: «Хотим добавить команду в основное майское меню Window!». Что ж,
желание маньяка - закон...
IsUI -menus;
// Result: AEdeformersSubMenu AEdynamicsSubMenu AEhelpMenu AEkinematicsSubMenu AElightSub-
Menu AEshadingSubMenu
Удобнее, кстати, сделать это «в столбик», с помощью команды print, печатающей массив
строк, возвращаемый командой IsUI
Почитав полученный список, можно найти в нем строки начинающиеся на слово main. Это
и есть названия всех меню из главного окна MAYA. Нас интересует меню с названием mainWindow-
Menu.
Если мы знаем название меню, то добавить к нему дополнительный пункт можно командой
menultem, в которой надо указать, к какому меню мы собираемся добавить новый пункт.
Для меню, точно так же, как и для кнопки, с помощью флагов -I и -с указываются текстовое
deleteUI MINALLWIN;
начисто удалит авторский пункт меню и вернет меню Window прежний вид.
Даже если вы еще не объявили процедуру minAllWin, новый пункт меню все равно
добавится, только будет выдавать сообщение об ошибке при попытке его выполнить.
Если вы хотите добавить совершенно новое меню в окно MAYA, следует использовать
команду menu, а в качестве родителя (флаг -parent) указать главное окно MAYA. Например:
Для взрослых. Для команд работы с меню есть вариант команды setParent, позволяющий
указать, к какому меню мы собираеся последовательно добавлять новые пункты командами menu-
Item. Для этого достаточно выполнить
Совет. Давайте своим меню осмысленные имена. Это позволит вам удалить их
позже - или отредактировать.
В заключение могу добавить, что если вы хотите добавлять меню в свои окна, при создании
окна следует включить флаг -menubar, выключенный по умолчанию. Например:
Сохраните файл в вашей папке scripts, чтобы он был виден для MAYA.
Перегрузите MAYA.
Важно знать о том, что все команды из файла userSetup.mel выполняются до открытия
новой сцены. Если вы написали в этом файле строки, создающие новые объекты или меняющие
значения атрибутов существующих объектов (например, стандартных камер), они не будут иметь
никакого эффекта, так как MAYA создаст новую сцену после выполнения команд из файла user
Setup.mel.
Если вы хотите, чтобы в вашей новой сцене всегда создавался новый объект(ы) (например,
камера bottom) вы должны добавить нужные команды в файл initAfter.mel, который можно
Приведу пример для начинающих хакеров, как «подправлять» интерфейс MAYA безопасными
методами, а заодно, как искать нужные для редактирования файлы.
Если вы нажимаете над объектом на экране правую кнопку мыши, появляется контекстное
меню, которое вы, предположим, хотите дополнить. Иногда удобно бывает спрятать или удалить
объект, не выбирая его (например, вы уже выбрали нужные вершины и хотите спрятать мешающий
объект, чтобы продолжить выбор вершин). Добавим в это меню пару пунктов. Как добраться до
этого меню? В каком родном майском файле оно описано.
Получив список файлов, методом пристального взгляда или методом перебора определяем,
что нам нужен файл dagMenuProc.mel.
Чтобы вернуться к исходному варианту меню, вам не надо снова открывать файл и
комментировать или удалять так нужные строки. Достаточно просто переименовать его. После
этого MAYA после перезапуска перестанет находить описание процедуры dagMenuProc в вашей
папке и отправится искать ее в свои папки, где лежит оригинальная версия.
О глобальных переменных
Иногда вам могут понадобиться глобальные переменные, чтобы иметь возможность
запоминать данные вне процедур и блоков.
}
// —
global proc fun2()
{
global int $GlobalValue;
int $b;
Конечно, удобно открывать справочники и учебники прямо в панели MAYA, однако наличие
браузера имеет еще много дополнительных и не сразу очевидных преимуществ.
window;
columnLayout;
webBrowser -width 800 -height 600
-url "file:///C:/Program Files/Alias/Maya6.5/bin/res/intro/intro.html";
showWindow;
В-четвертых, вам все же хочется иметь на странице поля и кнопки, вы можете использовать
javascript вкупе с каким-нибудь визуальным построителем интерфейсов. При условии, что вам,
конечно, знаком javascript.
В-пятых, Macromedia Flash легко прикручивается к майскому браузеру (надо лишь при
установке указать, вместо дефолтной, папку типа
C:\Program Files\Alias\MayaN.N\bin\plugins
в которой содержится информация о встроенном браузере). После этого вы можете использовать
все возможности Flash для создания интерфейсов.
Прежде, чем писать скрипт, вы должны хорошо себе представлять, что конкретно он
должен делать. Затем нужно найти в документации (или методом опроса знакомых) нужные
команды и организовать их в нужном порядке. Для этого вам могут понадобиться четыре вещи.
Во-вторых, условные переходы типа if() {} else{}, для сравнения данных и выполнения
наборов команд при выполнении определенных условий.
В-третьих, циклы для повторения набора команд нужное количество раз и для перебора
объектов в списке.
В-четвертых, процедуры, позволяющие объявить целый набор команд в виде одной MEL-
команды.
Освоив эти приемы, вы можете писать довольно непростые скрипты, постоянно расширяя
свои возможности с помощью чтения документации и чужих программ.
4. Для хоть какой-то защиты от бесконечных циклов есть несколько вариантов. Первый
- официальный: использовать команду progressBar с флагом -islnterruptable для работы с main
progress bar (см. описание команды progressBar). Второй - неофициальный: нужно скачать
плагин keylnterrupt с сайта www.highend3d.com и использовать в цикле функцию опроса нажатых
клавищ.
if(objExists("myCurve")) { . . . }
8. Если вы открываете новое окно, проверьте, не открыто ли оно уже. И в случае его
существования, удалите его, чтобы всегда создавать только одну копию окна. Для этого не
забывайте давать окнам имена.
10. Мировые координаты компонент (например, вершин) можно узнать с помощью команд
pointPosition или xf orm. Последняя команда - исключительна полезна для работы с трансформациями
и пивотами.
11. Команда eval (или evalEcho) позволяет выполнить любую переменную, содержащую
строку, как MEL-команду. Ее удобно использовать при построении кривых или поверхностей,
накапливая длинную строку в цикле, а потом выполняя ее одним махом, как команду.
12. Вот несколько полезных команд, наличие которых не так очевидно и отыскать
которые методом тыка не всегда возможно:
13. Последний совет специально для исследователей MEL. Как можно чаще используйте
команду whatls. Если она вдруг выдаст странный ответ типа Run Time Command:
whatls RenderlntoNewWindow;
// Result: Run Time Command //
runTimeCommand -q -с RenderlntoNewWindow;
// Result: renderlntoNewWindow render //
whatls renderlntoNewWindow;
// Result: Mel procedure found in: C:/Program Files/Atias/Maya9.5/scripts/others/renderWindowPan-
el.mel //
За день до отлета, поздним вечером, я, как обычно, сидел за двумя своими компьютерами
и неистово нажимал кнопки, рисуя в уме нечеловеческие красоты французской столицы. И тут в
комнату зашел мой начальник, однокурсник Гриша, и, увидев меня за компьютерами, удивленно
спросил: «Ты ведь завтра летишь в Париж?». Я довольно кивнул. Следующий вопрос был уже
менее понятен: «Ты что, так полетишь в Париж?». Глядя на мои вопросительно ползущие брови,
Гриша уточнил: «Ты что, полетишь в Париж в таком виде?». Надо сказать, что вид у меня был
вполне технический: любимая футболка-долгожитель, довольно целые джинсы и очень длинные
волосы. Гриша, человек хорошего вкуса и легкого пижонства, тоже, очевидно, мысленно наделял
Париж какими-то сверхестественными романтическими свойствами и ему, Грише, казалось
кощунственным лететь туда, не одевшись соответственно и не приведя себя в соответствие с
иллюзорными представлениями.
Когда мы вернулись назад, наш завскладом (мой очередной однокурсник Джон) взглянув
на меня, появившегося в проеме двери офиса, вежливо спросил: «Вы из какой компании? Получать
или заказывать?». Потом он долго корил меня за то, что я не хожу в таком виде на работу каждый
день. По его мнению, все девушки прилегающих к офису районов были бы счастливы и невменяемы
при одном только моем появлении. (Джон, кстати, сам ходил на работу в галстуке.)
Честно сказать, я сам себя плохо узнавал в новом обличье. Чувство какой-то незащищенности
усугублялось короткой прической, а при попытке сесть на рабочее место галстук от Юдашкина
агрессивно бросался на клавиатуру.
Однако на следующий день, я, напялив на себя для пущей важности модный белый
плащ, вылетел рейсом Москва-Париж. Прибыл я на место довольно поздно и, добравшись до
шедеврально-урбанистического района Ля Дефанс, разместился в Новотеле и уснул, как убитый,
переполненный впечатлениями и ожиданиями.
Каково же было мое удивление, разочарование, смущение, ярость и досада, когда утром,
облачившись в свои романтические доспехи, я спустился в холл и попал с общество остальных
специалистов, приехавших на семинар. Стоит ли упоминать, что все они были одеты в любимые
футболки и архетипичные джинсы. Я клял Гришу, Джона и себя за лубочный образ мысли,
мчась по коридору и срывая с себя чужеродные покровы. Хорошо хоть нормальная одежда была
благоразумно захвачена с собой, и скоро я уже чувствовал себя в своей тарелке, поскрипывая
старыми коссовками. Волосы, правда, пришлось отращивать целый год.
С тех пор меня совершенно не тянет в Париж. А также в парикмахерскую. Ну, и на Новый Арбат...
Paint Effects
Рисовальные эффекты
Именно так зачастую переводят название модуля Paint Effects.
В основе Paint Effects лежит понятие штриха (Stroke), который можно нарисовать на любой
поверхности, на обычной двумерной плоскости или просто в произвольной области трехмерного
пространства. В первом и последнем случаях это кривая на поверхности или в ЗD-пространстве,
обладающая набором свойств, определяющих, как этот штрих будет выглядеть и как будет вести
себя в сцене. Если это штрих, из которого должны расти деревья или волосы, то при любом
положении камеры это будут настоящие деревья или волосы, которые еще и развеваются на ветру и
имеют набор динамических характеристик, таких, как упругость или плотность. Трюк заключается
в том, что трехмерные поверхности в данном случае не используются, а в каждый момент времени
с чудовищной скоростью генерируется плоское изображение процедурного трехмерного объекта,
каким он должен быть в этом месте - с учетом положения камеры, источников света, анимации,
динамики и пр. Если сделать облет такого объекта, скажем дерева, то получится совершенно
корректная картина, с трехмерным объектом в центре.
В понятие "кисть" (brush) в данном случае входит набор свойств, которыми обладают
оставляемые ею штрихи. Кроме упомянутых деревьев и волос, рисовать можно огнем, молниями,
различными растениями, жирными трехмерными мазками масляных красок, макаронами (да-да!),
водой, снегом и много еще чем. Это лишь часть кистей, уже имеющихся в Paint Effects, но ведь
кисти можно модифицировать, делать новые, можно смешивать их между собой и, естественно,
сохранять, создавая свои библиотеки. Рисовать можно и текстурами, которые накладываются
вдоль штриха различными способами. Коль скоро вид штриха определяется набором его
атрибутов, то различные кисти - это просто MEL-скрипты, заполняющие атрибуты определенными
значениями. Для удобства атрибуты разбиты на функциональные группы, отвечающие за размер
кисти, цвет и текстурирование, тени, иллюминацию, свечение, топологию создания и анимацию
роста при рисовании, поведение и силы взаимодействия, скручивание, жесткость и множество
других параметров. Естественно, что для штрихов определяется чувствительность к нажатию - в
случае использования пера. Созданные таким образом объекты могут отбрасывать тени на себя
и окружающие поверхности, могут деформироваться при помощи обычных сплайновых кривых,
способны конвертироваться в полигоны и обладают массой удивительных свойств.
Анимация 955
движениями мыши или пера измазать всю перспективную камеру, время от времени меняя кисти.
Можно также изредка нажимать кнопку Render и исторгать восхищенные возгласы или крики
отвращения.
Не забывайте, что во время рисования у вас в руках инструмент Paint Effects Tool, и чтобы
избавиться от него, достаточно выбрать Select Tool или нажать ' q ' .
Имейте в виду, что можно рисовать не только «по земле», но по любой поверхности. Для
этого достаточно предварительно выбрать ее и сделать «рисуемой»: Paint Effects=>Make Paintable,
а затем продолжить эксперименты, уже проводя штрихи на ней.
Если вы нажмете клавишу '8', то попадете в панель Paint Effects. Конечно, очень здорово
наблюдать штрихи Paint Effects прямо во время рисования такими же, какими они выглядят
при рендеринге. Однако будьте готовы к странным перерисовкам экрана, подвисаниям MAYA и
прочим мелким неприятностям, особенно если у вас не самая свежая видеокарта. Я использую
этот режим, только для обычного плоского рисования (Paint=>Paint Canvas). В других случаях, я
стараюсь не нажимать '8' и не использовать Panels=>Panel=>Paint Effects. Кстати, чтобы вернуться
в нормальный режим, надо просто снова нажать '8'.
С одной стороны Paint Effects - это средство создания трехмерных объектов. Благодаря
возможности конвертации любого штриха в полигональную поверхность, можно с уверенностью
отнести Paint Effects к средствам моделирования.
Для особо эстетствующих умов я бы мог назвать Paint Effects L-системой с человеческим лицом.
Судя по тому, что сами разработчики запихали меню Paint Effects в режим Rendering, для них этот
модуль ближе всего к визуализации.
Впрочем, как бы мы ни назвали модуль Paint Effects, это никак не повлияет на его возможные
применения.
Дело в том, что невозможно назвать, для чего конкретно лучше всего использовать Paint
Effects, так же, как нельзя сказать, что лошади в MAYA получаются отлично, а вот чайники - так
себе. Вы должны сами определить границы использования Paint Effects, экспериментируя с их
многочисленными атрибутами.
Чтобы не попасть под огонь критики, я просто приблизительно переведу список категорий
кистей, доступных в стандартной поставке. Итак с помощью Paint Effects можно распылять краски,
красить шкуры животных, делать постройки, облака, электрические эффекты, перья, волокно,
огонь, плоть и кровь, цветы, продукты питания, разные глупости, галактики, стекло, свечения,
травку, волосы, несъедобные жидкости, штрихи фломастеров, металл, чайники, масляные краски,
бумагу, пастельные и карандашные рисунки, мелкотравчатые растения, деревья, подводный мир,
акварели, воду, природные явления.
Так как любую кривую можно превратить в штрих Paint Effects, то задача рендеринга кривых
(wireframe rendering) решается в MAYA просто и быстро, причем внешний вид кривых определяется
параметрами кистей, включая текстуры и тени на кривых.
Paint Effects также часто применяются для создания нефотореалистичных эффектов (NPR).
Один из примеров - Tomcat Cartoon Shader (http://www.toonshade.com/), исключительно удачный
плагин к MAYA, позволяющий рендерить объекты в мультипликационном стиле.
В седьмой версии MAYA появился новый модуль MAYA Toon, для создания контуров и заливок,
основанный на технологии Paint Effects.
Штрихи Paint Effects, просчитанные отдельным слоем (и, возможно, с анимацией), могут
быть эффективно использованы на этапе композитинга. Например, растущие орнаменты могут
быть превращены с помощью нужных фильтров в морозные узоры, постепенно заполняющие весь
экран.
Если я добавлю, что штрихи Paint Effects можно подставлять в частицы и устраивать, к
примеру, взрыв на макаронной фабрике или салют из веток молодого дуба, то некоторые из еще
неокрепших майских пользователей испытают некоторую растерянность.
Штрих - это линия, которую пользователь рисует на экране мышью или пером.
Соответственно, штрих имеет набор атрибутов (как и любой объект в MAYA), определяющий его
свойства.
Надо понимать, что в основе штриха, даже можно сказать «под штрихом», всегда
лежит реальная сплайновая кривая. Она, как правило, спрятана (hidden), поэтому на экране не
отображается. Далее я буду употреблять термин «нижележащая кривая» (Stroke Path Curve),
напоминающий о том, что штрих это всегда пара, состоящая из кривой и ноды типа stroke.
Такая кривая всегда создается в момент рисования штриха. По умолчанию она имеет
вторую степень, однако вы можете проделать с ней любые безнравственные действия с помощью
операций редактирования сплайновых кривых (меню Edit Curves).
Сам по себе штрих - это не кривая, а нода типа stroke со своими атрибутами, которая
«лежит» на кривой, и определяет свойства самого штриха. Ее атрибуты появляются, как правило,
во второй закладке в Attribute Editor, в то время как в третьей закладке находятся атрибуты
кисти.
Начало и конец штриха на кривой определяют атрибуты Min Clip и Max Clip. Штрих может
начинаться в середине нижележащей кривой. Эти атрибуты очень удобно использовать для
анимации «ползущих» или «растущих» штрихов.
Нижележащая кривая всегда имеет нормаль, поэтому при выключенном атрибуте Use Nor
mal, штрих будет использовать именно нормаль с кривой, а при включенном фиксированное
направление нормали, заданное в поле Normal. Нормаль нужна в тех случаях, когда из штриха
что-то растет, чтобы определить направление «произрастания».
Если штрих нарисован на поверхности (или на плоскости сетки), то атрибут Surface Offset
позволяет «утопить» весь штрих или же приподнять его над этой поверхностью.
Не сомневаюсь, что некоторые пытливые умы уже изнемогают от желания задать вопрос,
ответ на который звучит следующим образом: да, любую обычную кривую можно превратить в
штрих Paint Effects.
В общем случае, вам довольно редко придется редактировать атрибуты самого штриха
- как правило, все настройки производятся с параметрами кисти.
Для взрослых. Если вы используете перо, то при рисовании в атрибутах штриха, сохраняется
не только количество (плотность) точек, но и сила нажатия (pressure) на перо во время рисования.
Это распределение силы нажатия можно затем использовать для управления любым атрибутом
кисти в разделе Pressure Mapping.
Если вы уже поэкспериментировали с кистями, кое-кто из вас мог заметить, что все кисти,
даже радикально отличающиеся друг от друга - это все один и тот же объект, точнее нода типа
brush. Таким образом, все кисти отличаются друг от друга только значениям атрибутов для одной
и той же ноды. Если проводить навязчивую аналогию с текстурами, то все штрихи радикально
разного внешнего вида, от макарон до цветов - это все однотипные кривые, затекстурированные
одной и той же текстурой с различными значениями цвета, прозрачности, размера, ширины, шума
и массы других параметров.
Во-первых, кисти, которые вы выбираете в окне Visor - это банальные MEL-скрипты, просто
задающие нужные значения соответствующим атрибутам кисти, используемой для рисования.
В-третьих, коль скоро и макароны и цветы суть один объект с разными атрибутами,
можно организовать смешивание (!) макарон и цветов. В результате получится кисть, значения
Для того, чтобы смешать кисти, достаточно выбрать в окне Visor, к примеру, макароны, а
затем, даже ничего не рисуя, нажать правую кнопку мыши над любой другой кистью, например,
над цветами, а затем выбрать Blend Brush 50%.
После этого у вас в руках окажется кисть, состоящая из цвето-макарон. Смешивать также
можно только значения атрибутов, определяющих форму (Blend Shape) или только цвет (Blend
Shading).
Смешивание кистей
Откройте новую сцену.
В окне Visor, в разделе food выберите кисть nooddles.mel, а затем снова назначьте эту
кисть на выбранную окружность: Paint Effects=>Curve Utilities=>Attach Brush to Curves.
Из окружности полезут макароны.
Все операции, копирующие параметры кисти с выбранного штриха (Get Settings from Se
lected Stroke) или на выбранный штрих (Apply Settings to ...), используют Template Brush как буфер
для хранения параметров кисти. В этом смысле Template Brush сильно напоминает обычный буфер
обмена, куда можно скопировать выделенный текст, а затем вставить его в нужное место. Следует
постоянно помнить, что в этом буфере всегда находятся параметры какой-нибудь кисти, либо
выбранной вручную, либо скопированной с выбранного штриха при помощи операции Get Settings
from Selected Stroke.
Атрибуты кисти
Бесстрашные умы, ведомые майским принципом - изучать новый объект, исследуя
назначение его атрибутов, наверняка были несколько обескуражены количеством атрибутов
для ноды типа brush. Чтобы еще больше устрашить отважных исследователей, могу предложить
выбрать саму кисть как объект (например, нажав кнопку Select в Attribute Editor, в третьей закладке
для атрибутов кисти), а затем открыть Channel Box и почитать на досуге списочек атрибутов,
разворачивающийся до пола.
Боюсь, что у меня нет никакого хитрого совета для того, чтобы побыстрее разобраться с
устройством кистей, кроме банальной рекомендации прочитать раздел документации «Paint Ef
fects Brush Settings» (проще найти его через поиск, чем вручную), последовательно описывающий
назначение всех атрибутов кисти. Сам я когда-то распечатал эти сто страниц и неторопливо их
прочел. Я также далек от мысли переводить этот раздел на русский язык, некоторые авторы уже
пытались это делать. Приведу лишь описания ключевых для понимания атрибутов, а также тех из
них, чье использование довольно неочевидно.
Для удобства работы с такой прорвой атрибутов удобнее всего использовать Attribute Edi
tor, где они (атрибуты) разнесены по разделам. В дальнейшем я постараюсь указывать название
раздела при ссылке на тот или иной атрибут.
Если Tubes=Off, все атрибуты из раздела Tubes становятся недоступны и никак не влияют
на внешний вид штриха.
Ниже я опишу два примера для работы с простыми и «ветвистыми» кистями, а сейчас
опишу еще немного ключевых атрибутов кистей.
Атрибут Brush Width (раздел Brush Profile) изменяет только ширину штриха, что в случае
ветвистых кистей определяет окрестность вокруг штриха, из которой растут трубки.
Если задать значение Stamp Density слишком маленьким, например, равным единице, то
диски сразу станут видны.
Соответственно, чем больше Stamp Density, тем более плотным будет изображение, но
время рендеринга также будет возрастать из-за увеличивающегося количества дисков. По-другому
можно сказать, что Stamp Density определяет степень перекрытия дисков между собой.
Для просчета штрихов Paint Effects используется отдельный рендерер. Сцена, содержащая
Paint Effects, просчитывается в два прохода, отдельно для штрихов и для «нормальных» объектов.
После чего изображения штрихов и остальных объектов складываются методами композитинга с
использованием информации о глубине (Z-channel). MAYA сама занимается таким композитингом,
но если вам сильно хочется или крайне необходимо сделать это вручную, такая возможность
есть.
Достаточно в Render Globals открыть раздел Paint Effects Rendering Options и расставить
там нужным образом галки Enable Stroke Rendering и Only Render Strokes.
Однако помните, что при складывании слоев МАУА использует дополнительную инсайдерскую
информацию, полученную при рендеринге и многослойные каналы глубины (Z-depth). Поэтому,
как правило, результат композитинга слоев, сделанный MAYA, будет лучше попыток «склеить»
изображения самостоятельно в программе типа Shake или After Effects.
Тени от штрихов могут быть просчитаны методом Depth Map. Поддерживается как
отбрасывание теней на другие «реальные» поверхности, так и самозатенение. Также есть
возможность генерации быстрых «фальшивых» теней. Все атрибуты, относящиеся к теням,
находятся в разделе Shadow Effects. Естественно, что raytracing-тени не поддерживаются.
Редко кто начинает разработку кисти с нуля, то есть с параметров по умолчанию. Гораздо
проще взять уже готовую кисть, максимально подходящую для текущей задачи, и настроить ее
атрибуты так, чтобы она отвечала необходимым требованиям.
Для этого, по нажатию правой кнопки мыши, перейдите в режим Edges и выберите всю
сферу целиком.
Убедитесь в том, что группа groupl, состоящая из кривых, выбрана, и выполните операцию
Paint Effects=>Curve Utilities=>Attach Brush to Curves.
Все выбранные кривые будут превращены в штрихи, на которых назначены кисти, имеющие
точно такие же значения атрибутов, как и последняя использованная кисть, то есть кисть ballpoin
tRed.mel из буфера Template Brush.
Одна незадача. Как следует из Attribute Editor, для каждого штриха создалась своя
собственная кисть и если мы хотим редактировать внешний вид каркасной сферы, скажем так, из
одного места, то неплохо было бы «синхронизировать» все кисти, а еще проще говоря, назначить
одну кисть на все штрихи. На данный момент все штрихи имеют разные кисти, хотя и с идентичными
значениями атрибутов.
Выберите все штрихи (например, так: Edit=>Select All by Type=>Strokes), а затем выполните
операцию Paint Effects=>Share One Brush, которая возьмет кисть с последнего выбранного штриха
Теперь если выбрать любой штрих, то для него в Attribute Editor появляются атрибуты
одной и той же кисти, типа ballPointRed780.
Просчитайте изображение.
Только самые глазастые сумеют разглядеть тонкие красные линии на экране, а самые
сообразительные нажмут кнопку отображения альфа-канала, чтобы убедиться, что штрихи все-
таки отрендерились.
Просчитайте изображение.
Если вы хотите придать «проволоке» более металлический вид, задайте параметры блика
в разделе Illumination: 5pecular=0.4, Specular Power=60, Specular Соlоr=бледно-красный.
Если мы хотим назначить текстуру на цвет, надо включить галку Map Color, затем выбрать
нужный тип текстуры.
Примечание. Опция Map Displacement действует только в том случае, если тип
кисти установлен как Brush Type=Mesh. В этом случае штрих рендерится не в виде
микродисков, а как цилиндрическая полигональная трубка.
Задайте ниже атрибуты фрактала: Fractal Amplitude=5, Fractal Ratio=1, Fractal Thresholds,
так, чтобы придать цвету довольно грубый и жесткий вид.
Для этого выберите камеру persp в Outliner и откройте для нее в Attribute Editor раздел
Environment. Там задайте Background Color абсолютно белым.
Снова вернитесь к атрибутам кисти. Наиболее пытливые умы разглядели в разделе Textur
ing два атрибута для текстур, Тех Color 1 и Тех Color2, вроде как определяющих цвет текстуры, в
нашем случае фрактала. Однако несмотря на то, что эти цвета черно-белые, сфера имеет явно
выраженную красную окраску.
Дело в том, что цвета текстуры Тех Color1 и Тех Color2 умножаются на основной цвет
штриха, заданный в разделе Shading с помощью атрибута Color1. Кроме того, они дополнительно
умножаются на значение атрибута Тех Color Scale.
Поэтому если вы хотите (а вы наверняка хотите), чтобы цвет штриха целиком определялся
цветами текстуры Тех Color1 и Тех Color2, просто сделайте атрибут Color1 в разделе Shading
абсолютно белым.
Теперь можно задавать любые значения для Тех Color 1 и Тех Color2.
Нас может еще смущать, что при таком рисованном стиле штрихи выглядят слишком
«круглыми» или «трехмерными». Очевидно, что реальное освещение, заданное нами в начале,
теперь как бы мешает.
Качество рендеринга штрихов задается в Render Globals. Установки для параметра Quality,
в отличие от нормальных поверхностей, не влияют на уровень антиалиасинга штрихов.
Для того, чтобы улучшить качество рендеринга штрихов, надо в Render Globals открыть
раздел Paint Effects Rendering Options и включить галки Oversample и Oversample Post Filter.
Просчитайте картинку.
В данном случае, нас не интересуют тени от штрихов на самих штрихах, поэтому можно
не выключать опцию Use Mid Dist Dmap. В противном случае пришлось бы выключить ее и задать
значение Dmap Bias=0.2, чтобы убрать тень от плоскости на самой плоскости.
Можно задать для плоскости белый цвет, однако более красивым решением будет использование
материала Use Background.
Выберите плоскость, нажмите над ней правую кнопку мыши и выберите в меню:
Materials=>Assign New Material=> Use Background.
В атрибутах этого материала задайте Shadow Mask=0.5, чтобы сделать тень более серой.
Иконка должна принять вид выбранного региона. Теперь вы в любой момент можете
выбирать новую гениальную кисть и использовать ее в своей работе.
Попробуем сделать новую кисть с нуля. Кроме того, пусть она будет не растительного, а
животного происхождения. В процессе создания кисти разберем назначение ключевых атрибутов
и внутреннее устройство иерархических кистей. Конечно, описать все атрибуты ноды типа brush
по-прежнему не входит в мои планы, но поняв принципы организации и использования атрибутов,
можно без труда создавать собственные библиотеки кистей.
Рисование по поверхности
Сейчас мы нанесем на поверхность гениальный мазок. Этот штрих мы впоследствии
превратим в стаю муравьев, а потом даже заставим их бодро бегать. Как и в предыдущем
примере, я бы сам, пожалуй, нарисовал обычную кривую на поверхности и превратил ее в штрих
- но как же я тогда расскажу про операцию Make Paintable и про сглаживание штрихов? Поэтому в
образовательных целях начну с рассказа о том, как рисовать штрихи на поверхности,
Прежде всего «обнулите» кисть, находящуюся в буфере Template Brush. Ведь мы будем
создавать ее с нуля.
Выполните Paint Effects=>Reset Template Brush. Теперь для этой кисти заданы параметры
по умолчанию - унылый черный штрих.
Выберите поверхность и выполните Paint Effects=>Make Paintable.
Теперь все последующие штрихи будут ложиться на эту поверхность, а не на горизонтальную
плоскость XZ.
Возьмите в руки кисть: Paint Effects=>Paint Effects Tool.
Для пытливых умов замечу: чтобы увидеть сплайновую кривую, лежащую в основе штриха,
надо в Outliner показать Display=>Shapes и заглянуть в «шэйп» плоскости.
Если вновь проведенный штрих уже выбран, загляните в Attribute Editor. Так как руки у
вас наверняка дрожали от волнения (или по любой другой причине), штрих мог выйти не совсем
гладким.
Задайте в атрибутах штриха Smoothing=10, это сгладит форму штриха.
Поэтому в разделе Tubes=>Creation задайте пока Tubes per Step=0, a Start Tube=1.
В начале штриха вырастет одинокий стартовый отросток.
Коль скоро все ваши муравьи примерно одного размера, задайте Length Min=0.7, Length
Мах=0.8. Когда муравьев будет много, их длина будет варьироваться в этом диапазоне.
Предлагаю следующий выход. Коль скоро штрих пока довольно неплотный, имеет смысл
Если штрих выбран, откройте Option Box операции Modify=>Convert=>Paint Effects to Poly
gons. Задайте Vertex Color Mode=Color; Quad Output=On; Hide Strokes=Off; Poly Limit=0.
Последний параметр снимает ограничение на максимальный размер полученной при
конвертации полигональной сетки. Мы также не хотим прятать исходные штрихи.
Настройка ширины
Снова выберите штрих, и в атрибутах кисти в разделе Creation задайте Tube Widthl =0.2,
Tube Width2=0.2.
Перейдите в ниже в раздел Width Scale и, напрягая память, вспомните, как, по-вашему,
выглядит муравей в профиль. Постарайтесь, в соответствии с этими воспоминаниями, задать
график для атрибута Width Scale.
Совершенно очевидно, что для того, чтобы отразить результат воспоминаний о муравьях,
не хватает сечений на полигональной трубке,.
Совет. Старайтесь задать значение Segments с самого начала, чтобы потом его
не трогать. Так как это ключевой атрибут, определяющий количество микро
отрезков, из которых состоят штрихи, он также задает гибкость штриха. При
использовании деформаций последующее изменение значения Segments может
приводить к неожиданному скручиванию штрихов, вследствие изменившейся
гибкости и жесткости.
Включение опции Twigs (ветки) дает неплохой начальный результат для изготовления
конечностей.
Сейчас муравей, в общем, почти готов, но, правда, смотрит он куда-то вдаль. Вернем его
на путь истинный то есть поставим вдоль пути-штриха.
Установите все эти четыре атрибута (Elevation Min/Max, Azimuth Min/Max) в ноль.
Муравей, конечно, повалится на землю и даже развернется по касательной к штриху в
точке, где он произрастает. Однако на земле он будет валяться кое-как, на боку, и все усилия,
направленные на то, чтобы привести его в чувство, с помощью атрибутов из разделов Creation и
Grow, ни к чему не приведут.
Называется этот атрибут Twist Rand и искать его надо в разделе Tubes=>Behaviour=>Twist.
Это приподнимет весь штрих над поверхностью, однако имейте в виду, что муравей пока
просто громадный, и после того, как мы его радикально уменьшим (Global Scale) и размножим,
значение Surface Offset надо будет уменьшить.
Анимация листьев-конечностей
Чтобы подергать муравья за лапы, откройте раздел Leaves в атрибутах кисти и пошевелите
вручную за атрибуты Leaf Start, Leaf Anglel/2 и Leaf Twirl. Понятно, что ставить ключи на движение
лап - это безумие, поэтому нам на помощь придет процедурная анимация, то есть expressions.
Чтобы «дергать» за лапы постоянно во время анимации и при этом не держаться за мышь,
введите в поле Leaf Anglel следующее выражение, начинающееся со знака «равно»:
=90+ noise(time*15)*50;
Примечание. Конечно, эти движения синхронны для всех лап, но мы ведь на данный
момент лишь создаем видимость шевеления конечностями, и этого вполне
достаточно. Кроме того, задать формулу для индивидуальной анимации каждой
лапы довольно сложно (хотя и можно), а займет это некоторый объём книги в
виде безумного количества кода на MEL. Для фанатов программирования дам совет
обратить внимание на атрибут Runtime Script в разделе User Mel Scripts.
Для анимации остальных атрибутов нажмите правую кнопку мыши над сиреневым полем
Leaf Anglel и выберите Edit Expression.
Имейте в виду, что "brush2" это имя кисти, которую мы редактируем. Если у вас оно
другое, используйте в Expression Editor точное имя вашей кисти.
Все эти безумные формулы задают колебания около значений, определенных нами ранее.
Те же, кого пугает одно лишь упоминание об expression, могут попытаться воспользоваться
разделом Tubes=>Behavior=>Turbulence, однако создаваемая таким образом анимация действует
на все сегменты, а не только на листья-лапы, и поэтому больше подходит для раскачивания всего
туловища-ствола целиком.
Установите в разделе Shading цвет Color1 в белый, и убедитесь, что в подразделе Tube
Shading цвет Color2 также белый.
Перейдите в раздел Texturing и включите галку Map Color. После этого нужно определить
тип текстуры, накладываемой на штрих.
Ниже, в поле Image Name, введите имя текстуры - например, выберите из стандартного
набора текстур для кистей Paint Effects карту для кожи змеи:
X:\Program Files\Alias\MayaX.X\brushlmages\snakeskin2.iff
Параметры повторения тектуры (Repeat U/V) и размывания ее (Blur Mult) можете подобрать
по своему усмотрению.
Муравей несколько плоский. Это всё из-за того, что по умолчанию кисть не освещается
источниками света и поэтому не имеет трёхмерного объема.
А заодно, чтобы муравей был более «блестящим», установите атрибуты блика: 5pecular=1,
Specular Power=80.
Самый первый атрибут в Attribute Editor определяет технологический метод просчета для
кисти. Установите Brush Type=Mesh.
Штрихи с кистью такого типа уже не будут визуализироваться как набор дисков, а в
процессе рендеринга будут просчитываться как настоящие полигональные трубки.
Замечу, однако, что процесс превращения штрихов в полигоны происходит в этом случае
«на лету» и только в процессе рендеринга. Никакой новой геометрии в сцене не появляется, и,
следовательно, память на нее не расходуется.
Отрендерите картинку.
В разделе Brush Profile задайте Softness=0, отменив тем самым сглаживание краев.
С туловищем муравья теперь полный порядок. Покрасим лапы с помощью текстуры. До сих
пор они имели такой же узор, как и туловище, однако окрашивались в зеленоватый оттенок.
Тектстурирование листьев-конечностей
Откройте раздел Tubes=>Growth=>Leaves и сразу измените цвета Leaf Color1 и Leaf Color2
на чисто белый, чтобы при умножении на текстуру, они не вызывали изменения цвета.
Снимите галку Leaf Use Branch Тех, которая по умолчанию задает использование для
листьев текстуры основного ствола.
X:\Program Files\Alias\MayaX.X\brushlmages\snake1.jpg
Мы не будем назначать на усы отдельную текстуру и снимать галку Flower Use Branch Тех,
поэтому они будут иметь тот же узор, что туловище, но более темного оттенка.
Размножение муравьев
Теперь займемся разведение муравьев в больших количествах. Прежде всего уменьшим
нашего монстра.
Затем перейдите в раздел Tubes=>Creations и установите Tubes Per 5tep=2; Start Tubes=0.
Возникнет узкая дорожка из муравьев.
Чтобы ее расширить, откройте раздел Brush Profile и увеличьте ширину штриха: Brush
Width=4. Дорожка превратится в шоссе из муравьев.
Теперь займемся анимацией по пути. Чтобы создать движение вдоль пути надо анимировать
длину и расположение самого штриха.
Улучшение анимации
Не углубляясь в бесконечное улучшение анимации, дам некоторые рекомендации по
добавлению известного хаоса и индивидуальных движений в поток муравьев.
Для начала не забудьте в атрибутах штриха задать корректное значение Surface Offset,
чтобы муравьи не парили над поверхностью, а ползали по ней.
Можно слегка проанимировать ширину штриха Brush Profile - для получения эффекта
расползания.
PaintEffecis 985
Wind) тем, что первый нагибает стволы целиком, а второй больше действует на
концы-верхушки.
Для таких целей используются кривые, сохраняющие силу нажатия на перо при рисовании
штрихов. «А если нет пера, и есть только одинокая мышь?» - спросят неимущие умы. В этом случае
такие кривые можно создать и отредактировать в любой момент времени.
Идея состоит в том, что если немного потаскать эту кривую за контрольные точки, что
разницу с первоначальной формой можно использовать для модификации атрибутов на тех
участках, где кривая изменилась.
Таким образом, можно задать связь между формой кривой (точнее, ее разницей с
оригинальной формой) и любым атрибутом кисти, лежащей на штрихе. Поэкспериментируйте с
огромным выпадающим списком Pressure Map1.
К сожалению, данная техника плохо работает с анимацией MinClip/MaxClip, так как в этом
случае длина штриха и его положение в пространстве становятся непостоянными. Соответственно,
в каждом кадре будет изменяться расстояние между штрихом и созданной кривой, что приводит к
«расползанию» штриха. В принципе можно согласовать анимацию длины штриха и формы кривой
Pressure Curve, но это потребует некоторых усилий и работы с Hypergraph.
Заметьте также, что при создании Pressure Curve в сцене появится новый expression,
собирающий данные о расстоянии между штрихом и кривой, и передающий эти данные как силу
нажатия (Pressure) в атрибуты штриха.
Тени
Осталось положить любимую текстуру на «землю» и включить тени у источника света.
Напомню, что Paint Effects использует только тени типа Depth Map.
Выберите источник света pointLightl и включите в Attribute Editor, в разделе Shadows,
галку Use Depth Map Shadow.
Поставьте разрешение карты теней побольше (Dmap Resolution=2048) и «размойте» тени
(Dmap Filter Size=4).
Выключите галку Use Mid Dist Dmap и после этого, если необходимо, немного увеличьте
Bias (0.005), чтобы вручную задать отступ тени от «земли», которая сама на себя отбрасывает тень
в случае Use Mid Dist Dmap=Off.
Теперь можете отсчитать анимацию целиком. Можете устраивать облеты камерой вокруг
массового переселения муравьев и смело влетать в толпу переселенцев, не пугаясь крупных
планов. (Кстати, в атрибутах штриха по умолчанию включена галочка Motion Blurred.)
Во-вторых, после выключения опции Use Mid Dist Dmap, как правило, необходимо настроить
атрибут Dmap Bias, чтобы вручную задать отступ тени от объекта, который ее отбрасывает. Обычно
нужно немного увеличить значение этого атрибута.
В-четвертых, так как штрихи - довольно тонкие объекты, лучше размывать тень от них.
Атрибут Filter Size должен быть установлен по крайней мере в двойку.
В-пятых, в некоторых случаях, когда граница тени вдруг проходит в неположенном месте,
требуется отключить Auto Focus и вручную задать Width Focus. Про значения Width Focus для
разных типов источников света подробнее читайте в главе про освещение.
С помощью атрибутов из раздела Gaps можно «выкусить» целые участки штриха и сделать
анимацию прерывистых линий, типа дождевых струй или всяческих штрихпунктиров.
В принципе, наряду с процедурными деформациями есть возможность гнуть штрихи Paint Effects
вручную. Для этого используются специальные кривые, о которых мы сейчас и поговорим.
Установите в атрибутах кисти, в разделе Brush Profile, ширину штриха Brush Width=0.1,
чтобы розы росли поближе к кривой.
Перейдите в камеру front и нарисуйте две вертикальные кривые по краям окружности,
растущие из «земли».
Разберем, как контролировать степень влияния кривых на штрихи. Напомню, что после
проделанной операции кривые являются деформерами для штрихов, а следовательно, где-то
должны располагаться и атрибуты этих деформеров.
Задайте сначала Curve Follow=0, а потом большое значение притяжения: Curve Attract=5,
чтобы убедиться, что розы действительно притягиваются к кривым.
Обратите внимание: если штрихи достаточно гибкие (то есть имеют много
сегментов), то притяжение к кривым происходить неравномерно, как будто у
сегментов есть жесткость.
Задайте Curve Follow=0.9, чтобы «выпрямить» розы, то есть заставить из расти вдоль
контрольных кривых.
Третий атрибут, Curve Max Dist, определяет максимальный радиус действия контрольной
кривой. Если его значение равно нулю, то ограничения на радиус действия нет, и штрихи всегда
находятся под усредненным влиянием всех контрольных кривых, независимо от расстояния до
них.
Задайте Curve Max Dist=.5. Тогда розы, растущие из правой полуокружности будут
притягиваться к одной кривой, а из левой - к другой. Иными словами, деформация одной из
кривых никак не скажется на удаленных от нее розах.
Таким образом, вставляя в нужные места контрольные кривые и анимируя их, можно
добиваться ручного контроля над положением и формой штрихов. Контрольные кривые можно
анимировать обычными деформерами или с помощью blendshape, их можно превратить в мягкие
тела и гнуть с помощью динамики частиц. Очевидно, что при анимации формы кривых любыми
стандартными методами все изменения будут немедленно отражаться и на форме штрихов.
В Outliner появится новая нода hairSystem1, отвечающая за свойства системы волос (или
динамических кривых).
Все, что нужно сделать, это выбрать динамически движущиеся кривые и сделать их
контрольными кривыми для роз.
Выберите обе динамические кривые на экране, затем выберите штрих и снова выполните
операцию Paint Effects=>Curve Utilities=>Set Stroke Control Curves. Это заменит предыдущие
контрольные кривые на новые.
Все значения атрибутов Curve Follow, Curve Attract, Curve Max Dist останутся прежними,
поэтому нет нужды их настраивать заново.
Про остальные особенности динамики волос можете почитать в нужной главе, а сейчас
для системы волос hairSystem1 просто включите небольшую турбулентность (lntensity=0.2) в
разделе Turbulence, чтобы создать иллюзию ветра, покачивающего розы (точнее, покачивающего
контрольные динамические кривые).
Таким образом, вы можете анимировать контрольные кривые как угодно, и все ваши
эксперименты будут немедленно отражаться на форме и положении штрихов.
Однако в тех случаях, когда вы просто хотите придать штрихам упругости, не прибегая
к помощи динамики и контрольных кривых, можно воспользоваться возможностью создания
встроенных пружин.
Встроенные пружины
В том случае, когда вы хотите, чтобы штрихи просто упруго реагировали на перемещения
нижележащей поверхности или кривой, из которой они растут, достаточно воспользоваться
системой процедурных пружин, без использования контрольных кривых. Примером может служить
покачивание цветка в движущемся горшке или остаточные движения волос после резкой остановки
движения головы.
Чтобы изменить упругость или жесткость пружин, достаточно выбрать штрих и в атрибутах
кисти открыть последний раздел Extra Attributes. Там находятся добавленные в ходе операции
Make Brush Spring динамические атрибуты, которые можно редактировать.
Paint'Effecis 993
Для взрослых. Вы всегда можете разыскать и модифицировать автоматически
созданный expression в окне Expression Editor. Его незамысловатый код
свидетельствует о том, что на основе координат кривой, из которой растут
штрихи, в текущем и предыдущем кадрах вычисляется вектор силы, направленный
в сторону, противоположную движению. Этот вектор присваивается атрибуту
кисти Uniform Force, определяющему произвольную деформацию, действующую на
штрих.
Для того, чтобы избавиться от пружин, достаточно в атрибутах кисти открыть раздел
Tubes=>Behavior=>Forces и нажать правую кнопку мыши над полем Uniform Force, а затем выбрать
в выпавшем меню Delete Expression.
После этого возникнет объект в виде сферы (или куба), влияющий на штрих выбранным
вами образом.
Если открыть для модификатора Attribute Editor, то можно задать, каким образом он будет
модифицировать атрибуты штриха и кисти.
Например, все штрихи, попадающие внутрь модификатора, могут менять свой цвет
(анимация температуры).
Однако иногда встает задача анимации роста, то есть удлинения всех сегментов поперек
линии штриха.
Конечно, первое, что приходит в голову в этом случае это анимация атрибутов Length Min
и Length Max. Однако это повлияет лишь на основной ствол штриха. Листья, цветочки и прочие
детали придется также удлинять вручную.
Анимация атрибута Global Scale принесет весьма посредственный результат: общее укрупнение и
расширение размеров всего штриха.
Дляанимации плавноговыращивания всяческой растительности (и нетолько растительности)
в атрибутах кисти существует специальный раздел Flow Animation.
Для практического примера используйте предыдущую сцену или создайте простой штрих,
из которого растут цветы в достаточном количестве.
Для того, чтобы работать с анимацией роста, есть несколько простых правил.
Во-первых, выберите штрих, и в разделе Flow Animation для атрибутов кисти включите
галку Time Clip.
Во-вторых, задайте скорость анимации роста. Например, Flow Speed=1. Скорость анимации
измеряется в циклах в секунду, так что не задавайте слишком больших значений.
В-третьих, задайте начальное время, с которого начнется анимация роста. Это время
задается в секундах, так что если вы зададите Start Time=2, то штрихи начнут расти с пятидесятого
кадра (при условии, что глобальная скорость анимации установлена в 25 fps).
Если задать End Time=4, розы начнут исчезать, еще не появившись полностью после сотого
кадра.
Таким образом, вы можете выращивать штрихи Paint Effects в нужном месте с необходимой
скоростью. Не забывайте устанавливать время исчезновения (End Time) достаточно большим,
чтобы не допустить внезапного пропадания штрихов с экрана.
Для взрослых. Атрибут Time по умолчанию связан с глобальным системным временем.
Однако, как и в случаях с частицами или другими объектами, имеющими связь со временем, вы
можете искажать течение времени, ускорять и замедлять его, разворачивать его вспять, просто
разорвав стандартную связь и устанавливая ключи на атрибут Time.
Искусственное размножение
Если вы делаете с помощью Paint Effects «густые» процедурные объекты типа волос
или травы, не требующие листьев или цветочков с ягодками, существует способ радикального
увеличения плотности или густоты создаваемой растительности за счет применения технологии
Multi Streaks. Ее принцип основан полностью на трюке, который используется при размножении
частиц типа Multi Points или Multi Streaks.
Авторисование
Часто возникает задача равномерного покрытия поверхности штрихами. В отличие от
меха или волос, штрихи Paint Effects не растут прямо из поверхности, а используют кривые как
свою основу. Поэтому задача сводится к рисованию множества кривых-штрихов, равномерно
располагающихся на поверхности. В принципе вы можете написать такой скрипт самостоятельно,
но для не совсем взрослых мальчиков такой скрипт уже написан и располагается в меню Paint Ef
fects в виде операции Auto Paint.
Есть еще один способ просчитывать Paint Effects как полноправного участника сцены, а
не как пост-процесс. Это использование Renderman for Maya. Рейтрейсинг, тени Deep Shadow, все
новомодные «фишки» рендеринга - к вашим услугам при просчете штрихов Paint Effects.
Если вы хотите, чтобы штрихи «прятались» за объектом, установите Depth Type=Closest Vis
ible Depth. Если вы используете с сцене также туман (fog), то вы должны использовать включить
галку Transparency Based Depth для достижения необходимого эффекта.
Если создаваемые вами кисти довольно густые и тяжелые и, как следствие, еле ворочаются
на экране, задавайте для таких штрихов низкое качество отображения. Для этого установите
значение атрибута Display Quality для штриха равным 50, 25 или 10 процентам. «Круглое» значение
поможет мысленно оценить реальную густоту при рендеринге по сравнению с экранной картинкой.
Если, например, Display Quality=25, плотность штрихов на экране будет в четыре раза меньше,
чем при рендеринге. Помните также, что в атрибутах самой кисти есть параметр Simplify Meth
od, определяющий, как понижать качество отображения на экране: либо сокращая количество
сегментов в линиях (segments), либо сокращая число самих линий (tubes per step).
Помните о том, что чем больше основные стволы будут ветвиться (раздваиваться), тем
больше будет веток, и как следствие, листьев, и прочих деталей. Причем рост количества деталей
будет весьма стремительным. За ветвление отвечает атрибут Split Max Depth в разделе Branches,
так что увеличивайте его с осторожностью.
Количество линий (tubes) и их сегментов задается атрибутами Tubes per Step и Segments. Их
увеличение замедляет рендеринг и отображение прямо пропорционально. Кроме того, изменение
количества сегментов радикально изменяет форму штриха, поэтому старайтесь задать число
сегментов в самом начале редактирования кисти.
Если камера находится далеко, то есть план совсем общий, то вместо большого количества
деталей типа листьев, быстрее и проще использовать один-два крупных листа или даже толстые
ветки с соответствующей текстурой густой кроны. Впрочем, этот трюк давно применяется на
общих планах с текстурированными плашками вместо реальной геометрии, так что для штрихов он
может быть просто нужным образом адаптирован, тем более, что текстурировать штрихи довольно
несложно.
Если штрихов много и все они были созданы вручную, то интерактивное отображение
на экране можно ускорить, «упростив» кривые, лежащие в основе штрихов. Для этого можно
воспользоваться операцией Paint Effects=>Curve Utilities=>Simplify Stroke Path Curves. Как правило,
нарисованные штрихи порождают кривые, содержащие сотни контрольных вершин. Сократив их
количество, можно существенно оптимизировать сцену.
Еще один способ оптимизировать работу со штрихами состоит в следующем: надо зайти на
сайте www.highend3d.com и в разделе Maya=>Tutorials найти и прочитать развернутые комментарии
на все случаи жизни (Paint Effects FAQ) от разработчика модуля Paint Effects Данкана Бринсмита.
Динамика в MAYA является еще одним способом создания анимации. Однако анимация в
этом случае не определяется как набор ключевых кадров или формул, задающих, где и в какое
время объекту необходимо точно быть. Вместо этого, задается только начальное состояние
объекта (или системы объектов), а затем формулируется свод законов, определяющих правила
воздействия окружающего мира на объект. Такие, например, как сила ветра, притяжение земли,
бардак в роте, сопротивление воздуха и проч. Дальнейшее движение объекта MAYA рассчитывает
сама, на основе этих законов и начальных условий.
Динамика сплошных сред, которая не может быть адекватно описана с помощью систем
частиц - один из наиболее сложных и ресурсоемких типов динамики. Для моделирования поведения
жидкостей и газов приходится решать системы уравнений в частных производных, которые требуют
А как же динамика мягких тел (soft body dynamics), о которой все столько слышали? Это
всего лишь часть динамики систем частиц. Остроумная и эффективная идея заключается в том,
что частицы могут полностью контролировать движение контрольных вершин поверхности или
кривой. Иначе говоря, точки контрольные точки поверхности намертво «прилипают» к частицам
и двигаются вместе с ними по законам динамики, при этом деформируя поверхность. Главный
плюс динамики мягких тел (хотя удачнее было бы называть ее динамикой деформируемых тел)
- ее интерактивность. Благодаря этому эта технология часто служит эффективной альтернативой
системам анимации тканей.
Динамика твердых тел
Начнем со слепого примера. То есть сделаем некоторую последовательность действий
без комментариев, вслепую, а затем поговорим о принципах динамики твердых тел, на примере
только что произведенных, лихорадочных действий.
Колбасинг
Создайте NURBS-сферу.
Размножьте ее. Зайдите в Option Box для Edit=>Duplicate и установите TranslateZ=3; Number
of Copies=4.
Нажмите Duplicate.
Законы динамики
Для адекватной работы с динамикой необходимо иметь представление о том, как все-
таки вычисляются траектории объектов на основе заданных параметров и какие правила надо
соблюдать, чтобы динамика работала корректно и предсказуемо.
Для расчета движения тех или иных объектов всегда используется некий Решатель (Solv
er), то есть тот, кто решает, как будут двигаться объекты, которыми он управляет. Для твердых
тел это Rigid Body Solver, для одежды cpSolver, для волос - hairSystem. Атрибуты таких решателей,
как правило, доступны через Attribute Editor и определяют то, как точно или как быстро будет
производится расчет движения и какие факторы будут при этом учитываться. Не обязательно
вникать в суть алгоритмов, используемых в этих решателях, важно усвоить один общий принцип
работы всех этих «больших expressions».
То есть, чтобы знать о том, где объект будет находиться в сто первом кадре, MAYA должна
знать, где объект находился в предыдущем, сотом кадре. В свою очередь, чтобы узнать положение
в сотом кадре, ей нужна информация из девяносто девятого и т.д. Таким образом, чтобы
рассчитать положение объекта к сто первому кадру, MAYA должна последовательно просчитать
все предыдущие сто кадров.
Закон динамики 1.
Скорость воспроизведения анимации должна быть всегда равна Play Every Frame.
Закон динамики 2.
Анимация должна воспроизводиться всегда только вперед.
Попытки проиграть анимацию назад ни к чему не приводят. MAYA запоминает несколько
предыдущих кадров, но сделать расчет движения назад уже выше ее возможностей. Дело в том,
что численные методы, лежащие в основе расчета траекторий и используемые Rigid Body Solv
er, не работают «вспять». Еще раз: положение объекта в текущем кадре вычисляется на основе
информации о предыдущем кадре.
Закон динамики 3.
Первый кадр анимации всегда должен быть «первым» с точки зрения динамики.
Иначе говоря, номер стартового кадра для воспроизведения анимации должен совпадать с
атрибутом startTime для Rigid Body Solver. Дело в том, что когда вы создаете первое твердое тело
(а точнее когда появляется новый Rigid Body Solver), MAYA запоминает номер начального кадра
анимации и делает его первым кадром для начала расчета динамики.
Если после этого вы сдвинете начальный кадр на TimeLine, при воспроизведении MAYA
перестанет попадать в первый кадр динамики и возвращать объекты в стартовые позиции. У вас
просто все «залипнет».
Закон динамики 4.
Нельзя безответственно щелкать мышью в TimeLine и там же, абы как,
перетаскивать мышью текущее время.
Когда вы щелкаете мышью на временной линейке, пытаясь сразу встать, к примеру, в
пятьсот пятый кадр, MAYA пытается посчитать позиции объектов в этом кадре и ищет информацию
об их положении в предыдущем, пятьсот четвертом кадре, однако вы же не были ни в пятьсот
четвертом, ни в пятьсот третьем кадрах, поэтому MAYA робко ставит объекты в положение «от
балды». Это в последние годы характер MAYA сильно улучшился, а раньше она просто зависала от
такой бесцеремонности, пытаясь одним махом просчитать все пятьсот недостающих кадров.
Поэкспериментируйте.
Сравните результат.
Совет. Если вам нужно «ненадолго заскочить» в любой кадр без проигрывания
анимации (и, как следствие, без перепросчета динамики или обновления Construc
tion History), используйте на таймлайне среднюю кнопку мыши.
Закон динамики 5.
Твердые тела не должны пересекаться в начальном кадре.
Во всех кадрах, кроме начального, MAYA отслеживает столкновения между объектами и не
дает им проникать друг в друга. Единственный кадр, в котором их можно перемещать вручную,
это начальный кадр динамики. В нем MAYA никак не может вам помешать расположить объекты
так, чтобы они пересеклись, и злорадно нажать кнопку Play. Но ничего хорошего не выйдет. MAYA
разразится в Script Editor сообщениями о взаимопересечении твердых тел и впадет в легкий
ступор.
Если в ваши планы не входит доводить MAYA до истерики, избегайте проникновения твердых
тел друг в друга в первом кадре.
Об этом необходимо помнить каждый раз при создании нового поля. Зачастую пользователи,
привыкшие к автоматическому созданию твердых тел и назначению полей, забывают выбрать
поверхность , а потом сильно удивляются, почему это созданные поля не влияют на объекты и
пытаются наплодить еще пару-тройку более «надежных» полей.
Совет. Посмотреть, какие поля влияют на выбранный объект, можно в окне Dy
namic Relationships, однако еще проще это сделать прямо в окне камеры в режиме
wireframe. Розовым окрашиваются иконки полей, влияющих на выбранный объект,
и наоборот, если выбрать в Outliner любое поле, то розовыми становятся все
объекты, на которые это поле действует.
Пассивные твердые тела служат лишь для того, чтобы служить препятствием на
пути активных твердых тех. Это просто поверхности, намазанные «Колгейтом»,
от которых могут отскакивать активные тела. На них не действуют поля, они
не сотрясаются от ударов. Зато их можно анимировать всеми традиционными
способами, задавая их движение «вручную».
Если ставить ключи на имеющееся пассивное твердое тело, оно действительно начинает
двигаться по ключам с одной маленькой «засадой»: ключей не видно на TimeLine! Более того,
попытка удалить ключи через Channel Box ни к чему не приводит. Ключи у пассивного твердого
тела можно удалить только в Graph Editor! Поэтому я бы посоветовал перед анимацией любого
пассивного твердого тела группировать его с самим собой, а ключи ставить на получившуюся
группу (если вы не собираетесь анимировать пассивность/активность - но об этом см. ниже).
Если же ставить ключи на имеющееся активное твердое тело, то ключи-то будут поставлены, однако,
вместо того чтобы их игнорировать, как положено активному твердому телу, произойдет смешивание
двух анимаций: от динамики и от ключей. Причем по умолчанию приоритет анимационной кривой
равен единице, а вес динамики равен нулю. При этом активное твердое тело начинает вести себя
непредсказуемо и к нему добавляется атрибут типа blendRigidBody#, отвечающий за смешивание
двух типов анимаций. Чтобы как-то исправить положение надо установить его в единицу, чтобы
тело управлялось только динамикой. Пытливые умы спросят, а зачем ставить ключи на активное
тело? Ответ будет дан ниже, при обсуждении анимации активности твердых тел.
При создании твердых тел MAYA предлагает ненавязчивый сервис: для симметричных
сплайновых поверхностей центр масс твердого тела слегка смещается от центра (это связано
с разбиением сплайновых поверхностей на полигоны для динамики). Если для шара обнулить
атрибут centerOfMass, то он будет уныло скакать в центре плоскости.
Атрибуты типа centerOfMass (центр масс), impulse (грубо говоря, ускорение), spinlmpulse
(вращательное ускорение), mass (масса) оказывают влияние только на активные твердые тела, в
то время как bounciness (упругость) или friction (трение) изменяют характер взаимодействия для
обоих типов твердых тел.
Пытливейшие умы немедленно воскликнут: «Так ведь можно организовать, таким образом,
чемпионат по бросанию твердых тел!». Сначала пассивное твердое тело анимируется обычным
способом, например, следуя с помощью констрейна за размахивающейся рукой персонажа, а
затем, в момент броска, анимируется изменение атрибута active с off на on. И твердое тело должно
взлететь в воздух, наплевав на любые констрейны, так как оно становится в этот момент активным
твердым телом. Сейчас мы проверим эту гипотезу и заодно сделаем упражнение, иллюстрирующее
уже перечисленные законы динамики.
Закон динамики 6.
Твердые тела должны сталкиваться внешними сторонами. Иначе говоря, нормали у
сталкивающихся поверхностей должны торчать наружу, а точнее в сторону столкновения. У любой
поверхности есть две стороны, и твердые тела должны сталкиваться теми сторонами, из которых
Этот закон связан с тем, что при столкновении объектов MAYA должна определять, в какую
сторону отталкивать поверхности друг от друга после столкновения. За направление отталкивания
берется нормаль к поверхности, поэтому в последнем случае шар «проваливается» в плоскость и
«выталкивается» вниз, по нормали к плоскости.
Катание шаров
Создайте новую сцену.
Перейдите в камеру front. С помощью CV Curve Tool постройте профиль кегли.
Используйте привязку к сетке и располагайте первые две-три точки на горизонтальной
оси, давая вертикальную "устойчивость" профилю.
Последние две точки также расположите на одной горизонтальной прямой, чтобы сделать
гладкую вершину. Ведите кривую по часовой стрелке.
Выберите все кегли и, на всякий случай, установите в Channel Box для них translateY=0.
Создайте плоскость любого типа.
Совет. Все построения всегда проводите в первом кадре! Это позволит избежать
неожиданностей при проигрывании анимации.
Теперь надо дать шару начальную скорость, и для этого не надо воздействовать на него
Нажмите Play.
Шар, не торопясь и не вращаясь, плывет над дорожкой с заданной скоростью и вяло
врезается в пирамиду. Очевидно, на него не действует сила тяжести. Коль скоро поле гравитации
уже есть, осталось только присоединить шар к нему.
Очевидно, что шару не хватает массивности, ведь сейчас массы кеглей и шара одинаковы
и равны единице.
Вопрос первый. Если анимация вас устраивает, может быть, имеет смысл избавиться от
динамики и «запечь» движения всех объектов в ключи, то есть в анимационные кривые? Уход
от динамики имеет смысл по многим причинам. Например, вы вдруг захотите передать сцену с
анимацией пользователям другой 3D-программы или в отдельную систему рендеринга, которая
ничего не знает про майскую динамику. Или у вас возникнут сомнения, что рендеринг корректно
подхватит динамику при просчете с пятисотого кадра. И, наконец, вам захочется ожесточенно
повозить мышкой по таймлайну, проигрывая анимацию вперед-назад.
Вопрос второй. Кто-то выше упоминал про бросание твердых тел. А тут идеальный случай,
чтобы вложить шар в конечность персонажа и бросить его, анимируя эту конечность.
Чтобы увеличить частоту проверок между кадрами, надо уменьшить значение атрибута
Step Size для ноды rigidSolver, которая отвечает за просчет динамики. Закладку этой ноды всегда
можно отыскать в Attribute Editor для любого твердого тела или можно напрямую найти ее в меню
Solvers=>Rigid Body Solver.
Для начала надо перейти в камеру front и сделать простую руку, делающую бросок в
течение сорока кадров. Одного IK Handle вполне хватит для постановки анимации.
Готовый файл с такой рукой называется bowlingHandStart.ma.
Хотя казалось бы, какое движение может быть у пассивного твердого тела от динамики?
Тем не менее, даже анимация атрибута blendPoint не может помочь: шар просто отваливается и
замирает в неопределенной позиции.
Чтобы сделать все «по-старому» (так, как в ранних версиях MAYA), то есть отцепить вовремя
шар от руки, проанимировав атрибут active, надо сначала приконстрейнить объект к руке, потом
сделать из него пассивное твердое тело и только потом поставить ключи на атрибут active.
Выберите шар и удалите с него твердое тело: Edit=>Delete by Type=>Rigid Bodies.
Теперь выберите IK Handle, затем шар и «прибейте» шар к руке: Constrain=>Point.
Выберите шар и создайте пассивное твердое тело: Soft/Rigid Bodies=>Create Passive Rigid Body.
Никаких дополнительных атрибутов и смешивания анимации не возникло. Меня это слегка
удивляет.
Теперь мы имеем пассивное твердое тело, зажатое в руке, и надеемся бросить его,
поставив два ключа в соседних кадрах.
Поставьте ключ на атрибут active=off, например, в тридцать пятом кадре, затем перейдите
в тридцать шестой кадр, установите active=on и поставьте еще один ключ.
При проигрывании анимации шар в тридцать шестом кадре превращается в активное
твердое тело, отцепляется от руки, наследует начальную скорость с анимационной кривой и
плавно плывет по воздуху.
Присоедините его к гравитации.
А скорость бросания можно теперь регулировать, изменяя анимацию руки. Шар будет
наследовать скорость и направление полета в момент отпускания. Не забывайте только, что
момент отпускания определяется по положению двух соседних active-ключей у твердого тела.
Сохраните файл (bowlingHandFinal.ma).
Вывод следующий: чтобы бросить объект как твердое тело, надо сначала приконстрейнить
его к другому движущемуся объекту, а затем превратить его в пассивное твердое тело. В момент
броска следует анимировать в двух соседних кадрах изменение атрибута active с off на on.
Пытливые умы могут аналогичным образом также «поймать» объект, просто подведя руку
в нужное положение рядом с объектом и анимировав атрибут active обратно, с on на off. Результат
«ловли» можно посмотреть в файле bowlingHandCatch.ma.
Объект может быть анимирован «неявным» образом, то есть может не зависеть от своей
анимационной кривой, а зависеть от анимации другого объекта либо через Set Driven Key, либо
через IK Solver, констрейн или expression. Самый популярный пример - это скелет, анимированный
с помощью IK Handles. Сами кости не содержат ключей, однако часто бывает необходимо перевести
движения IK Handles в анимацию самого скелета (то есть костей), например, при экспорте в игровой
движок.
Во всех таких случаях можно превратить движение объекта в анимацию по ключам. В нашем
случае кегли и шар движутся по законам динамики, поэтому построим для них анимационные
кривые и заодно посмотрим, как «вычищать» динамику из сцены.
Выберите все кегли и шар.
Откройте Option Box операции Edit=>Keys=>Bake Simulation.
Установите Time Range=Start/End и задайте временной диапазон, на котором следует
Параметр Sample by определяет, как часто будут «пробиваться» ключи для выбранных
атрибутов, единица же означает, что ключи будут ставиться в каждом кадре. В случае
множественных столкновений лучше оставить этот параметр равным единице.
Нажмите Bake.
MAYA проиграет один раз анимацию на указанном отрезке времени и сконвертирует
траектории в анимационные кривые.
Возможно, что ключи не будут видны на выбранных объектах, так как они до сих пор
являются твердыми телами, которые следует немедленно удалить.
Выберите кегли и шар (если они еще не выбраны) и выполните Edit=>Delete All by Type=>Rigid
Bodies.
Чтобы окончательно «зачистить» динамику, удалите поле гравитации. (Дотошные умы
могут также удалить Rigid Body Solver.)
Теперь можно неистово проигрывать анимацию в любом направлении и с любой
скоростью.
Если зайти в Graph Editor, можно убедиться, что новоиспеченные анимационные кривые
выглядят слегка угрожающе и редактированию, вообще говоря, не подлежат.
Свойства полей
До сих пор мы использовали только одно поле гравитации и в основном работали со
свойствами твердых тел. При изучении свойств полей, естественно, проще всего применить
метод тыка, создавая новые поля, присоединяя их к объектам и исследуя результат воздействия.
Кроме того, вооружившись главным принципом изучения MAYA, нужно просто посмотреть на
атрибуты создаваемых полей и усвоить, за какие свойства полей эти атрибуты отвечают. Было
бы нерационально (да и неинтересно) перечислять здесь список всех имеющихся полей, нудно
описывая их свойства. Давайте сделаем небольшой пример, иллюстрирующий работу с полями и
обобщающий характерные свойства всех полей вообще.
Примечание. По поводу полей чаще всего задаются такие вопросы. Первый из них
- что такое поле Newton и чем оно отличается от гравитации или от поля Ra
dial? Ответ: Ньютоновское поле похоже на точечную гравитацию, то есть тела
ускоряются не вдоль некоторого общего направления, а притягиваются к точке
- центру поля. Сила притяжения зависит от массы тел и от расстояния до центра
поля (хотя атрибут useMaxDistance no умолчанию выключен), а наличие атрибута
minDistance позволяет выключить поле с некоторой окрестности от его центра.
Второй вопрос - что такое поле Volume Axis? Ответ: Это некоторое обобщение всех возможных
полей, позволяющее задать объем, внутри (или снаружи) которого действует поле. Можно задавать
характер движения вокруг или вдоль оси, проходящей через этот объем, и некоторые другие
свойства. С помощью этого поля удобно, например, наполнять частицами некоторые области
пространства или делать «объемные» эффекты (типа атомного взрыва). Кстати, ограничивать
объемом действие поля можно для всех имеющихся полей с помощью атрибута volumeShape.
Абсолютно у всех полей есть три главных атрибута, определяющих силу и зону влияния
поля. Остальные атрибуты определяют менее значительные свойства, а также свойства, уникальные
для конкретных полей.
Выберите все твердые тела и увеличьте bounciness до 0.9, чтобы игра стала более
веселой.
На выбранные тела навалите поле Vortex (вихрь), чтобы начать закручивать их вокруг
вертикальной оси (направление оси, очевидно, также задается атрибутами этого конкретного
поля).
Объекты постепенно раскручиваются и, под воздействием центробежной силы,
преодолевают притяжение к центру, определяемое радиальным полем. Попробуем ограничить
радиус действия поля vortexFieldl, так чтобы, выйдя за него, объекты попадали в объятия radial
Fieldl и снова стремились к центру.
С отличие от реальных планет, наши объекты будут постепенно ускоряться, пока не улетят в
открытый космос. Можно немного притормозить движение, добавив, например, силу сопротивления
среды (или, как говорят физики, «стабилизировать систему, добавив диссипации»).
Вывод. В сцене может быть некоторое количество твердых тел и некоторое количество
полей. На различные тела независимо могут воздействовать разные поля. Поля можно анимировать
так же, как обычные объекты, их можно объединять в группы и иерархии, а также связывать с
Подвесной таран
Сконструируем таран, представляющий собой бревно, подвешенное на двух цепях.
Лучшее бревно - это полигональный цилиндр, лежащий на боку (rotateX=90, scaleY = 5)
Сделайте его, выберите и создайте поле гравитации: Field=>Gravity.
Нажмите Play.
Цилиндр норовит выпасть снизу из монитора.
Попытки создать два Nail Constraint для одного цилиндра приводят к неутешительному
выводу о том, что констрейн всегда крепится к твердому телу строго в центре масс. Редактируя
положение атрибутов centerOfMass, можно смещать точку крепления, однако иметь два центра
масс невозможно по определению, и поэтому подвесить цилиндр за две точки так просто не
получится.
Выберите сначала первый кубик, затем цилиндр и выполните Soft/Rigid Bodies=>Create Pin
Constraint. Передвиньте центр созданного констрейна внутрь кубика.
Если хотите внезапно оборвать один из констрейнов, просто проанимируйте для него
изменение атрибута constrain с on на off в любом кадре.
Дальше будет несложно сделать так, чтобы полигональная прокси-сетка была «поближе»
к самой сабдив-поверхности. Для этого служит операция Subdiv Surfaces=>Collapse Hierarchy.
Выполните ее для выбранной сферы.
Именно эту сетку в дальнейшем следует использовать для расчета столкновений. Для
наглядности можно в Outliner даже удалить сабдив-shape у новой поверхности, а оставшуюся
полигональную сетку превратить в твердое тело. После чего взять первоначальную сферу, удалить
с нее твердое тело и припарентить ее к новой сетке.
Итак, чтобы можно было «бросать» и «стукать» твердые тела, полученные из сабдивов,
надо сделать несколько действий.
Если осколки готовы, надо найти способ заставить их разлетаться при ударе. Основная
проблема, которая может возникнуть в самом начале - это взаимопроникновение и большое
количество соударений в одном кадре.
Посмотрим, как ее можно решить на практике. Если вам лень делать посуду и уж тем
более пилить ее на куски, откройте файл teapotCracked.ma и убедитесь, что в нем находятся
несколько полигональных осколков, чайника плотно прилегающих друг к другу.
Не забывайте, что у всех осколков выключен атрибут collisions, поэтому никаких «залипаний»
между целым чайником и осколками не происходит.
Теперь аккуратно выберите все осколки и установите в Channel Box для твердых тел
атрибут active в off. Это сделает их пассивными твердыми телами. Обнулите у них начальную
скорость, чтобы они были совсем пассивными: initialVelocityY =0.
В Outliner или Hypergraph припарентите все осколки к целому чайнику (выделите,
После этого в момент удара осколки разлетаются и остаются на плоскости под действием
силы тяжести.
Анимация атрибута visibility остается на совести пытливых умов и не представляет
технических сложностей.
Теперь из носа падающего чайника непрерывно идетусловный пар. Можно теперь установить
в ноль значение атрибута rate для эмиттера и попытаться включить его только в момент удара.
Пытливые умы уже, конечно, слазили в раздел документации, предназначенный для взрослых
мальчиков, то есть в описание ноды типа rigidBody, и нашли, что у нее есть атрибут contactCount,
отвечающий за количество столкновений в текущем кадре. Иначе говоря, у любого твердого тела
(пассивного и активного) есть атрибут, имеющий, как правило, нулевое значение, но как только
в некотором кадре тело соударяется с другим объектом, в этот атрибут записывается количество
соударений именно (и только) в этом кадре. Если десять чайников синхронно упадут на плоскость,
то для пассивного твердого тела на плоскости в момент удара в атрибут contactCount запишется
значение 10. В тех кадрах, где тело ни с кем не контактирует, атрибут снова принимает нулевое
значение.
Теперь надо выбрать чайник и посмотреть, как называется твердое тело для него (rigid-
if(rigidBody17.contactCount>0) emitter1.rate=1000;
else emitter1.rate=0;
Теперь чайник падает быстрее, поэтому осколки становятся активными телами чуть позже
удара, и, продолжая следовать за чайником, разлетаются только при втором соударении.
Пытливые умы, однако, быстро сообразят, что вместо ключей, можно использовать
аналогичный expression для переключения статуса активности осколков точно в момент удара,
после чего чайник будет раскалываться на куски при столкновении с любым препятствием. Надо
только не забыть про то, что в первом кадре осколки обязаны быть пассивными.
Выберите в первом кадре все осколки и удалите для твердых тел в Channel Box ключи с атрибута
active.
Для наглядности создайте еще один expression следующего вида для любого осколка,
например, для rigidBody1:
Дальше все зависит от вашего темперамента. Если не лень, можете написать expression типа:
if(frame==1) {
rigidBody1.active=0; polySurface9,visibility=0;
rigidBody2.active=0; polySurface15.visibility=0;
rigidBody3.active=0; polySurface21.visibility=0;
// ....
teapot_Snape.visibility=1;
}
if (rigidBody1 7. contactCount>0) {
rigidBody1 .active=1; polySurface9.visibility=1;
rigidBody2.active=1; polySurfacel 5.visibUity=1;
rigidBody3.active=1; polySurface21.visibility=1;
// ...
teapot_Shape.visibility=0;
}
Если же написание длинного expression вызывает у вас отвращение, можете просто открыть
Connection Editor и соединить атрибут active осколка, проанимированного с помощью expression, со
всеми атрибутами active остальных осколков. (Выбрать ноды rigidBody можно в Outliner, включив
Display=>5hapes.)
} //endif
Для испускания частиц я использовал функцию emit, которая позволяет создать некоторое
количество частиц без всяких источников. Не забудьте только предварительно создать пустой
объект из частиц particleObj, который будет содержать испускаемые частицы. Это можно сделать,
просто выполнив команду "particle -n particleObj".
Идея о том, чтобы в момент столкновения сдвигать источник точно в место столкновения
и включать его там, не является удачной. Попробуйте и убедитесь сами, почему. В этом случае
expression будет выглядеть следующим образом:
if(rigidBody17.contactCount) {
emitter2.tx = rigidBody17.contactPosition[0].contactX;
emitter2.tx = rigidBody17.contactPosition[0].contactY;
emitter2.tx = rigidBody17.contactPosition[0].contactZ;
emitter2.rate=1000;
}
else emitter2.rate=0;
Поведение, а не траектория
Когда вы пытаетесь заставить двигаться в нужном направлении систему твердых тел,
старайтесь думать о поведении системы, а не о конкретных траекториях. В отличие от ключевой
анимации, вы воздействуете на траекторию твердых тел при помощи посредников: полей, свойств,
ударов или констрейнов. Поэтому ваше управление движением носит характер инструкций типа
«лететь в нужном направлении» или «вести себя определенным образом». Если вы пытаетесь
обеспечить точное попадание в нужное место в определенный момент времени, значит вы выбрали
не тот инструмент (я имею в виду динамику). Например, если вы пытаетесь попасть с помощью
динамики мячом в баскетбольное кольцо, вас ждет длительная возня с начальной скоростью и
Твердые тела движутся почти так, как вы хотите. Поэтому не требуйте от динамики точного
попадания в точку с координатами 5, 5, 5 ровно в десятом кадре.
Для анимации цепей и других «висячих» механизмов хорошо подходит динамика волос
или одежды, которая выдаст необходимое движение, а части механизма нужно будет должным
образом закрепить на деформирующейся кривой или поверхности.
Россыпи твердых тел с количеством более ста быстро доведут MAYA до истерики, так что в
этом случае используйте динамику частиц и технологию инстансирования (подстановки) объектов
в частицы.
Почаще испекайтесь
Если вас полностью устроил результат динамической симуляции, переведите ее в
ключи, удалите все тела, сохраните сцену и забудьте про настройки динамики. Это позволит
вам сосредоточиться на последующих задачах без необходимости прилежно выполнять законы
динамики. Можно также использовать кэширование с помощью операций Solvers=>Memory
Caching=>Enable/Disable/Delete.
Если вдруг после операции Bake обнаружились проблемы - например, объекты движутся
совсем не так, как во время обычного воспроизведения, вылечить это поможет включение
Кстати, для того чтобы после операции Bake снова сделать твердые тела динамическими,
а не анимированными по ключам, нужно удалить для них все анимационные кривые и выполнить
операцию Soft/Rigid Bodies=>Break Rigid Body Connections.
Небольшая история из жизни активных твердых тел. В далеком, историческом уже 1985
году мы с моим другом Парфентием поехали на прогулку в музей-усадьбу Архангельское. Поехали,
естественно, не одни. (Да и разве можно представить себе двух разгильдяев с третьего курса
университета, добровольно отправляющихся в музей-усадьбу?). Дело в том, что «на картошке»
(для недряхлых читателей: это - культовый феномен той поры, а не название дискотеки) мой
друг Парфентий познакомился с белокурой девушкой, и ему надо было срочно произвести на
нее впечатление. Дабы не бросать друга на произвол романтических отношений, я призвал на
помощь свою хорошую знакомую, и мы отправились производить убийственное впечатление
на ничего не подозревавшую блондинку. По такому случаю, мой друг Парфентий надел свой
умопомрачительный коричневый плащ и сделал очень приветливое лицо. Была поздняя осень
и будний день. Мы все четверо долго тряслись в полупустом рейсовом автобусе, и, наконец,
почти достигли цели. Цель была близка, но не давалась в руки, а точнее, в ноги. Огромные
ворота, предваряющие вход с усадьбу, оказались наглухо закрыты, и никаких признаков жизни
в зоне видимости не наблюдалось. За решетками забора призывно и романтично потряхивали
остатками листвы многовековые деревья, также жаждущие произвести впечатление на белокурую
бестию, но мы, к сожалению, находились по другую сторону жизни, где веселые проезжающие
камазики приветливо пшикали в нас выхлопными газами и норовили прижать поближе к забору.
Было принято решение действовать по правилу правой руки, то есть идти вправо вдоль забора,
ожидая либо открытой калитки, либо дырки в заборе, либо милостей судьбы. Музей-усадьба,
однако, оказался чудовищно велик, практически необъятен. И, что самое печальное, обнесен
бесконечным трехметровым забором из металлических прутьев с острыми концами. Когда мы
практически потеряли надежду, а блондинка заметно занервничала, мы заметили участок забора,
украшенный неопределенного вида ромбовидными металлическими украшениями. Они позволяли
практически без труда влезть на забор и также с него спуститься. Романтические кущи с той
стороны продолжали нас манить, и мы весело и по очереди преодолели преграду. Последним же
преодолевал ее мой друг Парфентий. Забравшись наверх, он не захотел бездарно и невыразительно
слезать вниз, а помня о целевом назначении поездки, легко и непринужденно прыгнул с высоты
трех метров. Однако шикарный коричневый плащ, не пожелав быть элементом спортивной формы,
коварно зацепился за острые концы прутьев забора. Мой друг рухнул вниз, как твердое тело, у
которого неожиданно включили все констрейны. Плащ оказался на удивление прочен, и мой друг
повис на заборе, запутавшийся в одежде и распятый в собственных рукавах. Там он жалобно и
возмущенно бился, пока мы, превозмогая приступы хохота и сострадая ближнему, не подползли к
нему, то и дело сгибаясь пополам от смеха, и не освободили его из объятий собственного плаща.
Последний был разорван ровно на две половины, а приветливое лицо Парфентия утратило отчего-
то свою непроницательность. Далее, нам все-таки удалось прогуляться по музею-усадьбе, и хотя
позднеосенняя температура задевала за ноль, мой друг, непринужденно перекинув половинки
плаща через руку, проявлял чудеса морозоустойчивости. Центральная же фигура всей этой
истории, ничего не подозревающая блондинка, была так поражена всем произошедшим, что
через некоторое время вышла замуж за моего друга Парфентия, и до сих пор находится под
впечатлением динамики твердых тел все эти годы.
Более причудливые применения частиц встречаются в виде концепции мягких тел (Soft
Body), когда при помощи частиц производится деформация поверхностей. Анимация остаточных
движений также может быть смоделирована с помощью системы частиц и мягких тел.
Отдельный вид использования частиц - это подстановка вместо них геометрических объектов
и симуляция культурно-массовых мероприятий. Такая подстановка, называемая инстансированием,
может быть использована для анимации косяков рыб, стай птиц, роя пчел или первомайской
демонстрации, когда объекты, имеющие собственную независимую анимацию, следуют вдоль
траекторий, определяемых движением частиц. Вопрос взаимодействия или столкновения объектов
в этом случае остается открытым и отдается на откуп более специализированным системам
анимации массовых беспорядков типа Massive.
Анимация 1045
и ускорением частиц. Кроме того, желательно иметь пытливый ум, склонный к экспериментам
и всяческим издевательствам над окружающей природой. С помощью динамики частиц можно
направить такие склонности в созидательное русло.
При создании разного рода эффектов приходится постоянно балансировать между двумя
полюсами. С одной стороны, реалистичность движения и соответствие физическим законам,
с другой - производимое впечатление и соответствие художественному замыслу. Приоритет,
естественно, имеет последний, поэтому, увлекшись игрой с полями и программированием
реальных взаимодействий, не старайтесь сделать все «по-честному», как в учебнике физики.
Легкое преувеличение физических законов, как правило, идет на пользу любому эффекту.
Природа частиц
Кстати, в соответствии с принципами корпускулярно-волнового дуализма, всё вокруг нас
суть частицы, да и сами мы из них состоим.
Поскольку вы уже знакомы с динамикой твердых тел, можно сказать, что частицы это
крошечные твердые тела, настолько мелкие, что у них отсутствует поверхность. Иначе говоря,
это бесконечно малые, но тяжелые точки. Из отсутствия поверхности следует их неспособность
сталкиваться друг с другом, то есть частицы по умолчанию «не чувствуют» друг друга, даже
находясь в одной точке пространства - они «проникают», или «пролетают», друг сквозь друга.
Именно отсутствие взаимных столкновений и, как следствие, необходимости эти столкновения
просчитывать делает возможным интерактивную анимацию тысяч частиц. Для эксперимента
можете создать сотню активных твердотельных шариков в виде горизонтальной сетки 10x10 и
напустить на них поле Radial с отрицательным значением magnitude. В момент столкновения
всех шаров MAYA попросится в небольшой отпуск, и дальнейшую анимацию нельзя будет назвать
интерактивной.
Если продолжить аналогию с твердыми телами, частицы могут иметь констрейн типа Spring,
то есть сетку из пружин, натянутую либо только между частицами, либо соединяющую частицы и
вершины поверхности.
Для частиц можно указывать цель, к которой они могут стремиться. Этой целью может
быть кривая, поверхность или другая система частиц.
Они имеют собственное время жизни и ещё массу интересных свойств. Речь о них пойдет ниже.
Работу с частицами можно условно разбить на три этапа: создание системы частиц, анимация
и визуализация. (И никаких скелетонов!). Начнем с создания нужного количества частиц.
Прежде всего, их можно нарисовать вручную при помощи Particles=>Particle Tool. Это,
конечно, довольно экзотический метод, позволяющий вам по умолчанию просто создавать
частицы на экране, аналогично процессу рисования кривых, и завершать создание объекта из
частиц нажатием Enter. Объект типа particle состоит из компонент, являющихся индивидуальными
частицами, так же, как кривая или поверхность состоят из своих контрольных вершин. В Op
tion Box для Particles=>Particle Tool есть настройки, позволяющие создавать сразу сетку или даже
куб из частиц, два раза щелкнув в окне, обозначая диагональ сетки, и нажав Enter. Это бывает
полезно, когда надо уложить частицы на плоскость ровным слоем.
Источники частиц
Чтобы распылить струю, установите атрибут spread, отвечающий за угол распыления, в 0.3
(единица соответствует полному раскрытию, или 180 градусам).
Примечание. Очень важно понимать, что при выполнении операции Create Emit
ter, создаются два объекта: сам источник и частицы, вылетающие из него. Это
следует хотя бы из Script Editor, выдающего следующую информацию:
emitter -pos 0 0 0 -type omni -r 100 . . . ;
// Result: emitter1 //
particle;
// Result: particle1 particleShape1 //
connectDynamic -em emitterl particlel;
Это автоматически присоединит созданное поле к выбранным частицам. Чтобы струя все-
таки била вверх, надо увеличить скорость испускания частиц из источника (или уменьшить силу
гравитации).
Выберите эмиттер и задайте значение атрибута speed равным 10, а также уменьшите spread
до 0.1.
Задайте rate=240.
Атрибут rate определяет, сколько частиц вылетает из источника в течение одной секунды.
Поэтому, если в общих установках у вас стоит скорость анимации, равная 24 кадрам в секунду, то
при напоре 240 частиц в секунду в каждом кадре будет появляться 10 новых частиц.
Создайте NURBS-конус.
Сделайте из него «тарелку» (scale = 5, 0.2, 5) и опустите его немного вниз (translateY=-1).
Частицы пролетают сквозь него без малейших сотрясений.
Для частиц существует свой вид «зубной пасты», которой надо покрыть поверхность,
чтобы она затвердела и стала отталкивать частицы. Столкновения частиц с поверхностью не имеют
никакого отношения к динамике твердых тел, и расчет их производится совершенно независимо,
их собственным Решателем (Solver).
Ещё одно отличие от твердых тел состоит в том, что частицам совершенно все равно, где
у поверхности нормаль. Они будут одинаково успешно отскакивать от обеих сторон поверхности.
Пытливые умы, наверное, уже в нетерпении елозят мышкой. Ведь если плотность
испускания может зависеть от площади поверхности, то, может быть, она может меняться и вдоль
самой поверхности?! Например, в зависимости от цвета поверхности, а точнее, в зависимости от
некоторой текстуры, определяющей области испускания с разной плотностью.
Выберите источник, откройте Attribute Editor и в разделе Texture Emission Attributes
найдите атрибут Texture Rate, позволяющий изменять плотность испускания в зависимости от
цвета текстуры (от яркости, если быть точным).
Нажмите на шашки справа от Texture Rate, чтобы назначить текстуру на этот атрибут.
Выберите в появившемся окне, например, Checker или File с вашей любимой картинкой.
Осталось включить самую главную галку Enable Texture Rate (находящуюся сразу под атрибутом
Пытливые умы, конечно, увидели, что над атрибутом Texture Rate есть аналогичная
конструкция для управления цветом частиц. И хотя про визуализацию частиц мы ещё не говорили,
проделаем похожие действия для того, чтобы частицы при испускании наследовали с текстуры
свой цвет.
Выключите галку Enable Texture Rate, чтобы было удобнее наблюдать эффект наследования
цвета по всей поверхности.
Включите галку Inherit Color (наследовать цвет) и нажмите на шашки справа от атрибута
Particle Color, чтобы назначить текстуру на этот атрибут.
Выберите в появившемся окне текстуру типа File и для нее загрузите в поле Image Name
любое растровое изображение (например, hotelFacade.jpg) из папки brushlmages, входящей в
состав MAYA.
Однако даже если вы не забудете включить отображение текстур на экране (6), цвет частиц
остается серым. Включение/выключение галки Inherit Color тоже не помогает, однако зоркие и
пытливые умы заметят в Script Editor возмущенные возгласы MAYA:
Warning: particleShapel does not have the following attribute: rgbPP. Please add this attribute in order
for inheritance to work.
Отсюда следует, что частицы не имеют атрибута, отвечающего за цвет (да-да, по умолчанию
частицы - бесцветно-серые) и что такой атрибут им надо добавить.
Чтобы сделать это, надо выбрать сами частицы, открыть Attribute Editor и в разделе Add
У каждого типа частиц есть свои атрибуты, отвечающие за специфические свойства того
или иного типа: например, у Spheres за размер отвечает радиус, а у Point - атрибут point size.
Поэтому после каждого изменения типа частиц необходимо нажать кнопку Current Render Type,
чтобы в Attribute Editor появились атрибуты (и слайдеры к ним) для этого, конкретного типа
частиц.
Совет. Очень удобно использовать тип Streaks для визуального контроля как
направления, так и величины скорости движения частиц. Размер и длину «хвоста»
у этик «стриков» можно выбрать в Attribute Editor и использовать их до тех пор,
пока не придет время визуализировать частицы нужным образом.
Выберите наиболее подходящий вам по вкусу тип для испускаемых с поверхности частиц,
задайте его размер, и давайте на его примере продолжим изучение других атрибутов частиц,
отвечающих за их жизнь и смерть.
Это напоминает ровный огонек с одним небольшим недостатком - все частицы умирают
синхронно и резко. Пожалуй, стоит добавить «долгожителей», то есть сделать так, чтобы одни
частицы жили дольше, а другие умирали раньше остальных.
Реально время жизни для частиц сейчас располагается в диапазоне [0.75; 1.25], так как
формула для вычисления возраста в случае Range range выглядит следующим образом:
Lifespan ± Lifespan Random/2.
Атрибут Random Range определяет, таким образом, диапазон разброса времени жизни, а
не величину отклонения.
Вернемся к дыму.
Выберите частицы.
Создайте поле турбулентности: Fields=>Turbulence.
Так как сквозняки должны возмущать воздух во всем пространстве, не затухая по мере
удаления от центра поля, сразу установите атрибут attenuation в ноль.
В Attribute Editor для поля турбулентности введите в ячейку атрибута phaseX следующее
выражение:
=noise(time)
и нажмите Enter.
Обратите внимание как ловко расширилась ячейка для ввода формулы при вводе знака
'='. Таким образом был быстро создан простой expression, изменяющий атрибут phaseX от -1 до
1. Функция noise это «помятый синус», его график представляет собой гладкую кривую, которая
«псевдопериодически» меняет свое значение в диапазоне от -1 до 1.
Если частота изменения формы поля кажется вам слишком высокой, нажмите правую
кнопку над атрибутом phaseX прямо в Attribute Editor и выберите Edit Expression.
В появившемся Expression Editor отредактируйте формулу следующим образом:
Выберите частицы, откройте Attribute Editor и в разделе Add Dynamic Attributes нажмите
кнопку Opacity.
Из двух вариантов выберите второй (Add Per Particle Attribute), чтобы добавить
индивидуальной прозрачности для каждой частицы.
Чуть выше, в разделе Per Particle (Array) Attributes, появится атрибут opacityPP, с которым,
очевидно надо что-то сделать.
Нажмите правую кнопку мыши на сером поле справа от имени атрибута, и в появившемся
меню выберите Create Ramp.
Чтобы отредактировать степень прозрачности частиц, снова нажмите правую кнопку мыши
на поле OpacityPP.
На этот раз там появится самое длинное меню в мире, прорвавшись сквозь которое
выберите Edit Ramp.
Вам потребуется некоторое время для того, что бы осознать, как текстура влияет на
прозрачность (точнее, как она «лежит» на частицах, ведь у них нет ни поверхности, ни UV-
координат), однако пытливые умы, используя метод пристального взгляда, быстро догадаются, что
Отредактируйте текстуру так, чтобы частицы с самого начала имели некоторую прозрачность
(серый цвет внизу), а начинали исчезать после половины прожитого времени жизни.
Это, в общем-то, экзотика, и для таких случаев лучше пользоваться expression, но иногда
удобно использовать позиции частиц как UV-координаты для текстуры, определяющей некоторые
свойства частиц - например, массу.
Следует различать время жизни (lifespan) и возраст частиц (age). Время жизни - это
атрибут, который можно редактировать и анимировать, влияя на продолжительность жизни частиц
на экране. Возраст - это не редактируемый (read-only) атрибут, который содержит информацию
о том, сколько времени прошло с момента рождения частицы. Как только значение атрибута age
становится больше значения, определяемого lifespan, частица исчезает.
Во-вторых, для разных типов частиц необходимы разные атрибуты для редактирования
внешнего вида частиц. Для сфер, например, нужен радиус, а для спрайтов размер по X и Y.
Поэтому вешать на частицы атрибуты на все случаи жизни (а точнее, для всех типов частиц) было
бы опять же неэкономно.
Понятно, что в первом случае добавляется один обычный числовой атрибут, который можно
разыскать и отредактировать в Attribute Editor в разделе Render Attributes. Во втором случае в
списке индивидуальных атрибутов в разделе Per Particle (Array) Attributes появляются атрибуты
rgbPP и opacityPP, соответственно. Резонно было бы задать вопрос: а можно ли задавать не только
индивидуальную прозрачность или цвет, но еще и радиус сферы или размер спрайта для каждой
частицы?
Конечно можно. Если для добавления цвета и прозрачности есть специальные кнопки,
Причем в этом списке находятся имена всех возможных атрибутов для добавления к
частицам. В том числе уже добавленные или существующие на выбранном объекте. При попытке
добавить такой, уже существующий атрибут будет просто выдаваться сообщение об ошибке.
Кроме того, в списке перечислены все атрибуты для всех типов частиц. И в принципе
можно добавить индивидуальный размер спрайтов к частицам типа сфер MAYA не будет вас ругать
и ошибки это не вызовет, так что руководствуйтесь здравым смыслом.
К тому же в этом списке в общую кучу свалены и per object атрибуты (то есть общие для
всех частиц) и per particle, или индивидуальные атрибуты. Причем отсутствие букв РР (Per Par
ticle) не означает, что атрибут имеет тип per object. Напротив, большинство атрибутов являются
индивидуальными, то есть добавляются к отдельным частицам.
К сожалению, эти атрибуты не перечислены в описании ноды particle, поэтому пытливые
умы, бескомпромиссно желающие ознакомится с их типом и предназначением, должны найти
в документации раздел List of particle attributes и прочитать необходимые комментарии (таких
разделов, с одинаковым именем, кстати, два - в разделе Dynamics и MEL and Expressions,
соответственно, причем первый из них более подробный). Ниже я расскажу о некоторых из них,
но, безусловно, не обо всех.
Наличие такого списка, естественно, не исключает того, что мы можем добавить к частицам
свой атрибут с произвольным именем и использовать его в своих целях, например, для Particle
Instancer, как будет рассказано ниже.
Component Editor
Для тех, кто любит вбивать цифры в клеточки, в MAYA встроена особая реинкарнация Mi
crosoft Excel, позволяющая быстро вбить значения десяти тысяч скоростей для каждой частицы
или отредактировать цвет каждой пятой из них. Эта реинкарнация расположена по адресу
Windows=>General Editors=>Component Editor. Чтобы увидеть в нем значения индивидуальных
атрибутов, следует выбрать некоторое количество частиц как компоненты, то есть по правой
кнопке мыши, а затем уже разыскать в Component Editor закладку Particles.
Теперь задача состоит в том, чтобы запомнить состояние частиц в текущем кадре, а
источник выключить или вообще удалить, чтобы в пространстве осталось независимое облако
частиц, не исчезающее каждый раз при возвращении в первый кадр.
Теперь просто удалите источник и снова проиграйте анимацию. Одна маленькая незадача
- частицы немного двигаются.
Нужно просто притормозить частицы, чтобы в первом кадре было просто неподвижное
облако. Самый простой способ состоит в том, чтобы вбить частицам нулевые скорости от руки.
Сделать это надо в первом кадре.
Нажмите правую кнопку мыши над частицами и выберите Particles.
Затем выберите все частицы прямо на экране и откройте Component Editor.
Разыщите в нем закладку Particles и обнулите значения всех атрибутов velocity для всех частиц.
Это просто сделать, выделив три заголовка столбцов Velocity и сразу напечатав ноль в появившуюся
ячейку. (Другой способ ввода значений в диапазон ячеек: выделить первую ячейку, а затем
- последнюю и нажать клавишу Shift.) Так как частиц довольно много, возможно придется
подождать.
select -rparticle1.pt[0:133331] ;
// Warning: Displaying the first 1024 rows from a total of 133334. //
Пока ничего не произошло, так как никаких значений для radiusPP не задано.
Нажмите правую кнопку мыши справа от имени атрибута и в появившемся меню выберите
Create Ramp.
Снова испугайтесь и запустите анимацию.
Возьмите себя в руки и методом пристального взгляда установите, что частицы стали
исчезать примерно через двадцать пять кадров после рождения, то есть за время жизни они
Так и есть. После создания текстуры ramp MAYA автоматически переключила параметр
Lifespan Mode в Constant, и время жизни частиц стало равным одной секунде.
Задайте Lifespan=4.
Радиус теперь, очевидно, изменяется в зависимости от градиента, задаваемого текстурой.
Доберемся до нее.
Нажмите правую кнопку справа от radiusPP (там теперь появилась ссылка на загадочный
arrayMapper), в выпавшем меню доберитесь до Edit Ramp.
Глядя на черно белый градиент, можно понять, что единичный радиус соответствует
белому цвету в нижней части текстуры, которая отвечает за начало времени жизни. Верхняя часть
текстуры соответствует концу времени жизни и черный цвет соответствует исчезающе-малому
радиусу.
Понятно, что диапазон значений от нуля до единицы, задаваемый текстурой, слишком велик
для значений радиуса. Но вместо того, чтобы ожесточенно уменьшать значение белого цвета,
проще уменьшить яркость всей текстуры, чтобы редактирование отдельных цветов оставалось
наглядным и контрастным.
Очевидно, что выбирая разные типы типы интерполяции для ramp и редактируя цвета и
их расположение на текстуре можно добиваться довольно забавных эффектов. Но все они будут
иметь одно ограничение: частицы должны иметь время жизни. Ведь если установить Lifespan
Mode = Live Forever, то радиус частиц перестанет меняться, так как частицы останутся «вечно
молодыми». Поэтому применение текстуры ramp, для анимации индивидуальных атрибутов, как
правило, ограничено плавным изменением значений в зависимости от возраста частиц.
Если же мы захотим назначить всем частицам разный радиус уже при рождении и в
дальнейшем менять его по произвольным законам (например схлопывать частицу при достижении
определенной частоты), нам не обойтись без написания expression.
Сохраните сцену (bubbles.mа). Рассмотрим принципы написания expression для частиц на
примере этих же пузырей.
radiusPP=rand(0.01, 0.1);
radiusPP=rand(0.01, 0.1);
radiusPP=radiusPP*1.01;
if(radiusPP<0.15) radiusPP=radiusPP*1.01;
if(radiusPP<0.15) radiusPP=radiusPP*1.01;
vector $pos = position;
vector $vel = velocity;
if (Spos.y > 2) {
velocity = << $vel.x, 0, $vel.z >>;
}
Это означает, что если частица забралась по вертикали выше, чем на 2, её скорость по вертикали
обнуляется и она продолжает движение только в горизонтальной плоскости.
if(radiusPP<0.15) radiusPP=radiusPP*1.01;
vector $pos = position;
vector $vel = velocity;
if (Spos.y > 2) {
velocity = « $vel.x+rand(-0.01,0.01), 0, $vel.z+rand(-0.01,0.01) »;
}
После таких оптимистических заявлений, надо поговорить о том, чем отличаются expres
sions для частиц (Particle Expressions) от обычных expressions, как и когда они выполняются и какие
основные трюки используются при анимации частиц с помощью expressions.
Runtime Expression для частиц похож на обычный expression для объектов - он выполняется
в каждом кадре при проигрывании анимации. Его основное отличие состоит в том, что он
выполняется в каждом кадре для каждой частицы. То есть если в кадре существует десять тысяч
частиц, то формула radiusPP=radiusPP*1.01 будет выполнена десять тысяч раз в каждом кадре! Об
этом следует помнить при написании особо изощренных expressions.
Creation Expression выполняется в каждом кадре, но только для тех частиц, которые в этом
кадре родились. В следующем кадре для них уже будет выполняться Runtime Expression.
Creation Expression служит, как правило, для задания начальных значений для
индивидуальных атрибутов частицы, которые либо будут далее изменены в Runtime Expression,
либо будут определять постоянные свойства частицы. Назначение случайного размера или цвета
в момент рождения - типичный пример использования Creation Expression.
Runtime Expression, если говорить формально, выполняется для каждой частицы, чей
возраст (то есть атрибут age) больше нуля, каждый раз, когда MAYA вычисляет динамику. Если
параметр Oversampling (отвечающий за точность обсчета частиц и устанавливаемый в Solvers=>Edit
Oversampling or Cache Settings) равен единице, выполнение происходит в каждом кадре. Если, к
примеру, он равен четырем, то вычисление динамики и, как следствие, выполнение Runtime Ex
pression происходит в четыре раза чаще (грубо говоря, четыре раза между соседними кадрами).
Ещё одно отличие от обычных expressions и объектов заключается в том, что для одного
объекта типа particle, а точнее, для ноды particleShape, всегда создается один Expression,
называемый как правило particleShapeX, в котором «зашиты» и Creation и Runtime Expressions. В
нем происходит вся работа с индивидуальными атрибутами частиц. Не надо создавать несколько
expressions для частиц! В Expression Editor такой expression всегда фигурирует под одним именем
и автоматически появляется, если выбрать shape объекта с частицами (то есть выбрать частицы и
нажать стрелку вниз).
Обычно Creation и Runtime Expressions редактируют и создают, попадая в Expression Editor
из Attribute Editor для частиц, нажав правую кнопку в поле индивидуальных атрибутов.
Это самый «легальный» способ открыть нужный expression, поэтому старайтесь использовать его.
Теперь посмотрим, какие трюки можно использовать при работе с Particle Expressions.
Как убить конкретную частицу?
Конечно, любители вбивать цифры в клетки предложат выделить часть частиц, затем
открыть Component Editor и вбить ноль в столбец lifespanPP, не забыв при этом переключить
параметр Lifespan Mode в LifespanPP Only и сохранить начальное положение. А если надо убить
каждую пятую частицу, или, начиная с третьей сотни, каждую восьмую, или не убить, а заморозить
на месте? Взрослые мальчики, естественно, напишут expression, который и проделает всю грязную
работу.
if(particleld>10) lifespanPP=0;
if(particleld%5==0)lifespanPP=0;
Это читается так: если остаток от деления нацело равен нулю, то - умереть. Это остаток от
деления номера частицы на пять. Остатки от деления проходят классе в четвертом, поэтому если
вы закончили только начальную школу, поверьте на слово.
Кстати, убивать частицу совсем не обязательно: можно просто обнулить её радиус или
переместить в другое место.
Иногда надо сделать так, чтобы изредка происходило некоторое событие, и степень
«редкости» хотелось бы регулировать.
Эта конструкция означает, что если очередное случайное число от нуля до единицы
оказалось больше, чем 0.9, то скорость частицы (ведь дело происходит при ее создании) меняется
на противоположную. Иначе можно сказать, что с вероятностью 10 процентов каждая следующая
частица полетит в другую сторону.
Главное достоинство этой функции - ее свойство возвращать новое случайное число при
каждом её вызове. То есть если в Runtime Expression для объекта из пяти тысяч частиц встречается
выражение типа
radiusPP=radiusPP+rand(-0.01, 0.01);
это означает, что в каждом кадре функция rand будет вызвана пять тысяч раз и добавит к
радиусам всех частиц пять тысяч разных значений.
С одной стороны, эта функция позволяет задать неодинаковость различных свойств для
частиц. С другой стороны, эта неодинаковость распределяется равномерно в том диапазоне,
который указан при вызове функции.
Специально для трехмерных атрибутов типа скорости или позиции, существует объемная
реинкарнация этой функции под название sphrand(L), возвращающая случайный вектор заданной
длины. Компоненты этого вектора могут быть отрицательными. А для цвета можно воспользоваться
вызовом rand(<<x, у, z >>), возвращающим вектор (три числа), компоненты которого лежат в
диапазоне, от нуля до х, у, z, соответственно.
Внимание!! Если вы встречаете примеры на создание Runtime Expression или сами начинаете
экспериментировать, создавайте Runtime BEFORE Dynamic, выполняющийся до динамики. Оставьте
создание Runtime after Dynamic до тех времен, когда вы точно будете знать, что хотите проделать
над частицами некоторые действия после вычисления динамики.
Чтобы почувствовать разницу между before Dynamics и after Dynamics, откройте файл
smoke.ma.
Для того, чтобы сделать дымок не таким тонким и слегка его надуть изнутри, выберите
частицы и создайте для них следующий Runtime before Dynamic Expression:
acceleration = sphrand(1);
Это ещё раз должно убедить вас использовать по умолчанию Runtime before Dynamic Expression.
Первая строка определяет вектор, торчащий из начала координат, в точку, где находится
локатор. Этот вектор одинаков для всех частиц, так как от них не зависит.
Третья строка вычитает второй вектор из первого. Те кто успешно закончил начальную
школу помнят, что результатом будет вектор, направленный из конца второго ($vloc) на конец
первого ($vloc). To есть результирующий вектор направлен от частицы к локатору.
Первое, что хочется подрегулировать это степень стремления, тот самый goal weight,
промелькнувший при выполнении операции Goal. Его надо искать в атрибутах частиц: в Channel
Box он появляется как атрибут goalWeight[0], а в Attribute Editor в разделе Goal Weights and Ob
ject под названием nurbsConeShape1. Это один и тот же атрибут, равный по умолчанию 0.5. Его
увеличение ведет у усилению притяжения частиц к поверхности, а установка в ноль заставляет
забыть о стремлении в поверхности вообще.
Совет. Для того, чтобы частиц не носились, как безумные, уменьшите атрибут
conserve для них. Всегда используйте conserve при работе с Goal.
Задайте conserve=0.95.
Теперь частицы «вспоминают» о своей цели только в сотом кадре и мягко стремятся к
своим вершинам.
Пытливые умы, однако, уже заметили, что в Attribute Editor появился ещё один
дополнительный атрибут в разделе Per Particle (Array) Attributes.
Таким образом, когда общая сила притяжения (goalWeigh[0]) станет равна 0.3, веса всех
частиц будут равномерно распределены в диапазоне от 0.15 до 4.5. Это заставит их стремиться к
поверхности с разной скоростью и добавит хаоса в их движение.
Кстати, в этом случае степень стремления задается для каждой частицы всего один раз -
при испускании, то есть в момент рождения. Чтобы сделать движение ещё менее упорядоченным,
скопируйте формулу для goalPP и создайте такой же Runtime Expression. Это заставит частицы
менять свою степень стремления к поверхности в каждом кадре.
Создайте ещё одну поверхность (например, политор, полигональный тор) или скопируйте
существующую.
Теперь частицы бодро летят на другую поверхность и после сотого кадра робко пытаются
дернуться в сторону конуса.
Очевидно, что вес новой поверхности больше, чем жалкие 0.3, которые имеет конус после
сотого кадра. Так и есть: в Channel Box для частиц теперь есть два атрибута goalWeight[0] и goal-
Weight[1], отвечающие за степень притяжения к конусу и тору, соответственно.
Поверхностей притяжения для частиц может быть сколько угодно, однако важно понимать,
что если количество атрибутов goalWeight[N] равно числу этих поверхностей, то атрибут goalPP
всегда один, и равняется индивидуальным для каждой частицы.
На этот случай есть секретные атрибуты, позволяющие точно указать для каждой частицы,
в какое место на поверхности ей стремиться.
Выделите частицы и в Attribute Editor, в разделе Add Dynamic Attributes, нажмите кнопку
General, чтобы добавить эти секретные атрибуты.
В закладке Particles выберите атрибуты goalU и goalV и нажмите ОК. Эти названия появятся
в списке per particle атрибутов, а частицы станут лететь в одну точку.
Если изменить диапазон разброса для goalU или goalV, частицы будут покрывать только
часть поверхности.
Например:
И в заключение приведу пример Creation Expression (он, кстати, может быть использован и
как Runtime Expression), который заставляет частицы покрывать поверхность не хаотично, а рядами,
в виде прямоугольной сетки заданной плотности (в предположении о том, что UV-координаты на
объекте также представляют собой прямоугольную область, как на всех NURBS-поверхностях):
goalU=(id/50.)%1;
goalV=int(id/50)/50.%1;
float $uRange=1.;
float $vRange=1.;
float $uGrid=50.;
float $vGrid=50.;
goalU=(id/$uGrid)%$uRange;
goalV=int(id/$uGrid)/$vGrid%$vRange;
Кропотливые умы наверняка заметят какие-то точки, летающие вокруг да около поверхности.
Точки при ближайшем выборе и рассмотрении оказываются частицами. А метод пристального
взгляда позволяет определить, что частицы движутся под действием поля турбулентности.
Осталось понять, откуда они взялись.
Как видите, идея действительно проста. И на этом можно было бы закончить, ведь если
вы знаете, как анимировать частицы, а также концепцию goal, нетрудно будет организовать
деформацию поверхностей нужным образом. Надо лишь помнить: частицы, образующие мягкое
тело, ничем не отличаются от обычных частиц.
Шутка. Про Particle Instancer я расскажу чуть позже, а сейчас изложу некоторое количество
замечаний и рассуждений относительно мягких тел.
Термин «мягкие» (soft) не совсем удачен, так как вызывает ассоциации с тканями, для
анимации которых существуют совершенно обособленные решения типа MAYA Cloth или Syflex
(см. www.syflex.biz). Назвать их «динамически деформируемые» было бы более корректно, но
настолько тяжеловесно, что я останусь в традиционной терминологии, а в устной майской русской
лексике прижился термин «софтбоди».
Сабдивы не позволяют превращать себя напрямую в мягкое тело, однако вы всегда можете
применить трюк, описанный выше для твердых тел: перейти в режим Polygon и превратить в
мягкое тело полигональную сетку, окружающую сабдив. Либо назначить на поверхность (этот
трюк справедлив не только для сабдивов, но и для сложных поверхностей других типов) Lattice-
деформер и превратить в мягкое тело его. Это создаст мягкие динамические деформации для
любой поверхности.
Удалите в предыдущем примере частицы или откройте новый файл и создайте сплайновую
плоскость заново (scale=20, patchesU=patchesV=30).
Выберите плоскость и откройте Option Box для Soft/Rigid Bodies=>Create Soft Body.
Постоянно помните о том, что существует невидимая поверхность и что частицы стремятся
к ней с заданным весом. Этот вес можно найти в Channel Box для частиц как значение атрибута
goalWeight[0].
Вспомним, что у каждой частицы может быть свой собственный вес (атрибут goalPP),
который умножается на общий goalWeight. С его помощью можно сделать некоторые участки
поверхности «мягче» или «жестче» остальных. Для частиц, образующих мягкие тела, имеется
возможность, вместо создания expressions для goalPP, просто раскрасить поверхность мягкого тела
в черно-белые оттенки, задавая, таким образом, распределение goalPP вдоль поверхности.
Выберите плоскость и возьмите в руки инструмент раскраски весов мягкого тела: Soft/
Rigid Bodies=>Paint Soft Body Weights Tool.
Поверхность сразу окрасится в белый цвет, так как goalPP для всех частиц равен единице
по умолчанию.
Покрашенные части слегка «провиснут». Идея состоит в том, чтобы закрепить только один
крайний ряд частиц, а остальные «отвязать» от невидимой goal-плоскости, задав для них goal-
РР=0.
Если некоторые частицы, кроме крайних, остались на месте, это значит, что в Component
Editor «влезло» только 1024 из всех выбранных частиц, а часть осталась неотредактированной.
Повторите редактирование goalPP для оставшихся частиц, аналогичным образом.
Осталось вставить пружины, чтобы удержать свободные частицы от падения на самое дно.
Так же, как и для твердых тел, между частицами можно вставлять пружины. При этом, если
выбрать конкретные частицы как компоненты (и даже точки поверхности вместе с ними), пружины
будут натянуты только между выбранными компонентами. Если же выбрать мягкое тело как объект,
пружины будут создаваться для всех частиц, составляющих мягкое тело. Естественно, что должна
быть возможность как-то определить общий закон распределения пружин для целого массива
частиц, не определяя индивидуальные связи для каждой пары частиц.
Для того, чтобы анимация крутилась быстрее, спрячьте только что созданные пружины
(Ctrl+h). Очевидно, что пружинам не хватает жесткости. Также очевидно, что жесткость
определяется через атрибут stiffness у вновь созданного объекта spring1, который можно выбрать
в Outliner.
Задайте stiffness=20.
Спрячьте частицы, для красоты, и уберите координатную сетку.
При проигрывании могут наблюдаться высокочастотные «биения».
Однако после этого, несмотря на то, что общее движение поверхности стало более
спокойным и затухающим, биения не прекратились. Для того, чтобы совсем от них избавиться,
надо увеличить точность просчета динамики частиц.
Для этого откройте Solvers=>Edit Oversampling or Cache Settings и введите значения 2 для
параметра Over Samples. Это позволит вычислять траектории и определять скорости частиц в два
раза чаще и, как следствие, в два раза точнее.
Чтобы понять, как это происходит, покажите на экране частицы и сделайте их сферами.
После этого можно убедиться, что ни одна частица не провалилась внутрь сферы. А проблема
заключается лишь в том, что контрольные точки сплайновой поверхности не лежат на самой
поверхности, и это позволяет занавеске проникать внутрь сферы.
Загрузите свою любимую модель (или файл headStart.ma) или создайте NURBS-сферу с
достаточным количеством изопарм.
Напомню, что при создании источника вместе с ним появляется объект типа particle, то
есть частицы, вылетающие из источника.
Эти частицы надо выбрать в Outliner (они наверняка называются particle - !), и безжалостно
удалить.
Это можно сделать в Dynamics Relationship, выбрав слева частицы, а справа источник (и не
забыв включить наверху опцию Emitters).
После этого, правда, ничего не изменится: новые частицы не появляются, старые стоят
на месте. Откройте Attribute Editor и в разделе Soft Body Attributes выключите галку Enforce Count
from History, которая удерживает постоянным количество частиц, составляющих мягкое тело и не
дает ему увеличиваться или уменьшаться.
Осталось сделать так, чтобы в первом кадре никаких частиц не было вообще. Для этого
просто надо задать им нулевое время жизни, подождать, когда все они исчезнут, и сохранить это
состояние как начальное.
Теперь сохраните это состояние как начальное для всей динамики: Solvers=>lnitial
State=>Set for All Dynamics.
Оригинальная поверхность, которая превращалась в мягкое тело, может быть как угодно
анимированной появляющееся «полотно» будет повторять все деформации и перемещения
оригинала.
Для поверхностей с большим числом вершин, особенно для полигонов, где нумерация
вершин не так очевидна, как для сплайнов, проще иногда создать Lattice-решетку и превратить ее
Частицы можно просто спрятать, однако, если вы хотите, чтобы источник «выплюнул» ровно
столько частиц, сколько составляют мягкое тело, посчитайте количество вершин у поверхности
(или решетки) и задайте это значение для атрибута maxCount у частиц в Attribute Editor. Это
позволит ограничить появление лишних частиц, а при маленьком времени жизни создать эффект
умирания и рождения поверхности заново.
В случае NURBS-поверхности можно подобрать значение rate для источника так, чтобы
в каждом кадре появлялось количество частиц, равное числу точек, образующих один ряд
контрольных вершин поверхности. Тогда «рождение» поверхности будет особенно «гладким».
Сохраните сцену (headSoftBody.ma).
В заключение отмечу, что динамика мягких тел применяется не только для деформации
непосредственно поверхностей, но и для создания динамической деформации кривых, которые
можно потом использовать, к примеру, как IK Spline Handle или Wrap Deformer.
Также мягкие тела можно применять для медитации. Если вам это интересно, выполните
следующие упражнение.
Выключите свет, займите удобную позу и нажмите Alt-v. Надеюсь, в этой жизни мы ещё
увидимся...
Импортный самолет всех времен и народов несколько велик для подстановки в частицы,
так что задайте для него scale=0.2.
Как обычно, можно действовать двумя методами: либо выполнить операцию подстановки
с параметрами по умолчанию, а потом поправить нужные атрибуты, либо зайти в Option Box и
настроить нужные параметры с самого начала.
Как следует из Help Line, чтобы подставить объект в частицы, надо сначала выбрать сам
объект (или объекты), потом частицы, а затем выполнить операцию подстановки. Однако если вы
откроете Option Box, сами частицы (так как они были выбраны в соответствии с рекомендациями
Help Line) попадут в список объектов для подстановки в самих себя. Это, естественно, создаст
некоторые проблемы и непонимание со стороны окружающих.
Возникнет довольно веселая стая самолетов. Однако есть одна проблема все они
оборудованы технологией вертикального взлета и поэтому перемещаются плоско-параллельно.
Чтобы исправить положение, надо, очевидно, отредактировать нужные атрибуты, но прежде
необходимо сформулировать, как должны лететь самолеты.
Это связано с тем, что opacityPP - одно число, a scale - сразу три значения.
Чтобы MAYA автоматически пересчитывала одно значение в три одинаковых атрибута,
включите галку Allow All Data Types и в списке Scale появятся все индивидуальные атрибуты
частицы, а не только состоящие из трех значений.
Самолеты резко встанут на крыло и начнут летать левым бортом вперед. Проблема
аналогична случаю движению вдоль пути. Мы не определили, где у самолетов «нос», и они летят,
поворачиваясь вперед своей локальной осью X.
Выберите оригинальный самолет и поверните его вокруг оси Y, так чтобы его нос смотрел
вдоль мировой оси X (rotateY=90).
Примечание. Помните о том, что, как и при движении вдоль пути, важна не
только ориентация «носа» объекта, но и направление, куда смотрит «макушка».
По умолчанию «макушка» - это локальная ось Y oбъекma(AimUpAxis), а направление
«вверх» задается вариантом AimWorldUp и, по умолчанию, является направлением
вдоль мировой оси Y (0,1,0).
Это заставит все объекты смотреть не вдоль вектора, а на точку в пространстве, занимаемую
локатором.
Можете увеличить rate у источника частиц и провести над ними любые издевательства
- самолеты будут послушно следовать за частицами. Только помните о том, что при столкновениях
с поверхностями будут использоваться частицы, поэтому объекты будут «проваливаться» в
поверхность (если надо, скопируйте и сдвиньте поверхность для обмана честных граждан).
Самолеты также ничего не знают (и никогда не узнают) друг про друга, ведь они - только
визуализация частиц, которые также ничего не знают друг о друге.
Множественная подстановка
Предположим, что у вас есть целая эскадрилья самолетов или набор птиц, зверей и рыб.
Если порядок вылета не так важен, можно создать несколько источников частиц и испускать
каждый объект из своего источника.
Ещё профессиональнее будет удалить все источники, кроме одного, а оставшиеся несколько
объектов типа particle присоединить к одному источнику, чтобы он испускал сразу несколько
видов частиц, подставленных разными объектами. (Надо только не забыть в этом случае у всех
частиц выставить разные значения в разделе Emission Random Stream Seeds, чтобы они вылетали
из одного источника по-разному.)
В Attribute Editor для частиц нажмите кнопку General в разделе Add Dynamic Attributes.
В появившемся окне для добавления атрибутов выберите Data Type=Float и Attribute
Type=Per Particle(Array).
Теперь надо задать закон изменения атрибута indexPP в зависимости от номера вылетающей
частицы.
Для того, чтобы объекты подставлялись в частицы по очереди и по кругу, создайте Crea
tion Expression:
indexPP=particleld%6;
Здесь число 6 - это количество подставляемых объектов. А формула читается так: индекс
равен остатку от деления номера частицы на шесть.
Если вы хотите, чтобы объекты вылетали не по очереди, а в случайном порядке, то Crea
tion Expression может выглядеть так:
После подстановки нескольких объектов в одну систему частиц выберите в Outliner объект
instancer и задайте для него Cycle=Sequental.
На помощь приходит понимание того, что вся динамика зависит от системного времени,
которое в свою очередь, является обычным майским объектом, соединенным с динамическими
объектами связью между атрибутами. Следовательно, если «перехватить» эту связь, а затем
время немного растянуть или сжать и подать обратно на вход к динамике, можно изменять общий
темп выполнения динамики в сцене. После таких туманных заявлений проделаем два небольших
примера на работу со временем.
Разорвите эту связь прямо в Attribute Editor (правая кнопка мыши - Break Connection), a
затем в поле аттрибута currentTime введите строку:
=(160.0/100.0)*time1. outTime;
Теперь вся сцена с кубиком длится ровно желаемые 100 кадров, причем мы полностью
сохранили контроль над всеми управляющими параметрами и при необходимости можем её легко
модифицировать.
Откройте файл fountain.mа и сделайте анимацию камеры с сотого по двухсотый кадр. Если
вам лень, откройте файл scaleParticleDynamicsStart.ma.
Задача состоит в том, чтобы частицы замирали в момент движения камеры и снова
начинали двигаться после двухсотого кадра. Идея анимировать conserve от нуля до единицы не
очень хороша, так как частицы просто безвольно упадут вниз после обнуления скорости. Будем
дейтвовать радикально - поставим ключи на собственное локальное время частиц (не путать с
временем жизни).
Выберите частицы, а в Attribute Editor разыщите атрибут currentTime.
Он имеет связь с глобальным временем timel.outTime, которую необходимо немедленно
разорвать (Break Connection).
Теперь выберите частицы, откройте Hypergraph и выполните Graph=>lnput And Output Con
nections.
Выберите в Outliner ноду t i m e l , включив там отображение всех объектов в сцены. Загрузите
time1 в левую часть Connection Editor, а в правую часть загрузите анимационную кривую particle-
Shape1_currentTime, которую можно выбрать в Hypergraph.
Вы можете захотеть заставить частицы отталкивать друг друга: например, для придания
объема скоплению частиц или для более равномерного их распределения в некоторой области.
Первый способ организовать взаимодействие частиц состоит в том, чтобы зайти на сайт
www.highend3d.com и в разделе MAYA выкачать несколько плагинов, вычисляющих поле взаимного
влияния частиц друг на друга. Все они делают примерно одно и тоже, а различаются лишь
производительностью.
Заранее хочу извиниться перед знатоками физики, признаваясь в том, что с точки зрения
науки мои дальнейшие рассуждения могут им показаться полным бредом. Однако построения «на
пальцах» позволяют создать довольно любопытную модель, пригодную не только для игры, но и
для философствования и рассуждений о смысле жизни.
Итак, откройте новую сцену, закройте глаза и представьте себе маленькую каплю воды в
невесомости. В наших рассуждениях она представляет собой набор молекул, на которые действуют
по крайней мере две силы.
Кандидатом на роль обеих сил будет поле типа Radial, позволяющее как притягивать, так
и отталкивать объекты. Осталось только придумать, как его «засунуть» в сами частицы.
Для этого откройте Option Box для Particles=>Particle Tool, включите галку Create Particle
Grid, затем выберите опцию With Text Fields и введите для Minimum и Maximun Corner значения
(-1,-1,-1) и (1,1,1), соответственно.
Совершенно очевидно, что центр действия поля находится в начале координат и что ни
о каком взаимном отталкивании речь пока не идет. Теперь осталось сделать так, чтобы частицы
стали источником поля.
Выполните Fields=>Use Selected As Source of Field (то есть «Использовать выбранный объект
как источник поля»).
Правда, после этой операции мало что изменится: поле по-прежнему находится в центре
и оттуда, не торопясь, влияет на частицы. Дело в том, что по умолчанию поле просто вставляется
в геометрический центр выбранного объекта и наследует его перемещения, оставаясь при этом
одной точкой. Чтобы поле стало действовать из каждой компоненты объекта, являющегося его
источником, надо в атрибутах самого поля включить параметр applyPerVertex.
Это снизит общую скорость движения молекул (напомню, что скорость частицы умножается
на значение conserve в каждом кадре) .
Теперь частицы ведут себя совсем по-другому. Можно выделить две стадии движения.
Примерно к сто двадцать пятому кадру молекулы из решетки превращаются в сферообразную
структуру, причем очень правильной и всячески симметричной формы.
Если поглядеть на нее с разных ракурсов, можно найти различные оси симметрии вдоль
мировых осей и вдоль диагоналей.
Увидев первый раз столь явный переход от порядка к хаосу, я, в «порядке бреда», усмотрел
в этом иллюстрацию второго закона термодинамики о возрастании энтропии в предоставленной
самой себе замкнутой системе. Проникшись идеями синергетики, я стал искать другие значения,
определяющие свойства полей, которые бы привели к организации более упорядоченных структур
молекул.
Сохранитеобязательносценустекущимизначениями(dropPreset.ma) и поэкспериментируйте
со значениями magnitude, attenuation и maxDistance у обоих полей. Отмечу, что идея симулировать
взаимодействия частиц несомненно удалась: система остается устойчива и при этом сохраняет
некоторый объем в пространстве.
Динамика частиц 11 37
Если теперь уменьшить силу притяжения (pushField.magnitude=22), то частицы образуют
кольца и дуги.
Теперь капля непонятного вещества круглая уже в первом кадре, и на нее можно
воздействовать различными силами.
Чтобы капля не съезжала, как на санках, с плоскости, задайте для появившейся в Chan
nel Box ноды geoConnectorl значения friction=1, это придаст трение или прилипание капли к
поверхности.
Динамика частиц 11 39
После этого молекулы перекатываются по плоскости, как мини-гусеница от танка, и перед
падением судорожно цепляются за край.
Экпериментируем дальше.
Создайте источник частиц: Particles=>Create Emitter.
Сразу же удалите в Outliner появившиеся вместе с ним частицы.
Затем выберите каплю, потом источник и выполните Particles=>L)se Selected Emitter.
Это присоединит молекулы к источнику, то есть из него начнут появляться частицы, для
которых уже созданы и настроены два поля, обеспечивающие взаимодействие.
Отодвиньте источник от капли и уменьшите наклон плоскости, например, до пяти градусов.
Чтобы из источника появилось столько же молекул, сколько составляет каплю, выберите
частицы и задайте значение атрибута maxCount=250 (так как в каплю входит 125 молекул).
Если частицы очень резко вылетают из источника (ведь они появляются практически в
одной точке и начинают жутко отталкиваться друг от друга), можно задать для источника значение
атрибута maxDistance=0.5, чтобы частицы испускались из него не в точке, а в некоторой окрестности
с радиусом 0.5.
Упавшие на плоскость капли начнут притягиваться друг к другу, поскольку это одна система
частиц - необходимо лишь, чтобы они находились не дальше друг от друга, чем значение maxDis-
tance для поля pullField. (Можете уменьшить силу гравитации, чтобы капли не сильно плющило.)
Сейчас самое время перейти к обсуждению методов визуализации частиц, так как вопрос
этот настолько назрел, что... В общем, потому что уже пора.
Кэширование частиц
Однако, прежде чем переходить к вопросам визуализации, я хотел бы отметить, что перед
визуализацией частицы, как правило, необходимо кэшировать, то есть сохранить их траектории на
диске в специальном файле. Этому есть несколько причин.
Чтобы создать кэш для выбранных частиц, в /??/ текущем диапазоне анимации достаточно
выполнить Solvers=>Create Particle Disk Cache. B Option Box этой операции можно указать имя для
кэша (точнее, имя папки, в которой он сохраняется внутри текущего проекта).
Если вы ещё не захлопнули книгу в ужасе от таких заявлений, давайте отрендерим уже
созданный дымок разными способами: аппаратным и обычным. Разница в скорости не будет так
заметна, поскольку количество частиц невелико, но основные принципы можно будет перенести и
на более массивные сцены.
Аппаратный дымок
Откройте файл smoke.та и убедитесь, что для источника частиц задан rate=300 и maxDis-
tance=0.02.
Чтобы дым был более прозрачный, нажмите в Attribute Editor для частиц правую кнопку
мыши в поле атрибута opacityPP и выберите Edit Ramp.
Сделайте нижний и средний слой почти черными, это придаст частицам большую
прозрачность на протяжении всего времени жизни. Мы не будем редактировать серый цвет частиц,
хотя эта возможность останется для дополнительных настроек внешнего вида.
Выберите для частиц Render Type= Multipoint и задайте Multi Count=30, Multi Radius=0.05,
Point Size=1.
Это создаст вокруг каждой реальной частицы ещё тридцать штук, которые будут
использованы только для визуализации и не будут обсчитываться динамикой.
Галка Line Smoothing делает из квадратных точек круглые и сглаживает края частиц типа
streaks. Поэтому включите её тоже.
Включите галку Multi Pass Rendering, и вы увидите, что при нажатии на «хлопушку» MAYA
рендерит текущий кадр трижды. Выберите RenderPasses=7, и количество проходов увеличится до
семи.
Зачем это нужно? Дело в том, что для частиц выбран тип Multi Point и при каждом
повторном рендеринге кадра, дополнительные частицы появляются вокруг основных по-разному.
Потом все семь проходов-изображений складываются и усредняются, что дает эффект размытия и
Чтобы дополнительно размыть как сам дымок, так и его края, надо «потрясти» камеру.
В разделе Multi-Pass Render Option включите галку Anti Alias Polygons (это и есть атрибут,
отвечающий за дрожание камеры).
Задайте величину «дрожания камеры» в поле Edge Smoothing=5, а чтобы увидеть как MAYA
«трясет» камеру, можно дополнительно включить/выключить в разделе Display Options галку
Grid.
Выберите частицы и задайте для них Point Size=25 (да-да, двадцать пять), Multi Radius=0.5,
a Multi Count=1.
«А зачем делать Multi Count равным единице?», возмутятся пытливые, но неокрепшие умы.
А затем, что при каждом проходе частицы будут появляться в разных местах одного кадра и при
Если вы хотите также сглаживания «по времени», укажите в поле Motion Blur количество
кадров, за которое будет просчитываться вышеуказанное количество проходов (если Motion Blur=0,
то просчитывается только текущий кадр).
Софтверный дым
Выберите частицы и в Attribute Editor задайте им Render Type=Cloud. Если теперь нажать
обычную кнопку Render Current Frame, частицы предстанут в окне Render View как странный
голубой дымок.
Уменьшите значения атрибутов Density и Blob Map, чтобы уменьшить плотность дыма и
понизить общую прозрачность.
Выберите частицы и отредактируйте текстуру для атрибута opacityPP, так чтобы частицы
были видны более отчетливо и постепенно исчезали - перед тем, как совсем исчезнуть.
Железный рендер
Количество модулей рендеринга в MAYA слегка подавляет, причем очередная версия так и
норовит подбросить ещё пару-другую методов рендерить объекты определенного типа.
До сих пор я употреблял термины «аппаратный» или «хардварный» рендер имея в виду
исключительно методы просчета через Hardware Render Buffer. Вплоть до пятой версии MAYA это
не вызывало никакого разночтения, однако в настоящее время приходится уточнять, что имеется
в виду под словом «аппаратный рендер».
Дело в том, что за время, прошедшее с выхода первой версии MAYA, сменилось не
одно поколение видеоускорителей. Современные видеокарты научились делать аппаратный
антиалайзинг, фильтровать текстуры, отображать бамп, работать со светом, туманом и многими
другими удивительными вещами. Однако Hardware Render Buffer за все эти годы не претерпел
практически никаких изменений. Его функцией всегда было одно: считать частицы со страшной
скоростью, максимально примитивным способом. То есть никаких преимуществ, кроме растущей
частоты ядра видеокарты и количества бортовой памяти, Hardware Render Buffer не использовал,
не использует и использовать не собирается. В этом есть определенное преимущество, так как уже
наработанные методы визуализации частиц будут давать предсказуемые результаты и в будущих
версиях MAYA.
Однако для просчета частиц он пока не может соперничать по скорости с Hardware Render
Buffer, а его способ работы с MultiPoints и MultiStreaks не позволяет использовать его для просчета
уже готовых сцен. Поэтому я ограничусь лишь упоминанием о том, что для его эффективного
использования вы должны иметь приличную видеокарту (требования к ней есть в документации),
и предложу проэкспериментировать с ним самостоятельно, на примере уже созданных сцен.
Пыль, дым, туман, легкая облачность, следы горения, снежок и все, что можно запихнуть
в текстуру - это, соответственно, спрайты.
Капли пота на лице трехмерного изваяния любимого начальника, подтеки крови, парафин,
кляксы в дневнике, прочие густые жидкости - Blobby Surfaces.
Работа со спрайтами
Рабочие лошадки среди хардверных частиц - спрайты и мультистрики. Основные приемы
работы со спрайтами заключаются в следующем.
Прежде всего надо определить, что за характер у дыма/пыли, которые надо сделать,
и, соответственно, выбрать размер спрайтов и текстуру для них. При потревоженых архаичных
пыльных взвесях, вялотекущих отравляющих газах, тлеющих останках стада мамонтов обычно
требуется большой размер спрайтов, не очень большое их количество, довольно мелкий
фрактальный рисунок в текстуре и медленное движение/вращение.
Для инверсионных следов самолетов, пыли из под колес вашего «Феррари», хвостов от
летящих к вам в офис ракет лучше всего подойдет большое количество небольших по размеру
спрайтов с несильно проработанной структурой. Тут важнее динамика, изменение прозрачности,
размера и т.д.
Спрайты лучше просчитывать с применением motion blur. Правда, для этого сразу купите
пару жестких дисков под кэш.
Лучше знать expressions, чем не знать... Это, впрочем, справедливо не только для
спрайтов, но ручная доводка их движения до воспаленного режиссерского замысла без expres
sions практически невозможна.
Кроме того, спрайты можно делать цветными! И не только подготавливая цветные текстуры.
Если у вас есть черно-белые спрайты, попробуйте добавить к частицам атрибут rgbPP.
Работа с мультистриками
Все пиротехники мира используют в своей работе мультистрики. Некоторые особенности
использования этого типа частиц можно сформулировать в следующем виде.
Motion blur для спрайтов, как правило, необходим, и для его адекватного использования
необходимо соблюдать два принципа:
Длинная история
Мое самое экстремальное путешествие (как ни странно, связанное с компьютерами)
было в 1996 году на Ближний и Средний Восток. Я тогда ещё занимался продажей компьютерной
техники, и мы активно искали новые рынки сбыта. В нашей стране становилось тесно, и мы решили
поехать, куда бы вы думали?... Правильно, в Ирак. Ходили слухи, что вот-вот снимут эмбарго,
установленное после войны в заливе, и возникла идея рвануть туда, чтобы подготовить почву для
будущего бизнеса, дабы сразу после снятия ограничений на торговлю въехать туда на белом коне
с принтером и монитором.
Рвануть, конечно, хотелось быстро и без проблем. Однако выяснилось, что самолеты туда
не летают, телефонной связи нет, а ближайший аэропорт находится в Иордании, в Аммане, его
столице, от которой до Багдада около тысячи километров. Притом по единственной дороге, через
пустыню, с непонятным названием. Так что быстро не получалось. Без проблем тоже. Несмотря
на благополучное получение виз, в последний момент отказался от поездки заранее найденный
и арендованный переводчик-проводник, уже не раз проделавший этот путь. Если бы я наперед
знал, как все будет происходить, или просто был бы постарше, я бы благоразумно отказался от
такого вояжа. Однако общая тяга к путешествиям и легкий, но устойчивый аромат адреналина,
исходивший от самой идеи, окончательно нарушили гормональный баланс, и через неделю мы
втроем сидели в полупустом самолете иорданских авиалиний, разучивая варианты вежливых
приветствий на арабском языке.
Начиналось все неплохо, отъезд на восток был назначен на раннее утро, и мы, утомленные
перелетами, переездами и переговорами, вползли в ближайший ресторан из лабиринта
предприятий питания многократнозвездочного отеля. Ресторан оказался индийский, и первая же
закуска, отправленная в рот, вызвала у меня желание вызвать пожарных, поэтому я попытался
торопливо заесть её близлежащим хлебом. Однако при выпечке хлеба вместо муки, скорее всего,
использовали красный перец, и вот я уже был готов испепелить своим дыханием всех местных
поваров. Помогла обычная советская ириска (это, кстати, реальный способ пожаротужения), и
я хорошо усвоил первый урок: в чужой стране не надо тащить в рот незнакомую, пусть даже
желудкопомрачительно выглядящую еду.
Мы быстро закрыли все окна, заперли двери и обратили свои не сильно отважные взоры
на водителя. Тот, впрочем, недолго общался с подоспевшими бойцами и, к нашему ужасу, быстро
открыл заднюю дверь салона неведомой ручкой в брюхе джипа-мутанта. Люди с автоматами, однако,
совершенно не проявили интереса к живым существам, то есть к нам, а вместо этого, отпихивая
друг друга, похватали наш многочисленный багаж и куда-то с ним побежали. Обескураженные,
мы могли лишь в полном изумлении последовать за ними.
И тут возникла самая экстремальная ситуация за всю поездку, хотя формально все
выглядело очень спокойно. Как выяснилось, попасть на территорию Ирака можно, если у тебя,
помимо визы, есть ещё приглашение или подтверждение от организации, имеющей дело с
иностранцами. Мы такого приглашения не имели, и тогда в качестве приглашающей стороны
стали бодро называть самое могущественное (после министерства обороны) министерство нефти,
в которое, собственно, и собирались попасть. Возник некий казус, для разрешения которого был
вызван весьма приветливый человек с дежурной улыбкой, прекрасно говоривший по-английски
(и, наверняка, по-русски, хотя и скрывавшай такую способность). Он отобрал наши паспорта и
проводил нас в зал для, типа, VIP персон, где четыре часа поил нас чаем, вел туманные разговоры
и периодически ненадолго отлучался. Он имел плохо скрываемые повадки человека, давно
работающего в органах, а мы имели шанс получить крупные неприятности, но все равно тупо и
безыскусно излагали свою легенду: о намерениях вести активные переговоры в министерстве
нефти. С одной стороны, он мог просто отправить нас обратно - по формальному признаку, ввиду
отсутствия необходимых бумаг. С другой стороны, имя могущественного бизнес-партнера и
обескураживающая уверенность трех наглых русских разгильдяев нагоняли на него сомнения.
Сильно помогло, конечно, и российское гражданство, ибо отношение к русским в Ираке тогда
было более чем дружественным, в чем нам пришлось ещё не раз убедиться, выслушивая слова
поддержки в нашу сторону и проклятия в адрес некоторых других стран.
Нам фантастически повезло, потому, что дело происходило в пятницу - а это официальный
Ниже, для обозначения всей технологии MAYA Fluids, я буду часто употреблять обычное
русское слово «флюиды». Будучи напечатанным вот так, родимой кириллицей, оно внесет некий
романтический оттенок в текст, довольно далекий от романтики: ведь в устной речи, в устойчивой
жаргонной традиции «майщиков», оно прижилось именно таким, без разъяснений. А ту жидкую
субстанцию, поведение которой моделируется с помощью флюидов, я буду называть «сплошной
средой» - чтобы подчеркнуть ее отличие от «несплошного» набора частиц.
Перед тем, как броситься с головой во море флюидов, я сильно рекомендую освоить
работу с частицами и основные принципы динамики, описанные с соответствующей главе.
Почему? По простой причине: многие свойства флюидов автоматически становятся понятны по
аналогии с частицами. Принципы вычисления динамики в каждом кадре и ограничения, с этим
связанные, для обеих технологий одинаковы. Методы кэширования также весьма схожи. Поэтому
для описания многих свойств я буду использовать аналогии с частицами или же наоборот - по мере
необходимости, акцентировать внимание на разнице в подходах.
Облака, сделанные с помощью флюидов, особенно хороши. Сквозь них можно летать, в них
можно плавать, к ним можно приближаться на любое расстояние, их можно отражать, преломлять,
затенять и даже считать с помощью mental ray. При этом изготавливать их довольно несложно,
динамического просчета они, как правило, не требуют, рендерятся предсказуемо, поэтому даже
если бы, кроме облаков, флюиды ничего больше делать не умели, они бы уже имели право на
существование как отдельная элегантная технология.
Формально говоря, есть еще целый класс феноменов, симулируемый с помощью флюидов.
Это «водные эффекты» (watereffects). Хотя правильнее их называть «эффекты водной поверхности».
К ним относятся океан (ocean) и водоем (pond). Они позволяют создавать и анимировать морскую
поверхность в любую погоду, равно как или более скромные явления, происходящие на поверхности
небольшого пруда, бассейна или лужи на затопленном перекрестке.
Флюиды 1161
Типы флюидов
Хотя океаны (ocean) и водоемы (pond) находятся в меню Fluids, язык все же не поворачивается
называть их флюидами, так как они представляют собой довольно обособленную технологию,
слабо напоминающую динамику жидких и газообразных сред. То есть формально и исторически
их к флюидам относят, но никогда так не называют. Ocean и Pond - достаточно независимые
имена, чтобы употреблять их по назначению. Часто их объединяют и относят к классу water ef
fects.
Более лапидарное объяснение модели работы флюидов звучит так: в каждом кадре
вычисляется динамика флюида, но ничто никуда не движется. Вместо этого, как в титрах к
матрице, неистово изменяются цифры в ячейках сетки контейнера. То, что вы видите на экране
-результат визуализации этих данных, тем или иным способом. В процессе визуализации данные,
интерполированные между ячейками, будут выведены на экран либо как полупрозрачный объем,
зависящий, в основном, от плотности, либо как поверхность, огибающая этот объем.
Флюиды 1163
Отсюда самое главное свойство флюидов - движение и взаимодействие среды всегда
рассчитывается и осуществляется внутри фиксированного объема. Его и называют контейнером.
Именно его разбивают на сетку из неподвижных точек-ячеек, в которых и производят вычисления
характеристик среды. За границами контейнера никакого движения и визуализации не происходит.
Внутри контейнера движения ячеек-точек также отсутствуют. Происходят только вычисления, и их
результат затем различными способами визуализируется.
Комментарий. Если вы уже вошли во вкус изучения MAYA и поняли основной принцип,
заключающийся в исследовании атрибутов нового объекта, вам будет гораздо
проще следить за моими рассуждениями, открыв Attribute Editor для любого
контейнера и последовательно исследуя все его разделы. На мой взгляд, описание
целого класса явлений с помощью всего одного базового объекта и набора его
атрибутов - это исключительно удачный и эффективный принцип, как с точки
зрения архитектуры программы, так и с позиции изучения и экспериментирования.
Очевидные или легко исследуемые «методом тыка» атрибуты вообще нет смысла
описывать, поэтому я остановлюсь на ключевых для понимания моментах.
Интуитивно понятно, что чем больше точек в контейнере (то есть чем больше его
пространственное разрешение), тем подробнее и точнее будет описываться поведение сплошной
среды. Однако время расчетов и рендеринга будет возрастать многократно (ибо количество точек
это приблизительно X*Y*Z).
Если изменять размер контейнера с помощью атрибутов Size, значение плотности и других
параметров в ячейках будет пропорционально изменяться. В этом состоит отличие от простого
растягивания. Вы также можете воспользоваться операцией Fluid Effects=>Extend Fluid.
Чтобы изменить пространственное разрешение контейнера, нужно использовать операцию
Fluid Effects=>Edit Fluid Resolution.
Так как сплошная среда имеет свойство перетекать из областей с большей плотностью
в области с меньшей плотностью (этот процесс называется диффузией), в точках контейнера
возникает распределение скоростей (velocity), характеризующих такое перетекание. Можно самому
задавать такое распределение скоростей, создавая эффекты принудительного перемешивания
или взбалтывания.
Ключевой момент для понимания здесь таков: если во всех точках задана одинаковая
плотность, никакого перемешивания, а следовательно, и движения среды не произойдет. Поэтому
ни к чему не приводят попытки начинающих пользователей: залить контейнер равномерной
плотностью, а потом запустить анимацию.
Флюиды 1165
Для создания совсем изысканных эффектов, учитывающих явления горения и
теплопереноса, в каждой точке рассчитываются параметры температуры (temperature) и запаса
горючести (fuel). Более нагретые участки стремятся подняться вверх и отображаются, как правило,
с увеличенной яркостью (incandescence), а горючесть в точке определяет (вместе с плотностью),
как долго еще будет идти реакция тепловыделения в этом месте. По умолчанию расчет этих
параметров выключен, то есть вычисление реакций горения не производится, так как они требуют
дополнительных и ощутимых вычислительных затрат.
Если плотность или любой другой атрибут изменяются динамически, то есть с помощью
солвера (Solver), производящего расчет динамики в каждом кадре, то контейнер называется
динамическим - как и эффекты, производимые с его помощью.
Если метод определен как Static Grid, значения параметра в точках сетки не будут
изменяться по времени. Выбор варианта Gradient позволяет быстро залить весь контейнер
предустановленными значениями параметра, которые также не будут изменяться при анимации.
Примечание. Динамически может изменяться только один атрибут, в то время как остальные
изменения будут заданы вручную либо с помощью статичных сеток, или с помощью градиентов.
Так, например, задав плотность как динамическую сеткоу, можно заморозить или даже просто
нарисовать распределение скоростей в пространстве, определив, таким образом, статичное поле,
которое будет «гонять» плотность по контейнеру.
Заполнение контейнера
Создайте трехмерный контейнер: Fluid Effects=>Create 3D Container. По умолчанию любой
контейнер пуст.
Флюиды 1167
Имейте в виду, что использование градиентной заливки автоматически превращает
метод заполнения сетки контейнера (Content Method) в Gradient, а рисование, напротив, может
производиться только по статической или динамической сетке. В этом смысле градиенты стоят
несколько особняком от других методов работы с содержимым контейнера.
Проще всего, конечно, воспользоваться уже кем-то заготовленным содержимым контейнера.
Если ваш трехмерный контейнер выбран, выполните Effects=>Add/Edit Content=>lnitial States.
В появившемся окне Visor выберите раздел Clouds and Fog=>3D, а затем перетащите и бросьте
иконку cloud3DApply.mel прямо на контейнер в окне камеры.
Это заполнит контейнер уже сохраненными данными.
Не забудьте переключиться в Shaded Mode, нажав 5.
Можно представлять себе начальное состояние как кэш, состоящий из одного кадра,
который можно загружать в разные контейнеры.
Для работы с ними достаточно открыть новую сцену, а затем выполнить Fluid Effects=>Get
Fluid Example. В появившемся окне Visor достаточно выбрать интересующим пример и втащить его
в окно камеры средней кнопкой мыши.
Флюиды 1169
Кроме того, на сайте компании Alias можно скачать дополнительные Fluids Web Packs,
комплекты готовых примеров для дальнейшего изучения.
Флюиды 1171
Так как по умолчанию включена галка Auto Set Initial State, можно начинать проигрывать
и останавливать анимацию, не выходя из инструмента рисования. Однако если вы покрасите что-
нибудь не в первом кадре, это состояние будет немедленно сохранено как начальное.
Перед тем, как ответить на вопрос, а почему все плывет вверх, а не вниз, опишу трюк с
изображением, которое можно загрузить в качестве карты плотности, цвета и других атрибутов.
Пытливые умы, уже изучившие общие принципы инструмента Artisan и работы с кистями, наверняка
помнят об общей возможности инструментов рисования: импортировать изображения как карты
для текущей операции рисования.
Совет. Для сглаживания переходов между слоями можно выбрать операцию Smooth
и залить ею весь контейнер.
Флюиды 1173
Динамическая анимация флюидов
Рассмотрим основные принципы динамики флюидов на примере двухмерного контейнера
- для того, чтобы анимация проигрывалась быстрее, а эксперименты были более интерактивными.
Все атрибуты, а следовательно, и свойства контейнеров, отвечающие за динамическую симуляцию,
совершенно одинаковы для плоских и объемных контейнеров. И все изложенное для первых будет
так же справедливо и для вторых.
Атрибут Damp соответствует примерно тому же свойству, что и Conserve для частиц.
Его суть заключается в общей «заторморженности» среды и достигается путем небольшого
принудительного понижения скорости в каждом кадре. Такое искусственное торможение, как и в
случае с частицами, иногда можно применять для стабилизации системы с высокими внутренними
скоростями.
Хотя понятие «точность» здесь, конечно, приобрело весьма расплывчатый смысл. Ведь
требуется максимально точное соответствие творческому замыслу, а не законам физики.
Поэтому я могу только сформулировать следующий вывод: результат просчета ста кадров
с Simulation Rate Scale=1 не совпадает с результатом, полученным за двести кадров с Simulation
Rate Scale=0.5. У них разная математическая точность просчета.
А вот за внутренний шаг вычислений динамики флюидов отвечает атрибут Solver Quality,
появившийся не так давно. Он отвечает именно за точность решения, и его увеличение приводит
к замедлению просчета, но темп анимации остается прежним.
Флюиды 1175
Прежде всего, это атрибут Density Scale, позволяющий глобально умножать плотность
всего контейнера на некоторую величину. Распределение плотности в контейнере задается, как
правило, в диапазоне значений от нуля до единицы, а атрибут Density Scale позволяет умножить
или растянуть все значения плотности до нужных пределов.
Для того, чтобы получить движение капли воды в воздухе, надо задать очень большую
«антиплавучесть», равную отношению плотности воды к плотности воздуха. При этом возникнут
очень большие внутренние скорости и станет понятно, что данная математическая модель не
совсем подходит для симулирования движения невязких тяжелых жидкостей в разреженной
среде.
Следует понимать, что на скорость всплывания (или падения на «дно») влияют оба
атрибута: Density Scale и Buoyancy. Однако второй определяет только динамическое свойство
среды, связанное с движением, а первый влияет как на движение, так и на внешний вид флюида,
связанный с плотностью и прозрачностью.
Флюиды 1177
Также несложно организовать столкновение среды с геометрическими объектами,
помещенными внутрь контейнера с помощью аналогичной частицам операции Fluid Effects=>Make
Collide. Однако для движущихся внутри контейнера объектов лучше использовать специальное
поле, так как MAYA плохо отслеживает движущуюся геометрию, взаимодейтвующую с флюидом.
Операция Fluid Effects=>Make Motion Field позволяет прикрепить к любому объекту поле, которое
будет действовать как «возмутитель» содержимого контейнера. Сила этого поля будет зависеть от
скорости его перемещения, причем вычисления будут производиться более быстро и точно, чем в
случае столкновения среды с произвольными объектами.
Для того, чтобы еще немного ускорить просчет, можно в разделе Display отключить
отображение как самого флюида (Shaded Display=Off), так и границ контейнера (Boundary
Draw=Bottom).
Работе с кэшами посвящено целых пять пунктов меню, так как без эффективного
использования кэширования трудно справиться с гигантскими вычислительными запросами
динамики сплошных сред. Кэш-файлы бывают трех типов, их можно резать, склеивать, удалять,
сегментировать, в общем, практически заниматься их монтажом. Я вкратце рассмотрю самый
общий случай создания одного кэш-файла для всей последовательности кадров для выбранного
контейнера.
Прежде всего, перед тем, как создавать кэш, сохраните сцену. Имя сцены будет
использовано при создании кэш-файлов, поэтому во избежание путаницы старайтесь давать сцене
имя заранее. Переименование сцены позже может затруднить нахождение нужных кэш-файлов.
Для создания кэша достаточно выбрать контейнер и открыть Option Box операции Create Cache.
Задав диапазон кадров для кэширования в разделе Cache Time Range, следует выбрать,
значения каких динамических атрибутов будут кэшироваться. Естественно, следует выбирать
только те атрибуты, для которых Content Method установлен в Dynamic Grid. Нет смысла кэшировать
атрибуты, которые не вычисляются динамикой.
После нажатия кнопки Create MAYA сделает один просчет указанного количества кадров, и
при повторном проигрывании анимации значения плотности и других выбранных при кэшировании
атрибутов будут читаться уже из файла.
Флюиды 1179
Кстати, можно вручную указать, что некоторые атрибуты не будут использовать данные из
кэша, несмотря на то, что кэш уже посчитан. Для этого надо снять соответствующие галки в At
tribute Editor, в разделе Grids Cache для контейнера.
В этой закладке есть поле Cache File Name, где можно указать имя ранее сохраненного
кэш-файла для загрузки его содержимого в выбранный контейнер. Когда вы создаете кэш, он
по умолчанию сохраняется в папке data текущего проекта под именем scenename_fluidShapeN.
mcfp. В дальнейшем вы можете его переименовывать, копировать в другое место и повторно
использовать. Часто имеет смысл иметь несколько просчитанных кэш-файлов для дальнейших
экспериментов с визуализацией флюидов.
Вы должны хорошо понимать, что в кэш записываются только динамические атрибуты типа
плотности или скорости, определяющие значения в ячейках контейнера. Значения «глобального»
атрибута Density Scale в кэш не записывается, их можно изменять и анимировать произвольно,
изменяя общую плотность для уже закэшированного контейнера. Это изменение плотности уже
не будет оказывать влияние на движение среды, так как произведено кэширование скоростей,
однако на внешний вид оно будет иметь самое непосредственное влияние.
Пока контейнер пуст, можно отредактировать его разрешение и размер прямо в Attribute Editor.
Задайте ResolutionY=20 и SizeY=20.
Выберите источник и поднимите его в верхнюю часть контейнера (translateY=8).
Чтобы дымок не поднимался вверх, а наоборот, с бешеной скоростью падал вниз (мы
ведь симулируем движение жидкости), откройте раздел Contents Detail и в подразделе Density
установите сильную «антиплавучесть» (Bouyance=-30) и изрядную плотность (Density Scale=5).
Флюиды 1181
Для экономии времени применим следующий трюк - приблизительный характер движения
можно отладить на грубом разрешении контейнера, а окончательный просчет и кэширование
произвести после увеличения разрешения.
В первый момент из источника вылетает некое облако и падает в виде утолщения вниз.
Отчасти это связано с тем, что для такого тяжелого вещества не хватает точности просчета (то
есть временной шаг вычисления динамики слишком велик). Также это связано с тем, что наша
жидкость врывается в неподвижную среду и пытается об нее затормозиться. Применим небольшой
трюк и проиграем немного анимации, пока жидкость не достигнет дна. В этот момент в контейнере
уже будет распределение скоростей, соответствующее падающей жидкости. Затем сохраним это
состояние как начальное и удалим из контейнера всю плотность. Таким образом, жидкость будет
попадать в контейнер, уже содержащий поле скоростей, соответствующих падению жидкости.
Конечно, реальная жидкость не склонна сильно тормозиться о воздух, но, как я уже упоминал
выше, чтобы симулировать падение реальной тяжелой жидкости, надо применять очень большие
значения для плотности, которые потребуют очень высокой точности просчета и гигантского
времени вычислений. Поэтому будем выкручиваться с помощью трюков.
Так как по умолчанию галка Auto Set Initial State включена, это состояние будет сохранено
как начальное.
Выйдите из Paint Fluid Tool и проиграйте анимацию: теперь струя не имеет вызывающего
утолщения в начале.
Откройте раздел Surface и включите опцию Surface Render. Туманная струя превратится в
полупрозрачную поверхность.
Флюиды 1183
Сразу откройте следующий раздел Shading и полностью уберите прозрачность (Transpar
ency). Это ускорит анимацию и улучшит отображение поверхности.
Создайте кэш.
Зайдите в Option Box операции Fluid Effects=>Create Cache.
Выберите для Cache Time Range опцию Start/End и задайте диапазон анимации 1-100.
Отметьте только атрибуты Density и Velocity для записи в кэш.
Нажмите Create и отправляйтесь пообедать. Когда вы вернетесь, кэш, возможно, уже
будет посчитан.
Флюиды 1185
Откройте раздел Shading Quality и выберите Render lnterpolator=Smooth. Это сгладит
поверхность, но не уберет «мохнатые» края.
Сохраните файл (liquidFinal.ma). MAYA начнет задумчиво жевать диск. Дело в том, что
в момент сохранения сцены все созданные кэш-файлы переписываются из временной папки в
директорию Data текущего проекта под соответствующими именами.
Флюиды 1187
К сожалению, на поверхность флюида нельзя назначить обычный материал (по крайней
мере, в текущей версии мне этого не удалось). Поэтому все оптические свойства поверхности
приходится симулировать с помощью атрибутов из разделов Surface и Environment. Мне также не
удалость заставить поверхность преломлять свет, чтобы получить эффект прозрачной жидкости.
Флюиды видны в отражениях и преломлениях, но сами ничего отражать и преломлять не могут.
Конвертирование в полигоны
Некоторые особо внимательные исследователи MAYA обнаружили операцию
Modify=>Convert=>Fluid to Polygons. Действительно, если содержимое контейнера может
отображаться в виде поверхности, то почему бы не сконвертировать эту поверхность в полигональную
сетку. Выбрав контейнер и выполнив указанную операцию, вы получите обычный полигональный
объект (даже с историей), к которому можно применять все стандартные методы полигонального
моделирования (хм..., а ну, попробуйте сделать из него сабдив). Дополнительно его можно будет
рендерить всевозможными способами как обычный объект. Я оставляю за рамками обсуждения
качество и профпригодность такого объекта, полагаясь на ваши оптимистичные эксперименты.
Помните только, что для улучшения качества поверхности необходимо увеличивать разрешение,
со всеми вытекающими отсюда последствиями.
Создайте объемный контейнер следующего разрешения (80, 5, 50) и размера (16, 1, 10).
Коль скоро мы не собираемся использовать динамику, сразу зайдите в раздел Contents
Details и установите Velocity=Off, Density=Gradient, Density Gradient=Y Gradient.
Это выключит всю динамику и зальет контейнер плотностью равномерно убывающей снизу
вверх. Таким образом, в нашей моделиоблака снизу будут выглядеть насыщеннее, чем сверху.
Флюиды 1189
К счастью, можно пропустить кошмарное количество атрибутов, связанных с динамикой, и
сразу перейти в раздел Shading.
Однако если задать Color lnput=Density, каждый цвет будет зависеть от значения плотности
в точках контейнера. Левый край градиента соответствует нулевому значению атрибута Density,
правый - единичному значению.
Пытливые умы наверняка разгрядели, что градиент самосвечения или раскаленности (In
candescence) по умолчанию зависит от температуры. Это позволяет делать участки с более высокой
температурой более яркими (желтый цвет справа соответствует большим значениям температуры,
черный слева - меньшим). Таким образом, флюид может окрашиваться по разному в зависимости
от физических свойств, а не только от положения в пространстве. У нас температура не задана, и
мы не будем использовать этот градиент.
В разделе Opacity градиент представлен в виде графика, так как прозрачность в данном
случае представляет из себя числовую величину. Так как Opacity lnput=Density, этот график
трактуется просто: чем больше плотность в точке, тем более непрозрачный объем в этой области. Вы
можете отредактировать график как угодно, и даже задать обратное распределение прозрачности:
где плотнее, там прозрачнее. Однако обычно этот график редактируют для создания более
плотных объемов с четкими границами, когда начало графика сдвигают влево, чтобы исключить
из отображения (сделать прозрачными) области с низкой плотностью. К этому мы еще вернемся.
Чтобы распределение цвета от серого к белому не было столь равномерным и искусственным,
можно назначить на любой из слоев Selected Color обычную текстуру типа Volume Noise или Cloud,
однако мы будем использовать встроенные к любой контейнер фрактальные текстуры, атрибуты
которых располагаются в разделе Texturing.
Особенность применения этих текстур заключается в том, что они назначаются не на сам
контейнер, а на цвета, определенные в разделах Color/lncandescence/Opacity. А еще точнее, на
атрибут Color Input (соответственно Incandescence/Opacity Input). Если это звучит угрожающе,
воспринимайте эти текстуры как добавление шума в градиенты, определенные в разделе Shad
ing.
Флюиды 1191
Принципиальным момент здесь в том, что в разделе Color задан бело-серый градиент,
состоящий минимум из двух слоев. Текстура вносит шум не в сами цвета, а в их смешивание,
поэтому если бы в градиенте был только один белый цвет, никакого эффекта текстура бы не
производила.
При этом неплотные области исчезнут совсем, так как непрозрачное отображение
начинается с регионов, где плотность не меньше, чем, условно говоря, 0.2.
Границы облаков (то есть места возрастания плотности) станут более четкими и резкими.
Прицельтесь камерой со стороны короткого края контейнера и отрендерите изображение
(используйте mental ray для экономии времени).
Для того, чтобы убрать артефакты в виде черных точек на краях, установите Quality=2 в
разделе Shading Quality.
Если мы хотим получить эффект пролета через облака, для этого не надо неистово
анимировать камеру. Вместо этого, заставим облака лететь на неподвижную камеру и используем
скрытое свойство цикличности процедурных текстур.
Флюиды 1193
Облака (а точнее, текстура) при этом сдвигаются параллельно оси X. Однако если вы
будете задавать для этого атрибута целочисленные значения (типа 1, 2, 3...), то увидите, что
картина не меняется (это справедливо только для целых значений атрибута Frequency Ratio). To
есть форма облаков периодически повторяется. Поэтому вместо того, чтобы рендерить огромную
последовательность пролета через облака, достаточно просчитать небольшое количество кадров,
задав в первом и последнем необходимые целочисленные (и разные) значения для атрибута
Texture Origin X. В этом случае первый и последний кадр будут визуально совпадать, а между
ними будут летящие на камеру облака. Анимацию после этого можно зациклить и размножить
средствами монтажа.
И не забудьте про Glow в разделе Shading, это позволит вам дополнительно подсветить картинку.
Если можете обходиться без динамики флюидов - используйте этот шанс. Старайтесь
во всех случаях, когда это возможно, вместо динамики применять статические контейнеры с
анимированными текстурами.
В некоторых случаях, таких, как взрывы, без динамики обойтись трудно. Тут бывает очень
полезно использовать обычные майские динамические поля для задания нужного характера
движения.
Для настройки текстур иногда удобнее задавать средний размер деталей при помощи Tex
ture Scale, а не выкручивая Frequency. Масштабирование текстуры в этом случае происходит более
предсказуемо.
Флюиды 1195
и полей.
Внутреннее время текстуры Texture Time - это рабочая лошадка в анимации дымов и
облаков. Всяческое клубление, морфинг, неуловимое ощущение движения задаются анимацией
этого атрибута.
Пролеты, проплывы, проезды сквозь флюид с любой заданной скоростью легко делаются
анимацией Texture Origin. Целочисленные значения этого атрибута будут давать повторяющуюся
картину, что очень полезно для зацикливания анимации.
Оптимизация визуализации
Некоторые слабохарактерные умы, наверное, отметили, что рендеринг флюидов - это
занятие для очень взрослых мальчиков и больших компьютеров. Для таких морально неустойчивых
пользователей приведу некоторые способы оптимизации рендеринга.
Пользуйтесь mental ray. Начиная с шестой версии, он умеет рендерить флюиды, причем в 6-10
раз быстрее, чем стандартный рендер. (Правда, пока до тех пор, пока вы не включите просчет
теней.)
То, что качество рендеринга (атрибут Shading Quality) надо стараться не задирать слишком
высоко - это слегка банальный совет, но тем не менее держите себя в руках.
Это же касается «рэйтрэйсинга». Прежде чем включить галку Raytracing, подумайте, можно ли
обойтись без него.
Если можете обойтись без теней (Self Shadow=Off) - обходитесь. Они пожирают время
рендеринга со страшной силой. Если не можете, попробуйте сначала обходиться встроенным
тенями (Self Shadow=On). Если все-таки вы хотите бросать тени от объектов на флюиды, используйте
Depth Map тени для источников света. Raytracing-тени убьют ваш рендеринг.
Если вам необходимо отбрасывать тени или отражения от флюидов на окружающие объекты,
попробуйте просто создать обычный геометрический объект, напоминающий по форме флюид
и отбрасывающий тени и отражения вместо него. Можете, если надо, деформировать его при
помощи BlendShape. Как правило, это все равно будет быстрее, чем честные тени и отражения.
Чем сильнее перепады в плотности, тем больше нужно задирать качество, поэтому, если возможно,
распределяйте плотность равномерно. Избегайте жестких краев и границ внутри контейнера.
Флюиды 1197
И в том и в другом случае на экране создаются совершенно одинаковые контейнеры, для
которых справедливо все описанное выше. С одним маленьким исключением.
Текстурные контейнеры не рендерятся. То есть не отображаются при просчете. Вместо этого, их
можно назначить как текстуру на любой доступный для этого канал. В этом состоит единственное
различие двух типов контейнеров.
Если еще немного расширить сознание, можно заметить, что обычный ЗD-контейнер можно
использовать как объемный материал (Volumetric Material), наравне с материалом Particle Cloud, и
назначать его на частицы типа Cloud.
Флюиды 1199
Примечание. Утилита Height Field применяется для визуального отображения
черно-белых текстур в виде «вспученной» (displacement) поверхности,
деформированной с помощью текстуры. Эта утилита, подобно другим утилитам
для рендеринга, может быть создана независимо и представляет собой обычную
Nurbs-поверхность, которая, однако, не рендерится, а только отображается на
экране. Атрибут Displacement этой утилиты обычно присоединяется к альфа-
каналу нужной текстуры.
Помните, что можно использовать некоторые атрибуты для задания свойств сплошной
среды. Так, например, атрибут Damp позволит придать волнам на поверхности свойство затухать,
a Gravity служит своеобразным аналогом жесткости сетки из пружин.
Естественно, что в разделе Environment задана карта отражений в виде градиента по высоте.
Вы можете использовать свои карты отражений и настроить размер и цвет блика. Цвет
поверхности определен, по умолчанию, как синий и как зависящий от температуры, на случай,
если вы решите скипятить всю воду в пруду. Так как температура, по умолчанию, не вычисляется,
вы может определить изменение цвета в зависимости от любого параметра.
Флюиды 1201
Opacity выступает теперь как высота возмущений на поверхности. А общая прозрачность
определяется атрибутом Transparency.
Рыбалка на озере
Посмотрим теперь, как можно эффективно анимировать поверхность водоема.
Если вам не хватает эстетического антуража, создайте NURBS-плоскость и помните ее с помощью
Artisan, чтобы сделать некое подобие углубления, соответствующее абстрактному водоему. Грубо
говоря, выкопайте котлован.
Дабы он не гнал такую сильную волну, просто понизьте для него интенсивность испускания
(Density/Voxel/Sec=2) и уменьшите его размер (scale=0.5).
А чтобы создать эффект от забрасывания поплавка, просто отключите интенсивность после
десятого кадра, поставив два ключа в десятом и одиннадцатом кадре, чтобы источник перестал
возмущать поверхность.
Чтобы волны разбежались и затухли, можно увеличить атрибут Damp самого контейнера,
но проще сильно задрать атрибут Fluid Dropoff для источника.
Установите Fluid Dropoff=10.
Wake применяют не только для бросания всяких глупостей в воду, но и для создания
следов на поверхности воды от движущихся объектов. Для этого положение источника надо просто
анимировать или прикрепить источник к движущемуся объекту. Не забывайте про Fluid Dropoff, a
в случае создания изысканных эффектов попробуйте испускать немного температуры, которая, по
умолчанию, управляет цветом поверхности и позволяет имитировать появление пены.
Кстати, если вы вооружены передовым знанием о природе объекта типа Pond, можете возмущать
поверхность воды не только с помощью «официального» Wake, но и просто изменяя содержимое
контейнера стандартными методами, например, рисуя в нужных местах фронт волны или
импортируя изображение как возмущение поверхности.
Флюиды 1203
Совет. Если будете рисовать плотностью по поверхности, включите в настройках
Paint Fluid Tool опцию Display=As Render. Получается очень зрелищно: рисовать
прямо во время анимации.
Буйки и поплавки
Разобравшись, как возмущать поверхность, рассмотрим обратный вопрос: как сама
поверхность может воздействовать на геометрические объекты. Дело в том, что на поверхности
воды имеет обыкновение плавать всякое безобразие, без которого вода уже не будет столь
правдоподобно выглядеть. Да и без поплавка на рыбалке обойтись трудно.
Для того, чтобы заставить объект плавать по поверхности, надо сначала создать что-то
типа «буйка», плавающего на воде, а затем любым подходящим способом прикрепить к этому
буйку реальный геометрический объект. Буйки бывают разных типов, в зависимости от сложности
поведения их на воде. Эти типы перечислены в меню Fluid Effects=>Pond и создаются для выбранного
контейнера.
Самый простой буек - это локатор (Surface Locator), который просто передвигается только
по вертикали, повторяя движение водной глади.
Для удобства создания плавающих объектов, можно сразу выбрать геометрический объект
и выполнить одну из операций: Float Selected Object, Make Boats, Make Motor Boats. Это создаст
буек-локатор соответствующего типа и привяжет выбранный объект к этому локатору.
Для создания поплавка, который не только притапливается, но и имеет свойство
наклоняться, лучше всего подходит Boat Locator.
Рыбалка на море
Перейдем теперь к более широким водным просторам. Понятно, что для отображения
и анимации больших водных пространств нужны некоторые трюки. В случае с океаном (Ocean)
трюк очень прост. Для симуляции огромной водной глади создается простая поверхность (NURBS-
плоскость) и на нее назначается хитрым образом написанный материал. Анимация водной глади
осуществляется за счет displacement, то есть деформации геометрии на этапе рендеринга
с помощью текстуры. Текстура, как и следует ожидать, не простая, а специальным образом
«заточенная» под создание волн и всяческих возмущений водной поверхности.
Флюиды 1205
назначьте на эту поверхность обычный материал типа Lambert с текстурой checker на канале
цвета.
Правда, для того, чтобы увидеть отображение текстуры на поверхности, вам придется
выключить галку Enable Overrides в разделе Drawing Overrides для ноды oceanPlaneShape1. Так как
материал для океана довольно сложный, отображение его на экране будет, во-первых, небыстрым,
а во-вторых, неадекватным, то есть неточным. Поэтому по умолчанию для поверхности океана
выключено отображение текстур.
Зачем нужна такая «каракатица»? Дело в том, что при взгляде на водную поверхность важна
проработка деталей только областей близких к камере, регионы же удаленные от наблюдателя
могут быть представлены весьма условно. Поэтому поверхность для симуляции океана имеет
более плотное расположение изопарм ближе к центру. Области ближе к краям поверхности
будут вероятнее всего отображать происходящее на горизонте и, следовательно, могут быть
представлены более грубо.
Поэтому при работе с океаном старайтесь сделать так, чтобы камера, как правило, смотрела
в район центра поверхности. Более того, специально для такого принудительного взгляда в центр
при создании океана предусмотрена галка Attach to Camera в Option Box операции Create Ocean.
Если она включена, то автоматически создается очень простой expression, перемещающий
поверхность океана по горизонтали так, чтобы она всегда была расположена своим центром
перед камерой. Дополнительно этот expression растягивает/сжимает поверхность в зависимости
от высоты камеры по вертикали, это помогает задавать оптимальный размер поверхности по
отношению в визуальному разрешению.
Цитирую:
oceanPlane1.translateX = persp.translateX;
oceanPlane1.translateZ = persp.translateZ;
float $scale = abs(150.0 * persp.translateY) + 10.0;
oceanPlane1.scaleX = $scale;
oceanPlane1.scaleY = $scale;
oceanPlane1.scaleZ = $scale;
Естественно, вы может отредактировать такой expression или создать свой (или даже не
использовать его вовсе), но просто помните о том, что надо целиться в центр океана.
Кстати, включив галку Create Preview Plane в Option Box операции Create Ocean, можно
автоматически создавать Preview Plane для вновь созданного океана.
Флюиды 1207
Динамическая анимация морской поверхности
Буйки, локаторы и прочий водоплавающий мусор создается и анимируется для океана точно
так же, как для объектов типа Pond. Поэтому пункты меню для работы с этими плавсредствами для
Ocean и Pond идентичны.
Звучит, конечно, несколько угрожающе, однако вы должны понимать, что Wake - это
динамический объект, и для просчета струи или буруна требуется вычисление динамики, так
как используется испускание плотности из источника. За пределами контейнера, естественно,
никаких бурунов не будет, поэтому задавайте размер и положение контейнера относительно
океана заранее.
Те, кто уследил за идеей анимации возмущений поверхности океана с помощью контейнеров,
могут выбрать такой Wake-контейнер и включить у него в разделе Display режим Shaded Display=As
Render, чтобы увидеть, как по текстуре расходятся черно-белые круги из плотности.
Для взрослых. Замечу, что хотя текстура выглядит как плоский контейнер, однако реально
это все-таки 3D-контейнер, у которого включили секретный атрибут is2D. Для флюидов-текстур
это имеет значение, так как трехмерная текстура (fluidTexture3D) будет проектироваться на
поверхность, а не «обтягивать» ее, как в случае 2D-текстуры.
Визуализация акватории
Для предварительной настройки визуализации морской поверхности удобно использовать,
во-первых, Preview Plane, а во-вторых, IPR Render. Этот процесс подкупает своей новизной: надо
просто подобрать параметры материала oceanShader, а затем удовлетворенно поставить анимацию
на просчет. Нет смысла перечислять названия и назначения многочисленных атрибутов материала,
они достаточно адекватны. А метод тыка и пристального взгляда на пробный рендер вполне
оправдывает себя в данном случае. Ограничусь лишь некоторыми комментариями.
Флюиды 1209
Общий масштаб (атрибут Scale) действует наоборот: чем больше значение, тем больше
реальных физических метров приходится на клетку экранной сетки и тем больше изображение
мельчает.
Для того, чтобы неистово летать над океаном, не надо крутить и размахивать камерой.
Задайте или даже анимируйте атрибут Observer Speed (скорость наблюдателя), чтобы создать
иллюзию движения над водой. Помните, что не стоит реально улетать камерой от центра
поверхности, симулирующей океан.
Wave Peaking характеризует остроту угла между волнами при их столкновении. Можно
назвать его «плескучесть». Имеет смысл, только если Wave Turbulence не равен нулю.
Foam Threshold определяет высоту волну, на которой начинает образовываться пена. Светлые
участки текстуры, симулирующие пену, можно использовать для всяких дополнительных трюков с
испусканием частиц с поверхности океана.
Во многих случаях будет гораздо быстрее адаптировать готовые примеры под ваши нужды
(если это, конечно, не новое слово в кислотных спецэффектах), чем с нуля разрабатывать сцену
целиком.
Обратите также внимание на то, что для создания тумана и облачности в примерах активно
используются объемные контейнеры.
Флюиды 1211
причем одновременно и все сразу. В роли объектов для столкновений с живой массой иногда
проплывали гитары или рюкзаки, но это не вызывало нарушений в общем движении внутри
контейнера. Они попирали все законы физики и являли собой образец броуновского движения
отнюдь не на молекулярном уровне.
Самое удивительное, что когда мы, наконец, прибыли в Будапешт, все молекулы
сплошной среды были, как новые. Они не помнили ничего такого особенного и были готовы к
новым приключениям. Все сидели на своих, непонятно откуда взявшихся местах и с любопытством
разглядывали подавленные, нет, растерянные лица наших венгерских друзей, которые и не
подозревали, что вино, производимое на их родных землях, оказывается, может вызывать такие
явления.
Подозреваю, что среди скрытых атрибутов объектов типа ftuidShape следует поискать
атрибуты, отвечающие за содержание алкоголя в контейнере и напрямую управляющие скоростью
и турбулентностью среды.
Работа с мехом в MAYA больше похожа на работу с текстурой, основной задачей является
придание поверхности специфического вида, а вопрос анимации если не второстепенный, то,
как минимум, не основной. Представляйте себе мех как сложный материал, назначенный на
поверхность и ответственный за то, как объект будет выглядеть.
К сожалению, в отличие от MAYA Hair, модуль MAYA Fur не был написан с нуля специально
для MAYA, а был приобретен компанией как технология и встроен в MAYA как плагин. Поэтому
способ работы с ним немного (действительно немного) отличается от общей идеологии работы в
MAYA. На внешнем уровне это заметно по структуре меню и отсутствию Option Box, а на внутреннем
определяется как чисто субъективное ощущение.
Для успешной работы с мехом должен быть загружен плагин Fur.mll. Если вы не видите
меню Fur рядом с Paint Effects в режиме Rendering, идите в Windows=>Setting/Preferences=>Plugin
Manager и включите там нужные галки.
Анимация 1215
Устройство MAYA Fur
Как правило, работа с мехом разбивается на несколько этапов. Это прежде всего
подготовка поверхности к созданию на ней меха. Затем идет назначение нового мехового покрова
на подготовленную поверхность и настройка его многочисленных атрибутов. Если деформации
поверхности недостаточно для анимации меха, задается анимация описывающих его атрибутов.
Далее настраиваются параметры визуализации и происходит непосредственный рендеринг.
Забегая вперед, скажу, что для визуализации меха используется специальный рендерер (fur-
Render), который позволяет просчитывать очень насыщенные и плотные меховые покровы.
А то, что вы видите на экране - лишь схематическое представление процедурного описания
меховой растительности, по аналогии с приблизительным отображением процедурных текстур
в окне камеры. Внутри сцены хранится лишь описание меха (Fur Description, то есть значения
соответствующих атрибутов), но никак не набор многочисленных ворсинок. Сам «настоящий» мех
генерируется только на этапе рендеринга.
Это делает его практически полностью похожим на процедурную текстуру, и далее я буду
придерживаться этой аналогии.
Мех назначается на весь объект целиком: к сожалению, нельзя выбрать отдельные грани и
назначить мех только на них. Ненужные участки просто выстригаются позже с помощью инструмента
Paint Fur Attributes Tool, о котором речь пойдет ниже. Альтернативный способ заключается в
удалении UV-координат с тех граней, где меха быть не должно.
Так же, как текстуру, мех (а точнее говоря - его описание FurDescription) можно «отдирать»
от поверхностей, переназначать на новые поверхности, удалять или просто дублировать. Все это
Основные атрибуты, определяющие свойства меха, принадлежат всего двум нодам. Это,
как и в случае с Pain Effects или Fluid Effects, сильно упрощает задачу изучения новой технологии,
так как для эффективных экспериментов с мехом нужно начать работать с ограниченным набором
атрибутов и в Attribute Editor, методом тыка, установить их предназначение.
Первая нода (FurFeedback) совсем небольшая, и отвечает только за то, как мех схематически
представлен на экране. Галка Color Feedback Enabled теперь по умолчанию включена, а параметр
Fur Accuracy также по умолчанию равен единице. Это означает, что на экране будет адекватно
отображаться цвет меха, а гибкость «экранных» ворсинок будет примерно соответствовать
реальным ворсинкам на рендере. Атрибуты U/V Samples определяют только количество или
плотность экранного представления меха, и никак не влияют на плотность реального меха при
рендеринге. Это чисто экранное свойство, предназначенное для визуального контроля формы и
цвета меха, но никак не плотности.
А все свойства «реального» меха определяются в закладке для ноды FurDescription.
Она является носителем практически всех свойств меха и вся работа по настройке меховых
особенностей производится в Attribute Editor для этой ноды.
Совет. Некоторые экстремалы, конечно, столь беззаветно любят Channel Box, что
редактируют атрибуты меха там. Однако в случае таких «богатых» атрибутами
объектов, как мех, кисти Paint Effect, флюидные контейнеры или частицы, удобно
работать именно с Attribute Editor, причем открывая его справа, в виде панели, а
не в отдельном окне.
Стоит только выполнить команду Edit Polygons=>Texture=>Unitize UVs (то есть загнать UV в
единичный диапазон), и мех мгновенно становится на место.
К счастью, мех научился корректно работать с UV-сетами (правда, только для полигонов,
но не для сабдивов). Поэтому можно отдельно создать отдельный UV-set специально для меха, а
затем присоединить к нему существующий мех.
При работе с полигонами иногда полезно бывает приготовить специальные «плашки» для
покрытия мехом. Эти «плашки» изготавливаются как скопированные с оригинальной поверхности
нужные грани. Сделать это можно операцией Edit Polygons=>Duplicate Faces. Благодаря Construc
tion History эти плашки будут повторять форму оригинальной поверхности, а сделать для них
необходимый для меха UV-маппинг довольно просто, например, с помощью Planar Mapping.
Откройте файл headModel.ma (или любой другой, содержащий вашу любимую модель
джульбарса или другого кандидата на омеховление).
Первая задача - как следует побрить модель, чтобы мех остался только в тех местах, где
надо. В нашем случае - в верхней части головы.
Чтобы мех не выглядел столь куцым, выберите его прямо на экране и задайте в Attribute
Editor для ноды FurFeedback значения U/V samples, адекватные производительности вашей
графической карты, например, 128.
Атрибут Density (плотность) нам пригодится только на этапе рендеринга, а значение Glo
bal Scale также может быть использовано позже для равномерного увеличения или уменьшения
всех свойств меха, так чтобы общая визуальное восприятие меха просто масштабировалось с
сохранением формы и пропорций.
Идея этого инструмента очень проста и напоминает способ работы с обычными текстурами
при помощи инструмента 3D Paint Tool. Сначала выбирается поверхность, затем канал/свойство и
производится раскрашивание поверхности этим свойством.
Выберите поверхность, а затем возьмите в руки инструмент Fur=> Paint Fur Attributes Tool.
Наряду с обычными настройками инструмента, проявится также небольшое окошко Paint
Fur Attributes Tool Settings, в котором можно выбирать атрибуты меха для рисования ими по
поверхности.
Выберите атрибут Baldness, а в окне Tool Settings задайте Value=0, чтобы рисовать нулевым
значением атрибута. Попробуйте немного побрить персонажа, расширяя области плешивости.
Затем установите Value=1 и покрасьте либо только верхнюю часть головы (имитируя
прическу), либо всю голову, за исключением лица (моделируя вожака бандерлогов), создавая мех
в нужных местах.
Активно меняйте радиус кисти. А также возьмите третий слева профиль кисти, полностью
заполненный круг, он лучше подходит для рисования четких границ. Подбривайте мех там, где
надо, с помощью Value=0, периодически сохраняя сцену.
Когда примерная область меховой части головы предводителя бандерлогов будет готова,
займемся подстрижкой или, как говорят лучшие собаководы, тримированием.
Однако после этого весь мех моментально укоротится до длины, равной единице! Ведь
рисовать мы можем только значениями атрибутов от нуля до единицы. Как быть?
Ответ скрывается в Attribute Editor и в том, как MAYA сохраняет значения отрисованных
атрибутов.
Чтобы понять, каким, спуститесь ниже, в Attribute Editor, и откройте раздел Details.
Там разыщите раздел Baldness и в нем откройте подраздел Maps.
Чтобы избавиться от этой карты и снова перейти к общему управлению атрибутом через
один слайдер, следует просто нажать кнопку Remove Item.
Разрешение карты задавалось при выборе атрибута для рисования в окошке Paint Fur Attributes
Tool Settings и по умолчанию равно 256x256. Соответственно, карта создается только после
использования инструмента Paint Fur Attributes Tool.
Сразу над разделом Maps есть некоторое количество атрибутов, изменяющих стандартное
применение карты атрибутов. Это прежде всего Map Multiplier, позволяющий умножить значения
черно-белой карты в диапазоне от нуля до единицы на любое число, чтобы можно было адекватно
рисовать атрибутами (например, длиной), имеющими диапазон изменения превосходящий
единичный отрезок.
Задайте небольшое значение Value и подстригите, например, щёки, виски или другие
области - по вашему усмотрению. Активно меняйте Value для различных участков. «Снять» немного
длины поможет операция Scale со значением около 0.9. Добавлять - операция Add и значение 0.1.
Не беда, что стрижка получается ступенчатой, как у студента парикмахерского университета.
В конце работы крайне рекомендуется выбрать операцию Smooth и залить (Flood) всю
поверхность этой операцией, причем неоднократно. Это сгладит все ступеньки и разгладит
распределение длины меха вдоль всей поверхности.
Вы должны понимать, что после такой стрижки на диске сохранилась карта распределения
длины, которую можно найти в папке furAttrMap. Поглядев на имена файлов в этой папке, вы
поймете, почему лучше сохранять сцену заранее с понятным именем.
Вы должны также понимать, что размытые края у карты Baldness ведут к «прорежению» меха
на границах, а это, в свою очередь, дает не очень красивый эффект просвечивания. Поэтому всегда
довольно затруднительно получить четкую границу меха, для этого приходится использовать карты
довольно больших разрешений (2048x2048), содержащие всего два цвета. В отличие от текстур,
все методы сглаживания или фильтрации карт ведут, как только что было сказано, к уменьшению
плотности меха на границах и эффекту просвечивания. Благо четкая граница мехового покрова
нечасто встречается в природе, да еще и на крупных планах. Но при работе с картами атрибутов
для меха вы должны понимать, как конкретная черно-белая карта управляет соответствующим
атрибутом. В данном примере я использовал для Baldness карту (2048x2048), которая сохранена в
файле headModelFurStart_Original_Head5hape_FurDescription1_Baldness.iff.
Если вам стало совсем лень красить всю голову или просто ничего не получилось, откройте
файл headModelFurStart.ma. Перед этим вам также необходимо скопировать папку furAttrMap с
диска в папку, содержащую ваш текущий проект, так как карты распределения плотности и длины
лежат именно там.
А сейчас те, кому уже невтерпеж, могут нажать кнопку Render. И получить довольно
плешивую модель в стиле «восставших из ада».
Это даст более плотную картину, но, тем не менее, и этого недостаточно, чтобы получить
плотный мех.
Задайте Density=50000. Это будет стартовая позиция для настройки и отладки остальных
параметров. На финальном просчете можно будет увеличить плотность еще в несколько раз.
Первое правило состоит в том, что мех никогда не растет так идеально прямо, ворсинка
к ворсинке. Немного настроим атрибуты меха для того, чтобы, не увеличивая плотности, создать
визуально густой покров.
Чтобы его хаотично наклонить по всей площади, установите Inclination=0, а затем зайдите
в раздел Details и в подразделе Inclination задайте Noise Amplitude=0.2.
Это немного растреплет мех, правда, в только одном направлении, так как атрибут Inclina
tion имеет свойство наклонять мех в одну сторону.
Находясь в разделе Details, задайте также неравномерность длины ворсинок: для этого в
разделе Length задайте Noise Amplitude=0.5, a Noise Frequency=40.
По умолчанию ворсинки меха очень тонкие, причем сужающиеся к концам. Но коль скоро в
нашем случае мех похож на волосы (хотя я упорно называю его мехом, чтобы вы помнили, с каким
модулем происходит работа), ничто не мешает сделать его потолще.
Важно понимать, что пресеты содержат лишь значения атрибутов, поэтому, если на вашем
персонаже уже есть карты для некоторых атрибутов (то есть вы успели покрасить, например,
длину меха), то при выборе пресета эти атрибуты не будут заменены на пресетные, а останутся
подсоединенными к текстурам. Также не будут заменяться заблокированные атрибуты.
Если создать новую сцену, а затем простую поверхность типа плоскости и покрыть ее мехом,
то при первом использовании Paint Fur Attributes Tool, пo умолчанию, предлагается «расчесать»
мех с помощью атрибута Direction, указанного в Paint Fur Attributes Tool Settings.
Дело в том, что для задания направления меха вдоль поверхности используется атрибут
Polar, вращающий ворсины вокруг оси, перпендикулярной поверхности. Но если атрибут Inclina
tion равен нулю, то все ворсины не наклонены к поверхности, а растут перпендикулярно ей и
следовательно просто вращаются вокруг своей оси при попытке расчесать мех. Если хоть немного
наклонить мех, то есть увеличить значение Inclination (или изменить значение Base/Tip Curl), то
усилия по расчесыванию несуществующим атрибутом Direction сразу станут визуально видны.
Замечу, что такая работа с Direction определяет только направление, а степень наклона
или приглаженности задается значениями Inclination. Никто не мешает вам красить обоими
значениями.
Расчесывание с помощью Direction сохраняется как карта для атрибута Polar. Однако
важно понимать, что рисование с помощью самого атрибута Polar имеет совсем другой результат.
Дело в том, что в режиме Direction работа с кистью не зависит от выбранной операции (Replace/
Add /Scale/Smooth) и от значения Value в настройках инструмента, а служит только для задания
направления и создания карты для атрибута Polar.
Поэтому прежде чем расчесывать любую модель с помощью параметра Direction, наклоните
или раскучерявьте мех хоть немного, иначе ваши усилия не будут видны на экране (хотя карта-
текстура для атрибута Polar будет создаваться в любом случае).
Наиболее любопытные умы даже могут рассмотреть такие карты для Polar и, при достаточно
степени расширенности сознания, пытаться интерпретировать черно-белое изображение как
значения поворотов ворсин вокруг своей оси.
Однако пытливые стилисты наверняка захотят положить текстуру на всю поверхность меха
или сделать, например, мелирование. Хорошо, займемся мелированием. Для него подойдет любая
текстура, в том числе и та, которую вы сами нарисуете.
Назначьте на атрибут Tip Color трехмерную текстуру Volume Noise.
Задайте для нее Depth Max=1 и Frequency=0.2, чтобы получить некоторое количество
черно-белых пятен.
Итак, после каждого назначения текстуры на любой атрибут меха, а также после
каждого изменения атрибутов этой текстуры, следует нажимать кнопку Bake, чтобы текстура
сконвертировалась в нужные карты для соответствующих атрибутов. Эти карты можно всегда
увидеть в Attribute Editor в разделе Details и посмотреть в папке furAttrMap текущего проекта.
ЕСЛИ ВЫ хотите прокрасить полученным узором мех до самых корней, вам надо назначить
эту же текстуру еще и на атрибут Base Color.
Освещение меха
Пытливые умы уже заметили, что в сцене появился источник света defaultLight, хотя
никаких усилии для этого не предпринималось. Дело в том, что для рендеринга меха необходим
хотя бы один реальный источник света. А крики пользователей, отрендеривших сцену без света,
(«Где же мой мех?»), так надоели службе технической поддержки, что по ее просьбе теперь при
попытке просчитать неосвещенный мех автоматически создается новый источник света типа direc-
tionalLight.
Воспользуемся этим источником для простоты, хотя вас никто не ограничивает в создании
любимого типа освещения.
До сих пор наш мех просвечивался от кончиков до основания, хотя в природе наблюдается
снижение освещенности при погружении в меховые глубины. То есть ворсины находящиеся ближе
к основанию, освещены хуже, чем кончики. Попытка включить тени для источника света ни к чему
не приводит. Однако пытливые умы наверняка нашли в Attribute Editor для источника света раздел
Fur Shading/Shadowing, который, впрочем, безнадежно пуст.
Чтобы заставить мех просчитывать самозатенение, надо указать, какие источники света
при этом будут использоваться. Делается это довольно нетривиально.
Кстати, исключить его обратно из расчета теней можно, выполнив Fur=>Fur Shadowing
Attributes=>Remove from Selected Light.
Атрибуты Back Shade определяют, как сильно затеняются участки поверхности, «смотрящие»
в противоположную от источника света сторону.
Совершенно неоценим атрибут Intensity Multiplier. Если вам хочется немного прибавить
освещения для меха, однако освещенность остальных объектов трогать совсем не хочется, можно
«докрутить» интенсивность источника света только для меха.
Однако при использовании AutoShading мех отбрасывает тени только сам на себя. Для того,
чтобы получить тень от меха на других объектах, вместо AutoShading надо просчитать реальные
тени от каждой ворсинки методом Depth Maps, при этом не забывая включить просчет теней у
самого источника света. А также купить еды и напитков, ибо за время рендеринга вы успеете пару
раз проголодаться.
К сожалению, считать Depth Map-тени от меха умеют только источники типа Spot Light,
поэтому для нашего defaultLight метод Shadow Maps даже не появляется в параметрах Fur Shading
Type.
На свой страх и риск можете превратить defaultLight в источник типа Spot Light, просто
поменяв его атрибут Туре прямо в Attribute Editor.
А также сдвинув его повыше (Translate=0,70,90).
После этого его надо заново добавить в вычисление затенения меха (Fur=>Fur Shadowing
Attributes=>Add to Selected Light), после чего включив для него галку Use Depth Map Shadows,
задайте для него Fur Shading Type= Shadow Maps.
Если вы забыли выключить Use Dmap Auto Focus в разделе Shadows для источника света,
MAYA выдаст сообщение в Script Editor, но посчитает картинку.
Как правило, вам не придется что-то менять в этих настройках, по крайней мере на
первоначальном этапе работы с мехом.
Напомню, что при просчете родным майским рендерером (MAYA Software), мех считается
специальной программой (furRender) как отдельный файл-изображение, содержащий альфа-канал
и канал глубины (Z-буфер), затем обычным образом просчитываются все остальные поверхности.
После этого два полученных изображения складываются по правилам композитинга с каналом
глубины.
Помните о том, что мех - это отдельная картинка, наложенная на основную сцену после
основного просчета. Взрослые мальчики могут осуществлять такое наложение самостоятельно.
Для этого достаточно выключить галку Сотр. Fur (СКОМПОЗИТИТЬ мех с остальной сценой) в
разделе Fur Render Options. После этого просчитанная сцена не будет складываться с мехом после
рендеринга, а отдельно просчитанные меховые изображения всегда можно разыскать в папке
furlmages текущего проекта. Они представляют собой только изображения меха с альфа-каналом.
Там же лежат отдельно просчитанные файлы, содержащие канал глубины.
Взрослые мальчики должны также понимать, что если один и тот же мех назначен сразу
на несколько поверхностей, то в зависимости от площади каждой поверхности, происходит
усреднение или выравнивание плотности. То есть если одна поверхность по площади в четыре
раза меньше другой, и на обе назначен один и тот же мех, плотность меха на первой поверхности
будет в четыре раза меньше. Такое поведение по умолчанию задается значением атрибута Calc.
Area Values=Per Fur Description. Выключить усреднение плотности можно, установив этот атрибут
в Off.
А совсем взрослые мальчики, назначив мех на обычную сферу, должны задаться вопросом:
почему мех не собирается в плотные пучки около полюсов сферы, подобно любой текстуре?
Чтобы предотвратить эффект неравномерного распределения, MAYA дополнительно создает карты
выравнивания (Equalizer Maps) и использует их для компенсации неравномерной параметризации
поверхностей. Как правило, MAYA справляется с такой задачей вполне адекватно, но совсем
неистовые экспериментаторы могут подключить свои карты распределения (Custom Equalizer
Maps). Для вышеотрендеренного вожака банделогов эта карта выглядит так:
Первая кроется в том, что при работе с NURBS-поверхностями для вычисления границы
меха используется отдельное разбиение поверхности на полигоны (Tessellation), отличное от
заданного для самой поверхности в Attribute Editor. При сильном несовпадении этих разбиений
могут возникать такие щели. Для борьбы с ними можно увеличить разбиение самой поверхности
или уменьшить значение атрибута Nurbs Tesselation в разделе Fur Render Options=>Advanced Op-
Еще одно проблемой может стать неадекватная яркость меха по сравнению с остальными
объектами, освещенными теми же источниками света, что и мех. Основным источником такой
яркости обычно являются блики. Возьмите за правило сразу устанавливать Specular Sharpness
минимум в 150, a Specular Color делать лишь немного отличным от черного. Только в случае
мокрого меха, вам могут понадобиться большие значения для цвета блика. Кроме того, атрибут
источников света Intensity Multiplier может помочь «прибрать» освещение только меха и только
для конкретных источников.
Использование motion blur также изрядно замедляет рендеринг. Если есть возможность
симулировать его в композитинге, не упускайте такой возможности.
Главная угроза времени рендеринга - плотность меха. Старайтесь держать ее как можно
ниже, а визуальную насыщенность меха симулировать другими атрибутами: шириной ворсин,
взлохмаченностью, искусственным затенением.
Если отрендерить меховой покров с нужного ракурса, а потом наложить это изображение
как текстуру на поверхность «под мех», это снизит просвечиваемость меха и требования к
плотности.
При попытке просчитать сцену с мехом в mental ray с качеством по умолчанию, картинка
получается, мягко говоря, экзотичная.
В нынешнем состоянии mental ray умеет делать с мехом очень многое: Raytraicing и
все с ним связанное, глубину резкости, шестнадцатибитный цвет при просчете, цветные тени и
прочее.
Однако он не умеет делать Auto Shading. К сожалению, даже без теней mental ray считает
мех весьма неторопливо, а при попытке включить тени время просчета становится вызывающе
долгим. Конечно, самозатенение можно симулировать, просто окрашивая основания ворсин
в более темный цвет, однако этот трюк не будет учитывать расположение источников света. Я
надеюсь, что к моменту выхода книги mental ray научится делать самозатенение и некоторые
другие вещи (например, усреднение плотности по площади поверхностей с мехом).
И только в том случае, если вы хотите воздействовать на мех локально, то есть пошевелить
его в конкретном месте, вам придется прибегнуть к помощи аттракторов.
Что же такое аттрактор? Это цепочка из двух костей, которую можно вставить в мех, после
чего близлежащие ворсины меха будут гнуться, пытаясь повторить форму этой цепочки. Хотя
форма эта, как вы понимаете, весьма незамысловатая простой «уголок» из двух костей.
Однако вы всегда останетесь заложниками того, что косточек всего две, и, следовательно,
будете привязаны к уголковой форме такого аттрактора. Соответственно, зигзаг или, хуже того,
косу с помощью аттрактора заплести не удастся. Пытливые умы, конечно, попытаются вставить
дополнительные косточки в аттрактор и даже не без успеха, но гибкости меху это не прибавит,
ибо на него влияют только две косточки.
Ответ, очевидно, лежит в особенностях реализации. Как я уже упоминал, технология Fur
была когда-то давно куплена у сторонней компании и внедрена, не как родной модуль, а как
плагин - со своими, соответственно, странностями. При покупке технологии забыли купить одну
маленькую деталь - самих разработчиков, поэтому улучшения модуля MAYA Fur уже много лет
носят косметический характер.
Попробуем немного «потрясти» мех. То есть создать иллюзию остаточных движений меха
после перемещения поверхности, на которой он растет.
Выберите ее, растяните и засадите ее мехом: Fur=>Attach Fur Descriptions New. Увеличьте
длину меха: Length=4.
Если выбрана поверхность, то в разделе Create будет доступна опция создания сетки
аттракторов (A grid of attractors on selected surface).
Чтобы создать один аттрактор в нужном месте поверхности, надо выбрать это нужное
место. В случае полигональной сетки, это грань (face). В случае NURBS-поверхности - surface
point.
Для изучения свойств самого аттрактора создадим сначала всего один такой объект в
начале координат.
Выберите в окне Create Attractors опцию One attractor at the origin, а в качестве типа (Type)
укажите Simple chain with linked joint rotations.
Столь длинное название означает, что вращения второй кости в цепочке будут повторять
вращения первой с некоторой задержкой по времени, указанной в поле Delay. Для такой задержки
используется простой expression.
Нажмите Create,
При попытке покрутить вторую кость вас ожидает неудача: для ее вращений был создан
expression, который симулирует запаздывание вращений второй кости относительно вращений
первой.
Можете изучить его на досуге и оценить его профпригодность, а сейчас выключите его
(Modify=>Evaluate Nodes=>Expressions) и согните вторую кость.
Судя по наличию раздела Details и его содержимому, все атрибуты аттракторов могут быть
распределены по поверхности, точно так же, как и свойства самого меха. Значениями атрибутов
аттракторов можно покрасить поверхность с помощью Paint Fur Attributes Tool, можно задать
хаотическое распределение, используя Noise Amplitude, в общем, использовать ту же идеологию,
что и для свойств меха. Другое дело, что аттракторов бывает не так много, как ворсин у меха, и
потому зачастую проще расставить их руками в нужных местах и в нужном количестве.
Несмотря на то, что он всего один, надо удалить не только его, как объект, но и весь набор
(Attractor Set) аттракторов, определяющий их свойства (в данном случае набор состоит из одного
аттрактора).
Теперь воспользуемся сеткой аттракторов, так как нам надо двигать весь мех.
Выберите плоскость, затем выполните Fur=>Create Attractors и в появившемся в окне
задайте создание сетки аттракторов (A grid of attractors on selected surface).
Судя по содержанию Outliner, каждый аттрактор - это сложное хитроумное устройство для
организации взаимодействия между динамикой и деформациями меха.
Запустите анимацию.
Сначала все пойдет хорошо, но затем аттракторы начнут такие неистовые пляски, что
тщательного разбирательства в их устройстве не избежать.
2. Эта кривая (curveN), кроме того, является мягким телом, то есть ее форма, в свою
очередь, управляется системой из четырех частиц (curveNParticle).
3. Движение этих частиц, в свою очередь, определяется как внешними полями (которых пока
нет), так и наличием goal-объекта, к которому они стремятся. Этот goal-объект - спрятанная копия
кривой, управляющей костями. Эта спрятанная goal-кривая (copyOfcurveN) не деформируется, а
просто торчит перпендикулярно поверхности и передвигается вместе с ней как прямой стержень.
Ее назначение - притягивать к себе частицы «мягкой» кривой. Вы можете показать ее, просто
включив у нее атрибут Visibility.
Вопрос только в том, почему же аттракторы выписывают такие кренделя, ведь в целом
система выглядит вполне работоспособной? А потому, что кто-то (даже пальцем не на кого
показать!..) при задании индивидуальных весов частиц (goalPP), определяющих силу стремления
к goal-кривой для каждой отдельной частицы, установил по умолчанию такие крохотные значения
для всех частиц, кроме первой (находящейся в основании кривой), что частицы практически
не притягиваются к торчащим перепендикулярно goal- кривым и болтаются на пружинках как
веревочки. Следовательно, и аттракторы безвольно болтаются в пространстве, не зная, что такое
настоящая меховая упругость.
Если вы хотите исправить положение, надо отредактировать вес для каждой частицы в
каждом аттракторе. Наименее медленно это можно сделать следующим образом.
А затем Show=>Dynamics.
На экране останутся только пружины и частицы.
Выберите только пружины и спрячьте их (Ctrl-h).
Затем выберите частицы и нажмите F8.
После этого выделите только верхний ряд частиц и для редактирования весов откройте
Windows=>General Editors=>Component Editor.
Выберите закладку Particles и убедитесь, что иезуитское значение 0.005 для атрибута goal-
РР действительно присутствует для всех выбранных крайних частиц.
Исправьте его на 0.3 для всех ячеек (для этого достаточно последовательно выбрать все
ячейки, нажимая Ctrl).
Затем выберите на экране следующий ряд ячеек и для них установите goalPP=0.5.
Для третьего ряда задайте goalPP=0.7.
Можете проиграть анимацию прямо сейчас, оценивая упругость колебаний частиц. Если
вас не устраивает движение, настройте веса дополнительно.
Нажмите F8, чтобы вернуться в объектный режим.
Самая трудоемкая часть процесса - настройка весов goalPP, и, честно сказать, я не понимаю,
почему до сих пор в окошке Create Attractors не появилось три дополнительных числовых поля для
задания этих весов при создании аттракторов (четвертый вес всегда равен единице и принадлежит
частице в начале «мягкой» кривой).
Я всегда замечал, что сценарии, хоть минимально основанные на реальных событиях или
происшествиях, имеют какую-то дополнительную выпуклость. Поэтому когда с моим приятелем
Андреем Авдеевым приключилась нижеизложенная история, я тут же понял, что это один из
лучших сценариев для анимационного ролика, которые я когда-либо слышал.
Дело в том, что Андрюня - кайтер. А кайтеры - это люди, катающиеся на кайтах. А кайты
- это такие здоровые воздушные змеи, которые болтаются в небе и таскают за собой кайтеров.
Точнее говоря, кайт - это такой микропарашют (или минипараплан), который запускают в небо,
точно так же, как воздушный змей. Стропы кайта крепятся на планку, которую держит кайтер.
Чтобы кайтер совсем не устал, у него на поясе закреплен крюк, которым он цепляется за петлю на
планке, давая рукам отдыхать и управлять движением кайта. При этом безумный кайтер цепляет
на ноги доску типа сноуборда и прыгает в воду. А дальше все происходит очень быстро: кайт
набирает высоту и тащит за собой кайтера, тот извивается всем телом и пытается встать на доску,
находясь при этом в воде. Если ему это удается, он несется по водной глади с квадратными глазами,
пытается управлять кайтом через планку, к которой он прицеплен крюком, и оглушительно визжит
от восторга и избытка адреналина. Все это относится к начинающим и некоторым продолжающим
кайтерам.
Итак, одним приятным летним вечером мой приятель Андрюня лихо катался на кайте на
живописном озере, берега которого были облюбованы местными отдыхающими для пикников и
других глупостей. Закладывая очередной вираж-разворот, Андрюня подъехал слишком близко к
берегу, и тут коварный ветер дунул со всей дури. Да так, что Андрюню мигом выволокло на берег
и со скоростью курьерского поезда потащило по особенностям местного рельефа. А на берегу
ничего не подозревавшие люди жарили шашлыки, пили вино, думали о вечном... Стремительным
тараном Андрюня разметал несколько стоянок, сорвал пару тентов и, пытаясь упираться в землю
хотя бы руками, помчался в сторону леса. Теперь представьте мир его глазами, то есть вид из
камеры, пролетающей сквозь костры, палатки, кусты и заросли. И на переднем плане судорожно
растопыренные руки, у которых между пальцев торчат пучки травы и листьев.
Оказалось, что пронзая одно из шашлычных стойбищ, Андрюня случайно атаковал корпусом
этого вепря, который принял вызов и вцепился в ближайшую часть этого самого корпуса. Кстати,
минуты через две на место финиша прибежал перепуганный хозяин собаки, которому пришлось
долго избивать свирепую псину, чтобы она наконец разжала челюсти. А Андрюня потом долго
клеил гидрокостюм на самом заметном месте, переосмысляя свое видение отношений между
собаками и кайтерами.
Так что если кто-то из вас надумает заняться кайтом, прежде всего купите хороший толстый
гидрокостюм и еще раз подумайте о возможных последствиях. А если кто-то решит увековечить
эту историю в анимационной форме, обращайтесь ко мне за дополнительными деталями.
Анимация 1251
Волосатый симулятор
Динамику волос в MAYA ждали давно. На фоне уже готовых симуляторов одежды, меха и
«твердотельной» динамики потребность в адекватной технологии для работы с волосами с каждой
новой версией ощущалась все сильнее. Кроме того, персонажная анимация все настойчивее
требовала настоящей динамики волос, утомившись от хитроумных трюков и высокотехнологичных
обманов зрителя в тех случаях, когда требовалось симулировать выразительное движение массы
волос на поверхности персонажа.
До сих пор для симуляции волос использовались разные уловки. Прически на средних
планах моделировались как обычные поверхности с тщательно подобранным материалом и
текстурой. Для более крупных и требовательных планов использовался мех адекватной длины - и
предпринимались героические усилия по его анимации. Технология Paint Effects спровоцировала
технологический скачок в области моделирования и анимации причесок, что способствовало
появлению множества способов симуляции волос с помощью процедурных кистей. Но так как
динамика волос в системе Paint Effects отсутствует, возникла хорошо описанная в Интернете идея
использовать динамику тканей для анимации штрихов Paint Effects с целью создания эффекта
движения волос. Этот действительно красивый подход использует ленты из ткани, движение
которых обеспечивает модуль MAYA Cloth, далее, используя принцип Construction History, края
лент дублируются и превращаются в кривые, а они, в свою очередь, становятся управляющими
объектами, контролирующими деформацию штрихов Paint Effects. К сожалению, при использовании
таких многоступенчатых трюков теряется сама сущность явления, то есть пользователь уже
не оперирует понятием «волосы», а с трудом удерживает в голове все запчасти агрегата для
создания иллюзии работы с волосами. Ближе всех к динамике волос, с моей точки зрения,
подошла динамика мягких тел. Либо сами кривые, превращенные в мягкие тела с частицами,
либо «содранные» изопармы с «мягких» поверхностей дают неплохое базовое движение и даже
позволяют обеспечить столкновение с препятствием. Однако «резиновость» и невозможность
организовать контроль самостолкновений ограничивает возможность применения мягких тел для
динамики волос.
Хочу заметить также, что разработка технологии для работы с волосами - задача, сама по
себе, очень и очень сложная. Ведь волосы, в отличие от поверхностей или скелетонов, объект очень
непростой. С одной стороны, это объект процедурный, то есть описываемый плотностью, длиной,
толщиной, лохматостью, кудрявостью и возникающий окончательно только на этапе рендеринга.
С другой стороны, с волосами хочется работать, как с набором кривых, имеющих вес, упругость,
трение и другие динамические свойства. С третьей стороны, при создании причесок с волосами
было бы неплохо работать, как с едиными объектом, например, как с поверхностью, для придания
ей нужной формы. С четвертой стороны, волосы иногда хочется стричь, то есть осуществлять
массовое тримирование кривых. И так далее. Таким образом, сами технологические требования к
волосам, как к объекту трехмерной графики чудовищно высоки, а пожелания к инструментам для
работы с таким объектом и вовсе фантастичны. Кроме того, для работы с волосами надо решать
некоторое количество внутренних спецзадач: организация взаимодействий между отдельными
участками, формирование констрейнов, специальные быстрые методы рендеринга и т.д. Тем не
менее, такая технология все-таки появилась в шестой версии MAYA, и, с моей точки зрения, это -
произведение искусства. Причем как с технической точки зрения, так и с точки зрения реализации
и встраивания в среду MAYA. С позиции следования общей логике майских инструментов и
соответствия парадигме «объект как набор атрибутов» модуль MAYA Hair является квинтэссенцией
майской идеологии. Похоже я увлекся. Но мне действительно нравится эта технология.
Да, благодаря быстрой динамике кривых, реализованной в MAYA Hair, стало возможно
Анимация 1255
быстро и, что немаловажно, интерактивно производить анимацию некоторых типов тканей, как
поверхностей, проходящих через набор динамических кривых. Всяческие занавесы, шторы,
сети, знамена и хоругви могут быть быстро смоделированы и оживлены с помощью некоторого
количества кривых.
Все, что связано с динамикой обобщенных веревок, также может быть реализовано
с помощью MAYA Hair. Тросы, провода, канаты, кабели, цепи, лески и даже шнурки - все это
кандидаты в динамические кривые.
Для задания анимации штрихов Paint Effects можно использовать динамику волос, используя
кривые как Control Curves.
Более того, рассказывая про архитектуру MAYA Hair, я буду постоянно ссылаться на аналогию
с майскими частицами и вновь проповедовать принципы динамики.
Здесь я приведу уже описанные ранее законы майской динамики без комментариев:
это лишь для тех, кто жить не может без симуляции волос, а потому не успел прочесть начало
главы по динамике твердых тел. Однако рекомендую все-таки прочесть обсуждение этих законов
в перерывах между неистовыми экспериментами, если, конечно, вы хотите понимать суть
происходящего перед вами на экране.
Закон динамики 2.
Анимация должна воспроизводиться всегда только вперед.
Закон динамики 3.
Первый кадр анимации всегда должен быть «начальным» с точки зрения динамики.
Закон динамики 4.
Нельзя безответственно щелкать мышью в TimeLine и так же безнравственно перетаскивать
мышью текущее время. До тех пор, пока вы не разберетесь с кэшированием, нажимайте только
кнопки Play, Stop и возвращайтесь в первый кадр.
Закон динамики 5.
Волосы не должны пересекать голову в начальном кадре. Это - новое прочтение закона о
твердых телах. Если вы задали столкновение волос с поверхностью, сделайте так, чтобы в первом
кадре волосы не проникали в эту поверхность, иначе они в ней намертво завязнут. Это относится,
понятное дело, не к основаниям волос, а к их свободным концам.
Чисто терминологически было бы корректно назвать модуль MAYA Hair динамикой кривых,
так как при работе с ним анимируется некоторое (вполне конкретное) количество кривых.
Соответственно, вы должны перестроить свое мышление на работу с отдельными кривыми,
а не с общей массой волос. Дело в том, что никакой суперкомпьютер не способен просчитать
реальную динамику ста пятидесяти тысяч волос, встречающихся в реальной природе на голове
среднелысого персонажа. Поэтому для обмана зрителей и для облегчения жизни технических
директоров используется весьма небольшое количество, скажем так, опорных кривых, задающих
общее движение всей массы волос. Именно с этим конкретным количеством кривых вам и
Волосы 1257
придется работать, как с объектами динамики. И только на этапе рендеринга появляется заданное
и достаточно большое количество волос, заполняющих пространство между опорными кривыми.
Я настоятельно советую вам помнить о такой «двойственной» природе компьютерных волос и
работать с ними, как с динамикой небольшого количества кривых. Чем меньше кривых будет
использоваться для анимации движения, тем быстрее будет обсчитываться динамика и тем
интерактивнее будет проходить работа. Соответственно, основной неформальной задачей будет
искусное заполнение пространства между динамическими кривыми уже на этапе рендеринга. Эта
задача похожа на проблему адекватного текстурирования поверхности, и к ней я вернусь при
обсуждении визуализации волос.
Для того, чтобы последовательно изучить внутреннее устройство системы волос, разберем
небольшой пример, использующий динамику волос с целях, не связанных с персонажной анимацией.
Во-первых, я не люблю персонажную анимацию, а во-вторых, на более простых примерах удобнее
демонстрировать максимум полезных свойств и законов.
Если выбрать Output=NURBS Curves, волосы будут представлены в виде обычных NURBS-
кривых. Если вы не собираетесь их визуализировать непосредственно как волосы, а намереваетесь,
например, использовать в виде деформеров или как управляющие кривые для анимации
поверхностей (либо, например, скелетов), это как раз тот самый случай. Или если вы собираетесь
создать вокруг каждой кривой extrude-трубку нужного профиля с адекватной текстурой, чтобы
визуализировать эти кривые как отдельную геометрию. Этот случай также является подходящим,
если вы намереваетесь рендерить кривые в своей любимой системе рендеринга, которая способна
это делать быстро и качественно. В принципе позже можно воспользоваться операцией назначения
кистей Paint Effects на кривые, однако лучше, конечно, заранее продумать способ визуализации
волос.
Если же вам нужно использовать реальные кривые в своих корыстных целях (например,
запустить по ним объект, как по пути) и одновременно вы хотите визуализировать их, пользуясь
преимуществами Paint Effects, можно выбрать вариант Output=Paint Effects and NURBS Curves. Он
также хорошо подходит, когда вы не можете решить, что же вам нужно.
Мы поступим именно так, а потом спрячем штрихи Paint Effects - до нужного момента.
Выберите Output=Paint Effects and NURBS Curves, а затем задайте U Count=50 и V Count=1,
чтобы создать один ряд из пятидесяти кривых, растущих по кругу.
Значения U/V Count определяют разрешение сетки из кривых, которая покроет всю поверхность.
Здесь необходимо остановиться и подумать о том, что на поверхности должны существовать
адекватные UV-координаты. Здесь ситуация полностью аналогична созданию меха.
Волосы 1259
поверхность, на которой расположены волосы.
Оставим без изменений параметр Points Per Hair, определяющий количество контрольных
вершин для кривой, то есть «гнучесть» волоса.
Не будем также трогать длину волос (Length), тем более что эти параметры можно будет
отредактировать после.
Не будем также включать галку Randomization, которая разбросает по поверхности, в
случайном порядке, сетку волос (в нашем случае нужен лишь один ряд).
Галка Equalize действует аналогично картам Equalizer Maps для меха и предназначена для
компенсации неравномерной параметризации поверхностей в областях типа полюсов сферы и для
ровного распределения волос в таких регионах. Ее тоже трогать не надо.
Теперь можно нажать, наконец, кнопку Create Hairs. Вследствие чего возникнет кольцо из
вертикальных кривых, окруженных небольшими пучками. Эти пучки и есть визуализация волос с
помощью штрихов Paint Effects, но, коль скоро мы будем обсуждать форму и внешний вид волос
позже, сейчас спрячем их, чтобы сосредоточиться на динамике и архитектуре системы волос.
Проще всего отключить отображение Paint Effects на экране с помощью меню панели камеры:
достаточно снять галку Show=>Strokes, и в перспективном окне останутся только центральные
кривые.
Пытливые умы, однако, быстро заметят непорядок при расположении волос. Во-первых, в
виде сверху отчетливо видно, что кривые не расположены по центрам сегментов. Во-вторых, их
i 260 Книга Сергея Цыпцына
не пятьдесят, как следовало ожидать. А в-третьих, в Outliner появилось несколько пустых групп,
наводящих на мысль о неудачном создании нескольких кривых. В чем причина неудачи?
Как и в случае с мехом, причина неудачи в ненастроенных UV-координатах.
Очевидно, при попытке создать один ряд из пятидесяти кривых, MAYA попыталась их
расположить вдоль V-координаты со значением V=0.5, разбивая U-диапазон на пятьдесят шагов.
Однако, как следует из раскладки UV-координат, некоторые значения (например, 11=0.02, V=0.5)
не принадлежат поверхности.
Поэтому, пустые группы результат неудачной попытки создать кривые в точках с UV-
координатами, не принадлежащими поверхности. Отсюда, кстати, следует и принцип, по которому
MAYA располагает сетку из волос-кривых на поверхности: единичный квадрат на плоскости UV-
координат равномерно (или не очень, если включены опции Randomization и Equalize) разбивается
на сетку значений U и V, и в этих местах выращиваются кривые. В принципе, такой алгоритм
работает неплохо, особенно на равномерно распределенных UV-координатах, но вы должны быть
в курсе этого, особенно когда выращиваете кривые на краях поверхностей. Напомню, что все
эти мелкие проблемы вылезают при работе с полигонами. У NURBS-поверхностей осложнений не
возникает.
Волосы 1261
Выберите цилиндр и выполните Hair=>Delete Entire Hair System, чтобы удалить все объекты,
относящиеся к волосам. К сожалению, пустые группы придется удалять вручную.
Так как все установки создания сохранились в Option Box и так как значение V=0.5
соответствует теперь середине цилиндра, будут созданы ровно пятьдесят кривых торчащих
горизонтально из боковой поверхности цилиндра. Помните также, что мы спрятали отображение
штрихов Paint Effects в окне камеры.
Запустите анимацию (сразу можете задать диапазон для проигрывания порядка двух тысяч
кадров). Кривые мягко согнутся вниз.
Теперь самое время разобраться, как устроена сама система волос и из чего она состоит.
Тем более, что на экране уже появились загадочные микрокружки в основаниях кривых. Верните
цилиндр в исходное положение. Как и при работе с частицами и твердыми телами, все перестроения
лучше выполнять в начальном кадре.
Последняя закладка содержит атрибуты системы волос как единого объекта. То есть
определяет свойства, общие для всех кривых и целиком описывающие характеристики, скажем
так, «прически». Опять по аналогии с частицами, нода hairSystemShape так же определяет свойства
системы волос, как нода particleShape задает общие характеристики системы частиц. Пропустив
пока раздел Clump and Hair Shape, отвечающий за форму прически, откройте раздел Dynamics,
содержащий атрибуты, определяющие динамические свойства волос.
Волосы 1263
Основное «механическое» свойство волос упругость (Stiffness).
Уменьшите значение этого атрибута до нуля, и кривые превратятся в веревки, безвольно
падающие вниз.
Кроме того, подраздел Stiffness Scale позволяет задать распределение жесткости вдоль
длины каждого волоса. Форма распределения по умолчанию симулирует эффект того, что ближе
к основанию волосы жестче, чем на концах.
Атрибут Drag отвечает за эффект сопротивления воздуха или, если посмотреть с другой
стороны, за массу волос. Увеличьте его до 0.1, и вы увидите легкие нити, плавно опускающиеся
вниз.
Задайте Drag=0 и получите динамику тяжелых веревок или даже цепочек, долго
болтающихся, по инерции, но в конце концов останавливающихся.
Аналогом атрибута conserve для частиц является атрибут Damp. Он служит для
искусственного торможения движения кривых. Если представить отдельную кривую в виде цепочки
из стержней и шарниров, то можно сказать, что Damp управляет трением или несмазанностью этих
шарниров. То есть этот атрибут задает внутреннее трение и сопротивление движению. Физическим
аналогом может служить короткий кусок тяжелого каната, который прекращает раскачиваться
не из-за трения о воздух, а в силу внутреннего трения. В случаях, когда в системе возникают
быстрые колебательные процессы, вызванные, например, сильной жесткостью волос или резкими
столкновениями, можно избежать раскачивания и дрожания кривых путем временного увеличения
значения Damp.
Остальные динамические атрибуты для волос (Dynamic Weight, Start Time, Current Time)
-полный аналог одноименных атрибутов для частиц.
Волосы 1265
Редактирование длины волос
Для того, чтобы изменять длину волос, в меню Hair есть очень простой инструмент (Scale
Hair Tool), не имеющий даже собственного манипулятора (курсора) - это, кстати, может быть
причиной «застревания» в этом инструменте, из-за этого его порой путают с Select Tool.
Если выбрать все волосы целиком (объект hairSystem), масштабироваться будут все кривые.
Однако можно выбрать лишь некоторые кривые и применить этот инструмент к только к ним.
Выберите в Outliner объект hairSystem1 и возьмите в руки инструмент парикмахера: Hair=>Scale
Hair Tool.
Теперь, чтобы удлинить волосы, достаточно кликнуть и потащить мышью вправо, а чтобы
укоротить влево.
Удивительно, но делать это можно не только в первом кадре, но даже во время проигрывания.
Подождите, пока кривые опустятся вниз, а затем остановитесь и растяните их примерно так, чтобы
они удвоились по длине и пересеклись в виде песочных часов.
Выберите на экране все кривые и повторите операцию Hair=>Set Start Position=>From Cur
rent. Вернитесь в первый кадр. Затем удалите radialFieldl. Теперь узел развязывается, и кривые
распадаются в стороны.
Волосы 1267
Примечание. В отличие от частиц, сохранение текущего положения в виде
начального фиксирует только позиции кривых. Скорости при этом просто
обнуляются.
В этом месте лучше сохранить сцену (hairCylinder.ma), ибо дальше будет длинный и
местами скучный разговор о столкновении динамических кривых с поверхностями. MAYA может не
выдержать такого занудства и зависнуть в самый неподходящий момент.
Запустите анимацию и дайте волю эмоциям. Кривые проходят сквозь поверхность, лишь
слегка покачнувшись при первом соприкосновении. В чем дело?
Тут самое время вспомнить динамику мягких тел, а также опять обратить ваше внимание
на фаворитов нашего хит-парада - частицы. Если кто-то из вас пытался делать тряпки из мягких
тел и сталкивать их с чем-нибудь (или пытался хотя бы выполнить упражнение из соответствующей
главы этой книги), вы помните, что мягкие тела сталкиваются с объектами при помощи
своих частиц, не обязательно лежащих на поверхности мягкого тела. Тоже самое относится к
динамическим кривым. Они взаимодействуют с поверхностями своими контрольными точками, а
никак не сегментами, соединяющими эти точки. Поэтому при настраивании столкновений кривых
с поверхностями всегда следует отчетливо представлять себе, из какого количества точек состоит
каждая кривая и достаточно ли этого количества, чтобы описать как столкновение, так и саму
форму кривой.
Самый простой способ оценить количество точек на кривой - это, естественно, метод
пристального взгляда.
Предположим, что количество точек (и, соответственно, сегментов), нас вполне устраивает
с точки зрения движения тяжелых веревок. В этом случае надо повнимательнее разобраться с
параметрами столкновения кривых с поверхностью.
Волосы 1269
наверняка будут разочарованы полученным результатом. Дело в том, что если
задать для этого атрибута значение больше двух, вместо дополнительных
подразбиений, вокруг каждой контрольной вершины будет возникать кольцо
из заданного количества точек-сэмплов. То есть в этом случае используется
принципиально другой метод увеличения точности просчета столкновений. Таким
образом, если у вас не хватает контрольных вершин для столкновений с узкими
или острыми объектами, используйте для Collide Over Sample значения 1 или 2.
Если же вы хотите более точно отслеживать коллизии для широких пучков или
толстых веревок, задавайте значения 3 и выше. Как раз про пучки и пойдет речь
дальше.
Здесь необходимо еще подробнее влезть в механизм просчета столкновений. Дело в том,
что на экране мы видим тонкие и бесплотные кривые, а вот при визуализации это будут вполне
конкретные объекты со своей шириной, или лучше даже сказать толщиной. В отличие от вездесущих
частиц, сиротливо сталкивающихся с поверхностями своими центрами, для кривых определен
зазор - цилиндрическая (точнее, конусообразная) окрестность вокруг каждой направляющей
кривой, используемая как толщина веревки или пучка волос.
К форме волос и прическам я еще вернусь, а сейчас хочу заострить внимание на том,
что при расчете столкновений учитывается ширина каждого пучка (clump). Это предотвращает
ситуацию, возникающую с частицами, когда с поверхностью сталкивалась бы только основная
центральная кривая, а половина достаточного широкого пучка, растущего вокруг нее, погружалась
бы в поверхность.
Установите Clump Width=0.01, то есть ширина пучков будет равна толщине самих волос.
Соответственно, и столкновения теперь будут рассчитываться для тонких веревок, а
не для толстых пучков. Особо любознательные умы могут также выровнять графики-профили,
определяющие изменение толщины вдоль направления кривых (Clump/Hair Width Scale).
W = Clump Width * Clump Width Scale + Hair Width + Collide Width Offset
Кстати, увидеть эту толщину можно, и не отображая штрих Paint Effects. Два последних
атрибута в разделе Collisions позволяют нарисовать на экране что-то похожее на кружки,
символизирующие динамическую толщину кривых.
Включите Draw Collide Width, и вы увидите вдоль каждой кривой небольшие кружки (а если
вы забыли установить Collide Width Offset=0.1, тогда просто точки). Правда, для того, чтобы они
появились, надо хотя бы немного сдвинуть камеру или перейти в следующий кадр. Чтобы кружков
Волосы 1271
нарисовалось побольше, установите Draw Collide Skip=0. Если они вас раздражают, выключите их
немедленно.
Атрибут Repulsion задает степень отталкивания друг от друга, a Static Cling имитирует силу
притяжения, похожую на прилипание волос друг к другу вследствие статического электричества.
Можете поэкспериментировать с этими атрибутами и отметить, как падает производительность
просчета динамики при включенном взаимодействии кривых. Не забудьте выключить его для
дальнейших экспериментов.
Сейчас, когда кривые распрямились, самое время опять сохранить текущее положение как
начальное.
Нас дрожание не смущает, но немного конфузит форма кривых. Совершенно очевидно, что
количества контрольных точек на кривых немного не хватает для придания им более гибкой формы.
Однако количество контрольных точек определялось только при создании и не фигурировало среди
атрибутов объекта hairSystem. Оказывается, можно определять количество сегментов для каждой
отдельной кривой, так же, как и ее степень и многие другие свойства. Для того, чтобы изменить
эти свойства, нужно добраться до индивидуальной природы каждой кривой. Этим мы сейчас и
займемся. А я напомню, что мы решили проблему столкновений без дополнительного увеличения
числа точек, и если бы форма и «гнучесть» кривых нас устраивала, не было бы необходимости
увеличивать количество сегментов.
Если посмотреть на тип ноды в этой закладке, то выяснится, что это follicle (фолликула),
а если нажать в нижней части Attribute Editor кнопку Select, то на экране выберется основание
кривой, этакий корешок. Если немного исхитриться, можно выбирать этот микрообъект прямо на
экране, но всегда проще выбрать кривую и разыскать нужную закладку в Attribute Editor.
Сразу отмечу, что в разделе Dynamics Overrides и Render Overrides находятся атрибуты,
которые позволяют изменить «общепартийные» свойства, заданные для всей системы волос
hairSystem, и дают возможность задать индивидуальные свойства для выбранной кривой. Так,
например, атрибут Stiffness в этом разделе задает индивидуальную упругость для конкретной
Волосы 1273
кривой, не зависящую от значения Stiffness, определенного для всех волос.
Пытливые умы наверняка заметили, что у каждой динамической кривой есть два атрибута
(Parameter U/V), определяющие точное расположение конкретной кривой на поверхности. Причем
эти атрибуты можно, абсолютно без комплексов, редактировать вручную.
Следующий вопрос состоит таков: как одним махом отредактировать Sample Density для
всех динамических кривых. На ум конечно приходит Channel Box, позволяющий редактировать
атрибуты для всех выбранных объектов, однако если выбрать все кривые на экране, в Channel Box,
к сожалению, появляются только обычные атрибуты кривых, а нужные нам свойства из закладки
follicle отсутствуют. Очевидно, что «корешки» кривых, то есть ноды типа follicle надо выбрать
отдельно. Самый нетворческий путь - начать возиться с Selection Masks. Менее прямолинейное
решение - разыскать в Outliner группу hairSystem1 Follicles и выбрать ее внутреннее содержание.
Однако часто бывает удобно выбирать конкретные кривые прямо на экране и обращаться к их
«динамическим» свойствам непосредственно в Channel Box. Для этого существует операция
конвертации типа выбранных объектов, аналогичная такой же операции для полигональных
компонент (Edit Polygons=>Selection).
Творческий выбор
Самый простой пример наиболее часто встречающей проблемы - как выбрать все
динамические кривые для конкретной системы волос hairSystem? Или наоборот, как для выбранной
кривой быстро выбрать всю систему волос? Для этих целей существует довольно остроумный пункт
меню: Hair=>Convert Selection.
Как только кривые остановятся, выполните Hair=>Set Start Position=>From Current. Это
должно стать привычкой для сохранения достигнутой в результате анимации формы. Вернитесь в
первый кадр.
Заметьте, что если выбраны все Follicles, нет необходимости выбирать все кривые перед
сохранением начального положения. Однако после этой операции выбранными становятся
так называемые стартовые (или начальные) кривые (Start Curves). Вот о них-то мы сейчас и
поговорим.
Поэтому следует обязательно запомнить, что если вы изменили значение Sample Density,
а затем выполнили операцию Set Start Position=>From Current, то следует немедленно установить
Sample Density в единицу, иначе количество точек еще раз увеличится.
Волосы 1275
Снова выберите объект hairSystem1, а затем выполните операцию Hair=>Convert
Selection=>to Follicles, чтобы добраться до индивидуальных свойств всех кривых.
Задайте Sample Density=1. Число точек на каждой кривой должно стать равным шестнадцати.
Очень важно понимать тот факт, что количество точек на динамических кривых определяется
как количество точек на стартовых кривых, умноженное на значение Sample Density для каждой
кривой. Именно в стартовых кривых, сохраняется количество точек, задаваемое в самом начале
при создании системы волос.
Кроме того, как я только что упоминал, при сохранении текущего (Current) состояния в
качестве начального (Start) с помощью операции Hair=>Set Start Position=>From Current сохраняется
не только форма, но и количество точек. Поэтому если для некоторых (или для всех) кривых
значение Sample Density отлично от единицы, обязательно верните его в единицу после сохранения
начального состояния.
Вы также должны понимать, что для одной системы волос hairSystem всегда существует,
как минимум, два набора кривых (как максимум, три - при наличии Rest Curves): текущий (Current)
и стартовый (Start).
Так как в первом кадре форма динамических кривых полностью определяется стартовыми
кривыми, это означает, что начальное состояние (или «прическу») можно задать, просто
отредактировав стартовые кривые всеми легальными и нелегальными методами. Осталось
выяснить, как показать скрытые стартовые кривые.
Далее вы можете нажимать кнопки вправо и влево, чтобы выбирать целые ряды контрольных
точек одновременно на всех кривых. Выберите таким образом кольцо из точек в районе «сгиба».
Волосы 1277
Однако при попытке смасштабировать или переместить точки возникает резонный вопрос:
а как быть с длиной кривых? - ведь таскание точек неизбежно меняет длину кривой.
Не пугайтесь. Стартовые кривые всегда представляют собой кривые первого порядка, ведь
их предназначение хранить информацию о положении точек и, следовательно, гладкость или
степень стартовых кривых не имеют значения.
Нажмите «I», затем с помощью Scale Tool сожмите немного точки к центру.
Не отпуская «I», выберите Move Tool и поднимите точки вверх, на уровень перегиба в
середине. Вы должны понимать, что после редактирования никакого сохранения начального
состояния не требуется, так как мы непосредственно редактируем стартовое положение кривых.
Если стартовые кривые определяют начальное положение системы волос, то есть позицию
в первом кадре, то остаточные кривые задают положение, которое стремится занять система волос
при отсутствии внешних сил. Иными словами, можно задать форму, к которой будут стремиться все
кривые и около которой они будут пытаться удержаться, при отсутствии внешних воздействий.
Используя житейские термины, можно сказать, что использование лака для волос
некоторыми легкомысленными женщинами для придания формы прическе полностью аналогично
использованию остаточных кривых. Ветер пытается растрепать прически ветреных блондинок,
однако волосы стремятся занять позицию, заданную при укладке. В случае веревок можно привести
аналогию с накрахмаленностью тканей, задающей некоторую форму, которую ткань стремиться
сохранить.
Примечание. С появление в седьмой версии MAYA нового атрибута Start Curve At
tract необходимость использования остаточных кривых отпала в значительном
большинстве случаев.
Волосы 1279
Попробуем накрахмалить нашу систему веревок.
Затем выберите все кривые и выполните операцию Hair=>5et Rest Position=>From Current.
Эта операция копирует текущее положение кривых и создает из него остаточные кривые.
Выберите систему волос hair System1 и в Attribute Editor установите Stiffness=0.15 в разделе Dy
namics.
Поиграйте с упругостью (Stiffness), чтобы убедиться, что она в самом деле управляет
степенью стремления системы веревок к остаточным кривым.
Используя пункт меню Hair=>Convert Selection, можно выбрать концевые точки остаточных
кривых и отредактировать их вручную, аналогично стартовым кривым. Все изменения формы
остаточных кривых немедленно отражаются на анимации.
Использование остаточных кривых (Rest Curves) - довольно полезный способ задания общей
формы для системы волос, особенно в тех случаях, когда речь идет о прическах. Я бы советовал
воспринимать остаточные кривые не как жесткую форму (в отличие от стартовых кривых), а скорее
как силу, которая стремится привести волосы в некоторое состояние и конкурирует с другими
силами.
Волосы 1281
Три типа кривых при работе с системой волос
Таким образом, при работе с системой волос мы обычно имеем дело с двумя или тремя
(при наличии Rest Curves) наборами кривых. Существует, правда, еще один тип кривых - пассивные
кривые (Passive Curves), но о них пойдет речь позже.
Прежде всего это сами динамические кривые, которые анимируются под действием
динамики. Они называются Current Curves (или Current Position).
Стартовые кривые (Start Curves, или Start Positions) задают форму и положение динамических
кривых в начальном кадре. Они автоматически создаются всегда, и их нельзя удалить без удаления
самих динамических кривых. Их можно редактировать вручную. Именно эти кривые определяют
базовое количество точек, из которых состоят динамические кривые.
Остаточные кривые (Rest Curves, или Rest Positions) определяют форму, которую стремятся
занять динамические кривые. Чем больше упругость кривых, тем сильнее и точнее они принимают
эту форму. Остаточные кривые не создаются по умолчанию (но при необходимости могут быть
построены при создании волос). Их также можно и нужно редактировать вручную всеми легальными
и нелегальными методами, однако количество точек на них менять не следует.
Сначала надо выбрать кривые и для них создать констрейн определенного типа
(Hair=>Create Constraint). Этот констрейн определяет в первом кадре (!), какие контрольные точки
для каждой кривой располагаются ближе всего к его центру (визуально констрейн представляется
как локатор), причем этот констрейн выбирает по одной точке с каждой кривой и накладывает
связи только на эти точки.
По этой причине, если вы собираетесь двигать или вращать модель, из которой растут
динамические волосы (и если эти волосы имеют назначенные констрейны), имеет смысл поместить
их констрейны в одну группу с моделью или просто припарентить их к ней, для того чтобы сохранить
фиксированным расстояние между констрейном и волосами в первом кадре.
Выберите все кривые и создайте констрейн Rubber Band (резиновая полоска или нить):
Hair=>Create Constraint=>Rubber Band.
Волосы 1283
Если проиграть анимацию, окажется, что эти упругие нити постоянно связывают концы
веревок с локатором.
Важно понимать, что это происходит только в первом кадре. Вычисляя необходимые
расстояния, MAYA гарантирует, что в начале анимации никакие отталкивающие или притягивающие
силы не появятся, а воздействие связей начнет проявляться только по мере изменения расстояния
от кривых до констрейна.
Каждый раз, когда вы будете двигать локатор в первом кадре, связи будут перескакивать
на ближайшие контрольные точки. Во всех остальных кадрах никаких перескоков не будет.
Вкратце опишу свойства и назначение каждого констрейна. Так как все констрейны имеют
одинаковую природу и набор атрибутов, вы можете одновременно экспериментировать с разными
типами констрейнов, просто переключая атрибут Constraint Method в Attribute Editor для уже
созданного констрейна.
Rubber Band (резиновые нити) притягивает к себе точки кривых, если расстояние до них
превышает дистанцию, определенную в первом кадре.
Волосы 1285
Transform просто замораживает намертво точки, определенные в первом кадре и
как бы «пригруппировывает» их к себе, так, что они двигаются вместе с ним, как единое
целое. Примечательно, что замороженные точки корректно наследуют все вращения и даже
масштабирование констрейна типа Transform. Его удобно использовать, например, в тех случаях,
когда вы хотите намотать волосы на руку или зафиксировать концы веревок.
Stick напоминает Rubber Band, однако вместо нитей здесь упругие стержни, которые
свободно вращаются вокруг центра локатора. Они также пытаются выталкивать кривые обратно,
если точки последних подходят к локатору ближе, чем дистанция, определенная в первом
кадре.
Hair Banch - единственный констрейн, который может прикладывать силу к точкам кривых
непосредственно в первом кадре. Этот констрейн пытается разбить волосы на пучки, имитируя,
с одной стороны, самостолкновения между кривыми и статическое слипание, с другой стороны.
Если точки кривых находятся ближе, чем значение, определенное атрибутом Clump Width (для
ноды hairSystem), то кривые отталкиваются друг от друга. Если точки подходят совсем близко друг
к другу, они начинают слипаться. Это единственный констрейн, который принимает во внимание
ширину пучков волос (Clumping), определенную для все системы волос. Симуляция взаимодействия
Атрибуты констрейнов
Поскольку все констрейны представляют из себя один и тот же объект с разным значением
атрибута Constraint Method, удобно изучить их немногочисленные атрибуты прямо в Attribute Edi
tor.
Атрибут Stiffness определяет силу, с которой констрейн действует на точки (это не касается
типа Transform).
Волосы 1287
Чтобы почувствовать различие в степени притяжения, задайте, например, Stiffness=0.01
для Rubber Band или Stiffness=5 для HairBunch.
Самое удивительно, что констрейны умеют «обрываться» при очень сильных воздействиях.
Если атрибут Glue Strength равен единице, это означает, что констрейн суперпрочный и никогда
не порвется. Однако значения меньше единицы означают, что если натяжение (или сила) между
точками и констрейном станет достаточно большим, то связь попросту разорвется, и кривая
вырвется на свободу. Причем насколько это самое «достаточно большим», как раз и определяется
значением атрибута Glue Strength.
Естественно, что атрибут Glue Strength можно анимировать, для симуляции разрыва связей
во время анимации.
Если вас смущает, что в первом кадре констрейн авторитарно захватывает ближайшие к
нему точки, вы можете прекратить этот произвол и самостоятельно задать набор точек с некоторым
значением параметра U, который будет прикреплен к констрейну. Для этого достаточно сменить
метод выбора точек в первом кадре (Point Method). Если выбрать Point Method=U Parameter, то с
помощью атрибута U Parameter можно задать набор точек на кривых с одинаковым значением U,
попадающих под воздействие констрейна.
Таким образом, в списке констрейнов еще два типа: Collision Sphere и Collision Cube. Они
позволяют создать для выбранных кривых объект для столкновений. Этот объект сферической или
кубической формы можно передвигать, вращать или масштабировать.
Примечание. Любители динамики твердых тел, ионечно, сразу сообразят, что это
аналог атрибута Standln, который подменяет реальную поверхность твердого
тела на примитивный куб или сферу для расчета столкновений с другими твердыми
телами.
Типичный способ применения констрейнов такого типа заключается в том, что после
создания волос для отработки столкновений с телом создается несколько констрейнов типа Colli
sion Sphere, один из которых имитирует столкновения с головой и располагается в соответствующем
месте, другие масштабируются и размещаются (или даже группируются к скелету) в тех местах,
где расположены плечи.
Все это, конечно, трюки и обман, однако если взять хорошополигональную модель и
выполнить Hair=>Make Collide, просчет столкновений будет происходить мало того, что не быстро,
а порой и несколько «неаккуратно», вынуждая увеличивать значение атрибута Collide Over Sam
ples и, тем самым, еще более растягивать время просчета динамики.
Во-вторых, столкновения с поверхностями можно задать только для всей системы волос
(hairSystem), а констрейны могут быть созданы только для выбранных кривых.
Острые грани, открытые края поверхностей, мелкие детали - все это «не по вкусу»
динамике кривых. Избегайте их.
И самое главное. Вместо реальных объектов максимально старайтесь, где это возможно,
использовать констрейны типа Collision Sphere и Collision Cube для просчета столкновений.
Аналогично твердым телам, для просчета соударений можно использовать не реальные
поверхности, а процедурные примитивы (типа куба или сферы), если они примерно воспроизводят
форму поверхности. Просчет таких коллизий происходит в разы быстрее и точнее.
Если также вам надо обеспечить столкновение волос с горизонтальной плоскостью, для
этого не надо создавать геометрию. Для этого достаточно в атрибутах системы волос (hairSystem)
в разделе Collisions включить галку Collide Ground и задать высоту плоскости с помощью атрибута
Ground Height. Просчет столкновений с такой горизонтальной плоскостью не требует никаких
Волосы 1289
дополнительных вычислительных затрат.
Избегайте просчета взаимных столкновений между кривыми (Self Collide). Если же этого
не избежать, старайтесь задавать число взаимодействующих между собой соседних кривых (Num
Collide Neighbors) минимально возможным: начните с двух-трех и увеличивайте, пока не добьетесь
нужного эффекта.
Если кто-нибудь заикнется о честных отражениях или преломлениях, я также замечу, что
для использования алгоритма трассировки лучей, вам придется загрузить в память всю геометрию
волос, то есть данные о количестве вершин, их позиции, цвет и прочие атрибуты, собранные с
пары миллионов волос. Я ничего не имею против против Raytracing, но просто хочу обозначить
следующий момент: волосы - не тот объект, который следует рендерить «в лоб». Существуют
методы легального обмана зрителя, так почему бы их не использовать? Пользователи Renderman
десятилетие жили без преломлений и отражений, при этом обманывали народ качественнее всех,
в то же время считая свои сцены быстрее всех.
Примечание. Плагин Renderman for Maya умеет считать майские волосы как
«родной» объект, не используя пост-эффекты.
Для mental ray уже появились коммерческие разработки сторонних компаний, позволяющие
использовать для визуализации волос так называемый «геометрический материал» (Geometry
Shader). Например, решения от компании Provide3d (смотрите на www.provide3d.com) позволяют
отрендерить не только волосы, создаваемые MAYA Hair, но и штрихи Paint Effects с помощью mental
ray, с использованием всех возможностей этого рендерера.
Примечание. Начиная с седьмой версии MAYA, mental ray также умеет считать
майские волосы как «родной» объект, не используя пост-эффекты.
Другой способ состоит в применении традиционного трюка для визуализации кривых, как
штрихов Paint Effects (это не имеет отношения к встроенным возможностям системы волос).
Вы берете любую кисть, а затем, выбрав кривые и применив операцию Paint Effects=>Curve
Utilities=>Assign Brush to Curve, визуализируете все сплайновые кривые с помощью наложения на
них выбранной кисти.
Волосы 1291
Далее, если вы исповедуете свою хитрую рендеринг-концепцию, то, вероятно, ваш
сакральный рендерер умеет рендерить кривые непосредственно. Поэтому вы можете получать
различные типы эффектов, на которые этот рендерер способен. Однако даже если вы используете
великий и ужасный Renderman, не спешите генерить полмиллиона волос: одна генерация rib-
файла займет у вас грандиозное время, а его размер будет несколько неудобоваримым. Наверняка
вам придется написать собственную dso-процедуру, для генерации волос «на лету», во время
рендеринга.
Примечание. В ноябре 2005 года на свет появился один из самых ожидаемых плагинов
для MAYA - под названием Renderman For Maya. Основное назначение этого плагина:
дать пользователям MAYA возможность просчитать свои уже готовые сцены с
помощью движка Renderman. Причем главное преимущество этого плагина состоит
в отсутствии необходимости настраивать сцены специально для рендеринга: все
материалы, ноды и объекты поддерживаются по умолчанию (кроме MAYA Fluids).
Не нужно писать материалы или делать конвертацию текстур - достаточно лишь
нажать кнопку «Отрендерить». К моему удивлению и восторгу, Renderman For Maya
прекрасно поддерживает и MAYA Hair и MAYA Fur и Paint Effects, причем не как пост
процесс, а в основном проходе рендеринга, вместе с остальной геометрией сцены.
Все эффекты, связанные с рейтрейсингом, также поддерживаются для MAYA Hair,
MAYA Fur u Paint Effects. Более того, специально для волос и меха идеально подходит
использование фирменной пиксаровской технологии расчета теней DeepShadow,
отлично работающей с «мохнатыми» объектами.
Первый - более программистский: создать ноду pfxHair и соединить ее нужной связью с системой
волос. Это делается с помощью двух команд:
Второй - более «гуманный», но менее изящный: достаточно выбрать систему волос (hairSys-
tem) и выполнить операцию Hair=>Assign Paint Effects Brush to Hair. (Об этой операции речь пойдет
позже.) Затем надо выбрать созданную ноду pfxHair, разыскать в Attribute Editor кисть Paint Effects
с названием типа brush1 и удалить ее с помощью кнопки Select и клавиши Delete.
Если это все звучит сложно и непонятно, скажем так: просто не обращайте внимания на
ноду pfxHair, но рассматривайте атрибуты в разделе Shading для системы волос hairSystem как
параметры текстуры или материала, определяющего внешний вид кривых.
Напомню, что динамические кривые были созданы с помощью операции Create Hair
с параметром Output=Paint Effects and NURBS Curves. А затем штрихи Paint Effects были просто
спрятаны в панели камеры.
Далее вся работа будет производиться с атрибутами ноды hairSystem. Поэтому сразу
выберите ее и не закрывайте Attribute Editor.
Волосы 1293
Следует выделить две группы атрибутов, одна из которых отвечает за форму системы
волос, а вторая за их цвет (прозрачность, блик и пр.). Первая группа атрибутов располагается в
разделе Clump and Hair Shape и задает количество волос для визуализации (но не для динамики!),
их толщину, гладкость и другие геометрические свойства. Вторая группа атрибутов находится в
разделе Shading и отвечает за цвет, прозрачность, блик и другие визуальные свойства.
Количество кривых в каждом пучке определяется атрибутом Hair Per Clump и по умолчанию
равно двадцати.
Совет. Когда волос становится очень уж много, MAYA с большим трудом начинает
«ворочать» их на экране. Чтобы показывать на экране только часть волос, у ноды
hairSystem есть атрибут Display Quality. Он задает в процентах, какую часть общей
массы волос отображать на экране. Используйте круглые значения, типа 10, 25,
50, чтобы адекватно представлять, что на экране находится только четверть
или половина всех волос.
Первое, что бросается в глаза, это «ломаность» штрихов Paint Effects. Ведь они не являются
сплайновыми кривыми, а просто представляют собой набор отрезков-сегментов. Поэтому, если вас
смущает угловатость кривых, установите атрибут Sub Segments в единицу. Это увеличит количество
сегментов вдвое, причем не только на экране, но и на финальной картинке.
Совет. Держите в уме общее количество сегментов для системы волос. Оно равно
общему количеству пучков (то есть числу динамических кривых), умноженному на
число волос в пучке, умноженному также на количество точек в каждой кривой и
дополнительно умноженному на количество подсегментов:
N = Num Curves * Hair Per Clump * (Num Points - 1) * (Sub Segments+1)
Это число определяет «тяжесть» системы волос, аналогично количеству граней для
Длина всех кривых в пучке по умолчанию одинакова, однако с помощью атрибута Thinning
можно задать укорачивание части волос в пучке, что дает эффект уменьшения густоты пучка по
мере удаления от основания.
Интуитивно понятно, что кривые в пучке растут «вокруг» центральной оси. В нашем случае
это как раз создает определенные проблемы, так как основания кривых располагаются на кромке
цилиндра.
Напомню, что все атрибуты типа графиков (Clump Width Scale, Hair Width Scale, Clump Curl,
Clump Flatness) дают распределение свойства вдоль длины волос. Слева находятся основания
кривых, справа - их концы. Поэтому вы можете задавать произвольное изменение толщины пучков
и самих волос вдоль их длины.
Волосы 1295
Остальные атрибуты легко исследуются по аналогии, «методом тыка». Например, для
создания химзавивки следует поколдовать с атрибутом Clump Curl. Следует также помнить об
установленной упругости кривых (Stiffness), которая тоже влияет на форму прически.
К этим атрибутам я еще вернусь, на более «персонажном» примере. А сейчас перейдем к
визуальным характеристикам волос.
Да, чуть не забыл про раздел Displacements! Если вы хотите поиздеваться над формой
волос с помощью всяких бигудей-завитушек (Curl) или просто хотите «помять» волосы (Noise) и
придать им малоухоженный вид, вам никак нельзя пропускать этот раздел. К счастью, атрибутов в
нем немного и разобраться с ними не так уж сложно. Обратите внимание: в отличие от атрибутов
из раздела Hair Shape and Clump, эти деформации воздействуют на индивидуальные кривые, а не
на пучки целиком.
Основной цвет волос задается атрибутом Hair Color. Для изменения основного цвета вдоль
длины волос используется атрибут Hair Color Scale, значение которого просто умножается на Hair
Color. Как правило, Hair Color Scale это черно-белый градиент, который определяет изменение
Для волос ничего подобного, по умолчанию, нет, однако у каждой динамической кривой
(определяющей пучок) есть индивидуальные атрибуты. Это прежде всего атрибуты Color Blend
и Color в разделе Render Overrides. Напомню, что добраться до индивидуальных свойств можно
через Hair=>Convert Selection=>to Follicles. Таким образом, у каждого пучка могут быть свои,
«персональные» свойства. Причем атрибут Color Blend определяет, насколько сильно используется
индивидуальный цвет пучка, то есть он определяет степень смешивания общего и индивидуального
цветов.
Волосы 1297
Так что если вы хотите создать отдельные прядки радикально иного цвета или мелировать
отдельные пучки, потребуется добраться до индивидуальных атрибутов отдельных динамических
кривых (которые содержатся в ноде типа follicle, описанной выше) и вручную задать им нужный
цвет и даже толщину. И еще - не забыть установить атрибут Color Blend в единицу.
Здесь хорошую услугу может оказать инструмент Paint Hair Tool. Достаточно выбрать
поверхность, на которой растут волосы, затем взять в руки Hair=>Paint Hair Tool. Затем установить
режим рисования Paint Mode=Edit Follicle Attributes, а в качестве атрибута выбрать Follicle
Attribute=Color Blend. В этом случае станет доступным поле Follicle Override Color, где можно
выбрать индивидуальный цвет волос.
Надо не забыть установить при этом значение Value=1 в параметрах Tool Settings самого
инструмента рисования.
Выберите систему волос hairSystem1 и задайте для нее атрибуты: Hair Per Clump=1, Clump
Width=0.
Этого достаточно, чтобы кисть стала последней выбранной кистью. Теперь можно выбрать
Select Tool, чтобы случайно ничего не нарисовать.
Проблема, однако, состоит в том, что растения растут как бы «из» кривых, а не вдоль
Волосы i 299
кривых. Кроме того, они весьма невелики и пытаются расти сразу в нескольких местах. Поправим
атрибуты кисти так, чтобы на каждую кривую приходилось по одному растению и чтобы каждое
растение росло вдоль кривой, то есть как бы повторяло ее форму.
Откройте раздел Tubes=>Creation и установите Tubes per Step=0; Tube Rand=0 и Start Tubes=1.
Это гарантирует, что из основания кривой будет расти ровно одно растение.
Чтобы удлинить стволы, задайте Length Min=Length Max=4. А чтобы подогнать общий размер
под длину кривых, используйте атрибут Global Scale=3.5.
Проделанные действия позволяют примерно подогнать под форму кривой любую кисть,
содержащую Tubes. Следует помнить, что все деформации (Displacements) или турбулентность будут
отталкивать растения от исходных кривых, поэтому всегда проверяйте значения соответствующих
атрибутов.
Для еще более точной подгонки под форму кривых можете использовать атрибут Segments
для кисти, ориентируясь на количество точек, из которых состоят исходные кривые.
Теперь растения полностью повторяют форму кривых и двигаются в соответствии с динамикой.
Ширина кисти (Brush Width) игнорируется и вместо нее используется толщина волос (Hair
Width).
Вместо цвета кисти (причем только вместо цвета основания Color1) используется цвет
волос Hair Color. Аналогично и остальные атрибуты из раздела Shading системы волос (Specular
Волосы 1301
Color и др.) заменяют соответствующие свойства кисти из раздела Illumination.
Как я уже упоминал, если вы хотите, чтобы вдоль каждой кривой произрастал только один
ствол (Tube), всегда ставьте Tubes per Step=0; Tube Rand=0 и Start Tubes=1.
И последнее: если вы вдруг захотите отрендерить кривые как бамбуковые палочки или
как макароны с помощью обычных штрихов Paint Effects (с выключенными Tubes), то не забывайте
про толщину (Hair Width), и кроме того вам наверняка придется увеличить атрибут RepeatU раз в
десять-двадцать, чтобы получить тот же вид, что и для оригинальной кисти.
Создание волос
Первый этап - создание волос. Назовем это созданием, чтобы не путать его со следующим
этапом: моделированием и причесыванием. Дело в том, что главный способ создания волос (во
всяком случае, он по списку первый в меню) предполагает создание волос одним махом, как
некое засеивание поверхности растительностью. Возникающую шапку волос надо будет причесать
и уложить на следующем этапе. Процесс укладки - дело архи-непростое, поэтому старайтесь
сразу создавать волосы так, чтобы они максимально напоминали по форме ту прическу, к которой
вы стремитесь. Для этого существует некоторое количество альтернативных способов создания
Еще один, довольно экзотичный способ заключается в испускании частиц с нужной области
поверхности. Затем с помощью полей и expressions траектории частиц настраиваются так, чтобы
они напоминали форму будущих волос. С помощью небольшого скрипта траектории нужного
количества частиц превращаются в кривые. При необходимости они могут быть дополнены
дополнительными пассивными кривыми. Некоторое количество таких скриптов можно найти на
сайте www.highend3.com. Мне встречалась одна статья в Интернете об использовании динамики
движения жидкости для придания формы волосам. С помощью такого подхода можно использовать
динамику флюидов для задания движения частиц, а траектории последних использовать как ворму
волос. Понимаю: звучит несколько патологически... Но следует помнить: волосы - объект тоже не
совсем нормальный.
Волосы 1303
Если попытаться создать систему волос на поверхности с помощью операции Create Hair,
то придется долго избавляться от ненужных волос в различных участках головы. Поэтому куда
логичнее и проще использовать Paint Hair Tool.
Количество точек на кривых равно всего шести, но мы можем изменить его позже.
Покрасьте поверхность в тех местах, где, по вашему мнению, могут произрастать волосы.
Пользуйтесь активно Undo, а также для удаления ненужных кривых переключайтесь в режим
удаления Paint Mode=Delete Follicles, чтобы избавиться от конкретных ненужных кривых.
Сейчас очень важно задать поверхность для взаимодействия с кривыми: очевидно, волосы
не должны проникать в голову. Если попытаться сделать это позже, то, возможно, некоторые
кривые уже таки проникнут в поверхность - в результате безумных экспериментов с динамикой
и борьбы за прическу. Они, эти кривые, будут, конечно же, застревать в поверхности и начнут
всячески портить вам нервы. Поэтому создадим поверхность для отталкивания кривых прямо
сейчас.
Как я уже упоминал выше, крайне эффективным с точки зрения просчета динамики -
будет использование констрейна типа Collide Sphere в качестве отталкивающей поверхности.
Волосы i 305
Это создаст сферу для столкновений - для всех кривых.
Задайте размеры сферы (scale = 5.67; 5.0; 6.5) и ее положение (translate = 0.01; 8.2; 2.75).
К точной настройке размеров мы вернемся позже, а сейчас сохраните сцену (headModeHairCre-
ated.ma).
Можно считать этап создания волос законченным, теперь можно переходить к обсуждению
прически.
А вот процесс укладки и создания причесок - это пока что довольно слабое место у MAYA
Hair. Существует некоторое количество методик и приемов, но все они скорее напоминают трюки
и ухищрения - они имеют мало общего с привычными инструментами парикмахера. Но если уж с
помощью Paint Effects было создано немало причесок, то все же с нынешним инструментарием
жизнь стала еще лучше.
В-третьих, создавая различные поля - типа Radial или Uniform, можно пытаться привести
волосы в нужное положение с их помощью. Такой подход годится для локальных эффектов, но
вряд ли подходит для общей формы прически.
Встаньте в первый кадр и выберите сначала объект hairSystem1, а затем концы всех
стартовых кривых: Hair=>Convert Selection=>to Start Curves End CVs. Возьмите в руки Move Tool,
затем нажмите и удерживайте клавишу «I» для фиксации длины кривых.
Примечание. Функция Undo просто не работает при фиксации длины кривых. Так
что будьте уверены в своих действиях, не допускайте дрожания рук и всегда
сохраняйте сцену перед редактированием кривых с фиксацией длины.
Возьмите Scale Tool, затем снова нажмите «I» и сожмите одним (!) уверенным движением
концы к центру.
Волосы i 307
Первое, что бросается в глаза: у кривых довольно мало сегментов и оттого они выглядят
излишне упругими и жесткими.
В Channel Box установите для всех выбранных кривых Start Direction=Start Curve Base, чтобы
основания волос повторяли форму стартовых кривых, а не торчали по нормали к поверхности.
Теперь волосы довольно безвольно падают вниз и повисают, как веревки. Им немного не хватает
формы и упругости. Для придания некоторой воздушности и наполненности воспользуемся
остаточными кривыми (Rest Curves). Это достаточно стандартный и действенный трюк для
удержания волос в определенной форме. Напомню, что остаточные кривые определяют положение
и форму, к которой стремятся волосы при отсутствии сильных воздействий и динамических полей.
Первый трюк состоит в том, чтобы определить остаточные кривые идентичными стартовым кривым
в данный момент. Сделаем это и посмотрим, как это можно использовать.
Если все кривые до сих пор выбраны (если нет, используйте, как обычно, Hair=>Convert
Selection=>to Follicles), выполните операцию Hair=>Set Rest Position=>From Start.
Запустите анимацию сначала при этом особых отличий в падении волос не видно.
Напомню, что степень стремления волос к остаточным кривым определяется их упругостью.
Поэтому выберите hairSystem1 и поиграйте с атрибутом Stiffness прямо во время анимации.
При значениях Stiffness около 0.3, волосы немного приподнимаются и приобретают
некоторую форму.
Дальнейшее улучшение формы может быть достигнуто за счет изменения атрибута Stiffness
Scale, определяющего распределение упругости вдоль длины волос. Вы можете слегка уменьшить
упругость около оснований и увеличить ее на концах.
Пытливые умы наверняка заметят небольшой «всплеск» (или «толчок») в районе оснований
волос в начале анимации. Это может быть связано с размером сферы для столкновений (Collide
Sphere), точнее с тем, что в первом кадре некоторые основания кривых попали внутрь сферы и
стремительно выталкиваются наружу. В данном случае это не очень большая проблема, так как
волосы все равно занимают нужную позицию. Однако в случае необходимости избавиться от такого
толчка можно проделать следующие действия. В первом кадре надо немного сжать сферу так,
чтобы основания кривых не попадали внутрь нее и поставить ключ на размер (Scale) сферы. Затем
запустить интерактивную анимацию (Solvers=>lnteractive Playback) и прямо во время проигрывания
увеличить сферу до прежних (или до нужных) размеров. После этого можно остановить анимацию
и снова поставить ключ на Scale сферы.
Волосы -J3Q9
Примечание. Вы можете управлять трением кривых о сферу через атрибут Fric
tion. Установите его в единицу, если вам кажется, что волосы скользят по сфере
слишком быстро.
Можно обойтись и без ключей и просто сохранить текущее положение кривых в качестве
начального, чтобы анимация начиналась с уже упавшими на свое место волосами. Именно это мы
сейчас и сделаем.
Теперь начальное состояние волос нас полностью устраивает, однако при проигрывании
анимации волосы ведут себя просто возмутительно. Казалось бы, они должны остаться около
начального положения, так как мы зафиксировали их в этом положении, когда кривые находились
в относительном покое. Вместо этого они инфантильно свисают как ..., ну, скажем, как спагетти,
и никакие усилия по увеличению упругости не могут привести их в чувство.
Все дело в коварном атрибуте Sample Density, значение которого равно трем. Как только
мы сохранили текущее положение как начальное, все стартовые кривые унаследовали количество
точек с текущего положения. Соответственно, количество точек на стартовых кривых утроилось,
однако значение Sample Density для всех кривых по-прежнему осталось равным трем, поэтому
количество точек на самих волосах еще раз утроилось. Нужно лишь не забыть немедленно вернуть
Sample Density в единицу после определения нового стартового положения кривых.
Если вас смущает ширина прически (височные области), выберите сферу hairConstraintl и
уменьшите ее размер вдоль оси X (scaleX=5.2).
Поэтому второй способ состоит в увеличении количества волос при помощи пассивных
кривых (Passive Curves). Такими кривыми можно дополнительно «засеять» поверхность между уже
существующими динамическими кривыми. Основная особенность пассивных кривых - в том, что их
не надо анимировать динамикой: они лишь повторяют форму соседних, динамических (активных)
кривых. Их главное преимущество - что их форму не надо моделировать: она автоматически
получается, за счет усреднения формы соседних кривых. Второе преимущество: на просчет их
формы не надо тратить дополнительное время. Их можно отдаленно сравнить с промежуточными
формами blendShape между соседними активными кривыми.
Итак, до сих пор мы имели дело с активными кривыми, а сейчас увеличим густоту волос,
пересаживая на голову пассивные кривые.
Выберите поверхность и возьмите в руки Hair=>Paint Hair Tool. В качестве режима рисования
выберите заполнение пассивными кривыми: Paint Mode=Create Passive Follicles.
Задайте плотность заполнения в два раза больше, чем при предыдущем рисовании, то есть Follicle
Волосы 1311
Density U=80, Follicle Density V=40.
Прежде чем приступить к рендерингу создайте два источника света: основной, direc-
tionaLight (rotate=-10; 10; 0; lntencity=1.4), и заполняющий, pointLight (translate=15; 5; 5; Intenc-
ity=0.5).
Первое, что бросается в глаза «ломанность» волос. Для визуализации нет необходимости
увеличивать количество точек на самих кривых, достаточно задать нужное количество подразбиений
для рендеринга.
Я обычно использую следующий трюк, чтобы не прятать волосы (штрихи Paint Effects) с
экрана совсем, через Show=>Strokes: я выбираю объект hairSystem и устанавливаю атрибут Display
Quality в очень маленькое значение от единицы до пяти. Это позволяет видеть общую форму
прически и в то же время не тормозит интерактивное отображение.
Просчитайте картинку.
Волосы пока редковаты. Понятно, что у нас в запасе есть убийственный атрибут Clump Per
Hair, но поговорим прежде о методах честного обмана и кажущегося увеличения плотности волос
без особых вычислительных затрат.
Во-первых, обычно не хватает визуальной густоты около оснований волос, хотя общая масса
выглядит довольно пристойно. Эту проблему можно решить соответствующим текстурированием
той части поверхности, на которой растут волосы. Например, вы может отрендерить только
волосы (без поверхности) в виде сверху, а потом наложить (как проекцию) это изображение на
поверхность (на один из слоев канала цвета), чтобы закрасить волосистую часть поверхности
текстурой, максимально похожей на сами волосы.
Во-вторых, можно увеличить густоту волос только на граничных областях, там, где сквозь
них просвечивает поверхность. Сейчас мы этим и займемся.
Выберите поверхность и возьмите Hair=>Paint Hair Tool.
Последний использованный режим должен быть Paint Mode=Create Passive Follicles.
Увеличьте плотность заполнения по V: Follicle Density V=80, затем уменьшите радиус кисти
и прокрасьте только переднюю границу волосяного покрова над лбом, затрагивая только два
первых ряда.
Теперь можно уменьшить ширину пучков для задания большей густоты: Clump
Волосы 1313
Width=0.25.
Чтобы волосы выглядели не таким грубыми, уменьшим их толщину: Hair Width = 0.005.
После этого надо обязательно увеличить качество антиалайзинга, так как при работе с такими
тонкими объектами неизбежно появление артефактов.
В закладке Maya Software в самом низу откройте раздел Paint Effects Rendering Options и
включите опции Oversample и Oversample Post Filter.
Если вас смущают супертонкие концы волос, вы можете отредактировать их форму через
атрибут Hair Width Scale и сделать их потолще.
Немного поработаем над цветом и бликом. В разделе Shading атрибут Hair Color Scale no
умолчанию задает потемнение цвета ближе к основанию волос, имитируя самозатенение и эффект
выгоревших волос ближе к концам.
Установите его полностью белым, чтобы цвет волос не изменялся вдоль длины, а тени мы
настроим в следующем разделе.
Увеличьте Specular Color примерно до половины и задайте «жесткий» блик Specular Power=10.
Просчитайте картинку.
Так как штрихи Paint Effects не являются поверхностями, то метод Use Mid Dist Dmap для
них не работает, и эту опцию необходимо выключить (Use Mid Dist Dmap=Off).
Кроме того, волосы довольно тонкие объекты, для них требуется довольно высокое
разрешение карт теней.
О ужас! Все покрылось не то сажей, не то мраком. А дело в том, что при выключенной
опции Use Mid Dist Dmap надо вручную настроить «отступ» начала тени от объекта, иначе тень от
поверхности будет видна на самой поверхности, как это и видно на иллюстрации.
Волосы 1315
Просчитайте изображение.
Глобальное удлинение
Предположим, что вам резко захотелось удлинить всю прическу целиком. Например, чтобы
посмотреть, как она выглядит с новоиспеченным шейдингом и освешением. Приведу пример
одного из возможных путей сделать это. Так как заниматься покраской поверхности с помощью
Paint Hair Tool в режиме Paint Mode=Extend Hairs совсем не хочется, попробуем удлинить напрямую
стартовые кривые с помощью стандартных средств сплайнового моделирования.
Нажмите Extend.
Сохраните это положение как начальное. Можете немного потрясти головой (нет не своей,
a Original_Head), поставив несколько ключей на повороты поверхности.
Просчитайте изображение.
Если вас смущают горизонтальная граница тени на концах волос, вам необходимо еще
немного настроить атрибуты тени у источника света.
Выберите источник света directionalLight1 и снимите опцию Dmap Auto Focus, и задайте
значение атрибута Dmap Width Focus=35, чтобы вручную задать область пространства, в которой
генерится карта теней.
Волосы 1317
Концы волос имеет смысл немного «проредить», а то они обрываются резко и в точности
повторяют форму пучков. Это можно сделать увеличив до 0.5 значение атрибута Thinning для
системы волос hairSystem1. Можете убрать также шум (Noise=0) и посмотреть, что получится.
Просчитайте изображение.
Когда кривых слишком много, имеет смысл не использовать NURBS Curves в качестве
представления волос. Применяйте Output=Paint Effects, задавайте Hair Per Clump=1 и Clump Width=0
для визуального контроля. Не забывайте про Display Quality. Штрихи Paint Effects отрисовываются
на экране в разы быстрее, чем кривые.
Самые «тяжелые» параметры - это Hair Per Clump и Sub Segments, поэтому старайтесь
держать их минимальными, добиваясь густоты другими методами.
Толщину пучков нужно, очевидно, подбирать, исходя из расстояния между пучками, потому
что если сделать ее слишком большой, возникнут проблемы на границе волосяного покрова, около
оснований волос (когда граница видна в кадре).
Толщина самих волос кардинально меняет восприятие объема и фактуры волос. Подбирайте
ее с осторожностью, особенно когда пытаетесь искусственно заполнить объем.
Не забывайте про атрибут Thinning. Он придает концам совершенно шикарный вид, если
только вы не делаете стрижку типа «каре».
Заплетание косичек
Если вы уже начали моделировать мощную косичку с помощью трех сплайновых кривых,
погодите немного. Возможность создания косичек встроена в систему волос изначально, причем,
как это полагается, в виде одной кнопки, точнее галки.
Любой пучок волос (Clump) можно превратить в косичку. Соответственно, должен быть
атрибут, отвечающий за такое превращение. Причем атрибут должен принадлежать не всей
системе волос, а быть индивидуальным, то есть задаваться отдельно для каждого пучка (folli
cle).
Волосы 1319
Если сцена с длинными волосами еще открыта, проделайте следующие действия, чтобы
заплести все пучки волос в косички.
При желании, с помощью Clump Width Scale, можно сделать толщину (профиль) косички
резко сужающейся в начале и плавно убывающей в остальной части.
Ширину самих волос можно сделать побольше: Hair Width=0.02, для «уплотнения косичек.
Задайте Thining=0.
Если хотите, можно немного растрепать прическу, чтобы лучше увидеть косички.
Выберите hairSystem1, затем создайте радиальное поле: Fields=>Radial и проиграйте
буквально несколько кадров.
Это уберет с экрана все пассивные пучки. Оставшиеся активные, нужно сделать гуще и толще.
Задайте Hair Per Clump=300; Clump Width=0.7.
Чтобы разворачивать косички вокруг своей продольной оси, можно использовать атрибут
Clump Twist.
Если вы хотите заплести одну огромную косу, для нее имеет смысл создать отдельную
вспомогательную систему волос. Основная система волос должна отвечать за покрытие головы
волосами, концы которых должны заканчиваться у основания косички. Вспомогательная система,
ответственная за саму косу, может состоять только из одного пучка/кривой с очень широким
основанием, что настраивается при помощи Clump Width Scale. Многие атрибуты этих систем
должны совпадать для общего внешнего вида.
Первая возможность стандартна. Коль скоро волосы представлены штрихами Paint Effects,
их можно сконвертировать в полигональные трубки и делать с ними все, что душе угодно. Правда,
вопрос о размере сцены остается более чем открытым, так вся геометрия будет сохраняться не в
виде описания и набора параметров, а в явном виде.
Волосы 1321
объект сцены. Чтобы получить удовлетворительный результат, вам надо сразу выставить довольно
высокое качество антиалиазинга в Render Globals, так как волосы - довольно капризный объект,
состоящий из мелких деталей.
При использовании такого материала вся геометрия волос генерится «на лету», только в
процессе рендеринга и не сохраняется в сцене. Правда, это не сильно уменьшает расход памяти,
что, возможно, является особенностью конкретной реализации геометрического материала для
волос.
Работа с кэшированием
Прежде чем закончить с проблемами визуализации, я хотел бы отметить, что перед
рендерингом волосы, как правило, необходимо кэшировать, то есть сохранить их траектории на
диске в специальном файле. Если вас устраивает движение волос и вы хотите, чтобы они двигались
каждый раз именно так, имеет смысл их скэшировать, а не пересчитывать их движение каждый
раз заново. В отличие от твердых тел, траектории волос нельзя «перевести в ключи», поэтому
использование кэширования - единственная альтернатива повторному просчету. Кроме то, вряд
ли у вас получится достойным образом отрендерить волосы с первого раза. Поэтому проще делать
очередные попытки визуализации с уже просчитанными заранее кривыми (если поведение и
траектории волос вас полностью устраивают). Также совершенно очевидно, что motion blur не будет
корректно работать с траекториями кривых, вычисляемыми прямо в процессе рендеринга. В общем
случае, динамика «не знает», что будет в следующем кадре, пока не доберется до него, поэтому
для работы с motion blur всегда необходимо производить предварительное кэширование.
Операции для работы с кэш-файлами для волос абсолютно стандартны и включают в себя
создание, удаление, добавление и отрезание кэш-файлов. Эти операции описаны в главах про
частицы и флюиды, а так как идеологически кэш-файлы для волос ничем {кроме содержимого)
не отличаются от таких же файлов для частиц, нет смысла тратить место и время на описание
полностью аналогичных операций.
Что это может дать? Прежде всего, это широкие возможности по автоматической анимации
формы кривых. Если раньше, для создания эффекта упругой конструкции, типа антенны,
необходимо было превратить кривую в новое мягкое тело, потом назначить оригинальную кривую
в качестве goal-объекта для частиц это мягкого тела и затем назначить для каждой частицы нужный
вес, то теперь сделать упругую кривую можно при помощи всего одной операции: Hair=>Make Se
lected Curve Dynamic.
Коль скоро любой набор кривых может быть превращен в, назовем их так, «динамические
веревки», то благодаря Construction History, возникает масса возможных использований анимации
Я выделю особо лишь три из них (это не означает, что остальные применения не заслуживают
внимания):
Кроме того, динамические кривые могут выступать в качестве аттракторов для меха,
обеспечивая динамическую анимацию меховых покровов.
Разрезание веревки
Попробуем превратить сплайновый объект в динамическую кривую, а затем разрезать его
пополам.
Волосы 1323
На экране появится дополнительные объекты. Это и есть динамические кривые. Исходные
части полуокружности являются для них стартовыми кривыми.
В сцене появится иконка новой системы волос hairSystem1, а также ноды follicle1 и fol-
Ucle2, отвечающие за индивидуальные свойства динамических кривых.
Концы немного провиснут, но все же - так как кривые имеют ощутимую упругость - останутся
Проиграйте анимацию.
Далее я хотел бы описать некоторые трюки при работе с волосами, которые не относятся к
стандартным способам создания и редактирования волос. Редкий трюк обходится без использования
Волосы 1325
скриптов, поэтому начнем с тех, что попроще. С наследования цвета волос с текстурной карты.
Дальнейшее изложение будет рассчитано на довольно взрослых мальчиков, а к остальным просьба:
не нервничать.
Попробуем сделать это же и для волос. Как уже было описано выше, у каждого пучка волос
(или динамической кривой, follicle) есть атрибуты Color Blend и Color. Напомню, что добраться
до индивидуальных свойств можно через Hair=>Convert Selection=>to Follicies. Атрибут Color
Blend определяет, насколько сильно используется индивидуальный цвет пучка, то есть степень
смешивания общего и индивидуального цветов.
Как догадались взрослые мальчики, речь идет о небольшом скрипте, поэтому страдающим
аллергией на скрипты читателям настоятельно рекомендуется срочно перейти к следующему
разделу.
Задача состоит в том, чтобы назначить тот же самый цвет и на волосы, растущие на сфере.
Волосы 1327
волосины внутри пучков в цвет текстуры, понадобится полторы страницы книги и немного времени,
поэтому я оставлю это за рамками изложения.
Измените зеленый цвет текстуры ramp1 на белый, а синий и красный - на черный. Задайте
lnterpolation=None.
string $it;
// цикл по всем кривым
for ($it in $list) {
// получение UV координат основания кривой
float $u = 'getAttr ($it+".parameterU")';
float $v = 'getAttr ($it+".parameterV")';
// запрос цвета в точке с такими коодинатами на текстуре rampl
float $col[] = 'colorAtPoint -о RGB -u $u -v $v ramp1';
// удаление кривой, если цвет (красный) меньше 0.9
if($col[0]<0.9) delete ('listConnections -t "nurbsCurve" $ i t ' ) $it;
}
Вместо наследования цвета, кривые просто удаляются, если цвет текстуры около их
основания меньше, чем 0.9 (в черном-белом варианте достаточно сравнивать красный канал
цвета).
Волосы 1329
Замечу, что приведенные скрипты будут работать и в том случае, если выбраны отдельные
кривые, а не только система волос целиком.
Кроме того, на основе считанной с текстуры информации можно не только удалять или
красить кривые, но и редактировать другие их свойства.
Аэродинамическая история
Я имею привычку не отмечать Новый год в Москве. Отсутствие снега, солнца, звезд и
других природных явлений делают этот город, по крайней мере зимой, малопригодным не только
для отмечания таких, сезонных праздников, но и для нормальной жизни вообще. Однажды меня
занесло в конце года в Молдавию, в гости к друзьям-музыкантам. Впрочем, история эта касается
не новогодних игрищ, а весьма экзотического возвращения на родину.
Надо сказать, что молдавская зима в том году выдалась необычно лютая. Обнаружив на
градуснике минус двадцать, я решил выехать в аэропорт пораньше. Это была ошибка. Добравшись
до здания аэровокзала, представлявшего собой стеклянную коробку типового проекта, я обнаружил,
что температура снаружи и внутри отличается на два, ну, максимум, на три градуса, все же,
очевидно, подогретая дыханием пассажиров, ожидавших своей участи. Участь, как выяснилось,
не сильно завидная.
Подъехал все тот же, заиндевевший автобус, и мы, растирая руки и лица, вывалились из
мертвой железной птицы и вскоре покатили в здание аэропорта. Там мы, как взрослые, снова
прошли паспортный контроль, затем таможню, все-таки граница, как-никак, и опять попали в
звенящее от мороза, знакомое нам стеклянное здание. Сплотившись к тому времени в единую
пассажирскую общность, мы бодро стучали в пластиковое окошко офиса авиакомпании с
предложениями немедленно посадить нас на другой самолет. Возникающий из ниоткуда коньяк
практически не помогал от холода и действовал скорее как утолитель жажды и средство стимуляции
жизнедеятельности организма.
Волосы 1331
А дальше, всего минут через десять, в салоне появился довольно бодрый представитель
авиакомпании, вежливо и доходчиво объяснивший, что компания приносит свои чудовищные
извинения за причиненные неудобства и готова немедленно выплатить всем полную стоимость
билетов прямо в здании аэропорта. Поначалу мы все аж подпрыгнули от радости - от того, что
заводить этого монстра никто больше не будет и что даже деньги нам вернут без потерь. Наиболее
промерзшие даже потянулись к выходу, навстречу морозному вечеру. Однако я, быстро проведя
перебор вариантов, оценил всю безысходность ситуации и буквально завопил на весь салон:
«Господа! Немедленно вернитесь на свои места!». Не знаю, в каком кино я насмотрелся сцен про
стихийные митинги среди мирного, но возмущенного населения, но дальше я пламенно верещал
хорошо поставленным, пусть вконец охрипшим голосом про то, что если мы выйдем отсюда и
получим деньги, никому до нас дела больше не будет. Про то, что следующий рейс на Москву
только через три дня, а где зимовать эти три дня, неизвестно. Про то, что билетов на самолет
через три дня может и не быть. Про то, что нас хотят очень ловко выставить на улицу, всучив нам
наши же деньги и оставив замерзать в ледяном аэропорту. (Про то, что у меня через сутки самолет
в Италию, я почему-то промолчал.) Завершил свою возмущенную речь я призывом немедленно
сесть на свои места и сидеть до полного заиндевения, пока нас не отправят в Москву любым
способом (кроме реанимации АН-24). Напоследок пригрозил представителю компании написать
огромную статью в газету, сотрудником которой я являюсь (это уже был чистой воды кураж, что
правда, то правда).
Невероятно, но в конце этого, эпохального пути нас ожидал хорошо прогретый, исправно
работающий, а главное - совершенно не глохнущий ТУ-134. Мы ввалились в него, как геологи в
баню, и попадали в свободные кресла. Присутствовавшие в салоне пассажиры с опаской смотрели
на наши помороженные, изборожденные духом мятежа лица и жались поближе друг к другу. Но у
нас хватило сил только на то, чтобы поднять тост «За Победу!» и рухнуть лицом в откидывающиеся
столики.
Кроме того, читая практические советы четырехлетней давности для тех, кто хочет считать
красивые картинки, я обнаружил, что каждый второй их них безнадежно устарел, в силу того,
что появились новые технологии, понятия и трюки, а также потому, что мощность компьютеров
стремительно выросла. Все, что относится к практической части рендеринга, стремительно
устаревает, порой в течение одного года, поэтому здесь очень сложно давать актуальные советы.
Конечно, базовые принципы, основанные на здравом смысле, не меняются и не надо назначать
огромные текстуры на объект, находящийся у горизонта или считать тени в каждом кадре для
статических объектов.
Рендеринг-движки
Не секрет, что встроенный майский рендерер не снискал всеобщей народной любви.
Эта рабочая лошадка была хороша для своего времени, однако потом ее успешно обошли более
резвые и интеллектуальные конкуренты. Проблемы с антиалиазингом, относительно невысокая
скорость, ограниченный рейтрейсинг сделали майский рендерер аутсайдером. Тем более, что
к MAYA за последние годы были «прикручены» все современные рендеринг-движки. Перечислю
лишь некоторые из них.
Обнаружив, что родной майский рендерер безнадежно устаревает, компания Alias сумела
исхитриться и заключила стратегическое соглашение с компанией Mental Images - о встраивании
программы mental ray непосредственно в MAYA. Конечно, это не прошло гладко, и крики о помощи
пользователей пятой версии MAYA до сих пор стоят в ушах службы технической поддержки.
Однако со временем интеграция mental ray и MAYA стала более гладкой, и теперь mental ray даже
рассматривается как основное решения для рендеринга в MAYA. Официально он называется men
tal ray for maya и иногда пишется как mrfm. Он выполнен в виде самостоятельного плагина и
не является надстройкой над независимым продуктом mental ray standalone, представляющим
собой рендерер из командной строки. Это разные программы с разными возможностями. Для
пытливых умов, наслышанных, что в пакете XSI тоже используется mental ray добавлю, что майская
реализация mental ray несколько отличается от «ксишной», на уровне ядра, и не является с ней
совместимой. Совсем взрослые мальчики, как правило, используют встроенный mental ray for
maya для генерации .mi-файлов, которые затем отправляют на вход для mental ray standalone.
Здесь я отсылаю всех интересующихся на сайт Павла Ледина (http://puppet.cgtalk.ru/), где вы
можете найти соответствующие скрипты и упражнения для адекватного использования mental ray
standalone совместно с MAYA.
В 2005 году компания Pixar выпустила гениальный продукт под названием Renderman for
Maya, или, сокращенно, RfM. Оформленный в виде плагина, он позволяет пользователям MAYA
нажать привычную кнопку Render и просчитать изображение с помощью движка Renderman. Вся
конвертация сцены, майских материалов, текстур, источников света происходит незаметно для
пользователя. Гениальность этого продукта заключается в его простой и понятной интеграции в
MAYA. Как правило, у конечного пользователя не возникает особых вопросов по использованию этого
решения. Однако за простоту надо платить, и поэтому некоторые традиционно сильные технологии
от Pixar не поддерживаются в этом продукте. Среди них генерация rib-файлов и использование
собственных dso-библиотек. Если вы хотите использовать всю техническую мощь Renderman, то
вам следует обратить внимание на пакет Renderman Artist Tools, описанный Алексеем Пузиковым
в соответствующей главе этой книги
И что же дальше?
Сделав пятиминутный перекур после двухлетней работы по написанию книги и хладнокровно
поразмыслив, я пришел к выводу, что глава, посвященная рендерингу в MAYA либо перерастает в
двухтомный труд «Понимая Рендеринг», либо не имеет смысла вообще, так как устареет, еще до
выхода книги. Немного обосную эти положения.
Если взять хотя бы тему освещения (как локального, так и глобального), то объем
материала, касающегося этой темы, не поместится не то что в главу, а в небольшую книгу. Или
чего стоит один только вопрос просчета теней? Модное глобальное освещение и способы борьбы
с его последствиями в анимации, тоже тянут на отдельное научное исследование. HDRI и IBL,
ambient occlusion и subsurface scattering, Final Gathering и Color Bleeding. Эти новые понятия,
появившиеся в последние годы, только проходят «обкатку» в области «большой анимации» и
«кинопроизводства».
Если говорить о войне рендереров, то есть конкретных решениях для рендеринга в MAYA,
то будущее весьма непредсказуемо.
Интеграция MAYA и mental ray без сомнения будет подвергнута переработке в следующих
версиях MAYA, ибо в данном виде (на момент седьмой версии), она не представляется, скажем
так, удобной и изящной. Следует ожидать упрощения и «дружественнофикации» как самого
интерфейса, так и документации к нему. Кроме того, изменения в следующих версиях mental
ray обязательно наложат отпечаток на способ интеграции его с MAYA. Это делает бессмысленным
описание текущей версии.
Мои личные симпатии на стороне Renderman for Maya, поскольку этот продукт - образец
продуманности и дружественной интеграции в MAYA. Сразу оговорюсь, что это продукт
предназначен прежде всего для конечных пользователей. Он легок в освоении, снабжен
компактной документацией и идеально подходит для начального освоения основ рендеринга.
Его рыночная судьба пока не определена, поэтому описывать его в книжке мне представляется
преждевременным.
А вот что гарантированно не устареет и не потеряет актуальности, так это информация про
основы рендеринга и стандарт Renderman, описанная Алексеем Пузиковым в соответствующей
главе. Всем, кто намерен связать хотя бы часть свой трудовой деятельности с рендерингом, я
советую перечитать эту главу пару раз.
Рендеринг 1335
1336 Книга Сергея Цыпцына
Renderman
Сношения с внешними рендерерами
или присовокупление к Renderman'y
Сколько я себя помню - всегда хотел написать книжку. В детстве казалось: человек,
который читает много книг, просто обязан уметь их писать. Это занятие я считал настолько легким
и непринуждеенным, что от собственно написания книги меня всегда отделяла какая-то малость
- домашнее задание в школе, например. Так что графоманом я был неправильным - книжек не
писал и не пытался, только думал: вот, когда-нибудь, вот было бы здорово...
Для тех, кому стало неинтересно читать эту главу уже сейчас, после первого абзаца,
сообщаю - продолжение разговора про Maya будет уже скоро, всего через полсотни страниц.
А для всех, кто остался с нами - после небольшой паузы, пока наиболее нетерпеливые
читатели листают страницы в поисках другой главы - лишь скажу: меня зовут Алексей Пузиков, и
моя мечта сбылась! Частично сбылась, конечно - ведь пишу я не целую книгу, а только эту главу.
Поговорим мы в ней только о внешних рендерерах, их связи с MAYA и о Renderman'e.
Так что же пропустят наши неугомонные друзья, кто уже ускакал отсюда на просторы
какой-нибудь другой главы? А вот что:
Правда, придется - раз уж мы так весело начали и замахнулись на такой объем информации
- поступить с читателем честно, указав также, чего вы в этой главе не найдете. А не найдете вы в ней
подробных учебников, упражнений и уроков, справочных руководств и перевода спецификаций.
Мир внешних рендереров необъятен, да что там говорить - про один Renderman можно (и нужно!)
написать не одну толстенную книжку - а у нас с вами в распоряжении всего лишь небольшая глава.
Так что ограничимся, для знакомства, неким набором ключевых моментов, опираясь на которые
вы сможете самостоятельно продолжить изучение этого нового мира и выйти на качественно
новый уровень в своей работе.
Зачем?
Почему же вообще возникла необходимость использовать внешние движки визуализации
в MAYA? Возьму на себя смелость высказать основную мысль этой главы уже на ее второй
странице, не углубляясь в дебри объяснений и дискуссий: стандартный MAYASoftware Renderer
попросту непригоден для использования в сколько-нибудь серьезном проекте, а в особенности - в
кинопроекте. Ох, не могу поверить, что я это мог сказать... И нет, еще хуже: что я написал это в
книжке про MAYA. Посмотрите кто-нибудь в окно - там, ненароком, небо в Дунай не упало?
Сказав А, скажем и Б: что, впрочем, рендерить чайники с помощью майского рендерера все
жеможно, но только если их не очень много.
Теперь, когда разгоряченные толпы поклонников MAYA уже занялись моими поисками,
попробуем понять, что же стало причиной такого провала в функциональности, в общем-то, весьма
высококачественного и продуманного продукта. Для начала, обратимся к первоисточникам, а
именно к документу под названием Design and Implementation of the MAYA Renderer , в котором
описываются основные идеи, положенные в основу MAYA Software Renderer. В качестве опорных
Анимация 1339
концепций, ставших краеугольными камнями дизайна этого рендерера, выделены следующие
вещи:
1. Стандартный рендерер MAYA должен быть лучше, чем его предшественники - рендереры
от TDI, Alias и Wavefront. В то же время, на начальных стадиях разработки нового рендерера
вместо него использовалось проверенное старое решение - Alias Renderer - которое затем, по мере
разработки, заменялось готовыми частями нового рендерера.
Следует отметить, что разработчики MAYA приложили уйму усилий для того, чтобы
максимально улучшить свой рендерер и хоть как-то адаптировать его для условий реального
производства . Однако возникает такое впечатление, что успех Bingo и других анимационных
проектов, сделанных исключительно при помощи встроенного движка, настолько повлиял на
умы программистов в Alias, что вместо того, чтобы действительно заняться оптимизацией своего
детища, они пошли на поводу у собственного менеджмента и начали вводить в него новые
возможности (впрочем, они поступили даже еще хуже: начали писать новые рендереры). Таким
образом, в MAYA появились PaintFX Tenderer, vector renderer, volume renderer и другие, не скрою,
приятные расширения стандартного рендерера - но это вовсе не исправило ситуации с основным
движком, а лишь привело к тому, что (автор пригнулся и прикрыл голову руками...) им просто
перестали пользоваться для сколько-нибудь серьезных задач. В конце концов, это увидели и
сами создатели MAYA, но они смирились со своим поражением, встроив в программу в качестве
стандартной опции mental ray. У них это получилось не так ловко, как у разработчиков из Softimage
- что не удивительно, если вспомнить, сколько лет mental ray поставляется в качестве рендерера
для Softimage и XSI. Однако, тем не менее, уже сейчас в стандартной поставке MAYA вы имеете
хороший и стабильный рендерер.
Так или иначе, интерфейс к внешним рендерерам в MAYA был всегда - собственно, было
бы очень удивительно, если бы в продукте с такой продуманной архитектурой его не было. Другой
вопрос - что из себя этот интерфейс представляет.
Так вот, хотя интерфейс внутренний отличался гибкостью и был направлен на реальные
запросы студий, позволяя встроить функциональность вызова внешнего рендерера в MAYA,
интерфейс визуальный, до недавнего времени, не мог уверенно взять установленную планку.
Пользователь, несомненно, мог написать свой плагин, встроить его в MAYA, создать для него окно
настроек с помошью MEL, даже встроиться в главное меню программы - но до пятой версии MAYA ему
не давали возможности встроиться в святая святых рендеринга: окно Render Globals. Запрашивать
значения переменных из этого окна было можно, а встроиться в него - нельзя. (Специально для
любителей теорий видеть во всем тайный сговор упомяну маленькую деталь: эту досадную мелочь
в MAYA исправили только одновременно со встраиванием mental ray...)
Мы познакомимся с ней подробнее чуть позже, а пока всего лишь отметим, что подавляющее
большинство рендереров запускаются именно из командной строки.
Таким образом, для того, чтобы заставить внешний движок просчитать картинку, вы должны
произвести некоторые действия. Приведем некий усредненный алгоритм потребной работы:
1. Во-первых, ваш экспортер, то есть тот плагин, который производит экспорт сцены из
MAYA во внешние файлы, итеративно обходит всю сцену и экспортирует ее геометрию и материалы
- обычно в некий новый файл собственного формата. Как известно, MAYA внутри представляет все
свои данные в виде набора нод; некоторые из них связанны в DAG (прямой незамкнутый граф). Наш
плагин должен обойти все ноды в этом графе, передвигаясь от предков к потомкам; для каждой
ноды мы должны определить, с кем она связана и какой тип информации она представляет, и в
зависимости от того, поддерживает ли наш внешний рендерер данную информацию - использовать
ее или пропустить. Задача обхода сцены упрощается тем, что программист может заранее
накладывать фильтр на граф перед тем, как проводить экспорт - например, если ваш рендерер
поддерживает только полигональную геометрию, то и обходить вам нужно только соответствующие
ноды. С другой стороны, в MAYA ОЧЕНЬ много различных типов нод и, скорее всего, вы не захотите
терять информацию только потому, что ваш рендерер не поддерживает тот или иной вид геометрии
или материалов. Это значит, что вашему плагину также придется заниматься преобразованием
информации и приведением ее в тот вид, который подходит для вашего рендерера. Очень многие
рендереры используют свои собственные системы описания материалов, гораздо более простые
или сложные по сравнению с теми, которые используются в MAYA - но все они, как минимум, от
нее отличаются, поэтому «правильный» плагин также должен понимать природу этих различий и
уметь их обходить.
2. Итак, ваш плагин продирается сквозь глубины DAG, сквозь все эти текстуры, материалы,
полигоны, NURBS, SDS, кривые, локаторы, источники света, камеры, объемные примитивы,
трансформы, анимационные кривые и ключи, деформеры, динамику и системы частиц, слои и
глобальные переменные. Некоторые рендереры воспринимают в виде входных данных файл, в
котором описывается как сама геометрия, так и те материалы, которые присоединены к ней.
Другие, напротив, разделяют эти понятия. Некоторые рендереры умеют хранить несколько кадров
в одном файле, другие не умеют - или умеют, но не рекомендуют: просто исходя из того, что
геометрия и материалы в сцене могут быть настолько сложны, что размеры полученных нами
файлов будут очень велики.
3. Все эти сакральные знания спрятаны внутри экспортера, который, пока вы читали
этот абзац, уже закончил экспорт и оставил на диске один или несколько файлов, которые
передаются в рендерер для просчета. Не суть важно, что произойдет в этом случае. Мы можем
просто запустить локальную копию рендерера, передав ей файлы и какие-то другие параметры.
Абсолютно естественно, что в процессе рендеринга может происходить как препроцесинг,
так и постпроцессинг данных, то есть будут выполняться какие-то скрипты, программы или их
комбинации, которые будут преобразовывать ваши данные перед рендерингом или по окончании
оного. Если вы работаете над каким-то большим проектом, то скорее всего вы используете
программно-аппаратное решение (в просторечии - "ферму", официально - "renderfarm"), которое
позволяет распараллеливать ваш рендеринг на несколько машин, находящихся в локальной сети,
будь то рабочие машины сотрудников или специальные компьютеры, выделенные для подобных
расчетов. В таком случае вы не будете вызывать ваш рендерер напрямую, а запустите другую
программу, которая уже и начнет раздачу подпроцессов в вашей ферме.
4. Как результат запуска постороннего движка, будет получена искомая картинка. Многие
современные рендереры имеют возможность рендерить прямо в окно MAYA. Благодаря этому, вы
получаете достаточно удобное средство для предварительного просмотра вашего рендеринга.
Вот, собственно, и все. Волшебство MAYA + умелые руки программистов в сочетании с
опытом работы во всех встречавшихся в процессе продуктах - и мы получаем неплохую основу для
настоящего студийного pipeline, который объединяет в себе сильные черты всех имеющихся на
вооружении продуктов.
Кстати, все хотел у кого-нибудь узнать: какого рода слово "пайплайн"? Считается, что это
очень важное сакральное слово, которое нужно произносить несколько раз в день, особенно глядя
на ошибки в своих «перловых» скриптах или на побитые картинки, оригиналы которых удалил
Я, думаю, вы уже обратили внимание, как я легко и непринужденно разделил две эти
вещи. Такое разделение имеет под собой достаточно серьезные основания.
Что же такое Renderman? Это - стандарт описания трехмерных данных для их последующей
визуализации. В сборнике часто встречающихся вопросов и ответов ньюсгруппы comp.graphics.
rendering.renderman написано так: "Renderman - стандартный интерфейс между программами
моделирования и рендеринга для создания высококачественного фотореалистического
изображения". Создавая стандарт Renderman (а работа эта началась в доисторические времена
- еще в 1987 году), компания Pixar поставила перед собой достаточно амбициозную цель: пытаясь
воспользоваться идеями формата файлов Postscript как некоей среды для обмена векторными
двухмерными данными (а к тому моменту Postscript был уже широко развит и использовался
повсеместно), сделать аналогичный шаг и создать новый универсальный формат для обмена
информацией между системами для моделирования и анимации и системами для рендеринга,
который был бы достаточно универсален для того, чтобы занять место Postscript в мире трехмерных
приложений.
#include <ri.h>
RtPoint Square[4] = { {.5,.5,.5}, {.5,-.5,.5},
{-.5,-.5,.5}, {-.5,.5,.5}};
int main(void)
{
RiBegin(RLNULL);
RiDisplay("RenderMan", RI_FRAMEBUFFER, "rgb", RI_NULL);
RiFormat((Rtlnt) 256, (Rtlnt) 192, 1.0);
RiShadingRate(1.O);
RiWorldBegin();
RiSurface("plastic", RI_NULL);
RiPolygon( (Rtlnt) 4, RI_P, (RtPointer) Square, RI_NULL);
RiWorldEnd();
RiEnd();
return 0;
}
RIB -очень хорошо продуманный расширяемый формат. Это сыграло большую роль в
Вторая составная часть стандарта Renderman - язык Renderman Shading Language или, в
приблизительном переводе, «язык закраски Renderman». Но не в наших привычках пользоваться
настолько корявым переводом, и потому в дальнейшем будем использовать общепринятую
аббревиатуру: SL.
Так вот, с этой точки зрения майские материалы шейдерами не являются. Вы можете
скомбинировать ноды в HyperShade в нужном порядке, получив тот или иной материал - но шейдера
в результате вы не получите.
Как мы уже говорили, шейдер на SL- это программа на С-подобном языке программирования,
описывающая алгоритмически визуальное представление объектов, а если выразиться точнее:
описывающая алгоритм расчета интегрированной освещенности и прозрачности для данной точки
поверхности геометрического примитива. Для большего удобства в этом языке были сделаны
некоторые изменения - например, были введены специальные типы данных, которые описывают
цвет и позицию в трехмерном пространстве; синтаксис языка и его стандартная библиотека
процедур были упрощены, оптимизированы и дополнены, по сравнению с оригинальным языком
С, для работы с такими типами данных; был веден набор глобальных переменных, несущих
Oi = Os;
Ci = Os * Cs * ( Ka*ambient() + Ks*specular(Nf,V,roughness) );
}
Как можно видеть, любой более или менее сведущий в программировании человек (в
особенности знающий язык С) способен достаточно быстро научиться писать данные шейдеры как
вручную (многие студии и разработчики все еще предпочитают этот путь), так и с использованием
специальных визуальных инструментов разработки шейдеров.
Еще одна сторона стандарта, о которой мало кто упоминает: он определяет не только
форматы файлов, которые применяются для обмена информацией между системами анимации
и моделирования и системой рендеринга, но и набор требований, который позволяет и другим
разработчикам создавать различные рендереры, которые могли бы принимать подобные файлы.
На самом деле стандарт никоим образом не указывает вам, какого рода рендеринг должен
происходить и какого рода обработка должна производиться с вашими файлами. Ваш рендерер
может быть рейтрейсером или использовать технологию сканлайн. Вы можете поддерживать
Global Illumination, можете быть REYES (Renders Everything You Ever Saw) - как prman; можете
быть объемным рендерером, гибридным, использовать A-Buffer, какие-то другие технологии
или их сочетания - стандарт не оговаривает таких подробностей и не ограничивает в деталях
реализации. Если вы хотите, чтобы ваш собственный рендерер стал официально совместимым со
стандартом Renderman, нужно лишь выполнить некий набор специальных требований (описанный
в спецификации стандарта и в книге Renderman Companion), а именно:
• Ray tracing
• Global illumination
• Level of detail
• Depth of field
• Motion blur
• Area light sources
Все это не осталось незамеченным - благодаря подобной гибкости стандарта, вкупе с его
открытостью и продуманностью, а также благодаря массированному продвижению компанией-
прародительницей - Pixar. Семена легли в благодатную почву всеобщего интереса к трехмерной
графике - на тот момент эта область знаний только начала развиваться и была освещающе новой,
а потому вдвойне интересной. А еще возник тогда интерес к специальным эффектам в кино.
Помните: Terminator 21... Jurassic Park?... Ox, как же давно это было!... Добавим в коктейль
отличный референсный продукт от самой Pixar - и получим воистину взрывоопасную смесь, которая
немедленно сдетонировала.
7. Производительность. Помните цифру наверху? 700 тысяч кадров. Которые вам нужно
отрендерить на вашей старенькой ферме за полгода. И не стоит рассчитывать на закон Мура
(«Мощность вычислительных устройств удваивается каждые 18 месяцев») - в нашей индустрии
действует другой закон, Блинна - «Вне зависимости от скорости компьютера, кадр считается
одинаковое количество времени». Как только вы проапгрейдите свои компьютеры, TD немедленно
найдет, чем занять их новые мощности.
10. Качество результата. Мы поставили его в конце, и этот параметр иногда сложно
измерить - но на самом деле это самый главный параметр, самое главное требование, основа всех
основ в рендеринге. Если вы делаете кино, то ваши картинки будут показаны на большом (а на
самом деле - на невероятно большом) экране, и каждый грязный и неправильный пиксель будет
иметь размеры, которые можно уже померить с помощью большой деревянной линейки (такие,
знаете, которыми так удобно размахивать, взявшись двумя руками). Любые артефакты, будь то
плохой антиалиасинг, неправильная апроксимация геометрии, ошибки отсечения, полосы Маха
- недопустимы. Более того, скорее всего вы делаете анимацию - а это означает, что также важно
соответствие кадров друг другу во всех деталях. Неподвижные объекты не должны дергаться,
медленно движущиеся - прыгать; антиалиасинг должен быть правильным и одинаковым для
объектов любого размера, находящихся на любой дистанции от камеры.
Ух! Объяснение получилось очень длинное и очень простое -prman полностью удовлетворяет
всем приведенным выше требованиям. А теперь сравните этот список с другим, относящимся к
стандартному рендереру MAYA.
Я чуть ли не единственный участник поездки, который еще не успел прочитать эту повесть.
Она хит сезона, она ходит по рукам, от нее невозможно оторваться, очередь выстроилась на
неделю вперед. Класс разделился на тех, кто прочитал Произведение - и со смаком обсуждает
перипетии сюжетных поворотов, и тех, кто еще не успел и может только тупо кивать, слушая эти
обсуждения.
Страницы уже немного замусолены, этот десяток листков был выдран из какого-то
новомодного журнала для молодежи, который уже не боится печатать "про секс", но все еще не
научился правильно пользоваться компьютерной версткой.
И вот оно, счастье: хозяин манускрипта едет со мной в одном купе (или это все-таки был
плацкарт)? Память услужливо подсовывает мне любые детали, кроме этой. Я пользуюсь моментом
- и встреваю без очереди, выпросив эти пожмаканые листики у хозяина и клятвенно пообещав, что
быстренько прочитаю и верну.
Я уже говорил, что на листиках не было номеров страниц? Так вот: их не было...
Всю чудовищность произошедшего я осознал лишь в тот момент, когда увидел на последней
странице ЗАГОЛОВОК повести. Как оказалось, все это время я боролся с сюжетом и плохим
освещением, читая повесть наоборот - от последнего листа к первому...
К чему городить воспоминания школьных лет в книжке про MAYA, спросите вы? Да просто
потому, что, по моему искреннему мнению, начинать рассказ о prman с описания функциональности
Renderman Artist Tools (RAT) - это все равно, что начинать читать интереснейшую книжку с конца.
Нет, не так - это все равно, что начинать читать учебник с конца. Это антипедагогично, антинаучно,
антиморально и вообще неправильно.
Конечно, можно было бы все-таки внять зову сердца и сделать из этой главы академический
учебник: начать с азов, постепенно продвигаясь ко все более и более сложным вещам. Но так
уж получилось, что самое интересное и самое презентабельно выглядящее в prman - это «две
большие разницы». Да и, в конце концов, мы же не ставим себе целью усыпить нашу аудиторию
посреди главы?
Кстати говоря, несмотря на то самое происшествие в поезде, я все еще не могу избавиться
от дурной привычки читать с конца журналы. Хотя в последнее время поступаю так все реже и
реже.
• RAT - Renderman Artist Tools набор инструментов и плагинов для связи MAYA и prman.
Если кто-то называет его «рэт» (то есть «крысой»), знайте: перед вами новичок. Закоренелый
трехмерщик непременно назовет его "рат" (и уж никак не "Ар-Эй-Ти").
• MTOR MAYA TO Renderman - собственно плагин для MAYA, который позволяет ей рендерить
при помощи Renderman-совместимых рендереров. Входит в состав RAT.
Продуктовая линейка Пиксар на момент написания этих строк включает в себя три продукта:
Renderman Pro Server (включающий в себя prman, Irma и Alfserver), RAT (в составе MTOR, Slim, Al
fred, "it") и Renderman For MAYA. Нужно было бы, конечно, для лицензионной чистоты расставить
в предыдущей фразе значки ™, в произвольном порядке, ну да ладно.
Еще раз для того, чтобы хоть что-то отрендерить, вам понадобится Pro Server. Для того,
чтобы связать MAYA и Pro Server, нужен RAT:
Renderman for MAYA отдельный новый продукт, боковая ветка эволюции prman и RAT, и он
предназначен для более удобной увязки этих продуктов, причем нацелен, в первую очередь, на
людей, ранее с Renderman'oM не сталкивавшихся. Мы не будем рассматривать Renderman For MAYA
в этой главе детально, поскольку на момент подготовки этой главы продукт все еще не был выпущен
в продажу и не был доступен для бета-тестирования. Для любознательных. Само название Render-
Man имеет любопытную историю. В самом начале основатели Pixar собирались создавать «железо»
- аппаратные решения для рендеринга. В идеале такой микрокомпьютер должен был быть очень
маленьким, чуть ли не карманным. Из таких компьютеров, согласно тогдашней идее, создавались
бы "render walls", так что они объединяли бы свои усилия в рамках одной задачи. Производством
такого железа могли заниматься кто угодно, но оно было бы полностью совместимым, поскольку
подчинялось бы стандарту Renderman. Тогда как раз появился карманный плейер для аудиокассет
фирмы Sony, который назывался Walkman, и вот, по аналогии с ним, будущее устройство назвали
Renderman.
MTOR
Первое, с чем столкнется пользователь MAYA, установивший комплект из Pro Server и RAT
(а работать с ними он будет именно в такой связке) - это MTOR. В интерфейсе MAYA это проявится
вот таким вот образом:
Набросайте в сцену несколько примитивов и добавьте источники света - пусть это будет
простой майский directLight:
На плечах MTOR лежит задача вывода геометрии в формат RIB и вызова других программ из
набора. Также он осуществляет поддержку совместимых с Renderman'oM сабдивов в интерфейсе
MAYA - видите в меню RenderMan последний пункт: Pixar Subdivs? Это оно.
По моему мнению, RAT - это попытка технарей из Pixar усидеть сразу на двух стульях, а
именно - сделать продукт, который одновременно был бы удобен для неопытного пользователя
и мог бы быть расширяем опытным пользователем. В общем, где-то табурет у них и получился:
пользоваться более-менее удобно, ручки все на месте, настроить под свои требования тоже
можно. С другой стороны, у такого подхода есть и свои проблемы, но о них потом.
Alfred
А у нас тем временем (сцена несложная и много времени на экспорт в RIB не ушло)
появляется окно Alfred:
Alfserver
Alfserver - это собственно агент, выполняющий задания Alfred. Название этой программы
несколько сбивает с толку, поскольку мы привыкли, что сервером называется одна головная
программа, к которой подсоединяется множество клиентов. В данном случае центрального
рендеринг-сервера, раздающего задачи клиентам, нет, и применяется обратная аналогия:
клиент-диспетчер задач один (это Alfred), и он сам распределяет задачи по серверам (Alfserv
er), установленным на рендеринг-машинах в ферме. Очевидно, что клиентов может быть много
(скажем, клиент может быть установлен на компьютере у каждого аниматора и работать по ночам,
пока аниматору снятся анимационные кривые), и все они будут распределять свои задачи по
серверам.
Для продвинутых. Конечно, все не так просто. При работе с Alfred'ом существует
возможность использовать утилиту maitre_d, которая будет выступать в качестве центрального
сервера но основной принцип работы от этого не изменится, поскольку утилита эта сама
распределять задачи не может, а всего-лишь собирает информацию о занятости систем и прочих
метриках и раздает ее всем желающим, а локальные диспетчеры используют эти метрики для
оптимизации нагрузки рендеринг-фермы.
It
А тем временем мы почти сразу же после появления окна Alfred видим новое окно - it, в
котором быстро проявляется наша картинка:
it (от Image Tool) - в оригинале вьюер для графических файлов, в последних версиях
вобравший в себя функциональность просмотрщика последовательностей, каталогизатора файлов
и даже композера. Я более чем уверен, что большинство пользователей RAT не используют даже
По умолчанию it выступает в качестве display target при рендеринге. Это удобно, если вы
хотите посчитать несколько различных картинок подряд, а затем сравнить их или выбрать лучшую
из серии.
Сравним полученную картинку с результатом рендеринга при помощи родного движка от MAYA:
Подробное описание всех функций этого окна оставим для документации по RAT - кстати
Пытливый читатель уже обнаружил параметр Display Resolution. На нашем скриншоте этот
параметр уже выставлен в 0, 0 - таким образом, мы всегда будем рендерить в размере выбранного
viewport'a MAYA (по умолчанию же этот параметр выставлен в 640x480). Кстати говоря, обратите
внимание на значки i рядом с именами параметров - это контекстная справка. Про возможность
установки (0,0) я узнал именно из нее.
SLIM
Вернемся к MTORy. Чего он делать, к сожалению, не умеет - так это конвертировать
майские материалы в шейдеры Renderman'a. По идее разработчиков RAT, этого от программы и не
требуется, поскольку считается, что все шейдеры будут либо написаны вручную, либо их создадут
с помощью SLIM - визуального конструктора шейдеров.
О SLIMe можно говорить очень долго. После Hypershade он может показаться несколько
архаичным, но, тем не менее, это достаточно удобный конструктор для шейдеров.
На самом деле, когда я занимался историей этого вопроса (чтобы кратко осветить его в
этой вставке, для любознательных), я был буквально ошеломлем тем количеством информации,
которая доступна в Интернете по поводу Визуального Программирования а ведь визуальное
построение шейдеров суть визуальное программирование и есть.
Более того, таким же образом (через кастомные атрибуты из SLIMa) вы можете добавлять
в сцену свой собственный RIB-код при помощи так называемых RIBbox (мы их уже упоминали в
отступлении для любознательных). Дальше больше: расширяемый SLIM (как и сам MTOR, при
помощи Tcl) позволяет вставлять в сцену TCLbox'ы, которые будут исполняться на этапе экспорта
сцены в RIB и имеют полный доступ как ко внутренним интерфейсам самой MAYA, так и к командам
MTOR и SLIM.
Для любознательных. Основной атрибут шейдера называется slimSurf; короткое имя, под
которым он фигурирует в скриптах и в файлах *.ma sss. В ASCII-файле MAYA это выглядит примерно
так:
Вернемся к нашим тестовым баранам. Давайте теперь немного усложним нашу сцену.
Поработайте немного над вашими примитивами. Раз уж заговорили про парнокопытных, у вас
должно получиться что-то вроде этого:
Эта модель - полигоны, переведенные в сабдивы (subdivision surfaces) при помощи команды
Modify=>Convert=>Polygons to Subdiv. Давайте опробуем SLIM на деле и назначим овечке материалы:
Renderman=>Slim=>New Palette.
Как видите, это довольно сильно напоминает Attribute Editor для стандарных майских
материалов.
Темноватый бархат получился, сделаем-ка его немного светлее. Изменяем Kd, поскольку
амбиентного источника у нас в сцене не будет (говорят, иметь их в сцене вредно), изменяем цвет,
все время проверяем результат, кликая на шарике. Добившись вменяемого результата, назначаем
созданный материал: в MAYA выбираем голову овечки, затем в основном окне SLIMa выбираем Ap
pearance=> Attach. Рендерим. (А вы уже вынесли на полку пункт меню RenderMan=>Render?)
И чтобы уже совсем сделать наш краткий туториал похожим на все остальные 1327
туториалов для начинающих, заполонивших Интернет, покажем, как собственно делаются в SLIMe
более сложные составные шейдеры.
Для любознательных. Число 1327 выбрано случайно. Кстати, о случайных числах - вот
вы знаете, например, как отличить TIFF файл по сигнатуре? Оказывается, очень просто - у него
третьим и четвертым байтом записано число 42: как сказано в спецификации, «an arbitrary but
carefully chosen number (42) that further identifies the file as a TIFF file» . Я думаю, вопрос о том,
почему выбор не пал на 43 или 41, неправомерен, поскольку они не являются пятым Каталонским
Числом.
Так вот, рядом с Velvet color кликнем на желтом квадратике и в выпавшем меню выбираем
Connection. В этой же строке справа в вываливающемся списке выбираем Noise. Должно получиться
что-то такое:
Irma
Irma - ре-рендерер. В общем, идея проста - вы рендерите один раз с помощью «Ирмы»,
которая кэширует необходимую информацию о сцене, освещении и шейдинге. Все последующие
разы ре-рендеринг использует эту информацию и происходит гораздо быстрее, без перегенерации
RIB-файлов и шейдеров. Irma понимает изменения параметров шейдеров, позиции источников
света и изменения в координатных системах - такие изменения будут просчитаны очень быстро.
Ближайший аналог Irma из мира MAYA - это, конечно же, IPR.
Что бы не говорили, а большую часть интересных новых идей уже кто-то придумал до нас.
Взять, например, ту же «Ирму» с IPROM. Самая первая реализация шейдеров в продакшне - та
самая, которую реализовал на Фортране Кен Перлин - использовала те же идеи: предварительный
рендеринг всего, что можно, в буфер и последующее наложение шейдеров. С другой стороны, с
тех пор утекло очень много воды, и в современных рендерерах большая часть времени тратится
именно на шейдеры. Тем полезнее для вас будет Irma.
И очень даже напрасно, хочу вам сказать, потому что истинная сила всех автономных
рендереров - именно там, в командной строке.
prman.exe
Большинство Renderman-совместимых рендереров состоит из трех программ: собственно
рендерера, компилятора шейдеров и компилятора текстур.
Не столь важно, получилось ли так исторически или просто все рендерерописатели Render
man-совместимых рендереров смотрели на Pixar в качестве образца - но подобная тройственная
архитектура сохраняется, с теми или иными отклонениями, во всех таких рендерерах. Отчасти в
этом есть некая дань стремлению к максимальной оптимизации процесса и разделению рендерера
на независимые модули. Отчасти - это отклик Unix-овского наследия. Отчасти - это слепок самой
идеи, заложенной в спецификацию Renderman (согласно которой процедурные материалы
(шейдеры) и описание геометрии хранятся в разных файлах, соответственно, в *.SL и в *.RIB). Так
или иначе, тенденция есть, и она сохраняется даже в случае с самыми современными рендерерами
-в их поставке вы тоже обнаружите три ехе-шника: рендерер, компилятор шейдеров и конвертер
текстур.
Вызовите свою любимую командную строку (если вы используете Windows, для этого
нужно в стартовом меню Run запустить cmd.exe) и уже в новом окне командной строки запустите
на выполнение prman.exe.
У новичков может возникнуть впечатление, что программа зависла: сразу после запуска
ничего не произошло, и обратно в командную строку мы не вернулись. На самом деле мы
столкнулись еще с одной особенностью программ, изначально написанных в расчете на консоль
Unix - эти программы предназначены, в том числе, и для работы в режиме пайпинга, то есть
передачи данных от одной программы к другой. Так вот, если такую программу запустить на
выполнение, не указав параметров, она будет ожидать, что данные будут поступать на вход от
других программ (для продвинутых: из stdin) или будут набираться с клавиатуры. Значит, нам
нужно это и сделать - запустить программу с параметрами.
Повторим наш экзерсис с рендерером, на этот раз передав программе в качестве параметра
имя test1.rib:
Как видите, в результате получилось... Гм... ничего у нас не получилось. В чем же причина?
Причин на самом деле несколько, и все они достаточно очевидны:
1. В нашей примитивной сцене нет источников света. Поэтому сцена получилась полностью
неосвещенной (умное название для эффекта "ничего не видно")
TransformEnd
Surface "plastic"
Sphere 1 -1 1 360
WorldEnd
prman test1.rib
Результат будет в точности такой же. Но это еще не все. Вы же знаете, что «туннелировать»
можно не только две программы, но и целые цепочки программ?
В качестве примера (скриптоненавистники могут пропустить страницу) напишем небольшой
скрипт на Perl, который будет заменять объявление материала Plastic на объявление материала
Stone. Делаем новый файл, называем его magic.pl и пишем нечто вот такое:
foreach (<>) {
s/plastic/stone/;
print;
}
Вы уже слышите, как тихонько зазвучало в воздухе исконно русское слово "pipeline"?
Просто подумайте о тех невероятных возможностях, дверь к которым мы только что приоткрыли.
Получается, что геометрию для рендерера совсем не обязательно выводить из MAYA (или 3dsmax,
или Houdini, или откуда угодно еще - на самом деле, неважно, откуда именно) - вы можете сами
писать небольшие программы или скрипты, которые будут или создавать новые файлы RIB или
модифицировать уже существующие. Более того, файлы эти можно запросто открывать в текстовых
редакторах, делать замены, переставлять куски местами, экспериментировать с различными
возможностями - и все это без запуска и использования безумных систем моделирования
и анимации. Да что уж там - изучение текста сгенерированных RIBOB представляет собой
захватывающее интеллектуальное психоделическое путешествие в мир трехмерной графики и во
внутреннее устройство вашего любимого моделлера. Как подействует это изменение в модели на
RIB? Что изменится, если сделать то или это? Какая картинка получится в том или ином случае?
Первый Renderman-совместимый был потом, и был это - BMRT. Но это уже - современная
история: с Интернетом, Амазоном, Пентиумами и ньюсгруппами.
Слева направо: программа catrib (из поставки Pixar Renderman Pro Server) переводит файл
test2.rib в бинарный формат и результат передает в программу gzip (вам придется скачать ее из
Интернета), которая упаковывает ее и передает дальше, в файл test2.gbin.
Для продвинутых. Я вам по секрету скажу - на самом деле можно делать и так:
prman test2.gbin
prman , а также некоторые другие рендереры, понимают такие файлы и отлично с ними
работают.
shader.exe
Вернемся к нашему шарику. Переименовываем файл в test3.rib и вносим небольшие
изменения - убираем строку, определяющую материал (Surface "plastic"):
TransformEnd
Sphere 1 -1 1 360
World End
. null
• constant
• matte
• metal
• shinymetal
• plastic
• paintedplastic
• ambientlight
• distantlight
• pointlight
• spotlight
• depthcue
• fog
• bumpy
• background
Так что поиграть уже есть с чем, но мы хотим сделать что-то свое. Представим себе, что
вы где-то из Интернета скачали шейдер, который обучает вас использованию в Shading Language
функции noise:
Для продвинутых. Нойз ("шум") - это отличный и обычно первый из приходящих в голову
способов добавить нерегулярности в "стерильную" компьютерную картинку.
Сохраните его в текстовый файл под названием noisetest.si рядом с файлом test3.rib.
Немного правим test3.rib, добавляя в него ссылку на новый материал:
TransformEnd
Surface "noisetest"
Sphere 1 -1 1 360
WorldEnd
Что происходит? Мы же, вроде бы, все правильно сделали, указали материал, положили
шейдер рядом - что не так? Ан нет, не все так просто. Перед непосредственным использованием
шейдер необходимо привести в состояние, которое будет максимально удобным для рендерера
- а попросту говоря, откомпилировать.
Для любознательных. Конечно же, рендерер мог бы и сам понять, чего от него хотят,
и откомпилировать шейдер внутри себя. Но это бы противоречило духу и одному из основных
принципов Unix ("для каждой задачи - своя небольшая программа"), исторической справедливости
и не дало бы нам в руки могучее оружие пайпинга - а оно нам доступно и в этом случае.
shader noisetest.si
Для продвинутых. Далеко не очевидна, особенно для начинающих, мысль, что шейдеры
вообще нужно компилировать. Даже если не затрагивать исторические корни языка шейдеров
(а именно, язык программирования С и модель работы с программами, написанными на нем),
Surface "noisetest"
Это строку можно модифицировать, чтобы передать шейдеру параметры, например, вот так:
Дальше - больше. Поскольку язык SL является потомком языка С, нам доступны такие
возможности С, как препроцессор и макросы. Проиллюстрируем это на простом примере. Немного
изменим наш шейдер:
Обратите внимание на то, что мы ввели в шейдер новую символьную константу (для
удобства она обозначена большими буквами - FREQD), которую можем переопределять вне
шейдера, в командной строке компилятора. Результат рендеринга будет, естественно, другим
(мы вернули строку подключения шейдера в исходное состояние):
shader noisetest.sl
Уже вкусно? Сейчас будет еще вкуснее. Поскольку в наших руках почти что язык С, мы
можем вынести куски кода в подключаемые файлы (included files) или, наоборот, использовать
уже готовые подключаемые файлы в своем шейдере. Один из самых интересных для изучения
начинающими include-файлов можно найти в RManNotes, небольшом онлайновом пособии по Ren-
derman Shading Language (его перевод на русский язык доступен на сайте Renderman.ru). Мы же
воспользуемся стандартными возможностями из поставки Renderman Pro Server. Подключаем к
нашему шейдеру библиотеку материалов:
#include "materials.h"
surface noisetest ( float freq=FREQD; )
{
Ci = color(MATERIAL_bronze*noise(freq*s,freq*t));
}
и вызываем компиляцию:
txmake.exe
В этом случае все совсем просто. Парадигма тотального ускорения рендеринга и
разумного потребления памяти требует, чтобы все, что поступало на вход рендерера, было
максимально оптимизировано. Для RIB'OB таким вариантом является бинарный формат, для SL
- откомпилированный код. Для текстур, которые вы можете использовать в своих шейдерах, тоже
3. Прочие хитрости, вроде оптимизации данных под конкретный рендерер - так, например,
prman при конвертации текстур может привести их размеры к величине, кратной степени
двойки.
Одно небольшое отличие txmake от своих консольных собратьев состоит в том, что текстуры
сами по себе текстовыми файлами не являются, то есть с ними наши фокусы с пайпингом работать
не будут.
Вот, собственно, и все, что я хотел про нее рассказать. Ах, да, я забыл пример. Похулиганим
немножко?
По причинам, которые мы только что указали, пусть текстура будет квадратной, 512x512
пикселей. Напишем на ней... напишем на ней.... чего бы такого написать, чтобы никого не обидеть
и чтобы литературный редактор пропустил? Вот, придумал:
Надпись
Просто и со вкусом. Добавляем вызов текстуры в наш шейдер (по этому поводу
переименованный в textured_noise.sl):
TransformEnd
TransformBegin
Rotate 90 1 0 0
Rotate 90 0 0 1
Surface "textured_noise"
Sphere 1 -1 1 360
TransformEnd
WorldEnd
Вот что мы сделали: исправили имя шейдера и немножко повернули наш шарик, чтобы
надпись нормально читалась.
Компилируем шейдер:
shader textured_noise.sl
Рендерим картинку:
prman test4.rib
Для любознательных. Вас никто не заставляет называть свои файлы тем или иным образом.
Вы можете хранить свой шейдеры в файлах с расширением *.shader; свою геометрию - в файлах
с расширением *.rib, *.ri или ".renderman; инклуды в файлах *.h или *.inc. Просто стремитесь к
тому, чтобы всегда придерживаться одного и того же логичного и удобного для вас именования
файлов. Система именования, которую я использую в этой главе, считается стандартной и широко
используется в литературе и документации.
Для продвинутых. В процессе обработки текстур RAT включает в название файла параметры
командной строки, которые использовались при вызове txmake. Например, вот так: metal024.tif.
ppu.tx. Расшифровку скрытого в этом имени тайного значения оставим в качестве задания для
самостоятельной работы для вас, продвинутые.
Могучая кучка
Собственно говоря, вычислительное ядро Renderman Pro Server состоит из трех программ:
prman, shader и txmake. Как мы уже говорили раньше, подавляющее большинство Renderman-
совместимых рендереров придерживается такой же архитектуры, просто называя файлы другими
именами. Приведем лишь некоторые из них:
А теперь представьте себе, что между любыми элементами этой новой диаграммы можно
встроить другие программы и скрипты на различных языках программирования, которые будут
преобразовывать ваши данные.
Вы считаете, что и этого мало? Ну, тогда давайте вернемся к нашей схеме и описанию
нашей триады и дополним ее некоторыми немаловажными деталями, которые мы не затронули в
первом заходе.
1. Утилита txmake принимает на входе файлы формата TIFF. На самом деле, список
поддерживаемых форматов гораздо длинее и включает в себя: MAYA IFF, SGI, SUN, TGA, Alias,
GIF, JPEG, LBM, BMP, ICO, форматы систем Х11 (например, майские иконки в файлах ХРМ), Рпо-
toCD, 24битные raw bitmaps и некоторые другие, а начиная с версии 12 - становящийся де-факто
стандартом индустрии OpenEXR.
2. В поставке Renderman Pro Server есть утилита sho.exe, которая позволяет конвертировать
между всеми этими форматами. Кстати говоря, в поставке MAYA есть утилита imgcvt.exe, которая
делает почти то же самое - конвертирует между форматами. Преимущество sho в том, что она может
еще и показывать файлы на экране. Признайтесь честно - когда вы в последний раз заглядывали
внутрь Maya/bin?
3. Язык шейдеров SL можно расширить за счет своих собственных процедур. Сделать это
можно, написав свою собственную DLL (в нашем случае называемую на юниксоидный лад: DSO).
Поверьте мне - это не так сложно, как кажется, и для этого совсем не обязательно знать язык С
или C++.- Я же вообще, с успехом писал DSO на Паскале. Классические примеры расширения SL
- Frankenrender (вызов одного рендерера из шейдера, исполняемого в другом рендерере; именно
так в стародавние времена в prman встраивали raytracing - просто вызывали BMRT) и Vtexture
(использование векторных файлов в качестве текстур).
4. Вы уже знаете, что формат RIB можно генерировать своими собственными программами;
это очевидно, поскольку формат это простой и в основной своей ипостаси - текстовый. О чем
мы в нашей главе не говорили - так это о том, что этот формат также можно расширять при
помощи динамических генераторов RIB-кода, вызовы которых встраиваются непосредственно
в сами RIB'bi. Такие генераторы можно писать как в виде DLL/DSO, так и непосредственно как
исполняемые файлы или даже скрипты на Perl. Комментарий в сторону. Я уже говорил, что Perl
- язык истинных криптоманьяков. Хорошим подтверждением этой гипотезы является тот факт, что
базовым скриптовым языком в ILM и Google избран Python.
5. Начиная с версии 11.5, prman позволяет встраивать ваши собственные фильтры внутрь
рендерера для более глубокого процессинга RIB. Опять-таки, эти фильтры представляют из
себя DLL/DSO с определенной схемой вызовов. Начиная с версии 12.0, эти фильтры описаны в
документации.
6. prman может рендерить во множество файловых форматов: TIFF, MAYA IFF, Softimage,
TGA, SGI, CIN, PIC, Alias. Но этот список можно легко увеличить при помощи своих собственных
плагинов, в этом случае называемых display drivers. Экспериментируя с prman в нашей главе, мы
рендерили сразу в окно просмотра; такая возможность реализуется при помощи плагина d_win-
dows.dll. Пробуя на зуб MTOR, мы считали картинку непосредственно в окно программы it - делается
Сведем все предшествующее описание, все эти десятки страниц, картинок и схем в один список:
1. Стандарт Renderman
2. Скорость работы
3. Соответствие тем нормам, которые мы определили как необходимые для продакшн рендерера
4. Удобство и простота в освоении
5. Расширяемость
Альтернативы?
Почему же множество людей, FX-домов и студий во всем мире НЕ используют Renderman
Pro Server? И тому есть множество причин.
На этом можно было бы и закончить, потому что по цене комплект, состоящий из Render-
man Pro Server, RAT + годичной подписки на услуги службы поддержки, почти догнал стоимость
(чуть было не написал - автомобиля) MAYA Unlimited... Надеюсь, вы оценили. Один этот факт ставит
жирный крест на этом продукте для маленьких студий, свободных художников - фрилансеров
и студентов, которые хотят поэкспериментировать с рендерером дома: все они выбирают либо
совместимые альтернативы, либо совершенно другие продукты.
Но я хотел заострить ваше внимание на другом аспекте проблемы. Да, prman - очень универсальный
рендерер. Но, согласно поговорке, когда вы берете в руки молоток, все предметы вокруг вас
начинают казаться гвоздями.
Вообще говоря, говорить о том, что какой-то рендерер не совместим с MAYA, особенно
после того, как вы познакомились с главой, посвященной MEL - глупо. Возможности MEL в области
вывода данных из MAYA настолько велики, что фактически любой рендерер, запускаемый из
командной строки, можно с теми или иными затратами прикрутить к Майе. И это будет работать.
А если вас перестанет устраивать скорость работы скрипта, вы просто перепишете ваш скрипт в
виде плагина (или попросите кого-то переписать ваш скрипт в виде плагина). Это означает, что
MAYA-совместимым является почти любой из существующих на рынке рендереров, запускаемых
из командной строки. Но, как говорил Козьма Прутков, нельзя объять необъятное - у нас здесь не
Большая Советская Энциклопедия, в конце концов. И поэтому мы сделаем небольшую выборку из
Какие рендереры?
Как-то вечером я задался вопросом: какие вообще на свете существуют рендереры и
почему они существуют вообще? Вопрос настолько же риторический, насколько и философский
- по аналогии, можно спросить, почему так много моделей лопат или молотков есть в магазине.
Во-первых, очень часто большая (а иногда и не очень большая) студия самостоятельно
изготавливает для себя рабочий инструментарий: начиная с рендерера и заканчивая системами
моделинга, анимации, цветокоррекции и композитинга. В таком случае сотрудники этой студии
получают максимальный контроль над результатами своего труда.
Чем же закончился тот вечер, когда я попытался объять необъятное? Простой схемой, на
которой я перечислил все известные мне (пусть только по названию) рендереры и провел между
некоторыми из них связи - будь то родственные, технологические или какие-то еще. Картинка
перед вами.
Gelato
Появления этого продукта ожидали многие. Еще не было достоверно известно, что он
существует, но все понимали, что внутри Nvidia что-то варится. Не могло не вариться - как не
может не взорваться критическая масса внутри атомной бомбы.
Но расскажем по порядку.
В июле 2000-го года три человека - Ларри Гритц, Мэтт Фарр и Крэг Колб (Larry Gritz,
Matt Pharr, Craig Kolb) - объединили усилия, чтобы создать новый Renderman-совместимый
рендерер. Ларри внес в копилку знаний свой рендерер BMRT и опыт работы в Pixar над prman'ом
и интеграцией prman и BMRT (помните, как я, рассказывая о возможностях расширения SL,
кратко упомянул Frankenrender?). Мэтт положил в пул свою идею (и написанную на ее основе
диссертацию) о кардинальном ускорении процесса raytracing'a - и опыт работы в Pixar над prman.
Крэг - опыт, накопленный в ходе разработки рендерера Rayshade. Объединившись под вывеской
Exluna и выбрав в качестве логотипа мультяшный космический кораблик, разработчики сделали
почти невозможное - в августе 2001-го года представили на суд публике новый рендерер - Entro
py. Качественный, быстрый, Renderman-совместимый рейтрейсер превосходил prman по набору
поддерживаемых алгоритмов рендеринга и стоил всего полторы тысячи долларов (не случайно
считается, что именно после появления Entropy в Pixar серьезно озаботились встраиванием ray
tracer'a в Renderman Pro Server - хотя скорее всего это не так, и работы шли параллельно). А какая
бы ни была продажная цена, стоил продукт гораздо дешевле.
Entropy был хитом и раскупался, как пирожки. Почва под ногами prman зашаталась, и
ответный ход не заставил себя ждать. К сожалению, он был не совсем приятным. Пятого марта
2002-го года Pixar подала на Exluna в суд, обвиняя комнанию в нарушении патентов, а 16-го мая,
во втором иске, обвинила трио основателей в плагиате (ведь два из них ранее работали в Pixar
и видели исходный код prman). Тщетно адвокаты молодой компании пытались бороться: куда
стартапу из 10 человек на втором году жизни тягаться против гиганта Pixar (со студией Диснея
за спиной). И несмотря на то, что причин для судебного разбирательства не было и патенты не
нарушались, наилучшим выходом для Exluna было: прекратить продажи своего продукта, продаться
Nvidia с потрохами и дать победителям урегулировать споры между собой.
Таким преемником оказался новый рендерер Gelato, анонсированный 19 апреля 2004-го года.
Основной особенностью Gelato, из-за которой его так любит пресса и так не любят
некоторые разработчики и TD, является то, что это первый продакшн рендерер, который
использует возможности вашей видеокарты для рендеринга - и более того, не работает, если у
вас не установлена определенная видеокарта - конечно же, с чипом от Nvidia. Но чтобы понять,
насколько серьезное преимущество оказывается в руках у тех, кто берет на вооружение этот
новый рендерер, отвлечемся немного и поговорим о процессорах, Законе Мура и современных
реалиях.
Итак, для запуска Gelato вам понадобится современный мощный компьютер под управлением
Windows XP или Linux и современная же, мощная профессиональная видеокарта на чипсете
от Nvidia - в частности, Quadra FX. Прежде чем мы попробуем новый рендерер в бою (вы тоже
можете это сделать - тестовая версия Gelato доступна для скачивания на сайте, и единственное
ограничение этой версии - водяной знак на результатах рендеринга), рассмотрим кратко основные
черты этого продукта.
Если посмотреть правде аккурат в глаза, то перечислять инновации Gelato вот таким
сухим списком скучновато не только для вас, но и для меня самого. Давайте лучше попробуем
сделать что-нибудь в MAYA и отрендерить в Gelato, а заодно и поговорим о достоинствах этого
рендерера.
В поставке Gelato идет Mango - плагин к MAYA, который встраивается в нее, в отличие от
MTOR, почти без проблем и позволяет использовать всю мощь обоих продуктов.
Создадим новый проект, новую сцену, импортируем нашу овечку (файл sheep.та на
диске). Овечка у нас полигональная, если вы еще не заметили - так что быстренько переводим ее
в Subdivision Surfaces: Modify => Convert => Polygon to Subdiv. Рендерим стандартным движком MAYA
(движок немного притормаживает), и наконец получаем картинку:
Все наши предыдущие картинки с овцой были на черном фоне, который уже немного
надоел - поэтому мы вставили в сцену большой шарик, который и дал нам серенький фон. Надоест
этот фон, уберем и его, и будем опять смотреть на черный задник, но пока нормально и так. Да,
на чем мы там остановились? Ах, да, Gelato...
Если рендерер у вас установился правильно, вам всего лишь нужновключить плагин
обычным способом и вызвать окно Render Globals:
Не нужно иметь зрение горного орла, чтобы увидеть, что не только рендеринг прошел
гораздо быстрее, но и в результате мы получили гораздо более качественную картинку (не меняя
при этом установок по умолчанию в обоих рендерерах). При этом Gelato подхватил все установки
MAYA и воспроизвел их своими средствами.
Что же произошло за кадром, пока мы слушали песню вентилятора нашей Nvidia GeForce
QuadroFX 3000 (кстати, пока я это писал - вентилятор уже выключился)? Заглянем в директорию
c:\temp - в ней появились 3 новых файла:
gelato. pyg
gelato.bat
gelato_perspShape.pyg
Внутри этих файлов находится самое интересное - геометрия, которую Mango экспортировал
из MAYA B собственный формат Gelato. Правильнее говоря - Mango эскпортировал в формат PYG - один
из форматов, поддерживаемых Gelato. Казалось бы, разница между двумя фразами минимальна,
но она показывает глубокое философское различие между Gelato и другими рендерерами. Это
- одно из тех различий, на которых мы остановимся и которое, возможно, вас удивит.
Различие это состоит в том, что в Gelato нет формата сцены по умолчанию. Формат
шейдера есть (GSL), а формата сцены - нет. Вместо этого пользователю представляется хорошо
документированный программный интерфейс API и возможность написать в соответствии с этим
интерфейсом плагин к рендереру, который и будет заниматься вопросами загрузки геометрии.
Понятное дело, что взять и просто так выпустить на рынок рендерер, в который по умолчанию
нельзя загрузить геометрию вообще - это глупость, поэтому для Gelato придумали свой собственный
формат PYG, представляющий из себя программу на языке Python. В общем, смотрите сами, перед
вами кусочек файла с овечкой:
World ()
PushTransform ()
SetTransform (((0.736097, 0, -0.676876, 0),
(-0.130758, 0.981164, -0.142198, 0),
(-0.664126, -0.193179, -0.722232, 0),
Энтузиасты Renderman немного скривились - что ж, в их руках такой мощной игрушки нет.
А мы тем временем нанесем им еще один удар - загрузив с сайта Nvidia плагин к Gelato, который
позволяет использовать в качестве файлов геометрии RIB-файлы. Действительно, а почему бы и
нет, если есть открытый API? Попробуем эту возможность в бою: временно откладываем в сторону
MAYA и вызываем командную строку:
gelato test2.rib
Как видно, Gelato без особых проблем справился с RIB'OM, благо шейдер "Plastic", который
мы использовали с нашей тестовой сцене, входит в поставку - равно как и все остальные шейдеры
из стандарта Renderman (сказывается Entropy-шное прошлое).
Это самое прошлое не раз будет напоминать о себе в наших изысканиях. Раз уж мы начали
копаться в командной строке, посмотрим, например, из чего же состоит наш новый друг. Ба!
Налицо уже набившая нам оскомину триада - рендерер, компилятор шейдеров и конвертор текстур,
но на этот раз они называются gelato.exe, gslc.exe и maketx.exe.
Внутри директории gelato/bin еще много всего интересного, например, утилита topyg,
которая позволяет перевести любой из поддерживаемых установленных вами плагинами форматов
геометрии в PYG: с ее помощью можно сравнить одну и ту же сцену в формате PYG и RIB и увидеть
явные аналогии. А мы возвращаемся к нашим баранам я хотел сказать, к нашей овечке и к
Maya.
Снова запускаем рендеринг - а рендерером у нас все так же стоит Gelato - и с удивлением
смотрим на результат:
ShaderGroupBegin ()
Shader ( "surface", "maya_place2dTexture", "place2dTexture1" )
Shader ( "surface", "maya_noise", "noisel", "float amplitude", 0.6529, "float depthMax", 4, "float
frequency", 11.57, "float frequencyRatio", 2.1158, "float noiseType", 0, "float ratio", 0.90082, "float
threshold", 0.22316)
ConnectShaders ("place2dTexture1", "outUV", "noisel", "uvCoord")
ConnectShaders ("place2dTexture1", "outUvFilterSize", "noisel", "uvFilterSize")
Shader ( "surface", "mayajambert", "lambert2", "color _color", (0.20932, 0.166365, 0.9091) )
ConnectShaders ("noisel", "outAlpha", "lambert2", "diffuse")
ShaderGroupEnd ()
Кто-то еще считает, что SLIM - самое удобное для создания шейдеров средство? Тогда пусть
бросает читать на этом месте, а мы тем временем продолжим перестройку сознания и галоп по
возможностям Gelato. Вернемся в директорию c:\temp и покажем, как сделать быстрый рендерер
еще быстрее. Удаляем gelato.bat, а бывшее его содержимое копируем в командную строку и
запускаем:
Должен признаться кое в чем... Вернее, я должен быть признаться в этом еще в начале
нашего рассказа про Gelato. Но лучше поздно, чем никогда: мне нравится этот рендерер. Он мне
действительно очень нравится, почти так же, как и prman (а по-моему, даже больше. - Прим.
редактора). У меня есть видеокарта Quadro FX, и да, я - бета-тестер Nvidia, соответственно,
имеющий доступ к внутренней информации (которая разглашению не подлежит) и бета-релизам
(про которые я вам умудрился не сказать ни слова - хотя очень хотелось). Мне тяжко осознавать,
что я как бы предаю свою искреннюю любовь к Renderman'y, но иногда, по вечерам, я тихонько
закрываю дверь своей комнаты и вместо того, чтобы экспериментировать с prman'ом, исследую
это самое «Джелато». Поэтому - еще раз - мне нужно было признаться с самого начала в том,
Что же у нас в сухом остатке? На рынке появился новый продукт, который в полной мере
отвечает обозначенным нами критериям production-качества, он прост для новичков, очень удобен
и гибок в использовании в руках опытных пользователей. Но для того, чтобы воспользоваться
всеми этими преимуществами, вам понадобится современный компьютер, оснащеный мощной
профессиональной видеокартой последнего поколения от Nvidia - то есть денег этой компании
вы заплатите два раза, сначала за рендерер, а потом за видеокарту (а третий раз - за «саппорт»).
Стоит ли этих денег, как минимум, двухкратное ускорение просчета сцены (полученное мной в
ходе антинаучных экспериментов, на одинаковых простых тестовых сценах, на одном и том же
компьютере, с Gelato 1.0R3 в сравнении с prman 11.5.3)? Решать вам.
Для продвинутых. Говорят, индейцы в лесах Амазонии знают, как запустить Gelato на
игровых видеокартах, а также на ноутбуках без Quadra FX. Это сакральное знание передается ими
на закрытых форумах в виде патчей к драйверам Nvidia, которые позволяют обычной видеокарте
эмулировать хай-эндовую - благо элементная база у них одинаковая. Даже и не знаю, что сказать
по этому поводу.
Jot
А первого февраля 2003-го года я оконфузился.
Чувствовал я себя при этом очень глупо, не очень уютно и вообще как-то сугубо некомфортно.
Эту историю я еще никому не рассказывал, потому что немного стыдно до сих пор. По прошествии
нескольких лет я потихоньку начинаю понимать, что все было не так уж и плохо и что зря я так
серьезно отношусь ко всяким мелким происшествиям. Тем более, что стыдиться-то, собственно,
и нечего. Но, как говорится в бородатом анекдоте, ложки-то нашлись, а осадок остался...
И чтобы выветрить осадок, я решил для излития души выбирать только между мегафоном
на набитой народом площади и книгой по MAYA. Сами видите, что выбрал.
А первого февраля 2003-го года Сергей Цыпцын проводила в Москве очередной семинар
по компьютерной графике ViAGra (Visual Art and Graphics). На этом семинаре у меня было
небольшое выступление на тему «Нефотореалистичный рендеринг». Следует отметить, что я уже
давно интересуюсь этой темой и экспериментирую с различными NPR техниками, используя в
своей работе Renderman-совместимые рендереры (а в последнее время и Gelato) как источники
информации для собственных программ и алгоритмов. И для своего выступления на «Виагре» я
подготовил не только доклад, но и небольшой показ своих собственных достижений, которыми
(втайне) очень гордился.
Я отлично понимаю, отчего все они так реагировали. Университетский проект, результат
долгих лет исследований студентов и профессоров, Jot - классический нефотореалистичный
рендерер «как в мультфильме», с возможностью работы из командной строки, простым форматом
файла и изюминкой - интерактивным редактором стилей закраски. Да, интерфейс этого
интерактивного редактора ужасен, но стиль его работы и - самое главное - результаты его работы
завораживают. Именно поэтому в качестве второго претендента на обзор в этой главе я избрал Jot
- это, к тому же, хороший пример того, как пристыковать к Майке посторонний специализированный
рендерер.
То есть сцена в формате JOT описывается в виде точек (вершин), из которых затем
собираются треугольники. Ничего военного, очень похоже на формат файла Wavefront 0BJ - и,
похоже, кроме этой геометрии, нас в файле ничего не интересует. Засучив рукава, быстренько
пишем небольшой скрипт на MEL для экспорта данных в нужный формат (текст скрипта любезно
предоставили Егор Чащин и Сергей Цыпцын; он также доступен на прилагаемом диске в файле
export_jot.MEL):
string $item;
for($item in $list)
{
select -hi -r ($item);
string $hi[] = 'Is -si';
string $it;
print ("EXPORTING:\n");
string $filename = $_filename;
int $FP = fopen($filename, "w");
for($it in $hi)
{
string $type = 'nodeType ($it)';
if($type == "mesh")
}
}
fclose($FP);
}
}
и получаем файл sheep.jot. Все, что нам осталось сделать - запустить Jot и насладиться
результатом:
Для продвинутых и неленивых. Пара советов. Обращайте внимание на то, куда смотрят
нормали вашей поверхности. И помните о том, что при помощи приведенного выше MEL-скрипта
мы можем экспортировать в Jot только один объект - поэтому не забывайте объединять все
полигоны в сцене в единый объект перед экспортом.
Этот рендерер (а его название расшифровывается как General Renderer of Unlimited Num
bers of Things ) имеет одно неоспоримое преимущество перед prman'ом - он использует A-buff-
ег модель рендеринга. В ситуации с батальной сценой с участием десятка тысяч персонажей,
Renderman Pro Server пытается оптимизировать расход памяти и бьет картинку на квадратные
кусочки, каждый из которых будет просчитываться отдельно. На тот случай, если уже обсчитанная
геометрия потребуется в следующем кусочке, информация о ней сохраняется в кэш - иначе
накладные расходы на выгрузку/загрузку/пересчет одного и того же серьезно замедлят процесс.
Для продвинутых. По-научному кусочки эти называются "бакеты". Prman в процессе рендеринга
использует бакеты размером, по умолчанию, 16x16 пикселей и затем обрабатывает сцену не
всю целиком, а по таким вот кусочкам - и по окончании работы с очередным куском занимаемая
им память освобождается. Так вот, проблема в том, что при огромных сценах, в особенности с
полупрозрачными и мелкими объектами, с большим displacement, с применением motion blur и
Depth of field (ну, то есть в типичном кино или телевизионном проекте) - в бакете накапливаются
очень большие объемы информации. Добавьте к этому кэш обработанной геометрии, о котором мы
говорили выше. Конечно, изворотливые пользователи придумали множество различных решений
и обходных маневров - но суть проблемы от этого не меняется.
Любопытно, что GRUNT начинался в 1992 году как универсальный рендерер (и анимационная
система) для операционной системы OS/2 и активно использовался при производстве мультфильмов
и телевизионной рекламы. В 1992-м году 32 мегабайта памяти на персональном компьютере были
огромным размером - и выбор технологии А-буфера дал возможность даже на таком маленьком
Во-первых, это возможность гибкой настройки для определенных задач. Ведь если у вас в
руках есть исходный код продукта и, более того, если вы - его автор, то никакой prman не даст вам
подобной гибкости. Обратите внимание: я говорю именно о гибкости, а не мощности или скорости
работы.
Spore
Рассказ об этом, не побоюсь громкого слова, революционном рендерере будет одной из
самых сложных для меня частей в главе. Все дело в том, что готовя материал к публикации, я
попытался пообщаться напрямую с людьми, непосредственно связанными с разработкой тех или
иных продуктов. В большинстве случаев мне это удалось - не скрою, многим разработчикам очень
приятно и лестно, когда результат их труда будет освещен в книге (пусть и не англоязычной).
Многим, но не Ричарду Бейли.
Результаты работы маленькой студии Ричарда Бейли под названием Image Savant выглядят
немного психоделически - впрочем, это не удивительно, потому что все свои инструменты
- а студия работает исключительно на своих собственных программах и рендерерах - Ричард
рассматривает как пробы в живописи и любительские арт-проекты. Впрочем, для небольшой
студии и психоделически выглядящего "любительского" портфолио у Image Savant неплохой
список заказчиков и фильмов - назовем лишь поверхность планеты Солярис в одноименном
американском римейке или внутренности Земли в фильме The Core.
Так о чем же мы могли говорить с Ричардом в ходе нашего онлайнового интервью, спросите
вы, если я ничего не узнал о его рендерере? О многом. Например, о том, что единственная
программа, которую используют в своей работе сотрудники Image Savant и которую они не написали
сами - это Shake, причем версии 1, без визуального интерфейса, исключительно через скрипты.
-И что переходить на более свежие версии эти мазохисты отказываются категорически. О том, что
в современном мире кинопродакшна, оказывается, вполне можно взять и открыть студию из трех
человек, которые займут свою собственную нишу и будут обеспечены работой на многие годы
вперед. Открыть студию, поясню, не имея ни копейки денег и ни одного заказа на старте. О том,
что хорошие, "правильные" программы пишутся чаще всего не программистами. О том, каким
будет следующий рендерер студии и что он позволит сделать (втайне надеюсь, что у них опять
все получится). О том, наконец, насколько сложен в изучении русский язык для англоязычных
- надеюсь, наша книга поможет Ричарду в решении и этой задачи.
И опять я вас чуток обманул. Потому что сейчас у нас будет еще и пункт номер ноль.
Человеку, только начинающему разбираться с Renderman Pro Server и MTOR, будет полезнее
пока оставаться в знакомом окружении родного интерфейса RenderMan Globals (как минимум, для
того, чтобы не было проблем с прохождением туториалов), но когда его рамки начнут вам мешать
- обратитесь к альтернативным решениям.
1390 Книга Сергея Цыпцына
Альтернативные Renderman-совместимые рендереры
В списке Renderman-совместимых рендереров, находящемся по адресу http://www.
dotcsw.com/links.html и любезно поддерживаемом одним из разработчиков такого рендерера
(Dot С Software, продукт под названием Render Dot С), на апрель 2005-го года находилось 23
продукта, из которых доступны для покупки или (в случае open source) бесплатного скачивания
более половины - 13 штук. Все они обладают теми или иными достоинствами и недостатками,
например, бесплатный Pixie - использует OpenGL и, соответственно, ресурсы видеокарты для
ускорения просчета сцены; недорогой AIR обгоняет всех конкурентов по набору возможностей
и по этому параметру единственный приблизился к prman. Флагманом Renderman-совместимого
рендеростроения с открытым исходным кодом является Aqsis - достаточно медленный, но
старательно пытающийся стать реальным противовесом коммерческим приложениям. Поскольку
все эти продукты Renderman-совместимые (а чтобы называться таким, рендерер должен строго
придерживаться основных положений стандарта), их можно использовать в качестве замены Ren
derman Pro Server, в особенности если вы не использовали какие-то специфические для prman
особенности SL и RIB - более того, вы можете их использовать вместе с MT0R и SLIM, специальным
образом настроив последние.
MayaMan
Одними из первых, кого не удовлетворили качество и ценовые запросы MT0R, стали
антиподы - австралийцы из студии Animal Logic. Уже одно происхождение продукта по всей
видимости дает ему хорошую фору по отношению к конкурентам - находясь на другой, нижней,
стороне нашего шарика, антиподы все время висят вниз головой, что помимо постоянного притока
Для того, чтобы попробовать МауаМап в деле, откройте свою любимую сцену или создайте
новую и подключите плагин. В главном меню MAYA появился новый пункт:
{
PROFILE("begin");
#pragma nolint
SURFACE_TEMPS;
APPLY_SLICE_PLANE else {
PROFILE("SETUP 0 BLINN");
BLINN_SETUP(v_0_);
if(only_do_opacity == 0) {
PROFILEfSETUP 1 BROWNIAN");
BROWN I AN_SETU P (v_1 _ ) ;
PROFILE("SETUP 2 PLACE3DTEXTURE");
PUCE3DTEXTURE_SETUP(v_2_);
PROFILE("SIMULATE 2 PLACE3DTEXTURE");
PLACE3DTEXTURE_SIM(v_2_);
v_1_placementMatrix = v_2_worldlnverseMatrix[0];
PROFILE("SIMULATE 1 BROWNIAN");
BROWNIAN_SIM(v_1_);
v_0_color = color(v_1_outColor);
}
PROFILE("SIMULATE 0 BLINN");
BLINN_SIM(v_0_);
Ci = v_0_outColor;
Oi = Os;
}
DEEP_SHADOW_OPACITY_HANDLER
PROFILE("end");
SURFACE_DEBUG_HOOK
}
He очень похоже на обычный шейдер, написанный на Renderman SL, правда? Тем не менее,
это обычый шейдер. Вся хитрость в том, что в этом шейдере очень широко используются такие
возможности языка SL, как макросы и подстановка значений. Если мы пропустим этот файл через
препроцессор срр, то сможем увидеть истинное лицо нашего шейдера - впрочем, я не буду сюда
его вставлять из-за достаточно большого размера - книжка-то у нас не резиновая.
Нам же осталось указать, что все возможности и настройки MayaMan доступны как через
MEL (посредством ноды под веселым названием MayaManNugget), так и из командной строки -
при помощи программы mayaman_batch_m6.exe (или mayaman_batch_m65.exe, в зависимости от
Для продвинутых. Несколько простых скриптов на MEL, которые упростят вашу работу с Maya-
Man. Во-первых, узнаем, какие вообще параметры есть у ноды MayaManNugget - и, соответственно,
у всего плагина:
setAttr "MayaManNugget.ShadingRate" 1;
setAttr "MayaManNugget.PixelSamplesX" 3;
setAttr "MayaManNugget.PixelSamplesY" 3;
setAttr "MayaManNugget.PixelFilterX" 3;
setAttr "MayaManNugget.PixelFilterY" 3;
Liquid
Существует целая каста людей, которые по принципиальным соображениям пользуются
исключительно бесплатным программным обеспечением, предоставляемым исключительно с
исходным кодом. Бальзамом на душу таким людям будет наш следующий плагин для MAYA - Liq
uid.
Впрочем, в 2002-м году Колин покинул студию и забрал Liquid с собой. После долгих
раздумий, он выложил исходный код плагина на сайте http://liquidMAYA.sourceforge.net/ - и с
этого момента фактически прекратил участие в судьбе своего проекта. Впрочем, его программа
попала в хорошие руки, и целая группа разработчиков занялась доводкой и улучшением продукта,
Из всех рассмотренных нами плагинов для работы с Renderman, Liquid является, по сути,
самым неудобным в повседневной работе. С другой стороны, у этого плагина огромный потенциал
- изначально ориентированная на задачи реального кинопроизводства архитектура, заложенная в
эту архитектуру скорость работы и гибкость дают надежду на дальнейшее развитие этого продукта
- например, некоторые студии вовсю используют Liquid в качестве основы для своих собственных
экспортеров и студийных пайплайнов.
Впрочем, в списке этих студий больше нет Weta Digital. После ухода Колина оказалось,
что второй и третий фильм трилогии "Властелин Колец" серьезно повысили требования к плагину
- а исправлять его было уже некому, да и копирайт на код остался у автора. Поэтому в студии
внедрили новое решение, по иронии судьбы (а скорее, обыгрывая предыдущий продукт - Liquid)
названное Solid (то есть не «жидкость», а «твердость»...).
ShaderMan
Когда-то, очень-очень давно, когда деревья не были такими высокими, а в prman еще
не встроили raytracing, я поймал себя на мысли, что в процессе написания шейдеров на SL все
время повторяю одни и те же шаги и постоянно использую одни и те же куски кода в качестве
образцов. Более того, у меня скопилась целая библиотека таких кусков и готовых шейдеров, на
которых я тренировался и учился, изучая чужой код и воплощенные в жизнь идеи (эта библиотека
существует и по сей день, в ней 685 файлов, и у меня сложилось впечатление, что в некоторые
из них я еще ни разу не смотрел). Так вот, я начал подумывать о том, чтобы каким-то образом
автоматизировать свою работу, написав специальную программу, упрощающую создание шейдеров
- но я не был уверен в том, как должна работать такая программа, на какие принципы опираться и
какой визуальный интерфейс наиболее удобный и быстрый.
Примерно в это же время появился новый продукт компании (тогда еще) Softimage
под названием XSI, в котором похожая идея с визуальным редактированием материалов была
воплощена в Render Tree - и после первого же скриншота я понял, в каком направлении мне
следует двигаться.
Как автор программы, я мог бы долго (подозреваю, что очень и очень долго, но не рискну
проверять, насколько долго на самом деле...) философствовать на тему о том, какие идеи заложены
в ее основу, как именно используется та или иная функция, в чем смысл всего происходящего и
главное - почему аборигены съели Кука... Но вместо этого - давайте попробуем сделать простой
шейдер и при этом сэкономить на типографской краске и обойтись минимумом скриншотов.
Чтобы добавить новый элемент в наш шейдер, можно воспользоваться левым деревом
(и перетянуть-бросить в смысле: «дрэг'н'дропнуть» - необходимые элементы из него), а также
контекстным меню рабочего стола или главным меню программы. Не суть важно, как - важно, что
добавим несколько бриков. Какие?
В правом верхнем углу окна имеем специальную область просмотра результатов рендеринга.
Достаточно выбрать мышкой из списка чего-нибудь нешарообразное, например, чайник (teapot)
и кликнуть в эту область - и сразу появится большое превью, с которым можно делать всякие
разности, например, смотреть по каналам RGB или установить рендеринг не всей картинки, а
только ее части. В общем, имеется в наличии некий мутант, собранный из возможностей fcheck,
it и других просмотрщиков.
Для продвинутых. Чтобы prman мог рендерить сразу в окно ShaderMan, мне пришлось
написать специальный display driver, который затем переписывался еще не раз, в том числе
полностью для Entropy, которая не поддерживала стандартные драйвера дисплея.
А мы, тем временем, через меню View отключаем все эти навороты и остаемся с голым
рабочим столом программы. При помощи контекстного меню добавляем новый брик: fractal/
fractal. Присоединяем его выход к входу Kd OrenNayar. Кстати, о Kd. Везде, где только можно
было, я старался придерживаться стандартных имен параметров шейдеров, которые приняты на
практике, например, Kd - это коэффициент диффузии. Но в определенный момент, столкнувшись
с вопросами новичков, в особенности пришедших из MAYA HyperShade, я придумал опцию View =>
Friendly Shader Parameters, которая дает параметрам шейдеров более дружественные и понятные
имена:
Каким образом результат нашей работы можно использовать в MAYA? Собственно в MAYA
- почти никак, потому что конечным результатом работы в ShaderMan является шейдер SL. Кроме
этого, вы можете экспортировать темплейты Slim, и уже их непосредственно подключать к MTOR.
Либо экспортировать специальные файлы для Liquid - и использовать их. Ну и, наконец, можно
отрендерить шейдер в текстуру, которую затем подсасывать в майские шейдеры.
На этой мажорной ноте придется оборвать наше повествование. Я много чего не рассказал
вам о ShaderMan. Например, о маркинговом меню (идея которого, когда я впервые увидел ее
в продуктах Alias, поразила меня до глубины души). Или о потенциальной расширяемости
программы, основанной на простом структурированом текстовом формате XML и усиленной языком
программирования Tel. Или о встроенной поддержке более чем десятка Renderman-совместимых
рендереров - и легком добавлении новых (опять с помощью волшебного слова правильно:
XML). Или о дружелюбности продукта, которую способны оценить новички, и, одновременно, его
мощности для опытных пользователей (я тоже раньше думал, что это почти нереально). Или про...
- о, вспомнил! О пункте меню File=> Import.
Кроме источников света мы также добавили аттрибут "identifier", который позволяет нам
дать имя объекту - такие аттрибуты добавляют, в том числе, все экспортеры из MAYA в RIB. И
только теперь импортируем в ShaderMan.
Мы только что загрузили внешний RIB файл в качестве сцены для использования в ShaderMan
- и программа предоставила нам возможность выбрать объект, на котором мы будем тестировать
наш шейдер (не случайно мы дали нашему объекту имя).
Вы слышали раньше про древнее китайские искусство Chi Ting? Первая информация об
исследованиях этого искусства появилась в 1988 году в статье Джима Блинна (того самого, который
Blinn shading model) под названием " THE ANCIENT CHINESE ART OF CHI-TING" (http://research.
microsoft.com/users/blinn/CHITING.HTM), однако Джим указал, что первенство в придумывании
названия для этого артефакта принадлежит Биллу Этре. Первое же упоминание об использовании
данного искуства в отношении Renderman, надо полагать, появилось в Siggraph-92 Renderman
Course Notes (что-то вроде: «Материалы учебного курса по Renderman во время Siggraph-92»).
/1адно, ладно, я больше не буду издеваться - название Chi Ting, если его прочитать в соответствии
с правилами английского языка, созвучно английскому же слову cheating - то есть, «жульничать»,
«надувать».
Работая в Лаборатории реактивного движения НАСА (NASA Jet Propulsion Laboratory) над
анимационным роликом, рассказывающем о пролете станции исследования дальнего космоса
«Вояджер» над Сатурном (вы наверняка видели этот ролик), Джим заметил, что на самом деле
зрителя мало интересует сам факт, что созданная анимация построена на точных физических
принципах и отображает истинную картину мира. Более того, использовать "взрослую физику"
при производстве такой анимации зачастую попросту невозможно (в силу нашего незнания,
неготовности или физической невозможности проводить расчеты такой сложности). Обратите
внимание - я не говорю про физические эксперименты и визуализацию их результатов, я говорю
про «Вояджер», красиво пролетающий мимо колец Сатурна.
Так почему бы, в таком случае, не срезать несколько углов и не обмануть зрителя,
упростив расчеты или изменив алгоритм, например? Если в стакане красиво плещется вода,
среднестатистическому посетителю кинотеатра (а телерекламосмотрителю - и подавно!) все
равно, настоящая там вода была в стакане, сымитированная на суперкомпьютере, при помощи
суперпродвинутых, метафизических Liber-формул - или это просто "грязный хак", который
выглядит как вода в стакане.
ShadingRate
В RenderMan существуют несколько настроек качества изображения, которые являются
критическими и без знания о которых вы не сможете добиться нормального баланса между
временем расчета и качеством картинки. Основная такая настройка - это ShadingRate.
Prman, равно как и многие другие рендереры, накладывает шейдеры после тесселяции
объекта на микрополигоны - будем называть их «сэмплами». Если посмотреть на этот вопрос
немного упрощенно, то ShadingRate - это то количество пикселей, которое рендерер будет
просчитывать за один вызов шейдера. Таким образом, вызов
ShadingRate 0.25
означает, что на каждый пиксель картинки шейдер будет вызван приблизительно 4 раза (1/0.25) в
различных точках внутри этого пикселя, а полученные значения будут усреднены и, соответственно,
качество картинки будет гораздо выше. Установка же такого значения:
ShadingRate 20
означает, что вызов шейдера будет производиться один раз на примерно 20 пикселей,
что даст гораздо худшее качество - но рендеринг завершится очень быстро. Так вот, поскольку
именно шейдинг в процессе обсчета картинки занимает большую часть времени (в особенности
для сложных процедурных шейдеров, например, с нойзом), эта настройка чаще всего используется
в Renderman'e.
TransformEnd
Surface "plastic"
Sphere 1 -1 1 360
WorldEnd
Transform End
Surface "plastic"
Sphere 1 -1 1 360
WorldEnd
Shadinglnterpolation "smooth"
Для продвинутых. Как понять, насколько быстрее закончился рендеринг? Можно посидеть
над компьютером с секундомером или песочными часами в руках или написать скрипт, который
будет отсчитывать время за вас. А можно вставить в RIB опцию вывода статистики:
или
в зависимости от того, насколько детальная информация вас интересует. Для наших двух
примеров оказывается, что количество сэмплов, которое prman создал в процессе рендеринга
для каждой из сцен, равняется 1030 для первой сцены и всего лишь 56 - для второй. Экономия
памяти составила 1 мегабайт; экономия времени - несколько раз (поскольку картинка маленькая
и простая, то сосчитать точно количество раз сложно даже с такой статистикой - для второй сцены
она показала 0 секунд).
Таким образом, вы можете установить высокое значение ShadingRate для той части сцены,
которая находится близко к камере, и низкое - для дальних или несущественных объектов. Более
того, используя MEL, это значение можно сделать динамически зависящим от расстояния от
объекта до камеры.
Для продвинутых. Опытные TD советуют использовать для просчета карт теней высокие
значения ShadingRate, вплоть до 32 (хотя все же не больше 8, если используется displacement).
Как оказалось, на видимое качество теней это почти не влияет, а ускорение просчета составляет
до 20 раз.
К сожалению, этот трюк хорошо работает не для всех типов теней; также его не
рекомендуется применять для key light и областей с сильным дисплейсментом из-за возможности
появления "грязи". Сами консультанты из Pixar также советуют при использовании motion blur
увеличивать ShadingRate - поскольку объекты и так будут "разблюрены", то небольшое падение
качества к видимому ухудшению картинки не приведет.
PixelSamples
Архитектура REYES, на которой построен prman, в момент своего создания сильно отличалась
от общепринятых подходов к трехмерному рендерингу, в частности, из-за того, что процесс
шейдинга в ней происходит до определения видимости и вычисления краевого антиалиасинга
поверхностей.
Как это происходит? Получается, что на какой-то стадии шейдеры вызваны, объекты уже
закрашены, а картинка все еще девственно чиста? Что же тогда «красят» шейдеры?
Вот здесь и начинается собственно шейдинг: для каждого такого патчика будет
сформирован однократный вызов соответствующих шейдеров и каждый патчик получит свой цвет
и прозрачность. А если на поверхность назначен и displacement шейдер, патчики-сэмплы будут
сдвинуты в указанном шейдером направлении. Но повторяю: это все пока происходит в трехмерном
пространстве, и до картинной плоскости дело еще не дошло!
В реальности же все намного сложнее, в основном, из-за того, что тут мы попадаем в
царство Его Величества Антиалиасинга. Не вдаваясь в подробности, скажу лишь, что для этой
цели алгоритм REYES использует oversampling, то есть многократный точечный сэмплинг. Через
каждый пиксель картинной плоскости (грубо говоря, нашего конечного изображения) к сцене
провешивается несколько лучиков (точнее будет сказать, point samples, или точечных сэмплов,
- не путать с шейдинг сэмплами, с одной стороны, и со световыми лучами при рейтрейсинге
- с другой стороны!), и выясняется, с каким цветом/прозрачностью они уперлись в шейдинг
сэмплы. Эти значения взвешиваются по каждому пикселю, с использованием одной из нескольких
доступных для пользователя фильтрующих функций и в зависимости от удаленности лучиков от
центра пикселя. Результаты взвешивания записываются в пиксель готовой картинки.
Если копнуть еще глубже, выяснится, что в реальности Prman провешивает лучики, не
разбивая каждый пиксель на регулярную сетку, размером, скажем, 5x5, как в нашем примере, а
случайным образом разбрасывая их в пределах ячеек этой сетки. По науке это называется Stochas
tic Sampling - именно на эту технологию Pixar получила свой патент, и именно при помощи этого
патента засудила компанию Exluna.
Интересно, что такие эффекты как Motion Blur и Depth of Field prman-ом производятся
как раз при помощи PixelSamples. Все очень просто: направления PixelSample-лучей, опять-
таки, случайным образом изменяются с учетом вектора «движения» шейдинг сэмплов и/или их
удаленности от «точки фокуса» камеры. Собственно, вот вам и объяснение того, что prman держит
PixelSamples 2 2
Это означает, что на каждый пиксель приходится 4 точечных сэмпла . Если мы изменим эту
величину (файл на диске pixelsamples11.rib):
TransformEnd
Surface "plastic"
Sphere 1 -1 1 360
WorldEnd
Управляя двумя переменными - ShadingRate (для любых участков вашей сцены) и Pixel-
Samples (для всей сцены) можно очень гибко настраивать рендеринг, добиваясь максимального
Для продвинутых. Покажем, как управлять этими параметрами при помощи утилиты срр
- как мы отмечали раньше, такая утилита есть в поставке почти всех рендереров, совместимых с
Renderman. Для этого внесем изменения в RIB (вы можете просто открыть cpptest.rib с диска):
TransformEnd
Surface "plastic"
Sphere 1 -1 1 360
World End
Мы определили внутри файла три символьные константы - SR, SX и SY. Теперь вызовем в
командной строке препроцессор:
LOD
Еще один трюк из арсенала «читинга» в Renderman - это Level of Details, или сокращенно
LOD. Смысл данной настройки состоит в том, что в RIB файле можно указывать не одну
геометрическую модель, а несколько, и при этом указать, начиная с какого расстояния до камеры
использовать ту или иную модель в данном месте сцены. Представьте себе битву с участием
сотен сражающихся. Без LOD все, что вы могли бы сделать - это использовать одну и ту же
высококачественную модель как для бойцов первого плана, так и для статистов на заднем плане и
что совсем печально - для огромной массы бойцов на горизонте, каждый из которых отрендерится
максимум в десяток пикселей. Применяя LOD, вы можете автоматически подставлять для переднего
плана - максимально детальную и проработанную модель; для среднего плана - что-то немного
упрощенное; для массовки на заднем плане - палку-палку-огуречик или вообще один полигон с
наложенной текстурой - и тем самым сильно уменьшить запросы по памяти и времени расчета. А
разницу никто не заметит.
ReadArchive "templates/teapot.inc"
В MAYA нечто подобное под названием instancing появилось лишь в версии 6.5; в Renderman
эта опция существует уже более 20ти лет.
Работает этот вызов в точности как и предыдущий, с одним важным отличием - в нем
указана область нахождения данного объекта в пространстве (в просторечии, bounding box). Так
вот, загрузка объекта в память рендерера произойдет только в том случае, если область объекта
пересечется с видимой областью камеры, и, следовательно, только тогда, когда расчеты сцены
дойдут до этой области.
Код нашего скрипта на Перле вызовется только в том случае, если он попадет в поле
зрения камеры, и только тогда, когда это необходимо.
Для любознательных. Именно эту технологию применила студия Dreamworks при съемках
мультфильма Shark Tale. В силу производственной необходимости, вся геометрия для этого
мультфильма была подготавлена во внутреннем формате студии, не совместимом с prman (для
совсем продвинутых - это были специальные NURBS'ы). Поэтому был написан процедурный
конвертер из этого формата; вызовы этого конвертера были вставлены в обычные RIB'ы. Таким
образом, на диске геометрия хранилась в удобном для Dreamworks формате и преобразовывалась
в RIB только во время рендеринга - и только в том случае, если в этом была необходимость.
Для продвинутых. Простой пример адаптивного шейдера. В процессе расчета ambient oc
clusion мы в каждом сэмпле выстреливаем некоторое количество лучиков в полусферу, причем
для того, чтобы в картинке не было грязи и чтобы при анимации она не дрожала, это некоторое
количество обычно является достаточно большим - как минимум, 256. Поскольку говорим мы о ray
tracing, любая оптимизация этого процесса будет к месту. Способ адаптации шейдера к свойствам
поверхности, на которой он вызван, состоит в том, чтобы смотреть на локальную кривизну
поверхности в данной точке (например, спрашивая об этом displacement shader, или просто
вычисляя ее по изменению текстурных координат и их производных) и если кривизна большая - то
в этой точке стрелять лучиков меньше (все равно за мелкими деталями грязи видно не будет), а
если небольшая - то побольше.
Еще один простой пример, чтобы немного взбударажить фонтазию нашего читателя.
Попробуйте поуправлять величиной спекуляра или размером дисплейсмента в зависимости
от расстояния до камеры. Или попробуйте наложить дисплейсмент только на края объекта,
ограничившись в остальной части более примитивным и скоростным бампом.
Для продвинутых-2. MTOR поддерживает мощный механизм для связи майских атрибутов
с шейдерами. Чтобы воспользоваться этим механизмом, достаточно добавить к любому майскому
объекту новый атрибут с именем, например, rmanFmyS. Приставка rmanF (таких приставок несколько
и они подробно описаны в документации) дает MTORy сигнал, что данный атрибут должен быть
обработан специальным образом и его значение должно быть подготовлено к экспорту. Все, что
остается сделать - это использовать полученное значение в шейдере, например, вот так:
Если какая-то часть сцены не попадает в камеру и не участвует в отражениях или в ambi
ent occlusion - удаляйте ее, вручную или при помощи скриптов. Если вместо огромного города,
смоделированного до последнего гвоздика на подоконнике, вполне пройдет текстура или mat
te-рисунок на заднике - удаляйте город. Считаете тени? Удаляйте все, что не видно из этого
источника света. Считаете отражения? Удаляйте все, что по другую сторону зеркала. В конечном
счете, рендерер это сделает и сам - но зачем заставлять его прокачивать гигабайты мусора, из
которого не получится ни одного полезного пикселя?
Особую пользу этот совет принесет вам в случае, если вы используете RAT. MTOR известен
своей втыкучестью в момент экспорта сцены («втыкучесть»-слово «нехорошее», «нелитературное»,
но зато очень хорошо иллюстрирующее суть процесса); небольшой скрипт на MEL, который
пробежится по сцене перед экспортом и выключит ту геометрию, какая в данный момент из камеры
не видна, ускорит генерацию RIB'OB ДЛЯ действительно сложных сцен на порядки.
По слоям
Рендеринг "по слоям" уже давно стал обязательным требованием работы в продакшн
хаусах. Обычно в отдельные файлы ("слои") выводятся все персонажи; отдельно от них считаются
спецэффекты (огонь, вода и прочие медные трубы); отдельно записываются environment. Затем
все эти отдельные слои сводятся воедино уже на этапе композинга; это снимает ограничения на
всевозможные настройки освещения и удаление-добавление персонажей в сцену, которые так
любят проделывать заказчики в самый последний момент.
Воспользуемся встроенными возможностями MTOR для того, чтобы показать, как вывести
в отдельный слой информацию о цвете модели, без учета ее освещенности. Для этого вызываем
окно настроек RenderMan=>RenderMan Globals..., в нем в табе Display переключаемся в локальный
таб второго уровня Secondary:
Что мы с вами только что сделали? Мы указали, что хотим отрендерить в отдельный файл
значение Cs (выбранное из длинного списка доступных переменных в поле Mode), которое в языке
шейдеров соответствует цвету объекта до того, как мы в шейдере применили к нему какие-то
операции. Вызываем рендерер и видим на экране вот это:
sho untitled.new_channel.0001.tif
Тот, кто до сих пор шарахается от командной строки, может использовать подростковую
программу, типа ACDSee.
Как видно, перед нами почти готовая заливка для мультипликационного персонажа.
Для продвинутых. Чтобы получить еще и картунную обводку (cartoon outline), выведите в
виде отдельного слоя карту нормалей и преобразуйте ее в любимом композере при помощи фильтра
Sobel. Вы получите достаточно примитивный и не всегда удачный, но вполне качественный контур,
особенно если отрендерите картинку в двойном разрешении, а потом уменьшите ее обратно - это
В код этого шейдера нужно внести некоторые дополнения, с тем, чтобы рендерер мог
увидеть внутренние переменные:
Ci = tex*noi;
}
Исправления, которые мы только что внесли, очевидны: мы создали две новые переменные,
которые специальным образом объявили в заголовке шейдера и этим переменным присвоили
значения внутри шейдера.
Дальше начинается самое интересное. Компилируем шейдер, копируем получившийся
файл aov.slo и используемую текстуру texture.tx в папку с майским проектом, прямо в корень
(файл с исходным кодом шейдера aov.sl можно не копировать). Возвращаемся в MAYA, и в окне
Slim делаем File=>lmport Appearance=> Import Appearance... (или нажимаем Ctrl-I). Выбираем наш
aov.slo и вуаля мы только что загрузили написаный руками шейдер в Slim. Импортированый таким
образом шейдер имеет массу ограничений - например, к его параметрам нельзя присоединять
другие темплейты, как мы это делали раньше - но тем не менее, удобство налицо.
Для продвинутых. Аналогичную операцию выполняет утилита командной строки toslim.
Дальнейшая процедура тривиальна - присоединяем шейдер к овечке и рендерим:
Полученные, таким образом, слои можно также использовать в качестве текстуры для
шейдера. Например, вы можете просчитать ambient occlusion для всей сцены один раз, а потом
подмешивать его в качестве текстуры в свой шейдер. Или все-таки делать это в композере - на
ваше усмотрение.
Для любопытных: Среди крупных студий до сих пор нет консенсуса в том, какие именно
слои и значения каких именно переменных нужны и важны для композа. Философия Weta Dig
ital, например, в этом случае состоит в том, что рендерить нужно в максимально готовом к
композитингу виде, с тем, чтобы композеры не воссоздавали сцену заново из множества слоев,
повторяя фактически работу рендерера. Например, в ходе работы над фильмом " I , Robot" компании
Digital Domain и Weta Digital разделили между собой планы с участием роботов NS5; при этом
Weta считала отдельно только металические и пластмассовые части; DD считал diffuse, specular и
отражение в отдельные файлы, и в результате получая десятки слоев на каждого робота.
Для продвинутых. Рендеринг по слоям - всего лишь один из множества методов борьбы за
уменьшение времени получения конечного результата при рендеринге. Еще один, похожий на него,
прием из той же серии - это всевозможное кэширование значений и последующее использование
этих кэшей рендерером без долгого пересчета. Копайтесь в документации к вашему рендереру
- например, для Prman ключевыми словами будут cache и brick.
К сожалению, при всей возможной автоматизации этих триков они все равно требуют
больших человеческих затрат опытных сотрудников, а их время стоит - что? Правильно: дороже
машинного. Что еще хуже - очень часто эти трюки не срабатывают или срабатывают не так, как
хотелось бы. И тогда приходится прибегать к честному рейтрейсингу и его родственникам - ambi
ent occlusion и GI.
Для продвинутых. Строго говоря, prman до сих пор не является рейтрейсером, даже
несмотря на то, что подобную функциональность он реализует в полной мере. Основным
алгоритмом, который он использует при рендеринге, является REYES; этот алгоритм полировался
и оптимизировался в течение более чем десятка лет. Поддержка raytracing была добавлена в
Renderman Pro Server не так уж и давно, и, судя по описаниям и опубликованным статьям, в
ядро рендерера она не встроена. Таким образом, если вы не используете эту поддержку, все
еще запускается старый-добрый, ультабыстрый REYES-движок. Если вам страсть как хочется
потрейсить, к нему присоединяется новый: движки интенсивно обмениваются данными и даже
совместно используют некоторые структуры в памяти, но все равно, ядро prman'a до сих пор
остается старым, a raytracing - это всего-лишь добавление к нему, существенно замедляющее
процесс.
Собственное все
Рассказывая о работе студии Digital Domain над фильмом " I , Robot", мы вскользь упомянули
тот факт, что в различные слои рендерятся не только различные части робота, но и различные
части шейдера, в частности diffuse-проход. Как это делается? Рассмотрим на примере стандартного
шейдера plastic:
surface plastic( float Ks=.5, Kd=.5, Ka=1,
roughness=.1; color specularcolor=1 )
{
normal Nf;
vector V;
Nf = faceforward( normalize(N), I );
V = -normalize(l);
Oi = Os;
Ci = Os * ( Cs * (Ka*ambient() + Kd*diffuse(Nf)) +
specularcolor * Ks * specular(Nf,V,roughness) );
}
Как видно из заголовка шейдера, никакие переменные из него вывести в виде отдельного
слоя не получится; для этого придется заниматься модификацией кода. Чтобы получить diffuse в
виде отдельного слоя, шейдер нужно изменить, например, вот таким образом:
Nf = faceforward( normalize(N), I );
V = -normalize(l);
diffuseC = Kd*diffuse(Nf);
Oi = Os;
Ci = Os * ( Cs * (Ka*ambient() + diffuseC) +
specularcolor * Ks * specular(Nf,V,roughness) );
}
Ничто не дает большего чуства контроля над ситуацией, как собственноручно сделанный,
отобранный и настроенный инструментарий. В особенности это касается шейдеров, и в еще
большей особенности - тех самых шейдеров, которые идут в стандартной поставке любого Render-
man-совместимого рендерера.
Эти шейдеры хороши, подробно описаны, по ним хорошо учиться - но потом наступает
момент, когда вы хотите чего-то нового, существующие возможности вас не устраивают: это
означает, что пора начинать писать свое.
Так вот, совет наш будет таким: не используйте стандартные шейдеры. С ними сложно
рендерить по слоям, с ними сложно настраивать освещение, экпериментировать с многослойными
текстурами. Напишите свои шейдеры, хорошенько их проверьте в бою, прооптимизируйте и
настройте под себя - и всегда и везде пользуйтесь ними.
Налицо патовая ситуация: явное проявление болезни под названием "nht,etncz глобальное
освещение" с осложнениями в виде невозможно детализированной модели.
Первым делом в таких случаях в руки берется топор и из сцены к такой-то бабушке удаляется
все, что не будет видно камере в конкретном кадре. Имена всех удаленных объектов аккуратно
записываются в отдельный файлик; таким образом нам будет легче убирать их в следующий раз,
когда гигантскую модель здания в очередной раз обновят.
Пришлось хитрить. Один раз для сцены было просчитано решение ambient occlusion и
записано в виде отдельного слоя. Этот слой затем аккуратно подмешивался в источники света
Кроме этих слотов, в сцену добавили один источник света с тенью, генерируемой при
помощи raytrace - к сожалению, без него не обошлось; использовались с десяток локальных
источников, которыми подмазывали, подкрашивали и подсвечивали.
Сначала рендерился основной проход - в нем все стекло выключили. В расчете ambient oc
clusion его тоже не было видно для камеры - но occlusion-лучи, выстреливаемые из каждой точки
сцены, стекло видели и, таким образом, добавили необходимые детали в освещение этажей.
И, наконец, отдельно считалось стекло. Кроме основного слоя, для каждой стекляшки
также считались нормали поверхности - потом, на этапе сборки, сцены из кусков в композере, при
помощи этих нормалей на гранях между стеклами (то есть в точке разрыва и резкого изменения
нормалей) усиливались блики.
Абсолютно естественно, что все роботы и люди, которых вы видели в кадре - тоже считались
отдельно и приклеивались уже на композере.
Как видите, все те советы и трюки, о которых мы с вами поговорили, более чем реальны и
применяются в реальном кино- и видео-производстве - данный пример с говорит сам за себя. Нам
остается дать последний в нашей главе - и самый главный совет.
Думайте о неожиданном
Экспериментируйте. Пробуйте. Применяйте новые интересные техники в необычных
ситуациях. Интернет битком набит информацией, новостями, туториалами. Почти каждый год
на сайте renderman.org выкладываются новые PDFы с материалами конференции Siggraph и
учебного курса по Renderman, проходящего на этой конференции. Эти документы - кладезь, это
неисчерпаемый поток знаний, умений и опыта, концентрированное знание множества очень умных
людей, которые оттачивают все эти приемы на каждодневной практике реального кино- и видео
производства. Их можно читать наискосок, проходить по шагам, постоянно сверяясь с текстом,
пытаться шаблонно использовать в своей работе - а можно подойти творчески и начать пробовать
и задавать вопросы.
Что будет, если на вход шейдера Blinn повесить выход шейдера Noise?
Можно ли использовать карту теней для ускорения просчета сцены? (Ответ: можно.)
А можно ли сделать такой свет, который был бы синим в тени, и белым в остальных
областях?
А как вам идея насчет двух карт глубины - одной из камеры, а другой из источника света
- и определения разницы между их значениями?
Мы строили, строили...
Вот и подошло к концу наше путешествие в мир рендеринга. Для того, чтобы дать вам
необходимые для дальнейшего самостоятельного продвижения опорные точки, приведу небольшой
список литературы. Список будет совсем небольшим, ведь у нас тут не библиография. Да и после
появления Google с Амазоном любой может изготовить такой или подобный список за считанные
минуты. Более того, мы, в отличие от остальной книги, приведем наш список здесь, в конце
главы. Раз уж получилось, что мы так себе, потихоньку, прошмыгнули внутрь книжки про MAYA, не
будем требовать себе места еще и в общем списке литературы.
Итак:
Основа основ Renderman. Начиная с азов, достигает нереальных глубин познания. Заставляет мозги
работать в ранее неизведанных направлениях - лично я по прочтении этой книжки заинтересовался
и занялся нефотореалистичным рендерингом. Интересно, в какую сторону повернутся мозги у
вас?
• Renderman Companion
Пока не появился Advanced RenderMan, эта книжка была основой основ. Капитально устарела,
к сожалению. Я долго думал, стоит ли включать эту книгу, настолько она устарела и настолько
она пугающе нацелена в первую очередь на программистов - но тем не менее, вот она, в нашем
списке.
И опять основа основ, на этот раз для тех, кто всерьез заинтересовался процедурными текстурами,
историей и современностью этого вопроса. Берите исключительно третье издание, в нем куча
нового материала и все картинки - цветные.
Далее - небольшой прыжок в сторону, для тех, кто хочет узнать, как вообще делаются
рендереры:
Учебник для тех, кто хочет написать свой собственный рендерер. В процессе изучения
этого фолианта читатель имеет возможность проследить процедуру создания своего рендерера,
оснащенного под самую завязку самыми современными технологиями, с подробным описанием
используемых алгоритмов - и с полным исходным кодом рендерера, напечатанным прямо в книге
(с использованием Literate Programming). 1000 страниц и почти 2.5 килограмма чистого счастья
для тех, кто понимает.
А это просто книжка, которую я читаю сейчас, в момент написания этого списка литературы.
Она не имеет никакого отношения к предмету разговора; просто она мне понравилась, может,
кому-то из вас тоже понравится. Не перепутайте случайно с Некрономиконом - это совсем разные
вещи.
И это еще, на самом-то деле, не конец. В наш век информационных технологий обойтись
одними книжками в своих исследованиях вам будет, скажем так, трудно. С другой стороны, в наш
век поглощений, закрытий и беспрестанных обновлений страниц, сайтов и компаний, приводить
огромные списки URL тоже, вроде как, неразумно. Так что, обойдемся - сколько там у нас было
книжек, девять? - девятью ссылками:
• renderman.ru
Отбросив ложную скромность, приведем сайт, который я создал и поддерживаю (при неоценимой
помощи и поддержке множества людей). Все о Renderman на русском языке, но в первую очередь
- сообщество, и лишь затем - учебник и помощник.
• renderman.org
Корень всего. Полуофициальный сайт, на котором есть все о Renderman. Бонус-трек: www.render-
man.org/RMR/OtherLinks/blackSIGGRAPH.html - история о закрытии Exluna.
• renderman.pixar.com
• www.dotcsw.com/links.html
• rendermanacademy.com
Академия Renderman. Сайт взял на себя трудную, но почетную обязанность: учить народ
Renderman'y, с чем, в меру сил и умения, справляется.
• film.nvidia.com
• jot.cs.princeton.edu
Домашняя страница рендерера Jot. Что еще сказать? Страница как страница, бывают и
лучше, конечно.
• Google.com
Этот адрес я мог и не писать, конечно. Найдется все, понимаешь. Бонус-ссылка: scholar.google.
com - специализированный поиск по научным работам, диссертациям и исследованиям.
А здесь хочу поблагодарить тех, чья помошь в работе над этой главой невозможно оценить.
Это Александр Сегаль, Сергей Невшупов, Константин Харитонов - без их комментариев, поправок
и советов эта глава не состоялась бы.
До встречи - и успехов!
К вопросу о благодарностях.
Здесь я хотел бы поблагодарить всех, кто явно или неявно помогал мне при написании этой
книги. Совершенно очевидно, что осилить данный труд в одиночку мне не удалось бы никогда.
Кроме того, было бы невозможно написать такую книгу, продолжая работать на постоянной
основе на каком-нибудь проекте или в студии. Поэтому прежде всего я благодарен издательству
Арт Хаус Медиа в лице Александра Шишкина и Ивана Пахомова, предоставивших мне возможность
в течение года работать профессиональным писателем, то есть писать книгу и больше ничего не
делать. Спасибо также Михаилу Шатилову за административную поддержку этого проекта.
В самом начале, при обсуждении плана книги и написании введения, мне здорово помог
Алексей Тихонов как литературный редактор и консультант. Он посвятил меня в некоторые
тонкости обращения с языком и некоторые секреты писательского искусства.
Хочу поблагодарить Сашу Костина, взявшего на себя огромный труд по подготовке макета
книги.
Очень полезным для написания книги оказалось непосредственное общение или переписка
со многими коллегами по цеху. Явно или неявно, общение с коллегами всегда повышает уровень
эрудиции, поэтому я благодарю Константина Харитонова, Аркадия Дубинина, Сашу Халявина,
Игоря Парщикова, Игоря Леводянского, Анатолия Капчинского, Ивана Тиунова, Армана Яхина,
Михаила Лесина, Игоря Даурова, Дмитрия Чурика, Олега Соловьева, Руслана Огородника и многих
других, кого я наверняка забыл упомянуть.
Спасибо Паше Ледину за просвещение меня во всем, что касается mental ray.
Хочу также поблагодарить Дмитрия Озерца, благодаря которому я попал в мир компьютерной
графики и прочно в нем обосновался. Спасибо также Дмитрию Лаврову за просветительскую
работу и консультации в старые добрые времена Alias Power Animator.
Спасибо Антону Петрову за советы, беседы и частые визиты в Египет. Спасибо Ивану
Спасибо всем моим друзьям, поддерживавшим меня всегда: Олегу Булгаку, Стеле Аргату,
Юрию Алябову. Спасибо Людмиле Константиновне Ярославцевой за духовные беседы, дружбу и
веру.
Мой сын родился, когда я писал введение к книге. Я подозреваю, что получил возможность
написать книгу из-за того, что он собрался прийти в этот мир. Спасибо моей жене Кате за
бесконечную веру в меня и поддержку, поддержку, поддержку.
Я также хочу выразить благодарность всем моим ученикам. В конце прошлого века, в
1999 году, я вернулся из отпуска, где безуспешно охотился за волнами на атлантическом
побережье Испании, и получил предложение от Жени Ландышева прочитать курс по MAYA для
восьми студентов из разных концов страны. Помню, что я сам был увлечен MAYA настолько, что
прочел курс на одном дыхании, без всякой подготовки, импровизируя и полагаясь на интуицию.
Парадоксально, но именно эти пять дней спонтанных лекций легли в основу будущего базового
курса по MAYA и составили его большую часть. Этот курс также в основном вошел в эту книгу,
неявно растворившись на ее страницах. После этого Женя предложил мне организовать школу
по обучению MAYA, а я, недолго думая, предложил модный тогда термин Realtime, после чего
родилась школа Реального времени. Я хочу отдельно поблагодарить Женю за это предложение,
ведь это круто изменило мою жизнь.
Я помню, что вначале я практически удваивал объем своих знаний после каждого курса,
ведь нет лучше способа изучить предмет, чем рассказать о нем кому-нибудь. Тем более, что MAYA
тогда была еще так загадочна и мало изучена, что каждый день работы в ней был источником
новых открытий. Тогда же я понял, что рассказывать про MAYA можно бесконечно, поэтому вскоре
родились новые курсы. И не только по MAYA.
Спасибо всем.
Цыпцын Сергей
Благодарности 1425
Просто учим сложной графике