Issuu on Google+


С Е Р И Я

К Н И Г

MAYA - издание первое -


.............................................................................................................................................................................

Издатель При поддержке интернет-портала CGTALK.RU www.KostlnPublishing.ru

Fl-Maya Все права защищены. ® 2006 Издательство KostinPublishing (000 “Костин ). Внимание! Книга защищена законом об авторских правах. Ни одна часть или изображение из этой книги не может быть опубликовано, перепечатано, отправлено электронным способом или другим любым способом без специального письменного разрешения издательства! Все эксклюзивные права на ее содержание принадлежат издательству. О любых нарушениях и незаконных копирования просьба сообщать в издательство по адресу: info@kostinpublishing.ru Внимание! Каждая книга имеет свой уникальный скрытый знак. Главный редактор: Александр Костин Координатор: Евгения Костина Верстка и дизайн: Александр Костин Отдельное спасибо: Юле Макарченко и Нике Карловой Печать: Август-Борг Информационная поддержка: Интернет портал CGTALK.RU, школа RealTime и CGSHOP.RU Издательство: Костин-Паблишинг™ - (000 “Костин”) Email: info@kostinpublishing.ru Web: www.KostinPublishing.ru

.............................................................................................................................................................................


.............................................................................................................................................................................

От издательства Давным-давно, в 1998 году компания Alias/Wavefront выпустила скандальный продукт под странным названием “Maya”. Программа собрала и органично объединила в себе все самое лучшее из множества пакетов, выпускаемых в то время самой компанией Alias/Wavefront. Многие студии стали покупать и активно использовать Maya (не без усилий производителя), что способствовало широкому распространению продукта, его популярности. Maya из года в год становилась все более востребованной программой, и не теряла своих позиций на рынке. Это позволило компании Alias успешно продать все нажитое за баснословную цену спустя 8 лет! И кому? Одному из своих конкурентов! Очень взвешенный и продуманный ход. Теперь Maya со всеми ее технологиями и алгоритмами принадлежит компании Autodesk. Что ждет Maya в будущем? Ясно только то, что компания Autodesk не собирается убирать с рынка такой незаурядный пакет. Нам кажется, что компания будет его активно развивать, и внедрять в конвейер своей линейки продуктов. В 1999 году два человека, Сергей Цыпцын и Евгений Ландышев решили создать школу Realtime School по обучению компьютерной графике в г. Москве. Именно изучение Maya стало первым курсом. Realtime School занимает лидирующее положение в России на рынке профессионального обучения компьютерной графике. Школа внимательно следит за потребностями рынка, и поэтому предлагает большое разнообразие курсов, возможность индивидуального обучения. На дворе 2006 год. Для нашего издательства этот год стал, в какой то мере, испытанием на прочность. Мы выпустили первую книгу в марте месяце под названием <ПОИНТ>. Она до сих пор пользуется большой популярностью, и мы с нетерпением ждем ее продолжения, выпуск которого намечен на конец этого года. Сейчас вы держите в руках первое издание из большой серии книг F1. В нем собраны уроки исключительно наших соотечественников. Книга <F1 :Maya> - это, прежде всего передача опыта профессионалами своего дела. Скорее практика, чем теория. Во время чтения книги, вы сумеете включиться в процесс, а не просто изучить правила по последовательности нажатия кнопок. Авторы материалов пытаются помочь вам сконцентрироваться на практическом применении программы, объяснить с помощью какого инструмента и каким наиболее приемлемым способом вы сможете добиться желаемого результата. Осталось пожелать увлекательного путешествия по страницам книги и плодотворного освоения новых горизонтов. С наилучшими пожеланиями

.............................................................................................................................................................................


ОБ АВТОРАХ .............................................................................................................................................................................

0б авторах Цыпцын Сергей Писатель, публицист, просветитель. Работает с Майя около девяти лет со времен дремучих бета-версий. Один из создателей школы Realtime. Свободный учитель, специализируется на обучении, консалтинге, решении проблем и написании экстремальных скриптов.

Забелин Владимир Окончил механико-математический факультет Московского государственного Университета. Кандидат физико-математических наук. Компьютерной графикой занимается с 1992 года. За 13 лет работы пришлось близко познакомиться с разными софтами: Autodesk 3d studio, Advanced Visualizer, Power Animator, Maya, After Effects, Shake и, естественно, с целым рядом “вспомогательных” программ-о Photoshop до Notepad.

.............................................................................................................................................................................


ОБ АВТОРАХ .............................................................................................................................................................................

Король Геннадий

Программист, музыкант. Учится в Computer Science университете города Tel-Aviv. Компьютерной графикой занимается с 12 лет. Активный участник портала CGTALK.RU в разделе по Maya.

Ледин Павел

По образованию художник. Закончил Абранцевский художественно-промышленный колледж им.Васнецова, а также Московский Государственный Открытый Педагогический университет им Шолохова, художественный факультет. Опыт работы в CG около 6 лет. Начинал с игровой индустрии, сейчас работает в индустрии кино и рекламы, занимаясь практическим всем что, относится к CG, но в основном специализируется на визуализации, шейдинге и лайтинге. Занимается написанием шейдеров для Mentalray, а также некоторых mel скриптов. Известен так же под псевдонимом Puppet.

.............................................................................................................................................................................


.............................................................................................................................................................................

Оглавление Настройка Maya под моделирование (кастомизация). Автор: Король Геннадий

18 Интим с программой или переходим на «ты» с Maya..................................................................... 19 Добавление удоб 21 Умные (context sensitive) хоткеи и marking менюшки......................................................................25 Stickey hotkeys......� 29 Вступление...........�

Майские волосы. Трюки и уловки. Автор: Цыпцын Сергей

34 Понимая волосы..................... ............................................................................................35 Эффективное выращивание..............................................................................................36 Жесткость это проблема................... .................................................................................41 Три типа кривых при работе с системой волос.................................................................41 Прически и укладки.............................................................................................................42 Коллизии прежде всего.......................................................................................................42 Симметричные трюки.........................................................................................................44 Ручная укладка....................................................................................................................45 Динамическая укладка.......................................................................................................46 Удлинение волос.................................................................................................................48 Остановка волос.................................................................................................................49 Визуализация волос...........................................................................................................49 Удаление симметрии..........................................................................................................51 Увеличение плотности........................................................................................................54 Трюки уплотнения...............................................................................................................55 Рекомендации по освоению MAYAHair...............................................................................

.............................................................................................................................................................................


.............................................................................................................................................................................

57 Трюки для взрослых..........................................................................................................60 Стрижка волос...................................................................................................................60 Att� 62 Крупные планы..................................................................................................................65 Работа с закэшированными системами волос................................................................66 Летающие волосы..............................................................................................................68 Растущие волосы или hairpartides....................................................................................70 Некоторые замечания по применению динамических кривых.......................................73 Универсальный совет для работы с волосами................................................................73 Свет и Тени........................................................................................................................

Свет мой, зеркальце, скажи... Автор: Забелин Владимир

76 Изменяем цвет отражения..................................................................................................79 Создание шейдера..............................................................................................................

Работаем с Mentalray. Автор: Ледин Павел

83 Различие между рендерами................................................................................................84 Преимущества MayaSoftware..............................................................................................84 Преимущества MentalRay....................................................................................................86 Переход на MentalRay и разница восприятия....................................................................87 Пон 87 Color.......� 88 Непонятные шейдера...........................................................................................................88 Вступ

93 Описание шеидеров..............................................................................................................93 Materials.� 98 Sha� 99 Volu� 99 ............................................................................................................................................................................. Cust�


.............................................................................................................................................................................

101 Photonic Materials............................................................................................................101 Photon Volumetric Materials............................................................................................101 Textures............................................................................................................................101 Environments...................................................................................................................106 Light� 106 Photon Emitters...............................................................................................................106 L� 106 Len� 106 Output Shaders...............................................................................................................107 Geometry.........................................................................................................................107 Contour............................................................................................................................107 Sample Compositing........................................................................................................107 Data Conversion..............................................................................................................109 State Shaders..................................................................................................................110 Miscellaneous..................................................................................................................110 Mentalray bake.................................................................................................................111 Bake to Texture................................................................................................................114 Bake to Vertices...............................................................................................................117 Написание шейдеров (Rendering в продакшне)...........................................................119 Для чего нужно писать шейдера?..................................................................................121 Подготовка и настройка проекта...................................................................................121 Первый шеидер...............................................................................................................124 Освещение...................................................................................................................... 126 Написание mi файлов.....................................................................................................129 Displacement Shaders.....................................................................................................

Команда emit.

Автор: Забелин Владимир

134 Столкновение твердых тел..............................................................................................145 .............................................................................................................................................................................


.............................................................................................................................................................................

UV маппинг вместе с Unfold UV’s. Автор: Король Геннадий

153 Готовимся к работе.........................................................................................................................154 Текстурим простейший объект......................................................................................................156 Разворачиваем модель головы.......................................................................................................159 Вступление......�

«Объемные» спрайты в Maya. Автор: Забелин Владимир

170 Неподвижные объекты и движущаяся камера.............................................................................170 Неподвижная камера и движущиеся объекты..............................................................................177 Заключение.......� 181 Вступление......�

.............................................................................................................................................................................


Настройка Maya пол моделирование .............................................................................................................................................................................

Автор: Король Геннадий

Настройка Maya под моделирование (“кастомизация”)

Большая часть рабочего процесса с современными пакетами сводится, по-сути, к лазанью по менюшкам, клацанью по кнопкам и тасканию ползунков. Все это есть рутина, и в наших интересах сократить количество оной до максимального минимума. В этом мастер классе я бы хотел пролить свет на одно из важных достоинств пакета Maya - возможности по кастомизации. За основу я решил взять кастомизацию моделирования, считающегося в народе слабым местом программы. В этой статье мы рассмотрим базовую “under the hood” работу с Maya. Создание базовых marking менюшек, используя эти команды. Пользуясь этими знаниями, мы заставим базовую команду “delete” (del) удалять выделенные полигональные ребра командой Delete Edge (Edit Polygons). Далее мы рассмотрим более продвинутые сетапы - умные хоткеи и marking menu. Идея в том, чтобы заставить одну единственную клавишу выполнять разные действия в зависимости от того, как и когда мы её нажимаем. В завершение мы, на примере Split Polygon Tool, рассмотрим очень удобный механизм работы с горячими клавишами - Stickey Hotkeys. Мы сможем резать полигоны с зажатой горячей клавишей, а по её отпускании “сетап” автоматически вернёт выделенные компоненты, предыдущий инструмент, и режим выделения компонентов. Я надеюсь, каждый в этой статье откроет для себя новые возможности любимого пакета и сможет сделать свою работу намного удобнее, так как описанные техники применимы во всех областях работы с Maya.

............................................................................................................................................................................. Король Геннадий


.............................................................................................................................................................................

Автор: Король Геннадий

Настройка Maya под моделирование (“кастомизация”)

Вступление: В этой статье я бы хотел поговорить об одном из самых важных достоинств майки - ее кастомизации. Видя много людей, пытающихся освоить пакет, но никогда всерьез не обращающих внимания на поистине внушительные возможности кастомизации, теряющих, таким образом, большую часть удовольствия от работы с программой, я решил пролить свет на эту тему. За основу я решил взять кастомизацию моделинга, считающегося в народе слабым местом программы. Но принципы применимы в любой другой области. Итак, для начала ответим на несколько часто задаваемых вопросов. 1: А зачем оно мне надо? Как сказал кто-то из мудрых: “It’s not about the tools, it’s about the workflow”, что в переводе на нормальный язык означает: “дело не в самих инструментах, дело в том, насколько удобно с ними работать”. Большая часть рабочего процесса сводится, по сути, к лазанью по менюшкам, клацанью кнопками, тасканию ползунков и т.д., и т.п. Все это есть рутина, и в наших интересах сократить количество оной до максимально возможного минимума. Важна также скорость доступа и интуитивность того, с чем мы работаем; желательно, чтобы смежные по смыслу операции были удобно сгруппированы вместе. При возможности, в одной менюшке или на одном хоткее, вместо огромного меню с кучей странных надписей (а ля Edit Polygons). Перебарщивать тоже не стоит слишком умные хоткеи или маркинг менюшки только добавят неудобств. «Сетап» должен быть как можно проще. Вряд ли после восьми часов работы вы бы хотели думать, какую комбинацию клавиш вам нажать, или в каком режиме и над какими объектами вызывать конкретную команду. Все должно быть максимально интуитивно и просто. 2: Но для этого же нужно знать MEL!? Я не программист - я художник! Почему это не сделано в самой майя? На вопрос, почему майя по дефолту не супер удобно кастомизирована, точный ответ дать могут, скорее всего, только дизайнеры программы. Но из своего опыта общения с людьми я заметил, что слово “удобно” и “хороший workflow” разными людьми понимается весьма по-разному. Разработчики приготовили нам готовую в употребление программку, нам же только осталось ее немного “приправить” на свой вкус. Именно “немного”, так как это действительно требует минимума действий и самого что ни на есть базового знания этого страшного слова “MEL”. Каждый в состоянии получить эти знания за пару часов целеустремленного изучения двух страниц хелпа, посвященного базовому синтаксису. Знания о том, как и где ставить точку с запятой, как выглядят переменные и флаги. Желательно так же понимать, как создаются маркинг менюшки и хоткеи. Все, что далее от нас потребуется, в принципе, - это понимание того, что майя выдает в Output win-dow, а затем удачное копирование этих команд. Далее, после легкой коррекции, мы просто присвоим эти команды на маркинг меню или хоткеи. “Но я не программер!!” Ты, вышел из класса!.. На самом деле, между тем чем мы будем заниматься, и программированием ; очень мало общего. Отговорочки из области “я не должен быть программистом, чтобы использовать программу, но программа этого требует”, по моему мнению, совсем “не катят”. В этой статье я несколько раз пройдусь по совершенно базовым вещам, а в случае с несколько более сложными сетапами я попытаюсь дать максимально понятное объяснение тому, что там происходит. Так же я постараюсь описать основные команды, которые могут пригодиться. Ну а для самых ленивых, не желающих входить в сут* дела, но жаждущих получить заветную кастомизацию, есть возможность просто переписать код после поверхностного просматривания статьи. Теперь, после отбора самых смелых и целеустремленных пользователей, пойдем дальше и попробуем реализовать слова на деле. .............................................................................................................................................................................


Настройка Maya под моделирование .............................................................................................................................................................................

Интим с программой или переходим на «ты» с Maya: Одним из первых шагов для сближения с программой является понимание того, что происходит у нее “под капотом”. Кто из вас водит машину? Большинство, хорошо. А кто из вас регулярно следит за ней, и даже может открыть капот и что-то починить? Все, молодцы. Теперь, кто из вас пользуется программой? Все, отлично. А кто из вас хоть раз заглядывал ей под “капот”, пытался привести что-либо в порядок подстроить? ..Молчание?.. Один, два,... все? Неужто больше никого? Итак, у всех в бардачке имеется коробочка с основными ��нструментами, ключами, отвертками и смазками? В Maya эта коробочка называется Script Editor. Именно с ним мы будем работать большую часть времени Возьмем простой пример общения с программой для ответа на основные вопросы по MEL На будущее: для лучшего понимания, для каждой темы я буду выбирать конкретный практический пример и на нем показывать основные принципы. Начнем с самого простого - часто при моделировании нам хочется создать разнообразные примитивы: всякие плоскости, шарики и иногда даже кубики Давайте создадим маленькую маркинг менюшку, включающую в себя создание основных примитивов. Перед созданием самого меню, которое, по сути, является набором мел кода прикрепленного к нужной кнопке, неплохо бы раздобыть тот самый заветный код В этом нам поможет Script Editor. Как вы уже заметили, Script Editor состоит из двух частей -грубо говоря, окна ввода и вывода. В окне вывода можно получить полную информацию о том, что происходит во время работы. Итак, посмотрим, как майка отзовется о нашем желании создать полигональный кубик: Идем в меню Create / Polygon primitives / Cube. Отвлечемся на мгновение от ненаглядного кубика и посмотрим, что говорит о нем сама программа. В Script Editor, в окне ввода читаем нечто наподобие: polyCube -w 1 -h 1 -d 1 -sx 1 -sy 1 // Result: pCubel polyCubel //

-sz 1 -ax 0 10 -tx 1 -ch 1;

Первая строчка показывает команду, которая была выполнена (polyCube), и флаги, с которыми мы ее выполнили (флаги - это парни с черточкой: например -w) Флаг - это, по сути, способ передачи конкретных параметров нужной команде. Пару слов о второй строчке кода, который нам написала майка, начинающегося со слова “// Result”: тут Maya говорит нам, что команда, которую мы выполнили, кроме конкретного эффекта над сценой, еще и возвращает значения. В данном случае - имя Transform и Shape-ноды созданного кубика. Эта информация весьма полезна, скажем, эти имена можно было бы засадить в переменную и делать с ними более интересные вещи по мере выполнения кода. Скопируйте первую строчку кода в окно ввода, выделите код и поиграйтесь с ним - поменяйте значения флагов, удалите парочку и т.д., и т.п. (нажимая Enter на Num паде можно выполнять выделенный код, не стирая его из самого эдитора). Полный список всех команд с описанием можно найти по знакомому адресу, по знакомой клавише в разделе Mel command reference. Итак, наигрались? Наверняка вы заметили, что майка выписывает весьма длинный код с множеством информации, но, на самом деле, большая часть флагов нам не нужна, так как существуют “заводские” значения, которые нам подходят, соответственно, в этих флагах нет нужды. Например, я удалил все флаги, кроме двух, определяющих ширину (-w) и высоту (-п) будущего кубика: polyCube -w 1 -h l; Эту команду уже можно использовать для нашего маркинг меню. Похожим способом можно раздобыть команды для создания шариков, цилиндров и прочих любимых примитивов. Я также решил в эту менюшку добавить код для создания источника света, локатора, камер и группирования. ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Вот команды, которые я использовал для создания точечного источника, локатора и группировки: spaceLocator -p 0 0 0; // локатор defaultPointLight(l, 1,1,1, 0, 0, 0,0,0, 1); // point light group; // групка Итак, лезем в Window - Settings Preferences - Marking menus. Создаем новое маркинг меню - Create marking menu. Обзываем его чем-нибудь осмысленным, скажем Create Menu. Теперь в каждой ячейке, кликом по правой кнопке мыши выбираем Edit menu item. Это, по сути, будущие кнопки в нашем маркинг меню. Даем каждой желаемое название и в поле с кодом вставляем ранее заготовленный код. Обратим внимание на возможность создания подменюшек (в данном случае я сделал подменю для создания разных камер -1 узловая, 2 узловая и т.д.). После каждого действия нажимаем Save and close. Тестируем наше маркинг меню - и вуаля, работает.. Я уже вижу хитрые улыбки знающих майщиков. Существует очень изящный способ создания такого же меню, только без сложных операций с самим кодом. Можно перетаскивать иконки с шелфа прямо на элементы маркинг менюшек средней кнопкой мыши. Так же элегантно можно перетаскивать кнопки с шелфа в input window скрипт эдитора. Например, бросьте иконку цилиндра с шелфа в скрипт эдитор. Получите команду CreatePolygonCylinder. В случае с созданием примитивов можно использовать и ее для добавления цилиндров в сцену. Но эту команду вы не найдете в хелпе. Это одна из множества процедур, которые майя создает при запуске (runTimeCommand). На эту команду удобно смотреть как на маленький скриптик, запакованный в процедуру с конкретным именем. Узнать, что находится внутри нее, можно так: run Time Command -q -c CreatePolygonCylinder; // Result: perfоrmpolyPrimitive Cylinder 0 // Maya нам по секрету рассказала что за код находится внутри этой команды. Но мы не остановимся, пока не узнаем всю правду, поскольку performPolyPrimitive по-прежнему не находится в референсе. Существует очень функциональная команда, которую можно вызвать следующим образом: whatls “а че это?”; // Result: Unknown // Эта команда расскажет, чем является фрукт, который мы ей подсунули. Продолжим наше расследование и спросим у команды, что такое performPolyPrimitive: whatls performPolyPrimitive; // Result: Script found in //AliasWavefront/Maya7 .0/scripts/others/perf ormPolyPrimitive .mel // Опа! Все ясно - это одна из процедур, определенных в стартовых скриптах майки, при этом нам любезно предоставлен адрес, по которому эту процедуру можно отыскать. Особые энтузиасты могут даже изучить содержимое процедуры. Вернемся к нашей CreatePolygonCylinder. Использование ее вместо кода имеет одно преимущество: в отличие от конкретной команды polyCylinder, CreatePolygonCylinder процедура создает примитив с настройками, указанными в опциях создания примитива. То есть если мы в окошке опций для цилиндра изменили радиус/кол. сегментов, наше маркинг меню создаст новый цилиндр с новыми опциями, в отличие от polyCylinder команды. .............................................................................................................................................................................


Настройка Maya под моделирование ............................................................................................................................................................................. Теперь мы разобрались, кто есть кто, как отличить базовую (API) команду от мел процедуры. Дело за малым: нужно сохранить наше маркинг меню, найти его в хоткей эдиторе, в категории User marking menus, и прицепить к любимой клавише. Обратите внимание на то, что команды для вызова маркинг меню - это по-прежнему просто набор мел кода, что дает нам возможность комбинировать маркинг меню с другими командами, менюшками и т.д.

Итак, я надеюсь, этот параграф дал вам базовое представление о том, что к чему. Вдоволь наигравшись (тонкий намек на основательное закрепление материала), идем дальше.

Добавление удобств. Заставляем стандартные вещи работать нестандартно. Вам никогда не хотелось изменить тот факт, что при включении режима компонентов правой кнопкой мыши, режим выделения по-прежнему остается объектным (в отличие от F8-F11)? Или что при удалении ребер совершенно естественной клавишей delete остаются вершины? Давайте изменим положение вещей. Для начала изменим поведение любимой клавиши - delete в отношении ребер. Определимся с тем, что нам нужно: известно, что для красивого убиения ребер (без остатка вершин) существует команда Delete Edge (Edit Polygons). Нам нужно узнать, выделены ли ребра в данный момент, и применить заветную команду; если нет то нужно дать майке делать то, что она делала ранее. Возникает пара вопросов: что если нам все же захочется удалить ребра обычным способом, оставив вершинки? Хм, добавим комбинацию - скажем, shift delete - для этих целей, А что если кроме ребер мы выделим что-нибудь еще? Тут несколько вариантов: если мы хотим чистенький и красивый скрипт, работающий в любых случаях, мы заставим работать его и при этих условиях. Если же мы делаем это для себя и предполагаем, что при удалении ребер ничего выделено не будет, мы пишем простой вариант скрипта. В данном примере я рассмотрю оба варианта. Перейдем от идейных вопросов к техническим. Нам нужно узнать, выделены ли ребра в данный момент, и нужно имя команды, удаляющей ребра. Но самое главное - как перехватить нажатие клавиши delete? Кто крикнул Hotkey Editor? А вот и нет... Нет там такой команды, так же, как и нет возможности прицепить что-либо к клавише delete. Как быть? Выделим ребро на модели, затем нажмем delete и посмотрим, что нам сказала по этому поводу майка: ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. doDelete; Вспомнив то, что выучили выше, воспользуемся whatls и узнаем, кем является этот doDelete: whatls doDelete; // ??? // Result: Mel procedure found in: : /AliasWavef ront/Maya7. O/scripts/others/doDelete .mel// Ясно: это процедура, находящаяся в одном из startup скриптов; адресок имеется. Все, что нужно сделать, - немного отредактировать этот скриптик. На самом деле, редактировать майские файлы я строго не рекомендую, разве что если только есть много свободного времени на переустановку программы. Вместо этого можно скопировать этот файл и скинуть его в папку: : \Documents and Settings\henry\My Documents\maya\7.0\scripfcs И данный скопированный файл уже можно редактировать. Таким образом, майка будет использовать последний вызванный файл (скрипты в папке Documents and Settings вызываются после майских стандартных скриптов; так как процедуры имеют одинаковые имена, Maya будет использовать процедуры из нашего файла). Чтобы убрать нашу модификацию, достаточно просто удалить (или переименовать) скрипт, при этом нет возможности запортить какой-либо из майских файлов. Приступаем к работе: копируем скрипт doDelete в локальную папку с документами, открываем его в любимом редакторе, находим поиском саму процедуру doDelete и смотрим. К нашему счастью, она весьма проста: global proc doDelete() { string $sel[] = ls -sl -dag’; // узнает имена выделенных объектов skinClusterPreDelete ($sel) ; // выполняет какую-то процедуру связанную с // удалением, что именно нас не волнует delete; // процедура удаления :-) } Примечание: этот файл найден в седьмой версии Maya, в других версиях файл может чуток отличаться. Все, что нам нужно сделать, - это добавить логический оператор if, который при условии выделенных эджей применит к ним оператор уничтожения. В обратном случае мы просто не делаем ничего и передаем работу старому коду Maya. Как определить, выделены ли ребра в данный момент? Существует отличная команда фильтр - filterExpand, которая фильтрует массив имен (или текущее выделение), оставляя только объекты нужного типа. Тип задается маской - целым числом. Например, 32 соответствует ребрам, 31 -вершинам, 34 фейсам и т.д. (полный список в референсе). К примеру, чтобы получить список всех выделенных ребер на данных момент, можно запустить: filterExpand -sm 32; // Result: pPlanel.e[0] pPlanel.e[2] pPlanel.е[3] Эта команда возвращает массив имен. Нам только остается узнать, с лько имен в массиве (ребер в выделении), и если их больше чем 0, значит, в выделении :ть ребра. Для вычисления размера массива или стринга (текста) воспользуемся командой size. .............................................................................................................................................................................


Настройка Maya под моделирование ............................................................................................................................................................................. Соберем все это вместе: if ( size (‘filterExpand -sin 32 ‘) > 0) // проверяем размер массива с именами ребер print “Опа, выделены ребрышки!”; else print “He выделено ни одного ребра.”; Этот простой паттерн просто скажет нам, выделены ли в данный момент ребра. Способом описанным в предыдущем параграфе, узнаем имя команды для убийства ребер: “polyDelEdge -cv true;”. Соберем вместе: if ( size (‘filterExpand -sm 32’) > 0) polyDelEdge -cv true;

// проверяем выделены ли ребра // удаляем их не щядя вершины

Обратите внимание на обратные кавычки и скобки - таким образом мы заставляем size пройтись по списку, который возвратит нам filterExpand -sm 32. Если список пуст, size вернет 0 - условие if’а, а не выполняется - соответственно мы не делаем ничего. Если же в выделении присутствовали ребра, удалим их процедурой polyDelEdge -cv true; Получаем отредактированную версию doDelete: global proc doDelete() { string $sel[] = ‘ls -sl -dag’; skinClusterPreDelete($sel); —>if ( size <’filterExpand -sm 32’) > 0) polyDelEdge -cv true; }

delete;

Таким образом, если выделены ребра - удаляем их нодой, затем скрипт выполнит стандартную процедуру delete и удалит все остальное (если что-то еще было выделено). Сохраняем новую версию скрипта doDelete и перезапускаем майку. Быстренько создаем кубик, хватаем ребра и жмем delete. Вуаля! Работает, как хотели, и все, что требовалось - это добавить две строчки простейшего кода. Вспомним о недостатках, оговоренных ранее. Теоретически наша модификация должна работать на нескольких выделенных объектах и ребрах. Скажем, если выделить кубик и ребро и нажать delete, майя нас удивит и выругается. Ошибка в том, что команда “polyDelEdge -cv true;” оперирует над ребрами. Мы вызываем ее без каких-либо параметров (перед “;” нет ни имени, ни списка с именами объектов); таким образом, команда вынуждена использовать текущее выделение. Но, так как в нем присутствует несколько выделенных объектов, код не работает. Использование команды для удаления ребер на целом объекте оператор применяет ко всем ребрам объекта, но отказывается работать при нескольких выделенных объектах. Мы же не хотим удалять все ребра выделенных объектов. Можно заставить polyDelEdge ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. оперировать только на выделенных ребрах, передав ему список их имен как параметр. Например, так: polyDelEdge -cv true (‘filterExpand -sm 32’) ; // заставляем polyDelEdge // работать только на ребрах Правим процедуру, проверяем. Проверять работу скрипта можно несколькими способами. Можно каждый раз изменять скриптовый файл, а потом перезагружать его, набрав “source doDelete;” (doDelete в нашем случае - это имя скриптового файла, над которым мы работаем). Я предпочитаю тестировать скрипт в скрипт эдиторе, или копировать его на шелф и тестировать там. Теперь займемся вторым недостатком. Что, если нам таки захочется применить “старенький” delete к ребрам? То есть удалить только ребра, оставив вершины. Можно использовать наш сетап и потом просто изменить опции ноды - убрать опцию. Но в данном случае мы модифицируем скрипт так, чтобы, скажем, при нажатии shift, delete вызывал старую процедуру и игнорировал наш сетап. Но ведь delete у нас нет в хоткей эдиторе, соответственно, нет возможности привязать его к шифту. Тут нам поможет еще одна полезная мел команда - “getModifiers”. Все, что она делает, -это возвращает индекс зажатого в данный момент модификатора/ов. Например, если во время вызова getModifiers был зажат шифт, процедура вернет 1, если контрол - 4 и.т.д. Выложите getModifiers на свободный шелф и понажимайте на нем при разных зажатых модификаторах, обратите внимание на result, который при этом выдается. Воспользуемся этой замечательной процедуркой: global proc doDelete() { string $sel[] = ls -sl -dagv; skinClusterPreDelete($sel); if ( size (‘filterExpand -sm 32’) > 0 && ‘getModifiers’ != 1 ) //добавили обязательное условие - шифт ве зажат polyDelEdge -cv true; delete; Тут && - and говорит, что оба условия должны выполняться одновременно (противоположное по смыслу выражение || - OR: одно из условий должно выполняться). Таким образом, если шифт зажат, оператор if не выполнит свою процедуру, так как одно из обязательных условий не выполняется (“!=” интерпретируется как “не равен”). Сохраняем скриптик, тестим и наслаждаемся...

.............................................................................................................................................................................


Настройка Maya под моделирование .............................................................................................................................................................................

Умные (context sensitive) хоткеи и marking менюшки. Принцип такого сетапа прост, но очень эффективен. Идея в том, чтобы заставить одну единственную клавишу выполнять кучу разных действий в зависимости от того, как и когда мы ее нажимаем. Помните marking menu для создания примитивов? Я повесил его на клавишу х (привязкой к сетке пользуюсь редко). Что если на эту же клавишу навесить еще одно маркинг меню? Скажем, если мы работаем с полигонами, - меню с основными poly операциями? Такие как глобальный merge вершин (я обычно перемещаю вершины друг к другу зажатой клавишей v, а потом применяю глобальный merge, который мерджит все близлежащие ребра), mirror, soft/hard edge, move component, localTools, delete history и т.д., и т.п. Помним так же про extrude? Что если нажатие-отпускание клавиши х будет экструдить еджи/ фейсы/вершины, а нажатие той же клавиши + левой кнопки мыши будет вызывать разные маркинг менюшки в зависимости от того, с чем мы работаем? Более того, можно привязать все это к текущему режиму. В режиме Modeling имеем одни менюшки/ действия, в режиме Animation - другие, в Dynamics - третьи... Ну, и в довесок можно узнать, где мы сейчас работаем, скажем, в перспективе использовать одно, в UV эдиторе - другое, а в гипершейде - третье... Технические вопросы: В первую очередь, требуется разное поведение скрипта при разных условиях. Это мы уже умеем делать - с помощью логического оператора if. Еще скрипт должен вызывать несколько разных маркинг менюшек. Также нужно собрать “Экструдер” - процедуру, умеющую экструдить все типы компонентов. Ну и самое важное - нужно каким-то образом определить, как именно мы нажимали на наш хоткей, было ли это быстрое нажатие-отпускание или вызов маркинг меню. Ну и не помешает процедурка, узнающая текущий режим в майке (Animation и т.д.). Начнем с процедуры под кодовым названием “Экструдер”. Ее задача - различить, что выделено в данный момент, и применить нужный экструд. Для выделенных ребер -экструд ребер, для фейсов - экструд фейсов. Для вершин - экструд вершин; если вы часто им пользуетесь, можно прицепить чтонибудь другое, часто применяемое к вершинкам - к примеру, merge. Вся информация о процедурах у нас есть, все, что нам потребуется, - это логический оператор if и filterExpand для определения типа компонентов. Процедуры экструда берем из шелфа: if (size(‘filterExpand -sm 32’) > 0) // выделены ребра ExtrudeEdge; // экструдим ребра else if (size (‘ filterExpand -sm 34’) > 0) // фейсы ExtrudeFace; // экструдим фейсы else if (size(‘filterExpand -sm 31’) > 0) // вершинки ExtrudeVertex; // экструдим вершинки Кстати, после проведения самого экструда, мне лично удобно перемещать его стандартным майским move tool’oм, поэтому можно добавить строчку, которая будет переключать show manipulator tool на move tool. Теперь подумаем, как можно определить, как именно был нажат хоткей. Главным образом, при нажатии хоткея выполняются две п��оцедуры: первая - при нажатии (press) клавиши, вторая - при отпускании (release). Самое логичное решение - это измерить время, прошедшее от нажатия клавиши до его отпускания. Если оно больше, скажем, полсекунды, значит, мы во время нажатия вызывали маркинг меню, иначе мы просто выполнили нажатие-отпускание клавиши. ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Представляю вам замечательную процедуру - timerX, которая поможет нам в измерении времени в Maya. Очень удобна для оптимизации скриптов/плагинов, а также для наших умных хоткеев. К примеру, чтобы узнать текущее “майское” время, наберем: timerX; // который час? // Result: 7705.16 // да вот ужо 7705 секунд как ты меня запустил Это время можно сохранить в переменной с помощью обратных кавычек, например, так: float $startTimer = ‘timerX’ //засаживаем майское время в переменную $startTimer Теперь наберите: timerX -startTime $startTimer; Майка скажет там, сколько секунд прошло с момента $startTimer до текущего времени. По сути, паттерн для измерения времени выполнения процедур выглядит следующим образом: float SstartTimer = ‘timerX”; .l.. // процедура X .... print ‘timerX -startTime $startTimer’; // напечатаем сколько времени заняло // выполнение процедуры X. Но как воспользоваться этим в случае с хоткеем? Ведь там у нас не один скрипт, выполняющий процедуру, а две отдельных процедуры, вызванных в разное время. Тут нам поможет глобальная переменная. Это такая переменная, значение которой можно запросить и изменить всегда, в любой процедуре, после того, как мы ее определили. Например, в нашем случае: global float $startTimer; //глобальная переменная, хранящая время нажатия хоткея $startTimer = ‘timerX’; //после объявления, присваиваем ей текущее майское время Теперь, если выполнить этот кусок кода, майка запишет, когда именно мы нажали на клавишу в переменную. Что бы прочитать это время в другой процедуре/скрипте, достаточно добавить в скрипт строчку: global float $startTimer; Таким образом, скрипт сможет обращаться к нашей переменной. Наконец, получим код для вычисления времени, прошедшего с момента нажатия клавиши до ее отпускания. Код добавим в процедуру release: global float $startTimer; float $totalTime = ‘timerX -startTime $startTimer’;

//узнаем “дельта” время

Вернемся к нашим маркинг менюшкам: помним, что это всего лишь набор мел кода? Нам нужно только определить, когда вызывать конкретное меню. В этом, как обычно, нам поможет логический оператор if. Мы хотели, чтобы во время работы с полигонами у нас под рукой была менюшка с часто используемыми поли инструментами, в обратном случае используется пресловутое меню для создания объектов, созданное в первой главе. .............................................................................................................................................................................


Настройка Maya под моделирование ............................................................................................................................................................................. Таким образом, мы убиваем двух зайцев сразу: с одной стороны, это очень удобно, с другой пропадает вероятность случайно создать какой-либо примитив во время работы с геометрией. Как точнее определить - работаем ли мы сейчас с полигонами или со сценой? Я пошел по пути наименьшего сопротивления - просто-напросто узнать, подсвечены (hilit-ed) ли на данный момент какие-либо объекты. Если да - вызовем маркинг меню для поли инструментов, если нет - меню “создания”. Чтобы узнать список подсвеченных на данный момент объектов, воспользуемся процедуркой ls и передадим ей флаг -hl (hilited), говорящий, что ей нужно отфильтровать все, кроме подсвеченных объектов. Далее просто узнаем размер этого списка знакомой процедурой size: size (‘ls -hl’); // возвращает количество подсвеченных объектов Заметим, что тут я не обращаю внимания на тип подсвеченного объекта, то есть на нурбс поверхности наш код также сработает. Позже можно усовершенствовать скрипт и по типу подсвеченного объекта определять, какое маркинг меню открывать. Теперь у нас есть все инструменты! Собираем вместе долгожданный сетап: Нужно построить хоткей команды: 1. процедура для нажатия на хоткей; 2. для отпускания хоткея соответственно. Начнем с создания новой команды в hotkey редакторе, я назвал ее CreatePolyEx-trude_ Hotkey_Press. Обратим внимание, что все наши маркинг менюшки хранятся в разделе User Marking Menus. При этом нам не нужно копировать код вызова маркинг меню, достаточно указать имя команды, которую мы обычно привязываем к хоткею! Например, для вызова меню Create достаточно набрать Create_Press (Create_Release для завершения работы с ним соответственно). Собираем код для CreatePolyExtrude_Hotkey_Press: global float $startTimer; $startTimer = ‘timerX’;

// первым делом засекаем время нажатия

if ( size (%ls -hl’) > 0 ) // проверяем подсвечен ли какой-либо объект PolyModelingTools_Press; // вызываем маркинг меншшку с поли инструментами else

//не подсвечен ни один объект Create_Press; // вызываем менюшку создания примитивов

Сохраняем созданную команду нажатием на клавишу Accept. Теперь займемся процедурой отпускания хоткея. Создадим новую команду в хоткей эдиторе - CreatePolyExtrude_Hotkey_Release. Поразмыслим над ее кодом. Прежде всего, нужно вызвать процедуру зачистки после marking менюшки. Например, Create_Release. Вызова только ее достаточно, так как Release код всех маркинг менюшек одинаков: if (‘popupMenu -exists tempMM’) { deleteUI tempMM; } // если временное pop up меню // существует - убиваем его // все вызванные маркинг меню создаются с именем tempMM Можно было написать и этот код, но Create_Release выглядит элегантнее. Затем мы должны измерить время нажатия клавиши и на его основании решить, запускать ли процедуру “Экструдер”. ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Получаем: Create_Release; // “чистим” после вызова маркинг менюшки global float $startTimer; // определяем глобальную переменную с временем if (‘timerX -startTime $startTimer’ < 0.5) // проверяем заняло ли нажатие хоткея меньше { //0.5 секунды, если да - вызываем ЭкструДер . if (size(‘filterExpand -sm 32’) > 0) ExtrudeEdge; else if(size(‘fUterExpand -sm 34’) > 0) ExtrudeFace; else if (size(‘filterExpand -sm 31’) > 0) ExtrudeVertex; } // обратите внимание, скобки добавлены для удобства чтения, технически можно опустись. Кстати, значение 0.5 секунды, скорее всего, не идеальное, я советую поиграться c ним и подстроить на свой вкус. Теперь все, что осталось сделать, - это посадить CreatePolyExtrude_Hotkey на ваш любимый хоткей. Не забудьте также посадить CreatePolyExtrude_Hotkey_Release на release event клавиши. Как только это будет сделано, можно приступить к тестингу.

.............................................................................................................................................................................


Настройка Maya под моделирование ............................................................................................................................................................................. Так же хотел бы в двух словах упомянуть о команде setMenuMode, которая расскажет нам о текущем режиме работы. Например: if (‘setMenuMode’ == “Animation”) Она проверит, работаем ли мы в данный момент в режиме Animation. Используя эту команду и еще один оператор if, можно заставить хоткей вести себя по-другому в режиме, отличном от Modeling. Также можно узнать, в каком эдиторе мы работаем в данный момент командой getPanel -wf; флаг -wf означает “with focus”, то есть активное окно на данный момент. Как обычно, бросьте этот код на шелф и посмотрите, что он выдает при разных выделенных окнах. Теперь все, что нужно для того, чтобы заставить майку выполнять разные хоткей в разных эдиторах, - это добавить if, как и в случае с setMenuMode, который в зависимости от конкретного эдитора будет вызывать конкретную команду/ менюшку. К примеру, с помощью этой команды очень легко модифицировать команду создания плоскости, например, чтобы плоскость создавалась именно в плоскости текущего вьюпорта. Правда, чтобы маркинг менюшки заработали, скажем, в UV эдиторе, для pop up меню нужно изменить родительский layout (флаг -parent), допустим, на polyTexturePlace-mentPanel1 (имя мне подсказала команда getPanel -wf). Для того чтобы маркинг менюшкс работала всегда и везде, можно изменить ее код так (жирным шрифтом): if (‘popupMenu -exists tempMM’) { deleteUI tempMM; } popupMenu -button 1 -ctl false -alt false -allowOptionBoxes true -parent (‘get Panel —wf’) -mm 1 tempMM; source “menu_CreateOptimised”; Просто считываем текущее активное окно и ставим его как parent layout для pop up меню. Думаю, это будет неплохим упражнением для закрепления материала.

Stickey hotkeys Для пользователей XSI это слово не ново. Скажем, мы решили модифицировать родной майский split polygon и повесить его на заветный “липкий” хоткей. Обычно при использовании сплита мы переключаемся в объектный режим, теряем выделение и должны переключаться обратно на старый инструмент. Все это - куча лишних операций, и избежать ее нам поможет идея “липкого” хоткея. Допустим, мы работаем с моделькой, в выделении есть какие-то фейсы; вращаем наши фейсы каким-то хитрым инструментом. Теперь зажимаем клавишу липкого хоткея, подсветился объект, мы переключились в split polygon инструмент. Режем модельку как нам нравится, теперь отпускаем клавишу и... возвращается старое выделение - наши полигончики, текущий инструмент автоматически переключается обратно, в нашем случае в rotate tool. Даже режим выделения компонентов вернется на прежний. Не сложно понять, насколько это удобно. При всей кажущейся сложности, данный сетап весьма тривиален. Давайте перейдем к техническим деталям: Если вам кажется, что понятие stickey хоткей - это что-то новое для майки, то вы ошибаетесь. Чем, по-вашему, является столь древняя маркинг менюшка? Тем самым, вся разница лишь в том, что вместо инструмента мы строим marking менюшку. Как мы уже узнали из предыдущих глав, в нашем распоряжении есть две команды для хоткея - нажатие и отпускание. Все, что нам нужно, - это запомнить инструмент, с которым мы работаем, ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. выделенные компоненты, подсвеченный (hilited) шейп, и, возможно, режим выделения (так как после использования сплита он почему-то переключается в объектный). Затем мы просто устанавливаем текущий инструмент - split polygon (в последствии вы сможете заменить это на любой другой инструмент). Далее инициативу перехватывает команда, назначенная на отпускание клавиши. Все, что от нее требуется, - это вернуть старый инструмент, selection, hilite и режим выделения. Возникает вопрос: как, собственно, узнать, какие именно компоненты были выделены до отпускания клавиши? Какой именно инструмент? Ничего нового - тот же принцип, что в предыдущем параграфе, только больше глобальных переменных. Для выделения, инструмента и хайлайта создадим три глобальных переменных. При нажатии на хоткей запомним в них текущий селекшн, инструмент и хайлайт соответственно. При отпускании хоткея просто восстановим все на место базовыми командами, которые вы не раз наблюдали в строке вывода майки. Итак, обо всем по порядку: В хоткей эдиторе, как обычно, создаем новую команду, оную я назвал StickySplit_ Press - команда нажатия на хоткей. Теперь дело за малым: достать код для этой команды. По старинке открываем родной скрипт эдитор и начинаем шуршать по клавишам. Чтобы узнать текущий инструмент, воспользуемся командой currentCtx, например, так: $Stickey_Ctx = ‘currentCtx’;

// сокращенно от:

stickey_context

Считываем текущее выделение: $Stickey_Sel = ‘ls -sl’;

// сокращенно от:

stickey_selecfcion

Считаем текущие подсвеченные для работы с компонентами (hilited) объекты: $Stickey_Hl = ‘ls -hl’;

// сокращенно oт:

stickey_hilite

Все, что теперь осталось сделать для этой команды, - это создать три глобальных переменных и присвоить им соответствующие значения. У меня получилось вот так: global string $Stickey_Ctx; $Stickey_Ctx = ‘currentCtx’; global string $Stickey_Sel [] ; //массив с именами выделенных объектов/компонентов $Stickey_Sel = ‘ls -sl’; global string $Stickey_Hl[] ; // массив с именами подсвеченных объектов $Stickey_Hl - ‘ls -hl’; Примечание: глобальные переменные не любят, когда в них сразу при создании! декларации пытаются засунуть значение (а ля: global string $Var = ‘ currentCtx’;), поэтому создание/ присвоение делается в два этапа. Последняя строчка в этой команде - включение poly сплита: setToolTo polySplitContext; Команды для инструментов, как обычно, извлечены способами, писанными в первых главах. Займемся командой для отпускания клавиши. Я назвал ее StickeySplit_Release. Все, что эта команда должна сделать, - достать из глобальных переменных старое выделение, инструмент и хайлайт и присвоить их к сцене. Чтобы процедура увидела нац. глобальные переменные, достаточно добавить те же куски кода из предыдущей команды: .............................................................................................................................................................................


Настройка Maya под моделирование ............................................................................................................................................................................. global string $Stickey_Ctx; global string $Stickey_Sel[]; global string $Stickey_Hl[]; Возвращаем выделение, инструмент и хайлайт на свои места: setToolTo $HKCtx; select $HKSelection; hilite $HKHilite; if (‘size $HKHilite’ > 0 ) //были ли при нажатии сплита были выделенны компоненты? changeSelectMode -component; //ставим режим выделения в компонентный Пару слов об изменении режима выделения: вместо создания еще одной глобальной переменной я просто узнаю, были ли выделены компоненты. Если да, то справедливо предположить, что режим выделения был компонентный - возвращаем его на место. Вуаля! Вешаем свежеиспеченные команды на любимый хоткей и с удовольствием изрезаем пару моделек “новым” инструментом... Не забываем, что данный сетап можно комбинировать с ранее созданными. Скажем, можно изменить стандартные QWERT инструменты следующим образом: при быстром нажатии мы переключаемся в инструмент безвозвратно. При продолжительном нажатии мы используем stickey хоткей, а после отпускания уже вернемся в предыдущий инструмент. Техника тут очень похожа, нужна всего лишь одна глобальная переменная для имени инструмента. Если у вас много stickey хоткеев, то можно использовать одни и те же переменные - так экономнее. Для узнавания продолжительности нажатия используем аналогичный сетап из предыдущей главы. Не забываем, что и stickey hotkey сетап можно соединить с остальными, возможности по совершенствованию ограничены лишь вашей фантазией и ленью. Я надеюсь в этой статье вы открыли для себя новые возможности и, возможно, грани любимого пакета.

............................................................................................................................................................................. Король Геннадий


Майские волосы. Трюки и уловки.

Майские волосы. Трюки и уловки. Автор: Сергей Цыпцын

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

............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Майские волосы. Трюки и уловки. Автор: Сергей Цыпцын

Майские волосы. Трюки и уловки. Часть первая Тема волос давно волновала майскую общественность. До шестой версии пользователи выкручивались как могли, симулируя анимацию волос разными хитроумными трюками. Приведу некоторые из них. Прически на средних планах моделируются как обычные поверхности с тщательно подобранным материалом и текстурой. Этот путь является наиболее быстрым и адекватным так как он совершенно предсказуем в плане времени и ресурсов. Библиотеки материалов для волос могут быть накоплены и использованы повторно, а внешний вид хорошо прогнозируется. Для более крупных и требовательных планов может быть использован мех адекватной длины. В этой области уже накоплен достаточный опыт, чтобы использовать уже готовые решения. Усилия по анимации меха быстро доведут вас до истерики, поэтому сразу умерьте свои аппетиты в этом направлении. Технология Paint Effects тоже предлагает некоторые решения в области моделирования и анимации причесок с помощью процедурных кистей. Но так как полноценная динамика волос в системе Paint Effects отсутствует, некоторое время назад возникла хорошо описанная в Интернете параноидальная идея - использовать динамику тканей для анимации штрихов Paint Effects с целью создания эффекта движения волос Этот технологический красивый подход использует ленты из ткани, движение которых обеспечивает модуль MAYA Cloth, далее, используя принцип Construction History, края лент дублируются и превращаются в кривые, которые в свою очередь являются управляющими объектами, контролирующими деформацию штрихов Paint Effects. К сожалению, при использовании таких многоступенчатых трюков теряется сама сущность явления, то есть пользователь уже не оперирует понятием «волосы», а с трудом удерживает в голове все запчасти агрегата для создания иллюзии работы с волосами. Ближе всех к динамике волос, с моей точки зрения, подошла динамика мягких тел. Однако «резиновость» и невозможность организовать контроль самостолкновений ограничивает возможность применения мягких тел для динамики волос.

Рекомендации по освоению MAYA Hair Как было упомянуто выше, работа с волосами - дело не сильно простое. Инструменты и методы MAYA Hair вобрали в себя основные идеи из многих уже существующих модулей MAYA: • Поверхность покрывается волосами аналогично MAYA Fur. • Анимации и кэширование часто напоминают работу с разогнанным (до предельной частоты) MAYA Cloth. • Сохранение начальных положений и наличие коллизий и притягивающих кривых сильно напоминают работу с частицами. • Взаимодействие с полями интегрировано с общей динамикой. Вы можете ничего не знать про мех, одежду или твердые тела, однако если вы ничего не знаете про частицы, то у вас есть проблемы, так как главный лозунг майских волос следующий: .............................................................................................................................................................................


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. ВОЛОСЫ - ЭТО ЧАСТИЦЫ!!! И работать с ними следует точно также как с частицами (тут я имею в виду анимацию). То есть настраивать, запускать в полет, корректировать, снова запускать, и так до полного удовлетворения или эмоционального кол��апса. В этой связи понимание законов и принципов динамики является абсолютно необходимым условием для адекватного изучения MAYA Hair. Приведу эти законы для неискушенных умов.

Закон динамики 1.

Скорость воспроизведения анимации должна быть всегда равна Play Every Frame.

Закон динамики 2.

Анимация должна воспроизводиться всегда только вперед.

Закон динамики 3.

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

Закон динамики 4.

Нельзя безответственно щелкать мышью в TimeLine и там же безнравственно перетаскивать мышью текущее время. До тех пор, пока вы не разберетесь с кэшированием, нажимайте только кнопки Play, Stop и возвращайтесь в первый кадр.

Закон динамики 5.

Волосы не должны пересекать голову в начальном кадре. Это новое прочтение закона о твердых телах. Если вы задали столкновение волос с поверхностью, то сделайте так, чтобы в первом кадре волосы не проникали в эту поверхность, иначе они в ней намертво завязнут. Это относится не к основаниям волос, а к свободным концам. Неформальный закон динамики. Большая скорость - главный враг динамики. Для золос это абсолютно справедливо, причем благодаря наличию упругости вероятность зозникновения быстрых перемещений в системе весьма высока. Для того, чтобы бороться с ними для волос есть специальный атрибут Iterations, определяющий точность вычислений и соответственно замедляющий просчет для высокой точности. О нем - немного позже.

Понимая волосы Чисто терминологически было бы корректно назвать модуль MAYA Hair динамикой кривых, так как при работе с ним анимируется некоторое (вполне конкретное) количество кривых. Соответственно вы должны перестроить свое мышление на работу с кривыми, а не с целой массой волос. Дело в том, что никакой суперкомпьютер не просчитает реальную динамику ста пятидесяти тысяч волос, встречающихся в реальной природе на голове среднелысого персонажа. Поэтому для обмана зрителей и для облегчения жизни технических директоров используется весьма небольшое количество, скажем так, опорных кривых, задающих общее движение всей массы волос. Именно с этим конкретным количеством кривых вам и придется работать как с объектами динамики. И только на этапе рендеринга появляется заданное и достаточно большое количество волос, заполняющих пространство между опорными кривыми. Я настоятельно советую вам помнить о такой «двойственной» природе компьютерных волос и работать с ними как с динамикой небольшого количества кривых. Чем меньше кривых будет использоваться для анимации движения, тем быстрее будет считаться динамика и тем интерактивнее будет работа. Соответственно основной неформальной задачей будет искусное заполнение пространства между динамическими кривыми уже на этапе рендеринга. ............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Эффективное выращивание

Основным условием успешного высаживания волос на благодатную поверхность является наличие адекватных UV-координат. Я не говорю «хороших», так как хорошими или плохими они бывают для несчастных текстурщиков, а для волос нужны непересекающиеся, нормализованные(!) и достаточно равномерные UV. Еще точнее говоря, волосы будут создаваться только в областях, где UVкоординаты имеют значения от ноля до единицы. Можете использовать этот факт для маскирования части поверхности от волос. •

Откройте (файл 1_headBadUV.ma).

• Выберите поверхность и выполните Hair=>Create Hair. Вы увидите странную поросль на правой половине головы. Откройте Window=>UV Texture Editor. UV-координаты для полигональной сетки идеальны, так как она была сконвертирована из сплайновой поверхности. Однако UV не нормализованы.

• Нормализуйте их: Polygons=>Normalize UV at UV Texture Editor. .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Волосы перераспределятся по поверхности равномерно. Всегда проверяйте UV-мапинг перед созданием волос, иначе вас ожидают разные сюрпризы, особенно во время рисования атрибутами. Я бы советовал сначала создать UV-координаты, а затем выращивать волосы. Если делать наоборот-, то на участках, где UV отсутствовали, волосы не появятся после создания UV. Очевидно, что для сплайновых поверхностей таких проблем нет в принципе. Специально для волосистой части головы (морды, тела) вы можете создать специальные патчи, то есть отдельные поверхности, из которых будут расти волосы. Это могут быть сплайновые плашки, либо участок полигональной поверхности, отрезанный операцией Duplicate Faces. Для такого участка сделать UV-координаты совсем несложно. Этот «скальп» можно просто припарентить к поверхности головы (голова редко деформируется). В случае деформаций можно использовать Wrap-деформер для согласования формы поверхностей. Операция Create Hair хороша для засаживания волосами целых газонов, однако если использовать ее для головы персонажа, то придется слишком много времени уделять эпиляции после этого. Поэтому хорошей альтернативой является выращивание волос с помощью покраски кистями. • Выберите созданные волосы на экране и удалите их: Hair=>Delete Entire Hair System. • Выберите поверхность и откройте Option Box для Paint Hair Tool. Установите следующие значения: U: Follicle Density=40; U: Follicle Density=20; Hair Length=10; Output=NURBS Curves;

............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Совет. Вы можете компенсировать разную параметризацию поверхности направлениям U и V с помощью разных значений Follicle Density U/V. Я обычно создаю волосы в виде кривых (Output=NURBS Curves). Всегда можно потом назначить на них кисти Paint Effects и получить нужный вид. А кривые потом можно спрятать или удалить. Кривые выглядят более «эстетически» на экране. Впрочем, если волос много, а динамика жестокая, то кривые могут быть источником подтормаживания В этом случае можно использовать Output=Paint Effects, причем ширину пучков сделать нулевой, а количество волос в пучке равным единице. Во время рисования по поверхности можно заметить, что волосы не «садятся» линию симметрии, хотя модель и ее UV-координат абсолютно симметричная поверьте мне.

Жмите Undo, а затем выполните в Script Editor следующее заклинание: optionVar -intValue createHairMaxDensity 101; Порисуйте снова на переносице. Так в чем же сакральность числа 101? Попробуем разобраться. По умолчанию рисование ведется на сетке из ячеек размером 100x100, поэтому линии ровно посередине сетки просто отсутствуют. Представьте себе сетку 4x4 и вы поймете, о чем идет речь. Таким образом, если вы хотите, чтобы ряды волос появлялись ровно посередине участка, то нужно использовать нечетное значение для createHair-MaxDensity. Примечание. Создайте сплайновую плоскость, в параметрах рисования задайте UIV Fol licle Density=4, порисуйте на плоскости волосами. Затем устанавливайте eScript Editor createHairMaxDensity=100 ucreateHairMaxDensity=101. Почувствуйте разницу. Помните, что вы всегда рисуете на сетке, а не на самой поверхности, и что у сетки есть максимальное разрешение. Очевидно, что такие тонкости могут понадобиться в некоторых специфических случаях, например, вам понадобится пробор или идеально равномерное заполнение поверхности. В общем случае нас мало волнует симметричность волосяного покрова. Рисуйте по поверхности, не заботясь о точном расположении волос и залезая с запасом на остальные участки поверхности. Сейчас мы удалим ненужные волосы одним махом. .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Прежде всего, сохраните сцену как 2_headPainted.ma Если вы уже возились с мехом, то помните, что для него были специальные карты атрибутов, позволяющие управлять длиной или «лысостью» вдоль поверхности с помощью текстур. Таким образом, очень неплохой идеей будет нарисовать или украсть текстуру, соответствующую волосистой части головы и в соответствии с ней «выстричь» лишние «волосины». К счастью, текстура уже украдена до вас и находится прямо в сцене под дивным именем file1. Для усиления эффекта, она даже назначена на цвет поверхности, хотя это совершенно необязательно. Нажмите «6» и вы все увидите.

............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Идея состоит в том, что можно написать маленький скрипт (без этого неинтересно), который пробежится по всем «волосинам», получит их UV-координаты, прочитает цвет текстуры в точках, откуда они растут, и в зависимости от этого цвета, либо оставит их на месте, либо удалит их совсем. Напишите такой скрипт и выполните его в Script Editor. Предварительно надо выбрать объект hairSystem1. string $texture = “file1”; // converting selection to follicles convertHairSelection “follicles”; // list of follicles string $list[] = ���ls -sl’; string $it; // for each follicle for ($it in $list) { // get UV-position float $u = ‘getAttr ($it+”.parameterU”)’; float $v = ‘getAttr ($it+”.parameterV”)’; // get color at point on surface under follicle float $col[] = ‘colorAtPoint -o RGB -u $u -v $v $texture’; // delete follicle and it’s curve if red channel is white if($col[0]>0.5) delete (‘listConnections -t “nurbsCurve” $it’) $it (“listTransforms $it’); } Теперь вы можете видеть «подстриженный» вариант.

Создание такой текстуры является чудовищно хорошей идеей, если только вы не используете «плашки». Эту текстуру можно использовать позже и для других целей, как будет показано ниже. Примечание. В седьмой версии появилась возможность сразу рисовать текстуру «лысости» прямо на поверхности. Мне, однако, не удалось пририручить этого зверя, в силу его жуткой нестабильности. Кроме того, имея уже готовую .............................................................................................................................................................................


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. текстуру, нарисованную где-нибудь, очень трудно прикрутить ее в качестве Baldness Tex ture. Вы можете попробовать сами, покрасив голову с помощью Paint Hair Texture и потом подсунуть готовую текстуру в ноду paintAttrShader. Единственное, что я могу посоветовать: выбирайте инструмент рисования только через меню Hair=> Paint Hair Tex ture, и не используйте Toolbox для доступа к этому инструменту. Теперь вы можете запустить анимацию и настроить жесткость волос. Выберите hairSysteml и установите Stiffness=0.03.

Жесткость это проблема

Основной враг динамики - высокие скорости. MAYA не успевает просчитывать «высокоскоростные» траектории, приходится улучшать точность расчета, это повышает время вычислений, тормозит интерактивность, накапливает ошибки. Высокие скорости появляются в системах, где есть высокие частоты колебаний, такие системы в математике лаже называются жесткими. Поэтому старайтесь избегать высоких значений для жесткости волос (Stiffness). Есть некоторое количество способов выкрутиться без реальной жесткости. Если сделать небольшим количество точек на текущих кривых (Current Curves), то это сделает их более «грубыми» и, следовательно, визуально более жесткими. Для управления количеством точек есть атрибут Sample Density для каждой «волосины- (folli-cle). Кроме того, невысокое количество точек упрощает создание начальной грубой формы прически. Высокие значения для атрибута Damp (более100) могут иногда симулировать жесткое поведение. Остаточные кривые (Rest curves), работающие в сотрудничестве с атрибутом Stiff-ness служат своеобразным «якорем», притягивающим к себе волосы. Можно также использовать различные констрейны для «приклеивания» волос друг к другу или к дополнительному объекту. Можно использовать несколько констрейнов и задавать для них Point Method=U Parameter, чтобы управлять псевдожесткостью вдоль длины волос. И самый эффективный способ состоит в задании притяжения к стартовым кривым. В седьмой версии MAYA появился чудовищно полезный атрибут под названием Start Curve At-tract. Он находится в разделе Dynamics и определяет, насколько текущие кривые стремятся «притянуться» к стартовым кривым. Если этот атрибут равен нулю, то эффекта притяжения нет, если равен единице, то текущие кривые намертво прилипают к стартовым кривым. Степень притяжения вдоль кривой изменяется в соответствии с кривой Stiffness Scale, так что вы без труда можете делать кончики более гибкими и «свободными», а основание более жестким. Использование этого атрибута (анимируемого притом!) позволяет избежать многих ухищрений с применением Rest Curves, а также легко делать жесткие волосы без необходимости увеличивать Stiffness и, следовательно, Iterations и, следовательно, время просчета динамики.

Три типа кривых при работе с системой волос.

Для тех, кто еще неискушен в динамике кривых, немного расскажу про ее внутреннее устройство. При работе с системой волос мы обычно имеем дело с двумя или тремя (при наличии Rest Curves) наборами кривых. Существует правда еще один тип кривых - пассивные кривые (Passive Curves), но о них пойдет речь позже. Прежде всего, это сами динамические кривые, которые анимируются под действием динамики. Они называются Current Curves (или Current Position). Никогда не редактируйте вручную сами динамические кривые! Вы же не пытаетесь таскать вручную отдельные частицы, поэтому сами волосы тоже трогать не надо. Стартовые кривые (Start Curves или Start Positions) задают форму и положение динамических кривых в начальном кадре. Они автоматически создаются всегда и их ............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. нельзя удалить без удаления самих динамических кривых. Их можно редактировать вручную. Именно эти кривые определяют базовое количество точек, из которых состоят динамические кривые. Остаточные кривые (Rest Curves или Rest Positions) определяют форму, которую стремятся занять динамические кривые. Чем больше упругость кривых, тем сильнее и точнее они принимают эту форму. Остаточные кривые не создаются по умолччанию (но при необходимости могут быть построены при создании волос). Их также можно и нужно редактировать вручную всеми легальными и нелегальными методами, однако количество точек на них менять не следует. С появлением в седьмой версии атрибута Start Curve At-tract, большинство решений, основанных на остаточных кривых, резко устарело и теперь они используются довольно редко. Стартовые и остаточные кривые могут быть в любой момент переопределены и заданы, например, как текущая форма динамических кривых. Все это делается через пункты меню Hairs=>Set Start(Rest) Position. Для редактирования формы этих кривых “в целом» также существует специальный пункт меню Hair=>Modify Curves. По умолчанию на экране отображаются только сами динамические кривые, показать же стартовые и/или остаточные кривые можно через меню Hairs=>Display. Так как эти кривые являются только вспомогательными и никак не отображаются в процессе рендеринга, они отрисовываются на экране как кривые первого порядка, ведь важны только позиции контрольных точек этих кривых.

Прически и укладки

Создание начальной прически - самая сложная и слабая часть майской системы волос. Можно использовать разные техники. Ручной способ, как обычно, самый быстрый. В совокупности с возможностью фиксировать длину кривых и цепляться за концы волос, он дает неплохие результаты. Вы можете накладывать деформеры и гнуть прическу целиком, а точнее стартовые кривые системы волос. Фиксировать длину в этом случае не получится. Для любителей экстрима есть возможность включить анимацию в режиме Interac-tive playback и попытаться расчесывать волосы с помощью констрейнов или обдувать их динамическими полями. Вы всегда можете сохранить текущее положение как начальное, используя операцию Set Start From Current. Другой способ создания уже почти причесанных волос заключается в превращении штрихов Paint Effects в кривые. Дело в том, что часть пользователей, измученная отсутствием в первых пяти версиях системы волос, научилась довольно ловко делать прически с помощью системы Paint Effects. Было бы неразумно отбрасывать накопленный опыт и заготовки, поэтому попросите знакомого скриптописателя написать небольшой код для конвертации штрихов Paint Effects в обычные кривые или используйте недавно появившийся пункт меню Modify=>Convert=>Paint Effects to Curves. Вы всегда можете превратить любые кривые в динамические кривые. Еще один довольно экзотичный способ (использовавшийся в старом добром Power Animator’e) заключается в испускании частиц с нужной области поверхности. Затем с помощью полей и expressions траектории частиц настраиваются так чтобы они напоминали форму будущих волос. С помощью небольшого скрипта траектории нужного количества частиц превращаются в кривые. При необходимости они могут быть дополнены дополнительными пассивными кривыми.

Коллизии прежде всего

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


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. нервы. Поэтому всегда создавайте поверхность для отталкивания кривых заранее. Вместо того, чтобы использовать модель головы в качестве поверхности для столкновений, гораздо эффективнее будет применение констрейна типа Collide Sphere. Если сфера не совсем повторяет форму головы, то проще сделать еще пяток сферок и вставить их в нужные места. Просчет столкновений с ними будет производиться в разы быстрее, чем с реальной поверхностью. • Выберите объект hairSystem1 и выполните операцию Hair=>Convert Selection=> to Follicles, так создание констрейна требует предварительного выбора кривых. • Затем выполните Hair=>Create Constraint=>Collide Sphere.

Задайте размеры сферы и ее положение, translate = 0.0; 8.2; 2.9

Сохраните сцену как 3_headCollisionSetup.ma ............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Симметричные трюки В тех случаях, когда вам требуются ровные проборы или другие симметричные прически, вы можете применить следующий подход. • Перейдите в камеру Front и выберите все волосины (follicle) на правой стороне головы (не зацепите hairConstraint1 при этом).

• • •

Удалите их. Теперь выберите оставшиеся кривые (не follicles!) кроме центрального ряда. Скопируйте их как инстансы.

• Тут же сгруппируйте скопированные кривые. • Задайте scaleX=-1 для новой группы. • Проиграйте анимацию. Скорость воспроизведения увеличится почти в два раза, так происходит просчет только для половины волос. Сохраните сцену как 4_headlnstancedHair.ma .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Ручная укладка По моему опыту, следует быть максимально бесцеремонным и таскать модель за волосы в нужном направлении. Тем более, что существуют предельно удобные способы выбирать и перемещать сразу все концы волос, а функция сохранения длины кривых во время редактирования позволяет перемещать их довольно правдоподобно. Воспользуемся этим подходом. Встаньте в первый кадр и выберите сначала объект hairSystem1, а затем концы всех стартовых кривых: Hair=>Convert Selection=>to Start Curves End CVs. Возьмите в руки Move Toot, затем нажмите и удерживайте клавишу «L» для фиксации длины кривых. Функция Undo просто не работает при фиксации длины кривых. Так что будьте уверены в своих действиях, не допускайте дрожания рук и всегда сохраняйте сцену перед редактированием кривых с фиксацией длины. Оттащите концы стартовых кривых немного назад, не допускайте обратного движения, тащите только в одну сторону. Если руки дрогнут, откройте сцену заново и пробуйте снова.

• Переключитесь в Scale Tool. • Нажмите Insert (клавишу «L» можно пока опустить) и оттащите pivot выделения назад, в район последних концов кривых. Снова нажмите Insert. • Снова нажмите «L» и сожмите одним(!) уверенным движением концы к центру.

............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Перемещать можно не только концевые точки кривых. Выбрав концы, можно нажимать стрелки вправо-влево, чтобы селектировать и перемещать ряды внутренних точек на кривых. Помните, что редактировать можно только стартовые или остаточные кривые. • Запустите анимацию и убедитесь в том, что динамические кривые упруго взлетают из нового положения вверх. Сохраните сцену немедленно как 5_headManualStyling.ma

Динамическая укладка

Запустите анимацию и убедитесь в том, что динамические кривые упруго взлетают из нового положения вверх. Первое, что бросается в глаза - это то, что кривые имеют довольно мало сегментов и оттого выглядят излишне упругими и жесткими. Увеличим количество точек на кривых. • Выберите объект hairSysteml и выполните Hair=>Convert Selection=>to Follicles. • Откройте Channel Box и задайте для всех выбранных кривых Sample Density=3. После этого количество точек и сегментов на всех кривых утроится и, следовательно они станут более гибкими. Немного смущают основания кривых. Они пытаются удерживаться перпендикулярно поверхности. Возможно, иногда это довольно полезно, но сейчас изменим такое поведение.

• В Channel Box установите для всех выбранных кривых Start Direction=Start Curve Base, чтобы основания волос повторяли форму стартовых кривых, а не торчали по нормали к поверхности. Теперь волосы довольно безвольно падают вниз и повисают как веревки. Им немного не хватает формы и упругости. • Выберите hairSystem1 и задайте Stiffness=0.3. • Проиграйте анимацию. Дальнейшее улучшение формы может быть достигнуто за счет изменения атрибута Stiffness Scale, определяющего распределение упругости вдоль длины во. Вы можете слегка уменьшить упругость около оснований и увеличить ее на концах. .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

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

• Проиграйте анимацию примерно до пятисотого кадра, пока волосы не успокоятся на своих местах. • Выберите кривые (Hair=>Convert Selection=>to Follicles) и выполните операцию Hair=>Set Start Position=>From Current.

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


............................................................................................................................................................................. Все дело в коварном атрибуте Sample Density, значение которого равно трем Как только мы сохранили текущее положение как начальное, все стартовые кривые унаследовали количество точек с текущего положения. Соответственно количество точек на стартовых кривых утроилось, однако значение Sample Density для всех кривых по-прежнему осталось равным трем, поэтому количество точек на самих волосах еще раз утроилось. Все о чем нужно помнить, это немедленное возвращение Sample Density единицу после определения нового стартового положения кривых. Выберите hairSystem1, затем Hair=>Convert Selection=>to Follicles и в Channel Воx задайте Sample Density=1. Теперь кривые остаются в покое.

Удлинение волос

Предположим, что вам захотелось несколько удлинить всю прическу целиком : Приведу пример одного из возможных путей сделать это. Так как заниматься покраской поверхности с помощью Paint Hair Tool в режиме Paint Mode=Extend Hairs совсем не хочется то попробуем удлинить напрямую стартовые кривые с помощью стандартных средств сплайнового моделирования. Выберите hairSystem1, затем выполните Hair=>Convert Selection=>to Start Curves. Перейдите в режим моделирования и откройте Option Box операции Edit Curves=>Extend=>Extend Curves. Задайте Extension Type=Extrapolate, Distance=10.

Стартовые кривые удлинятся, а вместе с ними вытянутся и сами волосы. Не забудьте включить отображение волос и заодно всех кривых: Hair=>Display=>All Curves. Запустите анимацию. Подождите пока волосы успокоятся. Выполните Hair=>Set Start Position=>from Current в надежде на то, что волосы не будут шевелиться в начале анимации. .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Остановка волос Однако в начале анимации происходит непонятное движение, которое невозможно побороть, сохраняя текущее положение как начальное. Кстати, в отличие от частиц, при сохранении начального состояния фиксируются только позиции точек кривых, а их скорости игнорируются. Один из способов успокоить кривые заключается в использовании остаточных кривых. Выберите все волосы и выполните Hair=>Set Rest Position=>from Start. Запустите анимацию. Подождите пока волосы успокоятся. Выполните снова Hair=>Set Start Position=>from Current Теперь волосы должны наконец-то затихнуть. Сохраните сцену как 6_headDynamicStyling.ma.

Визуализация волос Если вы собираетесь отрендерить волосы, то пока нужно задуматься как. Эстетствующие умы, с трудом переваривающие систему Paint Effects, наверняка с нетерпением желают отрендерить волосы по полной программе, то есть с отражениями, преломлениями, глобальным освещениемипроч имиглупостями. Для таких рафинированных эстетов существует несколько возможностей. Первая возможность стандартная. Коль скоро волосы представлены штрихами Paint Effects, то их можно сконвертировать в полигональные трубки и делать с ними все, что душе угодно. Правда вопрос о размере сцены остается более, чем открытым, так вся геометрия будет сохраняться не в виде описания и набора параметров, а в явном виде. Для такой конвертации даже существует специальный материал, который автоматически создается и накладывается на полигональные трубки после конвертации. Он максимально воспроизводит визуальные свойства волос и представляет собой обычный анизотропический материал с вполне адекватным набором атрибутов. Начиная с седьмой версии MAYA, mental ray научился рендерить волосы как полноценный объект сцены. Для того, чтобы получить удовлетворительный результат, вам надо сразу выставить довольно высокое качество антиалиазинга в Render Globals, так как волосы - довольно капризный объект, состоящий из мелких деталей. Кроме того, гениальный плагин под названием Renderman for Maya, умеет очень ловко считать майские волосы без всяких трюков и конвертаций. А использование фирменных пиксаровских теней типа DeepShadow, делает это решение весьма привлекательным. Однако по скорости никакой рендерер даже близко не может подойти к системе Paint Effects. Я рассмотрю этот способ подробнее, так как он имеет некоторое количество подводных камней. Прежде всего, у нас нет никаких Paint Effects, а есть только кривые, на которые следует навалить любую кисть, чтобы превратить кривые в штрихи. •

Выберите hairSystem1 и выполните Hair=>Assign Paint Effects Brush to Hair.

Опаньки! Наши симметричные инстансированные волосы не получили заветной кисти, хотя мы уже и забыли про трюк с симметрией.

............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Удалить симметрию мы еще успеем, а сейчас скопируйте ноду pfxHair1 как инстанс и сделайте ей scale= -1. • •

Создайте основной источник света (directionaLight: rotate= -10; 10; 0; lntencity=1.4). Также создайте заполняющий источник (pointLight: translate=15; 5; 5; lntencity=0.5).

В Attribute Editor появилась новая кисть с именем brush1. Если вы хотите рендерить волосы обычным способом, вам следует просто удалить ее, и MAYA будет использовать атрибуты ноды hairSystem1. Однако если вы хотите придать экзотический вид волосам, можете использовать атрибуты этой кисти. Имейте в виду, что существуют правила взаимодействия между атрибутами hairSystem1 и параметрами кисти типа brush, заключающиеся в следующем. Ширина кисти (Brush Width) игнорируется и вместо нее используется толщина волос (Hair Width). Вместо цвета кисти (причем только вместо цвета основания Color1) используется цвет волос Hair Color. Аналогично и остальные атрибуты из раздела Shading системы волос (Specular Color и др.) заменяют соответствующие свойства кисти из раздела Illumination. Кроме того, для того, чтобы отрендерить затекстурированные кривые с помощью обычных штрихов Paint Effects (с выключенными Tubes), то не забывайте про толщину (Hair Width), и, кроме того, вам наверняка придется увеличить атрибут RepeatU раз в десять-двадцать, чтобы получить тот же вид, что и для оригинальной кисти. • Например, выберите hairSysteml и установите Hair Per Clump=20; Sub Segments=1; Clump With=1 and Hair Width=0.1;. • Выберите закладку brush, откройте раздел Texturing в Attribute Editor. • Включите Map Color и Map Opacity. • Установите Texture Type=File. • Для Image Name используйте bubble.iff из библиотеки brushlmages. • Задайте RepeatU=40. • Отсоедините текстуру file1 от материала Lambert1 и просчитайте картинку. .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Обратите внимание, что цвет, заданный в hairSystem1, перемножается с цветом текстуры. Сохраните такую экзотику как 7_headPFXbrush.ma • • •

Для того, чтобы вернуться к нормальному виду для волос просто удалите кисть brush1. Задайте Hair Width=0.01. Посчитайте. Ужаснитесь.

Пришло время удалить симметричные кривые и заняться плотностью.

Удаление симметрии

Если вы соблазнились на трюки с симметрией, то пришло время за них расплачиваться.

• Спрячьте штрихи Paint Effects: Camera menu=>Show=>Strokes. • Выберите скопированный pfxHair2 и удалите его. ............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. •

Удалите group1, содержащую инстансированные кривые.

Идея состоит в том, чтобы симметрично скопировать стартовые кривые как нормальные объекты, превратить их в динамические кривые, а затем перенести в систему hairSys teml. Выберите hairSystem1, и выполните Hair=>Convert Selection=>to Start Curves. •

«Развыберите» центральный ряд кривых.

• Сдублируйте выбранные кривые на нормальные объекты (не инстансы). • Выполните в Script Editor следующую команду, чтобы симметрично отразить скопированные кривые. scale -p 0 0 0 -r -1 1 1; Выполните Use Freeze Transformations, чтобы убрать отрицательный масштаб.Теперь проще всего сделать скопированные кривые динамическими, перенести их в систему hairSystem1, а ноды типа follicle просто припарентить к голове. Однако в этом случае, новые динамические кривые не прикрепляются к голове, так как для них значение атрибута Parameter U/V, остается равным нулю. Кроме того, теряется связь с констрейнами. Небольшой скрипт может решить проблему с переносом динамических кривых и усаживанием их на выбранную поверхность. Этот скрипт называется landCurves.mel. • •

Если скопированные кривые уже выбраны, то выберите дополнительно поверхность головы. Выполните в Script Editor команду landCurves.

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. • Задайте Hair System=hairSystem1. • Нажмите большую кнопку и все кривые превратятся в волосы и унаследуют атрибуты из hairSystem1. Этот скрипт может быть использован для «подсаживания» любых новых кривых в уже существующую систему волос или для создания новой системы из существующих кривых и закрепления их на поверхности. Кстати, в восьмой версии MAYA при создании динамических кривых можно указать поверхность, к которой они должны «прилипнуть». Так что данный скрипт может быть использован в целях изучения устройства системы волос с точки зрения языка MEL. •

Проиграйте анимацию и заметьте несимметричную форму.

Дело в том, что остаточные кривые не были созданы для скопированных кривых. • Сделаем это сейчас. Выберите все текущие кривые и выполните Hair=>Set Rest Positions=>from Start. Кривые снова ведут себя возмутительно. Это связано с тем, что мы изменили ширину пучков (Hair Clump Width) пока настраивали рендеринг. Оказывается, динамика учитывает эту ширину для расчета столкновений! Это конечно прискорбно, так как мы захотим менять этот атрибут много раз, однако не хотим влиять на динамику. К счастью есть специальный атрибут Collision Width Offset, который позволяет корректировать область столкновений и может быть использован для компенсации изменения визуальной ширины пучков. •

Откройте Attribute Editor для hairSystem1 и создайте простой expression для Collision Width Offset

hairSystemShape1.collideWidthOffset=0.35-hairSystemShape1.clumpWidth ............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Это сделает ширину области коллизий независимой от ширины пучков. Можете поиграть анимацию и изменять в это время значение Hair Clump Width, наблюдая, что это не влияет на динамику. • Установите Hair Clump Width = 0.4. Пытливые умы могут добавить учет Hair Width в данный expression. Сохраните сцену как 8_headDuplicatedStartCurves.ma

Увеличение плотности

Самый простой, если не сказать тупой способ увеличить плотность волос для уже имеющейся системы волос заключается в заполнении ее пассивными кривыми. Они не участвуют в динамике, а лишь повторяют форму соседних активных кривых. • • • •

Выберите голову, а затем Paint Hair Tool. Задайте Paint Mode=Create Passive Follicles. Увеличьте в два раза плотность рисования: Follicle Density U=80, Follicle Density V=40. Покрасьте поверхность пассивными кривыми.

Не переживайте по поводу «лишних» участков. Сейчас мы их «сбреем». •

Выберите hairSystem1 и выполните «бреющий» скрипт.

string $texture = “file1”; // converting selection to follicles convertHairSelection “follicles”; // list of follicles string $list[] = ‘ls -sl’; string $it; // for each follicle for ($it in $list) { // get UV-position float $u = ‘getAttr ($it+”.parameterU”)’; float $v = ‘getAttr ($it+”.parameterV”)’ ; // get color at point on surface under follicle float $col[] = ‘colorAtPoint -o RGB -u $u -v $v file1’ ; // delete follicle and it’s curve if red channel is white if ($col[0]>0.5) delete (‘listConnections -t “nurbsCurve” (‘listTransforms $it’); }

$it ‘)$it

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Кстати, обратите внимание на некоторую неравномерность в расположении пассивных кривых относительно активных. Если вы помните, мы рисуем на сетке размером 101x101. Однако плотность рисования установлена в 80x40. Поэтому расположение кривых, нарисованных с разными плотностями, может быть неравномерным. Для того, чтобы избежать этого, надо было с самого начала установить createHairMaxDensity равным 81 или 161. •

Просчитайте картинку (Hair Per Clump=20; Sub Segments=1; Clump Width=0.4).

Задайте Display Quality = 10, чтобы убрать торможение на экране.

Трюки уплотнения

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

............................................................................................................................................................................. Сергей Цыпцын


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

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

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


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. Когда кривых слишком много, имеет смысл не использовать NURBS Curves в качестве представления волос. Применяйте Output=Paint Effects, задавайте Hair Per Clumb=1 и Clump Width=0 для визуального контроля. Не забывайте про Display Quality. Штрихи Paint Effects отрисовываются на экране в разы быстрее, чем кривые. Самые «тяжелые- параметры - это Hair Per Clump и Sub Segments, старайтесь держать их минимальными, добиваясь густоты другими методами. В разделе Multistreaks можно задать эффективное «размножение» волос только на этапе рендеринга, причем не требующее сильного увеличения времени просчета. Главное подобрать размер окрестности, в которой каждый волос копируется заданное количество раз. Такая окрестность очевидно не должна превышать в традиционных случаях размер пучка волос. Такая возможность полностью аналогична размножению частиц типа Multist-reak, когда движение просчитывается только для одной частицы, визуализируются сразу несколько в некоторой области вокруг нее. Очевидно, толщина пучков должна подбираться исходя из расстояния между пучками, если сделать ее слишком большой, то возникнут проблемы на границе волосяного покрова и около оснований волос (если граница видна в кадре). Легкий шум (noise) или изгиб в районе оснований тоже создаст иллюзию насыщенности, без увеличения количества кривых. Толщина самих волос кардинально меняет восприятие объема и фактуры волос. Подбирайте ее с осторожностью, особенно когда пытаетесь искусственно заполнить объем. Не забывайте про атрибут Thining. Он придает концам совершенно шикарный вид, если только вы не делаете стрижку типа «карэ». Ну и основным визуальным трюком для придания дополнительной плотности и маскировки просвечивающей поверхности является грамотное затенение. Сохраните файл как 9_headPassiveFill.ma

Свет и Тени

• Использование теней требует соблюдения набора некоторых правил, так как Paint Effects не являются обычными поверхностями и просчитываются по совершенно иным алгоритмам. • Задайте Clump Width=0.25 и Hair Width = 0.005. • Установите Hair Per Clump=50. • Также задайте Specular Color около 0.5 и определите жесткий блик: Specular Pow-er=10. • Выберите directionalLight1 и включите Use Dmap Shadows. Так как штрихи Paint Effects не являются поверхностями, то метод Use Mid Dist Dmap для них не работает и эту опцию необходимо выключить (Use Mid Dist Dmap=Off). Иначе волосы не будут отбрасывать тень сами на себя. Кроме того, волосы - это довольно тонкие объекты, для них требуется довольно высокое разрешение карт теней. • Установите Dmap Resoiution=2048. • Цвет тени Shadow Color сделайте серым, а не чисто черным. • Просчитайте изображение.

............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Жуть! Все покрылось мраком. Дело в том, что при выключенной опции Use Mid Dist Dmap надо вручную настроить «отступ» начала тени от объекта, иначе тень от поверхности будет видна на самой поверхности, как это видно на картинке. Сдвиньте начало тени от объекта, задав Dmap Bias=0.1. Дополнительно, чтобы тени не были такими жесткими, задайте Dmap Filter Size=5 чтобы немного их «размыть».

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

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Стрижка волос

Трюки для взрослых

Если вы хотите ровно подстричь волосы, не стоит хвататься за Paint Hair Tool в режиме Trim Hair. Есть более элегантный способ. Откройте файл 9a_headShadowed.ma. Он достаточно тяжелый, чтобы поэкспериментировать на нем. Можно спрятать штрихи Paint Effects или понизить качество их отображения. • Перейдите в камеру Side и создайте обычную кривую, с помощью которой вы собираетесь отрезать концы волос.

Перед тем как начать стрижку, нужно убедиться, что все волосы имеют стартовые кривые (некоторые пассивные текущие кривые могут их не иметь). • Поэтому на всякий случай перейдите в первый кадр, выберите все волосы (follicles) и выполните Set Start Position=>From Current. • Выберите все стартовые кривые (Convert Selection=>to Start Curves), а затем выберите нарисованную кривую. • Откройте Option Box для Edit Curves=>Cut Curves. • Задайте Find lntersections=ln 2D and 3D и Cut=Using Last Curve.

............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. •

Нажмите Cut, а затем удалите концы отрезанных волос (их удобно выбрать в Outlinег).

• Переключитесь на отображение текущих кривых и проиграйте анимации. • Если волосы начнут упрямо удлиняться, то следует обновить остаточные кривые и установить в Channel Box для всех follicles; Rest Pose=Same as Start.

Не забудьте поправить атрибут Thinning в этом случае.

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Attribute maps

Если проводить аналогии с картами атрибутов, то упоминавшийся выше скрипт для убирания лишних волос с поверхности с помощью текстуры, может быть использован для модификации любого атрибута, присущего отдельным волосинам. Можно проиллюстрировать это на примере текстурирования волос не вдоль длины, а вдоль поверхности, из которой они произрастают. Напомню, что у меха (MAYA Fur) есть кнопка Bake, которая забирает цвет с текстуры и накладывает его на мех вдоль поверхности на которой этот мех растет. Попробуем сделать это и для волос. Как уже было описано выше, у каждого пучка волос (или динамической кривой, follicle) есть атрибуты Color Blend и Color. Напомню что добраться до индивидуальных свойств можно через Hair=>Convert Selection=>to Folli-cies. Атрибут Color Blend определяет насколько сильно используется индивидуальный цвет пучка, то есть степень смешивания общего и индивидуального цветов. Среди индивидуальных свойств динамических кривых (follicle) присутствуют также атрибуты Parameter U/V, определяющие UV-координаты точки, из которой произрастает конкретный пучок. Имея эту информацию можно вычислить цвет текстуры, лежащей на поверхности, из которой растут кривые (кстати, не обязательно забирать цвет именно с этой текстуры, можно использовать любую карту) и назначить этот цвет на кривую, то есть на весь пучок. Как догадались взрослые мальчики, речь идет о небольшом скрипте, поэтому страдающие аллергией на скрипты читатели должны срочно перейти к следующему разделу. Проделаем небольшое упражнение. • Создайте полигональную сферу, задайте радиус равным пяти. • Создайте систему волос на поверхности. • Откройте Option Box операции Create Hair и задайте Output=Paint Effects, U_Count=20 V_ Count=20, Equalize=off. Это дополнительный (но необязательный) трюк для выращивания волос точно в центре граней. • Жмите Create.

• Задайте «для красоты» следующие параметры для системы волос hairSystem1: Hair Per Clump=20; Clump Width=1.2. Форму Clump Width Scale можно сделать уже к основанию и шире к концам. ............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

• Выберите сферу и положите на канал Color материала lambert1 какую-нибудь цветастую текстуру, например Ramp. Задайте для текстуры ramp1 значение Noise=1.

Задача состоит в том, чтобы назначить тот же самый цвет и на волосы, растущие на сфере. Сохраните файл (texturedHairStart.ma). •

Выберите hairSystem1, а в Script Editor выполните следующие строки:

// перевод выбранной системы волос в отдельные кривые convertHairSelection “follicles”; // получение списка кривых string $list[] в ‘ls -sl’; string $it; // цикл по всем кривым for (Sit in $list) { // получение UV координат основания кривой float $u = ‘getAttr ($it+”.parameterU”)’; float $v = ‘getAttr ($it+”.parameterV”)’; // запрос цвета в точке с такими коодинатами на текстуре rampl float $col[] = ‘colorAtPoint -о RGB -u $u -v $v rampl’; // назначение полученного цвета на кривую setAttr <$it+”.color”) -type double3 ($col[0]) ($col[l}) ($col[2]); // задание полного индивидуального цвета setAttr ($it+”.colorBlend”) 1; } .............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

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

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

............................................................................................................................................................................. Сергей Цыпцын


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

Хорошей идеей будет возможность нарисовать кривую вдоль границы и высадить волосы вдоль нее с нужной густотой. Речь идет о небольшом скрипте. • Откройте сцену 9d_headGoseUp.ma. Кривая для границы там уже нарисована. • Выберите эту кривую borderCurve, а затем выберите повеохность. Это важно. Разыщите на диске скрипт passiveFolliciesFromCurve.mel. и выполните следующую команду:

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. • Задайте Number of folocles =100 и нажмите могучую кнопку. Новые волосы создаются в точках поверхности, ближайших к выбранной кривой.

Использовав дополнительно Multistreaks, вы можете создать довольно плотную и ровную границу.

Работа с закэшированными системами волос

Иногда требуется изменить форму и даже поведение системы волос, которая уже была закодирована. Это можно сделать, используя нетривиальный подход к Blend Shapes. Идея состоит в том, что нужно использовать дополнительную систему волос. Ее Simu-lation Method будет задан как Static, это означает, что волосы будут всегда повторять форму стартовых кривых. Эта система будет использоваться только для визуализации, следовательно для нее также должно быть Output-Paint Effects. Закодированная система волос будет использована только для анимации и для нее имеет смысл использовать Output=NURBS Curves, ............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Трюк состоит в том, чтобы использовать закэшированную систему как таргет для стартовых кривых дополнительной системы. Эти стартовые кривые будут просто следовать за текущими кривыми анимированной системы волос. Вопрос только в аккуратном выборе нужных кривых и создании Blend Shapes. • Откройте файл 9e_headCached.ma. • Если кэш потерялся по дороге, пересоздайте его, это недолго.Есть несколько способов: путем копирования системы волос; можно импортировать систему волос в тот же файл, где она уже есть; или просто выбрать стартовые кривые и сделать их динамическими. Мы пойдем простейшим путем. • Выберите hairSystem1, а затем выберите ее стартовые кривые. • Сдублируйте эти кривые с параметрами по умолчанию. • «Распарентите» их (Edit=>Unparent) на всякий случай. • Сделайте эти кривые динамическими: Hair=>Make Selected Curves Dynamic • Выберите группу hairSystem20utputCurves и удалите ее, чтобы оставить только Paint Effects в качестве отображения волос. « Выберите hairSystem2 и назначьте на нее кисть Paint Effects: Hair=>Assign Paint Effects Brush to Hair. • Проверьте, не выключено ли отображение штрихов Paint Effects в камере. • Для hairSystern2 установите Simulation Method=Static, чтобы заморозить созданную систему динамических кривых. Теперь будьте аккуратны. • Выберите hairSystem2 и сконвертируйте выбор в стартовые кривые. Это сделает их видимыми не только на экране, но и в Outliner. • Выберите hairSystem1 и выполните Hair=>Display=>Current Position. Это сделает текущие кривые первой системы волос видимыми не только на экране, но и в Outliner. • Выберите в Outliner группу hairSystemlOutputCurves (именно группу, не сами кривые). • Дополнительно выберите группу hairSystem2Follicles. Должны быть выбраны две группы. • Откроите Option Box для операции Create BlendShape и задайте Origin=World. • Создайте Blend Shapes. MAYA проявит завидную смекалку и сама разберет содержимое групп на пары кривых, между которыми надо сделать морфинг. • Теперь спрячьте группы hairSystem1 Follicles и hairSystemlOutputCurves, чтобы сделать невидимой первую систему волос. • Доберитесь до ноды blendshape и установите вес Weight в единицу. Посмотрите на морфинг. Проиграйте анимацию.

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. ............................................................................................................................................................................. Теперь вы можете добиваться некоторых эффектов. Анимируя вес морфинга, можно усиливать или ослаблять эффект анимации. Значения больше единицы могут создавать эффект «преувеличения динамики». Кроме того, вы можете накладывать на стартовые кривые второй системы волос разные деформеры и всячески над ними издеваться. Это позволит делать дополнительные детали в прическе и укладке уже после динамики и даже кэширования.

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

Летающие волосы

Похожий метод может быть использован для срывания волосяного покрова с одной поверхности и усаживания его на другую поверхность. Откройте файл 9e_headTwoHeads.ma file. Там содержится две похожих системы волос (вторая была реимпортирована в сцены без использования name spacing). Опять вторая система будет статической и будет использована для только визуализации. Первая будет отвечать за анимацию. Идея состоит в том, чтобы взять стартовые кривые второй системы волос, превратить их в мягкие тела, а затем заставить их лететь на текущие кривые первой системы волос, используя последние как goal для частиц. •

Для начала разберемся с мягкими телами. Выберите second__hairSystem1 и сконвертируйте выбор в стартовые кривые. • Выполните Soft/ Rigid Bodies=>Make Soft Body (Duplicate, Make Original Soft; Hide Non-Soft=On; Make Non-Soft a Goal, Weight=0).

............................................................................................................................................................................. Сергей Цыпцын


............................................................................................................................................................................. Новые мягкие тела появятся в Outliner как second_curves*.

Хитрость состоит в том, что нужно последовательно выбрать каждую текущую кривую первой системы волос и назначить ее как goal для соответствующей мягкой кривой. Можно, конечно, сплясать щелкунчика, неистово кликая мышкой, однако пара команд в Script Editor могут сэкономить пару часов. • Если все мягкие тела выбраны, то выполните следующую команду, она запомнит список мягких тел: $soft=’ls -sl’; Теперь выберите все текущие кривые первой системы волос: откройте в Outliner группу hairSystem1OutputCurves и выберите все входящие в нее кривые, от первой до последней. • Выполните команду, запоминающую эти кривые в список: $goal=’ls -sl’; • А теперь выполните небольшое заклинание, перебирающее оба списка и создающее goal для мягких тел: for ($i=0; $i<size($soft); $i++) goal -w 0.5 -utr 0 -g $goal[$i] $soft[$i]; • Запустите анимацию. • Спрячьте группы hairSystem1Follicles и hairSystem1OutputCurves. • Теперь вы можете резвиться с летающими волосами в соответствии с вашим опытом работы с частицами. Поля и expressions к вашим услугам, • Для облегчения выбора всех частиц в сцене используйте команду “select *Particle”; Для этого вы также можете выбрать все мягкие тела в Outliner, а затем нажать стрелку вниз и стрелку вправо. • Если все частицы выбраны, вы можете редактировать их атрибуты в Channel Box. Для создания expression для всех частиц одновременно, используйте следующую мантру: $soft=’1s -sl’; for ($i=0; $i<size($soft); $i++) dynExpression -s “goalPP - rand(.5, 1.4);” -rbd $soft[$i]; Анимируя goal weights для частиц, вы можете заставлять волосы лететь на другую поверхность или возвращаться обратно. Например, чтобы превратить их в «стаю змей», используйте следующий шифр: $soft=’ls -sl’; .............................................................................................................................................................................


Ма��ские волосы. Трюки и уловки. ............................................................................................................................................................................. for ($i=0; $i<size($soft); $i++) dynExpression -s “goalPP = 1.-0.3*id/count,” -rbd $soft[$i]; Не забывайте о том, что частицы могут сталкиваться с поверхностями. Кроме того, система волос, на которую летят безумные мягкие кривые, может иметь собственную анимацию. Анимируя goal weight, можно смешивать эту анимацию с полетом кривых.

Растущие волосы или hair particles

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

Создайте point emitter. Идите в десятый кадр и задайте Rate=100. Поставьте ключ. В одиннадцатом кадре задайте Rate=0. Поставьте ключ.

Поиграйте анимацию. Теперь нужно просто превратить траектории частиц в кривые. •

Создайте для частиц Creation Expression:

vector $p = position; curve -d 1 -p ($p.x)

($p.y)

($p.z)

-n

(“traj”+int(id));

Он будет создавать кривую, состоящую из одной точки для каждой частицы в момент ее рождения. Точка будет совпадать с позицией частицы в момент рождения. •

Создайте Runtime Expression

vector $p = position; curve -p ($p.x) (Sp.y)

($p.z)

-a

(“traj”+int(id)) ;

Он будет добавлять новую точку к уже имеющейся кривой для каждой частицы в каждом кадре. Точка будет совпадать с позицией частицы в этом кадре. •

Чтобы всегда удалять все траектории в первом кадре, создайте обычный (non-particle) I expression:

if(frame==l) •

delete “traj*”;

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

............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Лучше установить очередь Undo равной 50 шагам иначе будет интенсивный расход памяти вследствие множественных операций создания и удаления. Когда частиц будет много, то можно рисовать траектории не для каждой частицы, а только для каждой пятой, десятой и т.д. Кроме того, можно добавлять точки к траектормям не в каждом кадре, а через каждые пять или десять кадров. Для этих целей идеально будет добавить пару атрибутов к обьекту particle1 и использовать их в expressions. • Добавьте два атрибута к particlel: everyld и everyFrame (integer, default=1)

Изменим expression, чтобы выполнять все действия не для всех частиц, а только для некоторых.

.............................................................................................................................................................................


Майские волосы. Трюки и уловки. .............................................................................................................................................................................

Creation expression:

if (id%particle1.everyld==0) { vector $p = partieleShapel.position; curve -d 1 -p ($p.x) ($p.y) ($p.z) }

-n

(“traj”+int(id)) ;

Runtime expression:

if(id%particle1.everyld==0 && frame%particle1.everyFrame==0) { vector $p = partieleShape1. position; curve -p ($p.x) ($p.y) ($p.z) -a (“traj”+int(id)); } • Поиграйте с новыми атрибутами и посмотрите на результат. Теперь можно добавлять поля, коллизии и другие способы управлять движением частиц. Можно также без изменений копировать эти expressions на любые частицы, например испускаемые с поверхности головы. А текстуру лысости можно использовать для обозначения области испускания. •

Откройте файл 9x2_ParticleHair.ma.

Там находится поверхность, испускающая частицы. Expression уже скопирован в сцену. Также в сцене есть пара радиальных полей, действующих на частицы. Проиграйте анимацию. • Выберите hairParticles. • Установите L0D_P=1, чтобы рисовать траектории для каждой частицы. • Можно также установить tessellation Factor=2000 для ноды geoConnector1, чтобы улучшить равномерное распределение испускаемых частиц. • Проиграйте 150 кадров анимации. • Удалите expression 1, чтобы траектории не удалились в первом кадре (используйте команду “delete expression1”). Можно также экспортировать траектории в отдельный файл. • • •

Удалите частицы, поля и источник частиц. Выберите все кривые из группы groupTrj. Превратите их в динамические кривые: Hair=>Make Selected Curve Dynamic.

Если вы хотите анимировать полученные волосы динамикой, не забудьте освободить их концы (Point Lock=Base). Чтобы удерживать пучок собранным, можно применять констрейны. Для задания жесткости пучка идеально подойдет атрибут Start Curve Attract в совокупности с градиентом Stiffness Scale. • • • •

Удалите группу hairSystem1 OutputCurves, чтобы ускорить просчет и сохранить память. Выберите hairSystem и добавьте кисть Paint Effects для визуализации волос. Установите Hair per Clump=25; Clump Width=0.2; Hair Width=0.05, Sub Segments=1. Настройте свет и просчитайте картинку.

............................................................................................................................................................................. Сергей Цыпцын


.............................................................................................................................................................................

Некоторые замечания по применению динамических кривых

Еще немного комментариев о динамике кривых. Довольно приятная ее особенность заключается в том, что абсолютно любую сплайновую кривую можно превратить в динамическую кривую. Подругому можно сказать, что любую кривую можно включить в систему волос. Что это может дать? Прежде всего, это широкие возможности по автоматической анимации формы кривых. Если раньше для создания эффекта упругой конструкции типа антенны необходимо было превратить кривую в новое мягкое тело, потом назначить оригинальную кривую в качестве goalобъекта для частиц это мягкого тела и затем назначить для каждой частицы нужный вес, то теперь сделать упругую кривую можно при помощи всего одной операции: Hair=>Make Selected Curve Dynamic. Коль скоро любой набор кривых может быть превращен в, назовем их так, «динамические веревки», то благодаря Construction History, возникает масса возможных использований анимации кривых для создания различных эффектов. Во-первых, проведя через динамические кривые поверхность типа Loft, вы получите довольно веселую анимацию ткани. Настройка столкновений с поверхностями, потребует некоторой ловкости рук, но, тем не менее, работа с такой тканью будет в разы быстрее, чем с MAYA Cloth, и в разы проще, чем с мягкими телами. Никакого отслеживания самопересечений, как вы понимаете, не предусматривается. Во-вторых, использование динамических кривых в качестве IK Spline Handle для управления движением длинных цепочек их костей, позволяет сэкономить массу времени при анимации всяческих хвостов, усов и прочих висяче-упругих конструкций. В-третьих, применение динамических кривых в качестве Wire Deformer позволяет сделать динамической (с точки зрения анимации) любую часть поверхности. Анимация остаточных движений при этом становится лишь вопросом правильной группировки кривой и поверхности. Кроме того, динамические кривые могут выступать в качестве аттракторов для меха, обеспечивая динамическую анимацию меховых покровов.

Универсальный совет для работы с волосами

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

.............................................................................................................................................................................


.............................................................................................................................................................................

Автор: Забелин Владимир

Свет мой, зеркальце, скажи... Maya обладает чрезвычайно гибкой и, значит, чрезвычайно мощной системой визуализации, базирующейся на системе шэйдинга (shading). “Shading” переводится как “тонирование”, однако, в применении к Maya такой перевод кажется мне недостаточно адекватным, поэтому я буду пользоваться русской транскрипцией английского термина. То же относится и к термину “шэйдер” (shader), который по своему функциональному значению существенно шире обычного понятия “материал”.

............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

Свет мой, зеркальце, скажи... Автор: Забелин Владимир

Создание шейдера Собственно, создание шэйдера в Maya заключается в построении Функциональной цепочки (более аккуратно выражаясь, графа) - shading network - из зависимых между собой функциональных узлов специального типа (shading nodes). Этот граф является неотъемлемой частью общего графа зависимостей (dependency graph, DG), поэтому, при определении свойств шэйдера, вдумчивый пользователь может задействовать не только специализированные (текстуры, материалы), но и вообще любые имеющиеся в Маya функциональные узлы. Такой “произвол” позволяет создавать не только художественные изображения с высокой степенью фотореалистичности, но и вносить в финальную картинку разного рода специальные эффекты, не вписывающиеся в рамки физических законов, которые называют нефотореалистической визуализацией (non-photo realistic render). Один из методов создания различных специальных эффектов шэйдинга основан на использовании выходных параметров (outColor, outGlowColor или outTransparency узла материала, то есть тех значений, которые получаются после учета освещенности расположения точек поверхности по отношению к камере, шероховатости и прочее.

В первом примере мы создадим зеркало, отражающее окружающие предметы в ��ерых тонах. Начнем с простой сцены: рюмка и отражающее ее зеркало (сцена reflection01. mb). Сосредоточим наше внимание на шэйдере зеркала. Начнем строить его на основе материала, который назовем mirror. В нашем примере мы использовали материал типа blinn, но это может быть и любой другой материал с отражающими способностями. Обратим внимание на высокие значения отражения (reflection=1) и цвет блика (specularColor) - белый. Не забудем, что для появления отражений необходимо в опциях визуализации (render globals) включить опцию Raytracing, а в самом материале в разделе Raytrace Options установить ненулевое (а в нашем случае это 4) значение параметра Reflec-tion Limit .............................................................................................................................................................................


Свет мой, зеркальце, скажи... .............................................................................................................................................................................

Вот так выглядит сцена после визуализации. Для измененияотражающихсвойствшэйдеранеобходимо разделить результирующий цвет поверхности (mirror.outColor) на две составляющие - цвет поверхности без отражений и цвет отражения. Откроем окно Hypershade и начнем.

1. Сдублируем материал mirror и переименуем копию в mirrorWithoutReflection duplicate -name

mirrorWithoutReflection mirror;

(В нашем случае материал зеркала чрезвычайно прост, но в более сложных случаях, например, с наложенной текстурой шероховатости, или с другими входными связями (input connections), имело бы смысл воспользоваться командой меню Edit -> Duplicate -> With Connections to Network)

2. У нового материала уменьшим Reflection Limit до 0. setAttr mirrorWithoutReflection.reflectionLimit 0; В результате мы получили два шэйдера, различие между которыми лишь в одном: первый способен отражать окружающие объекты, а второй - нет. Следовательно, разность между атрибутами outColor этих шэйдеров и есть искомое отражение в «чистом» виде.

3. Создаем утилиту plusMinusAverage (Create -> General Utilities -> Plus Minus Average).

Назовем ее difference: shadingNode -name difference -asUtility plusMinusAverage;

4. На первый 3D вход узла difference подаем значение outColor с шэйдера mirror, на второй - out-

Color с mirrorWithoutReflection и выбираем операцию Substruct (вычитание): connectAttr -f mirror. outColor difference.input3D[0] ; connectAttr -f mirrorWithoutReflection.outColor difference. input3D[l]; setAttr difference.operation 2;

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


.............................................................................................................................................................................

5. Создаем утилиту luminance, (Create -> Color Utilities -> Luminance), назовем ее gray-scale и

подадим на ее вход выходное значение узла difference.

shadingNode -name grayscale -asUtility luminance; connectAttr -f difference.output3D grayscale.value; Осталось только наложить измененное отражение (grayscale.outValue) отражения исходный шэйдер зеркала.

6.

Создаем еще одну утилиту plusMinusAverage (назовем ее Add), на 3D входы которой подаем outvalue узла add и outColor узла mirrorWithoutreflection: shadingNode connectAttr connectAttr connectAttr connectAttr

-name add -asUtility plusMinusAverage; -f grayscale.outvalue add.input3D[0].input3Dx; -f grayscale.outvalue add.input3D[0].input3Dy; -f grayscale.outvalue add.input3D[0].input3Dz; -f mirrorWithoutReflection.outColor add.input3D[l];

(Заметим, что результат утилиты скалярный, поэтому нам пришлось «накладывать черно-белое отражение покомпонентно). Теперь полученный результат нужно поместить в какой-то шэйдер. Поскольку в своих упражнениях мы использовали выходные значения цветов шэйдеров, то идеальным вариантом для нас будет использование Surface Shader материала.

7. Создаем Surface Shader материал и переименовываем его в grayscaleMirror (Create -> Materials -> Surface Shader);

shadingNode -name grayscaleMirror -asShader surfaceShader;

Sets -renderable true -noSurfaceShader true -empty -name grayscaleMirrorSG connectAttr -f grayscaleMirror.outColor grayscaleMirrorSG.surfaceShader;

8.

Результат наших экспериментов (add.outColor) связываем с атрибутом outColor шэйдера grayscaleMirror: connectAttr -f add.outColor grayscaleMirror.outColor; .............................................................................................................................................................................


Свет мой, зеркальце, скажи... ............................................................................................................................................................................. Итак, финальный шэйдер получен (файл reflection02.mb). Осталось для тех поверхностей, на которых лежал материал mirror, заменить его на grayscaleMirror. Результат визуализации оправдывает наши ожидания. Изменение отражения с цветного на черно-белое - не единственно возможный вариант. Можно использовать и гамма-коррекцию, и сдвиг цветового баланса - любой алгоритм, отвечающий требованиям производственной необходимости или собственной фантазии и настроения.

Изменяем цвет отражения

Заметим, что построенный нами шэйдер изменяет вид всех отражаемых объектов - в нашем случае, в черно-белом виде будут отражаться и рюмка, и стол. Иногда возникает похожая по формулировке, но абсолютно противоположная по смыслу задача: изменить вид отражения одного конкретного объекта во всех отражающих поверхностях. В качестве примера можно предложить отражение, интенсивность которого изменяется в зависимости от расстояния до отражающей поверхности - ближе к поверхности интенсивность отражения больше, выглядит более реалистично. Для решения подобной задачи можно воспользоваться простым трюком: использовать два различных объекта - один для визуализации самого объекта, а второй - для визуализации отражений. Начнем со сцены reflection01.mb

1. Сдублируем рюмку - ее имя glassObj (Edit -> Duplicate). Переименуем копию в glassObjCopy: 2. duplicate -name glassObjCopy glassObj; 3. Сдублируем материал нашей рюмки и добавим текстуру на прозрачность, например, черно-

белый ramp (в нашем примере лучше использовать проекционную текстуру; и не забудем ту же, но реверсированную по цвету, текстуру добавить на specular, чтобы избежать «паразитных» бликов)

............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

4. В атрибутах шэйпа нашей рюмки в разделе Render Stats снимем галку с атрибут ible In Reflec-

tion:

setAttr glassObjShape.visibleInReflection 0; Теперь наша рюмка будет рендериться, но не будет видна в отражениях,

5. В атрибутах шэйпа копии рюмки в том же разделе Render Stats снимем галку с атрбута Primary

Visibility:

setAttr glassObjCopy.primaryVisibility 0; Теперь копия нашей рюмки будет видна только в отражениях. Итак, один объект виден, но не отражается, второй - отражается, но невидим, (файл reflection04.mb)

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

.............................................................................................................................................................................


.............................................................................................................................................................................

Автор: Ледин Павел

Работаем с Mentalray Mentalray - является серьезным продакшн (production) визуализатором (далее: рендерер), поэтому для многих пользователей, особенно начинающих, он может показаться достаточно сложным и непонятным. Часто даже у пользователей, имеющих определенный опыт работы с другими рендерами, возникают проблемы. Следующий материал поможет немного быстрее понять mental ray. В первой главе рассказывается о некоторых принципиальных отличиях mental ray рендера от стандартного Maya Software рендера, о преимуществах и недостатках данных рендеров, о том, когда что лучше использовать. Очень часто наиболее животрепещущим вопросом для начинающих пользователей mental ray является то, как пользоваться “менталовскими” шейдерами. В главе про Custom Shaders речь пойдет о некоторых особенностях этих шейдеров, так же здесь описывается около половины из них; подробно раскрывается тема запекания, как очень важного процесса оптимизации сцены, описывается запекание в текстуру и в цвет вершин. Для тех, кто хочет “копнуть” глубже и полностью разобраться во внутреннем устройстве рендера, адресован материал по написанию шейдеров для mental ray. Пошагово описывается процесс создания проекта и написания нескольких самых простых шейдеров, таких как: constant, lambert и phong. Описывается процесс написания *.mi файлов и т.д. Данный материал рекомендован тем, кто хочет не просто попрактиковаться в навыках программирования, а разобраться в том, как же все устроено внутри, лучше понять принцип работы, ну, и, разумеется, написать нужные именно вам шейдера и тем самых оптимизировать и облегчить свою работу.

.............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

Автор: Ледин Павел

Mentalray

Различие между визуализаторами На сегодняшний день существует достаточно много разных визуализаторов которые отличаются и порой очень серьезно - по принципу работы, скорости и по конечному результату. Один рендер может считать красивое освещение, другой может быстро визуализировать огромное количество геометрии, ну а третий может вообще рассчитывать только нефотореалистичные изображения в стиле cartoon. Разумеется, для разных задач нужно выбирать именно тот рендер, который подходит в данном случае Но порой начинающему пользователю бывает очень сложно сориентироваться в имеющихся рендерах. Даже заглянув в Maya, мы увидим сразу 4 рендера, не говоря уже о рендерах поставляемых сторонними разработчиками. Визуализаторы от других разработчиков мы рассматривать не будем, а остановимся немного подробнее именно на стандартных майских рендерах. По названию Maya Vector Maya Hardware не сложно догадаться о назначении этих рендеров. Первый предназначен для рендера в стиле cartoon и векторных изображений, таких как *.swf и т.п. Второй Hardware Render, служит для визуализации сцены с помощью видеокарты - его, например можно использовать для визуализации частиц или же просто для предварительного рендера. Оба эти рендера достаточно специфичны и вряд ли могут претендовать на роль основного визуализатора. А вот Maya Software и mental ray вполне могут справиться такой задачей. Вот о них и пойдет речь дальше. Мы не будем выбирать “лучший” рендер а просто попытаемся объективно сравнить, рассмотрев преимущества и недостатки того и другого визуализатора.

Преимущества Maya Software В целом, по функциональности и количеству возможностей, Maya Software Render часто проигрывает Mental Ray, и иногда его наличие в пакете может показаться бессмысленным. Но не будем такими категоричными. Не стоит забывать, что Maya Software - это родной майский рендер, и он врожденно поддерживает все возможности Maya. В то время как mental ray приходится приспосабливаться, и не всегда легко реализовать все возможности Maya Software рендера. Реализация некоторых возможностей Maya Software рендера в mental ray иногда может выглядеть даже немного “коряво”. Чаще всего все нововведения в Maya изначально визуализируются только Maya Software рендером и лишь в последующих версиях обретают поддержку визуализации помощью mental ray. Надо заметить, что до сих пор mental ray поддерживает не все. Но список ограничений от версии к версии сокращается, и в данный момент в нем осталось совсем немного пунктов. Разработчики постарались, чтобы пользователь мог применять практически все инструменты Maya вне зависимости от используемого рендера. Но, несмотря на поддержку некоторых функций и возможностей mental ray, иногда в Maya Software они могут работать немного корректнее. Но это не единственное преимущество Maya Software. Родной рендер имеет еще несколько плюсов, о которых так же не стоит забывать. Например, если ваша сцена не очень “тяжелая”, в ней нет рейтрейсинга и шейдинг не очень сложный, то такая сцена часто может визуализироваться в Maya Software значительно быстрее, чем в mental ray Однако, при усложнении сцены и включении дополнительных функций, расклад монет измениться. Maya Software часто используется для быстрой визуализации не очень сложных сцен. ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Еще одно из принципиальных отличий и одновременно преимущество в том, что Maya Software “ест” напрямую майскую сцену, в то время как mental ray, а так же большинство других сторонних рендеров нуждается в конвертации сцены в свой формат. В случае Mental Ray Stand Alone сцена конвертируется в *.mi файл, который потом рендерится в отдельной программе (stand alone render). Встроенный в Maya mental ray делает все то же самое, за исключением того, что *.mi файл будет для нас невидимый. Для пользователя все будет незаметно - он просто нажмет на кнопку “Render” и получит картинку внутри Maya. Для простых сцен эта операция слишком быстра, чтобы влиять на время рендера, и часто пользователь просто не замечает ее. Но если в сцене очень много геометрии или просто количество объектов слишком велико, то эта фаза может занимать очень значительное время, особенно когда дело доходит до визуализации длинной анимации. Maya Software рендер не имеет данного недостатка, и, соответственно, сам процесс визуализации начнется быстрее. Другим сравнительнымпреимуществомявляется поддержка Maya Software рейдером Paint Effect’oB. В данный момент рендер Paint Effect’ов в mental ray невозможен без конвертации в геометрию, а, как известно, результат конвертированных в геометрию paint effect’oB немного отличается, не говоря уже о серьезно возросшем количестве полигонов, и как следствие - возросшем времени конвертации сцены. Хотя, надо заметить, что на данный момент существуют сторонние разработки, которые предлагают автоматическую конвертацию Paint Effect’ов и волос в геометрию во время рендера. Правда, при этом все равно во время рендера расход памяти будет очень велик. Если немного поразмыслить, можно представить себе два возможных способа реализации Paint Effect’ов в майском mental ray. Первое - это генерить геометрию geometry шейдерами во время рендера (с помощью geometry шейдеров), в этом случае Pain Effect’ы будут даже корректно отражаться и преломляться. Но минусом этого метода можно назвать серьезно возросший расход памяти, особенно когда Paint Effect’ов очень много в сцене, так как в итоге никакого волшебства не происходит, и все равно все превращается в полигоны, но уже на стадии рендера. В этом случае viewport не будет сильно перегружен геометрией, и мы сильно выиграем на стадии конвертации сцены. Второй метод похож на тот, что работает в Maya Software, то есть генерация Paint Effect’oB пост процессом (после рендера). Но тут есть одно но. Mental Ray не поддерживает генерацию чего-либо после рендера, отличного от картинки. То есть, если быть более точным, mental ray не имеет доступа к геометрии на фазе пост процесса, он может только взять получившиеся после рендера картинки (буфера) и что-то с ними сделать, например Glow, или 2D motion blur, или DOF и т.п. Пытливым умам, наверное, давно приходила в голову идея отрендерить картинку mental гау’ем, а потом сверху сгенерить Paint Effect’ы уже Maya Software рендером. Теоретически разработчики могли бы это реализовать, ведь это не так сложно, нужно было бы просто запустить после рендера mental гау’ем генерацию Paint Effect’ов с помощью Maya Software рендера, ведь это просто post process. Похожую идею разработчики Maya реализовали в пакете, начиная с версии 7.0, с помощью Render Layers. Данная технология позволяет не просто считать несколько разных слоев, но и визуализировать их разными рендерами. Собственно, именно это и нужно для визуализации Paint Effect’ов. Визуализируем всю сцену с помощью mental ray, a Paint Effect’ы рендерим в отдельном слое с помощью Maya Software - и проблема решена. Но тут есть небольшое ограничение. Если вы визуализируете вашу сцену не в Maya, а с помощью mental ray stand alone, то данная технология не подойдет. В итоге универсальным представляется только первый способ. Будем надеяться, что разработчики реализует его в одной из последующих версий. Maya Software корректно рендерит Subdivide Surfaces. Mental Ray же не поддерживает Partial Creases. Но это не такое большое ограничение, которое может быть устранено в одной из последующих версий Maya Mental Ray в Maya, в отличие от Maya Software рендера, не поддерживает рендер по полям (Field Rendering). .............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

Преимущества Mental Ray

Все выше перечисленное, так или иначе, можно назвать преимуществами Maya Software и одновременно недостатками Mental Ray for Maya. А теперь давайте обсудим основные преимущества mental ray. Прежде всего, mental ray - это быстрый и функциональный рейтрейсер. Если вы собираетесь рендерить сцену, насыщенную зеркальными и преломляющими поверхностями, например, стеклянные объекты, то, наверное, качественнее и быстрее будет это сделать именно с помощью mental ray. Так же mental ray поддерживает размытые отражения и преломления, чем не может похвастаться родной Maya Software рендер - данная возможность в нем отсутствует как класс. Другим и, наверное, самым заметным преимуществом mental ray является поддержка таких эффектов, как: Global Illumination, Final Gathering, Caustic и Volume Caus-tic. • • • •

Global Illumination (Gl) позволяет просчитывать физически корректное освещение с помощью фотонов. Final Gather (FG) - алгоритм, позволяющий увеличить скорость и качество GI,так же может использоваться как самостоятельный метод освещения, например, с помощью HDR images. Caustic создает эффект каустики от прозрачных и зеркальных объектов, например, яркое пятно, полученное после прохождения света через стакан с водой. Volume Caustic - луч каустики, видимый в пространстве, например, луч света, прошедший через увеличительное стекло. Все эти возможности предоставляют широкий спектр инструментов для создания “физически корректных” (в достаточной мере) эффектов.

Mental Ray поддерживает распределенный сетевой рендеринг (Distributed Network Rendering), то есть когда один кадр считается на нескольких машинах. Mental Ray также хорошо распараллеливает просчет на мультипроцессорных машинах (до 256 процессоров на одну машину). Интегрированный в Maya mental ray позволяет использовать до 4 локальных процессоров. Лицензия Maya Unlimited дает возможность бесплатно (не приобретая дополнительных лицензий) рендерить еще на 8 дополнительных сетевых процессора, используя Mental Ray Sattelite. Лицензия Maya Complete позволяет использовать только 2 дополнительных сетевых процессора. Использование Mental Ray Stand Alone позволяет снять все эти ограничения. Разумеется, для этого понадобится купить нужное количество лицензий. Следует заметить, что, если вы имеете Pentium 4 с поддержкой технологии Hyper Threading, то он будет работать быстрее, чем тот же процессор, но без НТ. Обычно прирост производительности от включения НТ на простых сценах не заметен, но в реальных тяжелых сценах он может оказаться достаточно серьезным, например, около 20%. Контурный шейдера позволяющий создавать эффект рисованного мультфильма (cartoon) или просто создавать материалы с контуром. Данная возможность может легкостью заменить Maya Vector рендер, с тем лишь исключением, что mental ray не может. сохранять результат как векторную графику. Multipass Rendering позволяет рендерить сцену за несколько раз, разделяя на разные объекты или элементы, при этом всегда видя всю сцену целиком. Например, вы можете отрендерить все объекты по отдельности, записав каждый объект в свой pass. При всех последующих рендерах отрендеренные объекты будут не пересчитываться, а просто браться из сохраненного пасса. В данной ситуации всегда можно пересчитать только ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. нужный объект (пасс) без пересчета всей сцены целиком. Так же можно помещать в пасс не объекты целиком, а элементы, например, только specular или diffuse и т.п. К сожалению, пока эта возможность вообще никак не реализована в Maya. Но, имея Mental Ray Stand Alone, а так же небольшой опыт написания шейдеров и базовые знания mel, можно реализовать эту возможность в Maya вручную. Будем надеяться, что разработчики скоро реализует эту отнюдь не лишнюю возможность. Одним из основных преимуществ mental ray можно назвать программируемость и расширяемость. Mental Ray позволяет писать шейдера на С или C++ почти для всех элементов сцены. Например, вы можете с легкостью написать шейдера таких типов, как: material, photon, volume, photon volume, light, photon emitter, texture, shadow, camera lens, environment, displacement, output, contour и geometry. В поставке с mental ray всегда идут 3 стандартных библиотеки шейдеров: base, physics и contour с исходным кодом, поэтому всегда можно посмотреть, как все устроено. А если вас что-то не устраивает в стандартных шейдерах, можно изменить или переписать шейдер как вам надо. При этом для написания простых шейдеров вам не понадобится глубокое знание программирования, достаточно будет лишь базовых знаний. Подробнее о написании шейдеров можно узнать из последней главы.

Переход на Mental Ray и разница восприятия

В данной главе описывается разница восприятия и некоторые особенности идеологии mental ray. Если у вас уже имеется опыт работы с любым другим рендером, он будет отнюдь не лишним при работе с mental ray, так как основные принципы везде одни и те же. Однако существует достаточно много идеологических различий и подходов, которые могут существенно влиять на работу. Предположим, вы уже имеете некоторый опыт работы с Maya Software рендером и пытаетесь освоить mental ray. Далее мы кратко рассмотрим некоторые различия в идеологиях, чтобы облегчить переход на mental ray.

Понятие “shader” Начнем, пожалуй, с понятия shader. Дело в том, что в Maya понятие шейдер относится в основном только к самим материалам, а в mental ray это понятие гораздо шире и более общее. Например, может быть не только Surface shader, но и Texture shader, Environment shader, Volume shader, а так же даже Light shader и Geometry shader. В общем, понятие шейдер применяется практически ко всему тому, что пользователь может сам написать или изменить. Надо сказать, что таких мест в mental ray достаточно много. Примечание; Некоторые из типов менталовских шейдеров до сих пор не поддерживаются Мaуа’ей, например(State Shader), но это достаточно специфичная групп,а и поэтому тот, кто знает, зачем они нужны и как ими пользоваться, найдет способ прикрутить их к Maya. Другой разницей, которая иногда приводит к недопонимаю у людей, воспитанных других рендерах, является тот факт, что непосредственно на объект можно назначить олько Surface Shader, но и, например, напрямую Texture Shader. To есть можно просто положить на обьект текстуру без как такового материала. Говоря более широко, с точки зрения шейдера, в mental ray нет разницы между mib_illum_blinn и обычным mib_texture_checkerboard или даже mib_reflect. To есть разделения на группы: material и texture достаточно условны. Разумеется, light shader’a, например, нельзя назначить на объект, но ряд других шейдеров можно. Для лучшего понимания я приведу еще один пример. Все знают, что в Maya есть Lay-ered Shader и Layered Texture. Первая нода служит для смешивания нескольких шейдеров, а вторая - для смешивания нескольких текстур. В mental ray же в обоих случаях можно .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. использоваться mib_.color.mix, потому что разницы как таковой, с точки зрения mental ray, между текстурой и шейдером нет. Но все же есть некоторые ограничения, и не все шейдера можно назначить на поверхность. Главный шеидер, лежащий непосредственно на поверхности, должен возвращать только один цвет, все же остальные могут возвращать сколько угодно color’ов или других типов данных. Не следует забывать, что все майские поверхностные шейдера возвращают по 4 соlог’а(цвета), и поэтому, при попытке положить на слот material shader’a любой из них, возникнет ни о чем не говорящая ошибка. Данную ошибку можно наблюдать, положив на material shader слот - например, майский Checker. Однако, все будет работать нормально если на его месте будет менталовский mib_ texture_checkerboard. Примечание: На слот material shader все же можно назначить майский шейдер, но для этого потребуется включить галку ‘Export with Shading Engine’ в shading group, В этом случае Maya во время рендера сама вставит ноду, которая сконвертит 4 color’a в rgba.

Color Майски й тип color отличается от менталовского color, хотя в интерфейсе они выглядят совершенно одинаково. Майский color - это структура, состоящая из 3 компонентов RGB, а менталовский color - структура, состоящая из 4 компонентов RGBA, то есть добавляется alpha канал. У Maya Software рендера не возникает проблем при попытке подсоединит Color на Vector (XYZ), так как оба эти типа представляют собой структуру, состоящую иза трех элементов rgb и xyz соответственно. При рендере mental ray все color’ы становятся четырехкомпонентные, добавляется альфа канал, и именно по этой причине возникают некоторые проблемы при попытке соединить color и vector друг с другом. API 0.0 warn 302018: type conflict: “weight3d” is type vector, “maya_checker” returns type color Ну, предупреждение есть предупреждение, и ничего особо страшного не произошло, и теоретически все должно работать корректно. При этом четвертый компонент цвета (Аl-pha), скорее всего, будет просто игнорирован. Но все же, в идеале такой ситуации стоит избегать, потому что не известно как может повести себя рендер в различных ситуациях. Некоторые люди уже написали свои шейдера (ноды) для решения этой проблемы, позволяющие конвертировать vector в color. То есть в том месте шейдинг нетворка, где вам нужно соединить vector с color, вы просто вставляете эту ноду, и она правильно делает конвертацию.

Непонятные шейдера Другим фактом, по началу пугающим начинающих, является наличие в mental ray больше количества разных типов шейдеров, часть из которых не имеют аналогов в Maya Soft-ware. Например, что делать с Geometry shader’ами? Или, куда и зачем подсоединять Lens shader’a? Об Custom’ых шейдерах можно узнать из следующей главы.

............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

Custom shaders Помимо стандартных майских шейдеров, мы можем видеть в Maya так же и так называемые. custom шейдера. Эти шейдера можно найти в Hypershade во вкладке “Create mental ray Nodes”.

Примечание: Если у вас в Hypershade нет вкладки Create mental ray Nodes, то, скорее всего у вас не загружен mental ray рендер в Plug-in Manager. Для того, чтобы его включить, идем в Window=>Settings/Preferences=>Plug-in Manager и ставим галку напротив Mayatomr.mll.

.............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Так что же такое custom shaders? На самом деле, это стандартные библиотеки шейдеров для mental ray, которые поставляются во все пакеты, куда интегрирован mental ray. Это можно сказать, минимально необходимый набор. Часть из этих шейдеров поставляется с исходным кодом, и каждый желающий может править их по своему усмотрению. Он могут служить хорошим примером для желающих написать свои собственные шейдера Это библиотеки: base, contour, physics, subsurface(без исходного кода) и paint(без исходного кода). В этих библиотеках можно найти различные шейдера, начиная от самых простых вроде Lambert, Blinn, и заканчивая достаточно сложными комплексными шейдерами для просчета Sub Surface Scattering’a (под поверхностное рассеивание света). Многие скажут: “А зачем нам blinn, когда в Maya уже есть свой blinn?” дело в том что существует несколько принципиальных различий между майскими и менталовским шейдерами. Они, скорее, идеологические, чем принципиальные. Рассмотрим эти различия на примере того же blinn’a. Основное различие касается работы шейдера с альфа каналом. Майские шейдера возвращают 4 цвета(rgb): Out Color, Out Glow Color, Out Matte Opacity, Out Transparency, то есть каждый шейдер просчитывает все эти компоненты по отдельности, А ст��ндартные менталовские шейдера, разумеется, не имеют Out Glow Color и Out Matte Opacity, a Out Color и Out Transparency объединены и просчитываются вместе, то есть как rgba. Именно по этой причине в одном шейдинг нетворке, например, в Layered шейдере, лучше не использовать вместе менталовские шейдера и майские, так как в этом случае чейнибудь альфа канал обязательно потеряется.

В данном случае видим, что теряется альфа канал из mib_illum_blinn ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

В этом случае теряются 3 канала: Out Glow Color, Out Matte Opacity и Out Transparency Если же в shading network (сеть из нескольких шейдеров) использовать только один тип шейдеров, например, только майские или только менталовские, то мы гарантированно получим корректный результат и правильный альфа канал. Разумеется, на двух разных объектах можно использовать разные шейдера, например на одном майские, а на другом менталовские. Именной по причине того, что альфа канал в майских шейдерах считается другим способом и отдельно, у custom шейдеров по умолчанию вообще отключен альфа канал, так как подразумевается, что будут пользоваться в основном майскими родными тендерами. Поэтому многие люди, обнаружив пропажу альфа канала на кастомных шейдерах, поднимают панику. А решается все просто включением в Render Settings опции ‘Pass Surface Color Alpha Channel’. Эту опцию следует включать всегда, когда вы используете кастомные шейдера - разумеется, если вам вообще нужен альфа канал. Так же майский blinn и большинство других менталовских шейдеров отличается по количеству параметров и иногда даже по их смыслу. Еще mib_illum_blinn может оказаться совсем немного быстрее майского Blinn, и это вполне логично, так как менталовский вариант намного проще майского аналога. Хотя, в принципе, разница в скорости мало заметна. Другая особенность касается просчета Indirect освещения (Global Illumination, Final Gather и каустика). На майских шейдерах Indirect освещение будет приблизительно в 3 раза слабее, чем на менталовских. В Maya освещение уже поделено на пи (3,14), что ближе к реальным значениям в природе и считается более корректным. Соответственно, если вы используете в одной сцене два вида шейдеров, следует быть осторожными с GI, FG и каустикой, так как освещение будет разное по интенсивности в зависимости от типа шейдера. Если вам все же хочется использовать и те и другие шейдера в одной сцене, а проблема с разной интенсивностью indirect освещения не дает вам покоя, то можно попробовать сделать следующее: .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Во всех майских шейдерах значение Irradiance Color ставим ярче в 3.14 раза. То есть выставляем значение Value у Irradiance Color в значение 3.14.

В результате получаем, что по интенсивности ненаправленного освещения менталовские и майские шейдера сравнялись. Но теперь оно слишком яркое. Для решения этой проблемы идем в Render Settings и находим там параметр Final Gather Scale (ну и Caustic Scale и Global Ilium Scale соответственно) и выставляем его в 3,14 раза слабее-то есть в значение 0,318, или на глаз как вам понравится. В итоге имеем одинаковое по интенсивности и не очень яркое ненаправленное освещение. Майские шейдера прекрасно работают с Maya Light Linker’oм, а у менталовских свой механизм линковки источников света. Для того, чтобы включить или исключить источник света из освещения конкретного шейдера, нужно вручную подсоединять Mes- sage источника света на элементы массива Lights шейдера. Так же большинство шейдеров имеют параметр Mode, отвечающий за работу со списком источников света. Если mode равен 0, то используются все источники света, подконекченные к шейдеру; если mode равен 1 (inclusive), то используются все источники, подключенные к Lights, если 2(exclu-sive), то используются все источники света за исключением тех, которые подсоединены к шейдеру. Когда mode установлен в значение 0, и ни один источник не подсоединен, то ничего соединять вручную не нужно - Maya сама проделывает эту операцию при экспорте (рендере)сцены. Примечание: Maya Light Linker поддерживает линковку источников света как к шейдерам, так и к объектам. Mental ray Light Linker поддерживает линковку только к самому шейдеру. Также хотелось бы немного рассказать о назначении менталовских шейдеров, то есть о том, куда их нужно подсоединять. Шейдера назначаются на соответствующие слоты в Shading Group. Можно воспользоваться Shading Group’ами, созданными вместе с майскими шейдерами. Если вы этим воспользуетесь, то майский шейдер, подсоединенный к Shading Group’e(Surface Material слот), будет игнорироваться во время визуализации, a mental гау’ем будет использоваться шейдер, подсоединенный к слоту Material Shader в закладке mental ray->Custom Shaders. ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

Шейдера из закладки Materials могут быть так же назначены непосредственно на объект без создания дополнительной шейдинг группы при этом Maya сама создаст Shading Group’y и подсоединит к ней шейдер. Заглянув во вкладку mental ray в Shading Group’e, мы сразу видим много слотов для разных типов шеидеров. Название слотов соответствуют названию групп менталовских шейдеров в Hypershade. Шейдер из определенной группы нужно подсоединять на соответствующий слот в Shading Group’e. Подробнее о типах шеидеров пойдет речь в следующей главе.

Описание шейдеров

В стандартной документации mental ray есть описание всех custom’ных шейдеров, но часто для обычного пользователя это описание может показаться слишком сухим и непонятным Многие считают, что эта документация для программистом, а не для художников. Отчасти так оно и есть, но, тем не менее, там можно найти всю необходимую информацию кроме туториального пересказа и красивых картинок. Поэтому в следующей главе эта тема описывается немного более понятным языком Описывается часть из этих шейдеров, рассказывается, как ими пользоваться и что они умеют. Данный материал не ставит цель дать полное описание абсолютно всех шейдеров, ведь главное понять принцип работы с ними. Поэтому будет говориться только о части всех имеющихся в Maya шейдеров, оставшиеся же шейдера можно изучить самостоятельно по аналогии с рассматриваемыми в этой главе.

Materials

В этой закладке лежат основные поверхностные шейдера, которые можно назначить непосредственно на объект. Чаще всего в этой группе находятся шейдера так называемых разных моделей освещения - например, таких как Lambert, phong и blinn. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Примечание: Шейдера из этой категории вы можете назначить прямо на объект, в этом случае Maya сама создаст Shading Group’y, подсоединит к ней шейдер и присвоит группу объекту. Следует заметить, что в этом случае Maya во viewports отобразит шейдер как зеленый Lambert, потому что Маyа не поддерживает просмотр mental ray шейдеров в OpenGL. Поэтому для более красивого отображения объектов во вьюпорте лучше использовать майские шейдера -, они будут корректно отображаться, и уже на них назначать менталовские, если это требуется. dgs_material - расшифровы вается как Diffuse Glossy Specular; материал может имитировать зеркальные объекты, метал, пластик и обычные диффузные объекты (lam-bert). Так же DGS может просчитывать объекты с размытым отражением и преломлениеш включая и анизотропное отражение. Примечание: Следует отметить, что в данном случае параметр Specular - это не блик как может показаться, а обычное зеркальное отражение. А параметр Glossy - это размытое отражение. Обычно следует использовать только одно из этих отражений, но, как ни странно, в Maya no умолчанию оба эти параметра включены.

Применение: Нужно положить dgs_material на Material Shader слот Shading Group’ы. Так же dgs_material shader может быть использован как Photon шейдер. То есть его можно запросто положить на слот Photon Shader dielectric_materjal - физически корректный шейдер для симуляции стекла, воды и жидкостей. Достаточно использовать простой и быстрый шейдер. Отражения и преломления основаны на формуле Fresnel’я. Шейдер учитывает толщину стекла, абсорбируя цвет в зависимости от длинны луча в диэлектрике. Поддерживает два диэлектрик-интерфейса: диэлектрик-воздух и диэлектрик-диэлектрик для правильной симуляции преломления и отражения в разных ситуациях. Примечание: Шейдер чувствителен к направлению нормали, то есть если на двух одинаковых объектах нормали развернуты в разные стороны, получиться совершенно разный результат, даже если эти объекты имеют включенную опцию Double Sided.

............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Применение: Шейдер, так же как и в случае с DGS, может быть использован как Material Shader и Photon Shader. mib_illum_lambert - классический диффузный шейдер без блика. По сути, э��о практически такой же ламберт, как и майский аналог, но с меньшим количеством параметров и выше описанными различиями.

Применение: Назначается на слот Material Shader. Так же можно назначить непосредственно на объекты, в этом случае Maya сама создаст Shading Group’y и подсоединит шейдер ей на Material Shader слот. mib_illum_phong - классический фонг шейдер с простым бликом.

mib_illum_blinn - обычный блинн шейдер, где блик зависит от параметра шероховатости (roughness) и угла взгляда.

.............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Примечание: Тут немного хотелось бы отметить параметр IOR, который новичку может показаться неуместным и странным в шейдере, так как вообще не имеет ни преломления, ни отражения. В данном случае параметр IOR отвечает за блик И, чтобы блик появился, значение параметра IOR нужно выставлять более 6.0 mib_illum_cooktorr - шейдер Cook-Torrance полностью эдентичный blinn за исключением того, что сила блика указывается не одним значением, а тремя (color), то есть можно установить силу блика для каждого компонента цвета RGB по отдельности. В результате можно получить интересный эффект.

mib_illum_ward - шейдер, иногда называемый Anisotropic, имеет разную “толщину” блика (glossy) по двум осям (векторам) - U и V.

Применение: Шейдер назначается на Material Shader слот. Так как U и V по умолчанию равны 0 0 0, то никакого блика мы не получим. Направления U и V нужно задать вручную. Это можно сделать разными способами. Например, можно создать mib_texture_rotate и mib_texture_vector. Потом соединить U и V ноды mib_texture_rotate с U и V mib_illum_ward’a. После этого на Input mib_tex-ture_rotate’a подсоединить выход с mib_texture_vector.

............................................................................................................................................................................. Ледин Павел


Работаем с Mentalray ............................................................................................................................................................................. mib_ illum_ward_deriv - шейдер, абсолютное подобие mib_illum_ward, за исключением того, что Uи V не задаются вручную, а берутся с направления поверхности (surface derivatives). Но, так как у полигонов и т.п. нет направления как такового, этот шейдер будет корректно работать только на Nurbs. Чаще всего его гораздо удобнее использовать, чем обычный mib_illum_ward, но зато возможность повернуть блик отсутствует.

Примечание: Шейдер mib_ilum_ward_deriv можно заставить работать и на полигональных объектах, если создать surface derivatives на основе UV раскладки. Для этого потребуется специальный шейдер, который проделает эту операцию. К сожалению, в стандартной поставке такого шейдера нет, но в данной ситуации можно воспользоваться шейдерами сторонних разработчиков. Например, один из таких шейдеров Denver можно найти по адресу: http://animus.bnnkster.net. Надо заметить, что при использовании анизотропика на полигональной геометрии качество анизотропичного эффекта будет зависеть от UV раскладки, а так же от количества граней на объекте. Чем мельче разбит объект, то есть имеет более высокую тесселяцию, тем более гладкий будет эффект. path_material - по параметрам этот шейдер в точности повторяет dgs_material, но работает он немного по другому. Шейдер интересен тем, что позволяет визуализировать вторичное освещение, такое как GI без включенного Gl, FG и каустики, причем достаточно хорошо, детально и без особых настроек. Основным недостатком можно назвать завышенные требования к самплингу - при низких настройках получается слишком заметный шум.

.............................................................................................................................................................................


............................................................................................................................................................................. Примечание: Если вы немного разбираетесь в написании шеидеров, то можно добавить локальные самплы для Indirect Diffuse этого шеидера, что позволит увеличить самплы на самом шейдере и считать сцену с нормальными глобальными сампламирендера, причем скорость самого шейдера при этом должна увеличиться Или же можно поискать в сети уже подправленную версию path_material. transmat - прозрачный поверхностный шейдер без параметров. Используется обычно в сочетании с Volume шейдерами, чтобы сам объект не визуализировался, а был виден только его объем. Применение: Шейдер применяется на слот Material Shader Shading Group’ы.

Shadow Shaders

Данный тип шейдеров предназначен для создания различных теней. По умолчанию, без какоголибо шейдера, все тени непрозрачные и черные. Создать прозрачную или цветную тень невозможно без использования shadow шейдеров. Когда мы используем Майские шейдера, нам не требуется назначать shadow шейдера, потому что Maya сама невидимо для пользователя при конвертации сцены создает и назначает эти шейдера в зависимости от того, какой шейдер назначен на поверхность. Когда же мы пользуемся менталовскими шейдерами, чуда не происходит, и нужно самим вручную назначать эти шейдера. Примечание: Этот шейдер будет работать только с Ray Trace или Detail Shad-owmap тенями; если использовать обычную Shadowmap тень, данные шейдера не будут вызываться и просчитываться, то есть тень будет сплошного черного цвета. Следует понимать, что шейдер применяется не к самой тени, а к объекту. Говоря другими словами, просто при просчете тени вызывается не основной шейдер поверхности, a shadow shader. Это сделано по причине того, что основной шейдер может содержать в себе много просчетов, совершенно не нужных для получения теней, например, отражения, блики, освещение и т.п. Поэтому вызывать полностью весь шейдер для просчета тени было бы очень накладно, и для теней используются Shadow Shader’a, которые могут просто возвращать цвет и прозрачность без ненужных просчетов. Так же это позволяет получить большую гибкость в настройке сцены. mib_shadow_transparency - данный шейдер позволяет задать цвет и прозрачность тени.

.............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Применение: Все Shadow Shader’a назначаются на Shadow Shader слот шейдинг группы. Параметром Color можно задать цвет тени, a Transp задает ее прозрачность. В Maya версии 7.0 и ниже, для того чтобы шейдер работал со всеми источниками света в сцене, нужно установить параметр mode в значение 1 или 3.

Volumetric Materials

Объемные шейдера отвечают за просчет объема внутри объекта и служат для создания различных эффектов, начиная от обычного тумана и заканчивая объемным светом и облаками. mib_volunie - простой объемный шейдер, основанный на длине луча внутри объекта. С помощью mib_volume можно создавать обычный туман и т.п.

Применение: Шейдер применяется на Volume Shader слот Shading Group’ы или камеры. В случае, если шейдер применяется на Shading Group’ы, то для того чтобы скрыть сам объект и получить только его объем, нужно еще на слот Material Shader подсоединить transmat шейдер, описанный выше. Parti_volume - более сложный объемный шейдер. В отличие от mib_volume шейдера, parti_votume может быть неоднородным, анизотропичным, а так же принимать тени. Может быть использован для создания облаков, мутных жидкостей и т.п.

............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Применение: Шейдер может быть использован так же, как и mib__volume. Примечание: Для получения теней на объеме нужно использовать менталовские шейдера для источников света. Так как майские стандартные источники света в этой ситуации почему-то не дают теней. Тип тени должен быть обязательно установлен в “Segments”. Так же на сам объект должен быть назначен полностью прозрачный mib_shadow_transparency в качестве shadow shader’a, чтобы стенка самого объекта не бросала тень на объем. mib_ray_marcher - объемный шейдер, который при прохождении луча через обьем через определенное расстояние, например, через каждый сантиметр, вызывает любой другой шейдер, указанный в поле Shader. Обычно таким шейдером становится 3d текстура. В результате мы видим как бы в объеме 3d текстуру, а не ее проекцию на поверхность.

mib_texture_checkerboard в качестве шейдера, вызываемого в объеме

слева mib_texture_polkasphere в качестве шейдера в объеме в центре то же самое, но на параметре Radius лежит текстура mib_texture_turbulence справа так же mib_texture_polkasphere с еще большим разбросом значений Radius

mib_ray_marcher внутри dielectric’a .............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

Displacement Staders

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

Photonic Materials

Шейдера, оперирующие фотонами. Данный тип тендеров используется только на стадии фотонного треисинга. По сути, это обычные Material Shaders, но только для фотонов. Например, если требуется, можно задать для основного просчета синий шейдер а для фотонов красный. По параметрам эти шейдера часто являются копией обычных Surface Shader’oB.

Photon Volumetric Materials

Данный тип шейдеров отвечает за поведение фотонов внутри объекта (в объеме). parti_volume_photon - шейдер, применимо к фотонам.

полностью идентичный parti_volume, только

Textures

Как следует из названия - это текстуры и все, что требуется для работы с ними. Например, сюда можно отнести растровые и процедурные текстуры, утилиты для трансформации текстурных координат и проекции текстур и т.п. mib_amb_occlusion - шейдер для просчета occlusion’a. Шейдер представляет большой интерес, так как является достаточно “дешевым” способом имитации ненаправленного освещения (GI и т.п.) в тех случаях, когда нужна не физическая корректность, а просто правдоподобие. Шейдер не зависит от освещения и может работать вообще без источников света. Чтобы правильно использовать occlusion, очень желательно понимать принцип его работы. В каждой точке шейдер проверяет дальность других объектов. Если объект расположен близко, то шейдер окрашивается в цвет, указанный в параметре Dark (обычно черный), если вблизи нет никаких объектов, то в результате точка примет цвет параметра Bright. Шейдер испускает определенное количество лучей по полусфере, каждый из которых возвращает либо Bright, полученный цвет усредняется. В результате получаем затенения во всех углах и между близко расположенными объектами, создавая эффект рассеянного освещения. ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

В зависимости от параметра output_mode шейдер будет выдавать разный результат. В значении 0 это будет обычный классический черно-белый occlusion (как показано на картинке выше). Значение 1 будет давать такой же результат за исключением того, что если луч не попал ни в один объект, то будет вызван Environment Shader или цвет фона и умножен на Bright. Причем если цвет фона или Environment Shader’a белый, то результат будет полностью идентичен значению output_mode 0. Если цвет фона черный, то все будет черное. В зависимости от текстуры на Environment Shader’e этим способом можно даже имитировать освещение, в некоторых случаях похожее на Final Gather. Если установить output_mode в значение 2, то результатом шейдера будут так называемы Bent нормали (в мировых координатах). Bent Normal - это нормаль, полученная усреднение направления всех лучей, не попавших ни в один объект, то есть те лучи, которые попал в Environment. Значение output_mode 3 так же выдает Bent Normal, но в координатах камеры.

output_mode 0

(смотрите цветные картинки на диске) :)

output_mode 1

.............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

output_mode 2

output_mode 3

Применение: Существует множество различных способов использования occlusion шейдера: 1. Первый способ - положить mib_amb_occlusion на ambient параметр любого из шейдеров. Именно от этого метода использования шейдер и получил название Ambient Occlusion, то есть затенение амбиента (рассеянный свет). В этом случае амбиент цвет будет только на наиболее очевидных и нужных местах. 2. Второй способ заключается в использовании mib_amb_occlusion в качестве основного шейдера. То есть его можно положить на слот Material Shader любой шейдинг группы. А на параметр Bright подсоединить уже сам шейдер поверхности, например mib_illum_ phong. В этом случае результат будет отличаться от первого метода, темные места, полученные от оклюжена, останутся темными даже на свету. Иногда данный способ называют Dirt или Diffuse Occlusion. 3. Mib_amb_occlusion можно использовать в слоеном шейдере, например, в качестве умножения на результат другого шейдера или текстуры. 4. Достаточно необычный способ состоит в использовании mib_amb_occlusion в качестве Light Shader’a. Для этого создаем источник света, и ему на слот Light Shader кидаем mib_amb_occtusion. В итоге на стороне объекта, повернутого к источнику света, вместо света просчитывается оклюжен, другая же сторона (за терминатором) остается черной. Большим плюсом этого метода является то, что не нужно переназначать шейдера на всех объектах и переделывать шейдинг, особенно когда объектов и шейдеров в сцене очень много. Однако этот метод дает меньшую гибкость в настройке. 5. Можно отрендерить Occlusion в чистом виде, положив его на Material Shader слот. Полученный результат используется на стадии композитинга, а там уже его можно использовать как угодно, например, просто умножить на результат основного рендера. Таким же образом можно просчитать Bent Normal, полученные при использовании out-putjnode со значениями 2 или 3 и использовать их, например, для смены освещения или добавления отражения на стадии композитинга. mib_bump_basis - утилита, вычисляющая два bump basis вектора на основе метода проецирования. Используется, в основном, для просчета бампа в связке с другими йодами. ............................................................................................................................................................................. Ледин Павел


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

Применение: Поначалу применение mib_passthrough_bump_map может показаться достаточно экзотическим и сложным. Ведь обычно в других рендерах bump создается просто включением одного параметра, в mental ray же вам потребуется создать и соединить определенным образом несколько шейдеров. Рассмотрим типичный случай, например, нужно добавить bump к dgs_material. Для этого: 1. Создаем собственно сам dgs_material. 2. Создаем по одной ноде: mib_color_mix, mib_passthrough_bump_map, mib__bump_basis и mib_texture_vector. 3. Ha mib_passthrough_bump_map на поле Тех создаем растровую текстуру. 4. Конектим U и V вектора mib__bump_basis ноды на U и V mib_passthrough_bump_map 5. Для создания текстурных координат конектим mib_texture_vector на параметр Coord ноды mib._ passthrougn_burnp._map. 6. Теперь сам шейдинг нетворк бампа собран, и его теперь нужно правильно подсоединить к dgs__ material, для этого мы воспользуемся mib_color_mix, как бы смешав бамп с нашим цветом шейдера. Нужно приконектить выход с mib_passthrough_bump_map на параметр Color_base ноды mib_color_ mix. 7. dgs_material подсоединяем на Color_0 mib_color_mix. 8. В ноде mib_color_mix устанавливаем Num в значение 1. 9. Нетворк готов. Теперь просто кладем mib_color_mix, например, на Material Shader слот шейдинг группы. Существует и немного другой способ применения bump: 1. Повторяем все, как описано в предыдущем варианте до пункта 5 (включительно). 2. Соединяем выход с mib_passthrough_bump_map на параметр Color_base ноды mib_ color_mix. 3. Берем наш dgs_material и выбираем любой параметр типа color, например Diffuse. Запоминаем его значение. И подсоединяем на его место выход с mib_color_mix. 4. Открываем mib_color_mix и выставляем Colorг_0 в то значение, которое было у нас на dgs_material на параметре Diffuse. Теперь если мы захотим исправить Diffuse, то нам придется настраивать Color_0 в ноде mib_color_mix. 5. Готово. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. mib_bump_map - шейдер, аналогичный mib_passthrough_bump_map, за исключением того, что возвращает не color, a vector. В качестве результата возвращается измененная нормаль. Шейдер используется так же как и mib_passthrough_bump_map.

mib_texture_checkerboard - обычный checker, но в отличие от майского аналога - это 3D текстура. Применение: Для создания текстурных координат mib_texture_checkerboard на Coord нужно присоединить mib_texture_vector. Шейдер может быть использован в различных ситуациях в шейдинг нетворке, так же его можно подсоединить непосредственно на слот Material Shader шейдинг группы. mib_texture_lookup - обычная текстура. Так же нуждается в правильных текстурных координатах, заданных с помощью mib_texture_vector. mib texture_filter_Iookup - аналог mib_texture_lookup, но с эллиптической Фильтрацией. Подходит в тех случаях, когда нужна высококачественная фильтрация текстуры. mib texture^polkadot - простая процедурная текстура, рисующая кружочки. mib_texture_polkasphere - 3d текстура, генерирующая сферы в текстурном пространстве. mib_texture_remap - нода, работающая с текстурными координатами. С помощью нее можно задать количество повторений любой текстуры(tile), подвигать и т.п. Применение: Нода вставляется на промежутке между текстурой и mib_texture_vec-tor. Получается, что mib_texture_vector генерит текстурные координаты, потом mib_texture_remap делает нужное повторение текстуры и смещение, и координаты в таком виде приходят уже на текстуру. Схема подсоединения выглядит приблизительно так: На текстуру, на параметр Coord, подсоединяется mib_texture_remap, к которой на Input подается mib_texture__vector. mib_texture_rotate - служит для поворота текстурных координат. Работает, так же как и mib_texture_ remap. mm_texture_turbulence - процедурная текстура турбулентности, можно даже сказать, что это некий вид нойза (noise). Шейдер возвращает тип float. Для конвертации float в color можно воспользоваться шейдером mib_color_interpolate. ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. mib_texture_vector - шейдер, генерящий текстурные координаты всевозможными проекциями и использованием уже существующих UVset’ов. В какой-то степени ноды mib_ texture_rotate, mib_texture_remap и mib_texture_vector вместе являются неким аналогом майских нод place2dTexture и ptace3dTexture. Применение: Подсоединяется обычно на параметр Coord текстуры или нод mib_tex-ture_remap и mib_texture_rotate. mib_texture_wave - трехмерная текстура волны. Амплитуда задается по трем осям XYZ. Координаты задаются с помощью mib_texture_vector.

Environments

Различные варианты окружения (environment), используемые обычно для отражения, просчета FG и просто смены цвета фона.

Lights

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

Photon Emitters

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

Light Maps

Шейдера, позволяющие при рендере записывать в текстуру какую то информацию. Обычно данный тип шейдеров используется, например, при запекании (baking). Так же данный тип шейдеров используется для генерации карты для Sub Surface Scattering’а на основе shadow map.

Lenses

Шейдера линз позволяют оперировать исходными лучами, идущими от камеры, менять направление луча и изменять результат. Например, с помощью линз шейдеров можно сделать: DOF (Depth Of Fields - глубина резкости), сферическую камеру (смотрящую во все стороны) и т.д. .............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

Output Shaders

Эти шейдера вызываются после того, как сам рендер завершен и оперируют получившимися картинками (буферами). Например, для создания эффекта Glow, DOF, mo-tion blur и тумана в пост процессе или просто для записи результата в какой то особенный формат.

Geometry

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

Contour

Контурные шейдера нужны для просчета контуров, например, для эффектов типа Cartoon.

Sample Compositing

К этой категории относятся все элементы шейдера, такие как отражение преломления, которые могут понадобиться при сборке своего собственного шейдера Представляют собой как бы детали конструктора. Например, сюда можно было бы отнести шейдера, которые просчитывают только блик или только тень и т.д. mib_transparency - просто добавляет прозрачность к шейдеру, подсоединенному к Input. Mib_transparency может понадобиться в тех случаях, когда имеется шейдер, у которого нет параметра прозрачности, например, mib_illum_larnbert или любой другой.

Применение: Можно положить mib_transparency нa MaterialShader слот шейдинг группы и ему на Input положить любой шейдер, к которому нужно добавить прозрачность, например, тот же mib_illum_lambert, а на параметр Transp подсоединяем карту прозрачности или просто выставляем нужный цвет.

mib_opacity - шейдер полностью идентичный mib_transparency, за исключением того, что параметр Opacity инвертирован.

............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. mib_reflect - шейдер для просчета обычного отражения или добавления его к другому шейдеру.

Применение: Если нам нужно добавить отражение, например, к mib_illum_lam- bert, то нужно всего лишь взять mib_reflect и положить его на слот Material Shader шейдинг группы и к нему на Input подсоединить mib_illum_lambert. Или же можно просто установить Input в черный и смешать в нужной пропорции с mib_illum_lambert с помощью mib_color_mix. mib_refract - все то же самое, что и в случае с mib_reflect, только относительно преломления.

mib_reflect и mfb_refract .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. mib_dielectric - шейдер, похожий по своему смыслу на mib_refract. Используется для добавления к шейдеру эффекта диэлектрика, то есть преломление и поглощение света (absorption) в зависимости от толщины объекта.

mib_twosided - шейдер утилита для создания двухстороннего материала. Шейдер имеет два слота типа color: первый для шейдера для передней стороны полигона и второй для задней стороны. Этот эффект можно повторить и с помощью нескольких стандартных майских нод (Condition и Samplerlnfo). Но одну ноду использовать удобнее, да и просчитываться она будет, скорее всего, немного быстрее.

Применение: Нужно положить mib_twosided на Material Shader слот шейдинг группы и назначить на Front и Black разные шейдера или цвета.

Data Conversion

Шейдера из итого раздела производят разные манипуляции с данными, конвертируют их, смешивают и т.д. mib_color_alpha - данный шейдер утилита берет альфа канал из Input и заменяет им компоненты RGB. В результате из входного цвета получается серый цвет на основе альфы. Применение: Шейдер mib_color_alpha применяется в шейдинг нетворке в различных ситуациях. Для использования нужно подсоединить на Input цвет, который должен стать серым, а результат уже использовать, как потребуется. mib_color_average - шейдер, так же как и предыдущий, делает цвет серым, но уже на основе усредненного значения RGB. Если немного подробнее, то формула будет приблизительно такая (R + G + В)/3. ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. mib_color_intensity - конвертирует цветовое значение в серый цвет. Иногда этот режим называют Luminosity, где каждый компонент умножается на свой множитель, так как компоненты RGB по своей интенсивности не равносильны. Формула будет выглядеть так: (R* 0.299 + G* 0.587 + В* 0,114)/3. mib_Color_interpolate - обычный градиент, в майской терминологии это Ramp. Так же может служить утилитой для конвертации float в color, именно поэтому шейдер находится во вкладке Data Conversion, а не Texture. Применение: Можно использовать в шейдинг нетворке в различных ситуациях, а так же положить напрямую на слот Material Shader. Шейдер сам по себе не использует UV координаты, поэтому ему на Input нужно падать float значение, отвечающее за положение на градиенте, например, для этих целей пойдет выход Facing Ratio с ноды Sample Info, или координату U, или V с ноды проекции текстур. mib_color_mix - шейдер для смешивания нескольких шейдеров или текстур возвращающих color. Mib_color_mix можно назвать аналогом Layered Shader’а и одновременно Layered Тех-ture, так как в идеологии mental ray между ними нет особой разницы. mib_Color_spread - шейдер, преобразующий 8 входных цветов в 8 других в различных режимах. Например, Average, Luminosity, R и т.п. Применение: Шейдер может быть использован в шейдинг нетворке, но не может быть назначен на слот Material Shader, так как mib_color_spread возвращает несколько цветов, и это приведет к ошибке при рендере.

State Shatters

Шейдера, позволяющие вмешиваться в просчет на стадии перед испусканием каждого eye ray и после его возвращения, а также перед началом рендера баккета и после его завершения. Так же эти шейдера позволяют вносить изменения на других стадиях рендера. По умолчанию вкладка пуста.

Miscellaneous

К этой категории относится все то, что не вошло в остальные. Обычно сюда попадают все шейдера, у которых не определен тип.

.............................................................................................................................................................................


Работаем с Mentalray .............................................................................................................................................................................

MENTAL RAY BAKE Требования к «правдивости» или фотореалистичности созданных с помощью компьютера изображении возрастают, что означает использование дорогих в вычислительном плане алгоритмов глобального освещения. Несмотря на существенный пост производительности процессоров, расчет фотореалистичного кадра для кино может занимать несколько суток. Поэтому естественно попытаться ускорить этот процесс за счет разнообразных технологических трюков, одним из которых является baking. Идея заключается в том, что для неподвижного объекта в неизменных условиях освещения совсем необязательно производить расчет освещения, распределения теней и так далее в каждом кадре - ведь ничего не меняется! Гораздо эффективнее сохранить эту информацию в текстуру и в дальнейшем использовать ее для визуализации (что дешево) вместо повторного расчета освещенности (что дорого). После запекания освещения объекта в текстуру (или в цвет вершин) в дальнейшем можно исключить запеченный объект из расчета освещения, что существенно ускоряет процесс визуализации без потери качества. То есть, в итоге получается текстура, в которой уже записано все освещение и шейдинг. Часто запекание используется для записи сложного освещения, полученного, например, с помощью Global Illumination, Final Gather или Area Lights для того чтобы не делать эти просчеты на каждом кадре и тем самым увеличить скорость рендера. Также запекание используется при визуализации разного рода пролета (camera fly) по интерьерам, где объекты неподвижны, но алгоритм освещения чрезвычайно дорогой - с использованием большого количества источников света, глобального освещения мягких теней. Запись информации об освещении и тенях в файловую текстуру (baking) позволит существенно сократить время просчета. Для примера представим себе интерьер комнаты, освещенный с помощью Global Illumination, Final Gather’a и множества источников света с размытыми тенями. Один кадр считается, допустим, 2 часа. Нам нужно визуализировать анимацию с камерой, пролетающей по комнате, скажем, кадров на 100200. И что же теперь, ставить на рендер и ждать две недели? В данной ситуации как раз очень уместно воспользоваться запеканием и записать в текстуру освещение на основных объектах, например, на полу, стенах и так далее, результате, потеряв немного времени на настройку сцены и сам процесс запекания, мы в десятки раз сокращаем время визуализации. А если постараться и запечь все объекты, то получим рендер кадра за считанные секунды при совершенно одинаковом качестве картинки. Примечание: Если вы планируете визуализацию длинной анимации и понимаете что простой рендер будет очень долгим, то лучше заранее подготовить обьекты для запекания соответствующим образом - это в последствии сэкономит много времени и облегчит вам работу. В общем, имеет смысл запекать все, что не изменяется от кадра к кадру и при этом долго просчитывается. Единственное, что обычно не подлежит запеканию, - это реальные отражения, преломления и блики. Так как эти компоненты зависят от положения камеры и, записав их, скажем, на первом кадре, мы получим корректный результат только в этом кадре, а на всех остальных блики и отражения/преломления останутся на месте и не будут реагировать на движение камеры. Сам процесс запекания поддерживает все элементы шейдера, включая отражение, преломление и блики, но результат будет корректный только в том случае, если камера не движется. Отдельным пунктом стоит отметить запекание оклюжена (occlusion), так как он является достаточно частым предметом для запекания, потому что он не зависит от освещения, и объект с запеченным оклюженом может быть даже потом анимирован. ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Baking так же известен как Light Mapping и используется в игровой индустрии для запекания в текстуру и в цвет вершин статичного освещения. Еще запекание часто используется для создания Reflection Мар’ов, что позволяет просчитывать отражение в реальном времени. Познакомимся с процедурой запекания в mental ray. Прежде всего, не забываем переключить текущий рендер в меню Render Settings на mental ray. Меню запекания вызывается из двух мест, прежде всего это вкладка Rendering Light-ing/ Shading=>Batch Bake(mental ray), а так же меню Modeling Edit Polygons=>CoLors=>Prelie ht (mental ray). В итоге, и оттуда, и оттуда вызывается одно и тоже меню с единственной лишь разницей в предустановленных параметрах. Первый вариант будет иметь поле Bake То в значении “Texture”, а во втором случае - в значении “Vertices”, то есть для запекания в текстуру и в цвет вершин соответственно.

Выбираем объекты, которые планируется запекать, и вызываем любое из понравившихся меню. После вызова меню можно заметить, что создались два объекта im’tialTextureBakeSet и initialVertexBakeSet. Так что же такое Bake Set? Это набор параметров для запекания, такие как разрешение текстуры, расширение выходного файла, битность и тд. Этот set назначается группе объектов с одинаковыми параметрами для запекания. Можно создать сколько угодно разных Bake Set’ов и назначить их соответствующим объектам. По умолчанию всем выделенным объектам назначается initialTextureBakeSet или initialVertexBakeSet. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Для создания нового Bake Set’a и присвоения его выделенным объектам идем Lighting/ Shading=>Assign New Bake Set, а для назначения уже существующего бейк сета - на объект; жмем Lighting/Shading=> Assign Existing Bake Set, где выбираем нужный сет. Примечание: В bake set помещаются имена шейпов, а не трансформов, поэтому стоит быть аккуратными, используя инстансы. Итак, вернемся к параметрам запекания. Objects to Bake - выберите из этого списка «запекать все объекты или только выделенные». Skip objects in initialBakeSets - если включено, то все объекты в initial bake-set’e будут игнорироваться при бейкинге, то есть будут запекаться только те объекты, которым назначен не default bake set. Bake To - бейкать в текстуру или в вертекс колор. Color Mode - режим Light and Color позволяет бейкать освещение и цвет объекта (весь шейдинг), Only Light - запекает только освещение, Only Global Illumination - запекает только global illumination, и последний режим Occlusion - позволяет запекать оклюжен. Bake Shadows - если включено, то тени запекаются тоже. Orthogonal Reflection - если эта опция отключена, то считается реальное отражение, основанное на положении камеры, то есть так, как это происходит во время рендера. При этом используется камера, которая указана в поле Camera. Когда эта опция включена, то все отраженные лучи становятся ортогональными (перпендикулярными) по отношению к поверхности, то есть не зависят от положения камеры. Но в результате текстура или цвет вертексов выразительнее смотрятся со всех сторон. Может использоваться для построения карты отражения (enviroment map) и тп. Например, для того, чтобы сделать карту окружения (отражения), достаточно запечь отражение на сфере, используя orthogonal reflection. Use Face Normals - можно выбрать «использовать нормали граней или интерполированные нормали вершин», как это происходит обычно при рендере. Normal Direction - указывает, на каком направлении нормалей объекта будет основано запекание - либо на лицевой, либо на задней, либо на той, что повернута к камере. Надо отметить одну странность: в Maya 7.0 данная опция по умолчанию находится в положении Surface Back, что явно неправильно. Camera - все камера зависимые эффекты, такие как отражения, преломления, блики и тд., будут основаны на положении камеры, указанной в этом поле. Keep Original Shading Network - если эта опция отключена, то Maya, после того как процесс запекания завершен, создает новые шейдера (Surface Shader) с запеченными текстурами и назначает их на соответствующие объекты. Если опция включена, то Maya оставляет текущие шейдера без изменения. Как показывает практика, обычно эту галку лучше отключить, чтобы сразу увидеть во вьюпорте результат запекания. А если мы хотим назначить текстуры вручную, то можно всегда нажать Undo, отменив последнее действие -это вернет все шейдера в оригинальное состояние. Разумеется, при этом текстуры останутся в той директории, куда было произведено запекание (по умолчанию это директория light-map текущего проекта). Use Bake Set Override - если включено, то все bake set’ы, назначенные на объекты, игнорируются, и используются ниже указанные настройки для всех объектов. ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

Bake to Texture

При запекании в текстуру, в результате создается текстурный файл заданного формата, который в последствии можно при необходимости отредактировать, например Photoshop’e и назначить на объект как обычную текстуру. Главное в запекании в текстуру - это правильный маппинг (UV координаты) так как от этого сильно зависит результат. Соответственно, к маппингу предъявляются определенные требования. Для корректного результата UV не должны пересекаться, то есть разные грани объекта не должны быть замаплены одним и тем же фрагментом текстуры. Иначе, если у нас две разных грани замаплены одним фрагментом текстурного пространства, мы получим одинаковое освещение на обеих гранях, что чаще всего не приемлемо. Надо отметь, что если у вас две разные грани будут иметь одинаковое освещение и вы заманили их одним фрагментом текстуры, например, симметричная модель, то следует иметь ввиду, что скорость запекания уменьшится, так как в этом случае все равно будут запекаться обе грани, и результат одной перезапишет результат другой. Также очень желательно, чтобы все UV координаты укладывались в диапазон от 0 до 1. То есть, исходя из выше сказанного, нам почти идеально подходит Automatic Map-ping. Но так как результат после автоматического маппинга, мягко говоря, не идеальный так как он не рационально использует текстурное пространство, его чаще всего приходиться подправлять руками. Хотя, в целом, результат такой, как нам нужен. Но что делать, если у нас уже есть маппинг, который не соответствует требованиям запекания и который нельзя менять? Разумеется, решение простое: нужно лишь создать новый мапинг (UVset) и использовать его при запекании. Создание нового UVset’а включается в опциях любого из мапингов.

Далее рассмотрим параметры Texture Bake Set’a: Filename Prefix - префикс будет добавлен перед именем каждой текстуры X Resolution - разрешение текстуры по оси X Y Resolution - разрешение текстуры по оси Y File Format - формат текстуры Bits Per Channel - количество бит на канал 8, 16 или 32(float). В большинстве случаев подойдет 8 бит, и лишь иногда 16 бит. 32 бита нужно только в том случае, если значения в текстуре должны превышать 1 или быть меньше 0, например, это может понадобиться для изготовления собственной HDRI карты. Но не стоит забывать, что не все форматы поддерживают 16 и 32 бита, из доступных форматов это поддерживает только TIF. Bake To One Map - mental ray будет запекать несколько объектов в одну текстуру. В основном это нужно, когда у вас несколько объектов замаплены в одном UV .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. пространстве координаты не пересекаются между собой. Или же, например, когда у вас на одном объекте назначено несколько разных шейдеров, если опция включена, то все они будут запечены в одну текстуру, в противном случае для каждого элемента и объекта будет создана своя собственная текстура. Bake Alpha - запекать альфу или нет Alpha Mode - если включена опция Bake Alpha, то это режим указывает как именно запекать альфу. Fnal Gather Quality - параметр, отвечающий за качество FG в предварительной фазе, то есть непосредственно перед запеканием (precompute phase). Если значение больше нуля, то mental ray использует предварительный просчет FG, то есть как бы строит равномерную сетку из FG точек. Если этот параметр равен 1, то качество будет приблизительно таким, как указано в Render Settings. Примечание: При обычной визуализации FG основывается на положении камеры, то есть там, где нужно, качество автоматически повышает, при запекании mental ray не может использовать этот алгоритм, потому что запекание происходит со всех сторон, и положение камеры не учитывается. Поэтому mental rау’ю, чтобы при запекании добиться качества, которое мы видим на рендере, как правило, нужно значительно завышать настройки FG, о чем прямым текстом говорится в документации. В частности, обычно нужно увеличивать количество FG лучей и уменьшать радиусы. Final Gather Reflect - качество FG в отражениях (зависит от Final Gather Qual-tity). Например, если стоит значение 0.25, то в отражении будет просчитана только каждая четвертая FG точка. Occlusion Rays - если запекается occlusion, то тут можно указать, сколько лучей (сэмплов) будет использовано аналогично шейдеру mib_amb_occlusion. occlusion Falloff - максимальная длина луча. Все объекты, находящиеся дальше этой дистанции, не учитываются. Обычно для увеличения скорости просчета этот параметр следует поставить как можно меньше, чтобы ненужная геометрия не участвовала в просчете, особенно если у вас большая и тяжелая сцена. UV Range - диапазон текстурного пространства, которое будет использовано при запекании. Обычно следует поставить Normal (0 to 1) или же установить нужное значение вручную. Fill Texture Seams - это достаточно важный параметр, отвечающий за отступ от края UV, то есть как бы запас. Измеряется в пикселах (текселях). Если не делать этот отступ, то на границах UV мы увидим черный цвет, особенно это будет заметно на диагональных линиях. Его следует установить в значение от 1 до 3, обычно 2 вполне достаточно. Странно, что по умолчанию он равен нулю.

Действие параметра Fill Texture Seams, слева значение - 0, справа - 3 ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Override mesh UV set assignment - если включено, то будет использован не дефолтный UV set, а тот, что указан в поле UV Set Name. UV Set Name - если у нас на объекте несколько UV set’oв, и мы планируем запекать не в дефолтный, а в специально подготовленный UV set, который мы назвали, например, lightmap, мы просто указываем тут это имя. Однако, здесь может возникнуть небольшое недоразумение. Дело в том, что шейдер Surface Shader, который обычно назначается на все объекты после запекания, очень странно работает во вьюпорте, в частности он не воспринимает никакие UVset’ы, кроме дефолтного map1. В итоге мы получаем правильную текстуру, рассчитанную на мапинг lightmap и положенную на дефолтный мапинг map1. Пугаться не стоит, так как при рендере все работает корректно. А для того, чтобы в этой ситуации проверить правильность запекания во вьюпорте, достаточно всего лишь заменить Surface Shader, например, на Lambert.

Render - Gl + FG + Area Light

View port screenshot Установив нужные настройки, просто жмем кнопку ‘Convert and Close’ и ждем. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Примечание: Для того чтобы видеть прогресс в Output Window, нужно в Render Settings, в закладке Traslation, установить ‘Export Verbosity’ в значение ‘Progress Messages’. После того как процесс запекания будет завершен, вы увидите готовые текстуры во вьюпорте или же сможете посмотреть их в директории lightmap (в зависимости от значения опции ‘Keep Original Shading Network’). Примечание: Если текстура во вьюпорте не соответствует тому, что должно получиться, удостоверьтесь, на тот ли UVset она ссылается. При этом, для просмотра результата лучше использовать Lambert шейдер, а не Surface Shader(Maya создает именно его). Следует отметить, что по умолчанию во время процесса запекания mental ray запускает по одному потоку на каждом процессоре. В каждом потоке запекается один объект, то есть получается, что одновременно на каждом процессоре запекается один объект. Это же относится и к псевдопроцессорам, таким как Intel Pentium 4 с технологией Hyper Threading. Если количество объектов больше чем процессоров, то запекание осуществляется по очереди. Исходя из выше сказанного, делаем вывод, что для максимальной загрузки компьютера, на котором более одного процессора нужно запекать сразу несколько объектов. Иначе, запекая, например один объект на двух процессорной машине мы получим 50% загрузку системы.

Bake to Vertices

При запекании в вершины (Vertex Color) не создается никакого файла или текстуры, а результат сразу применяется к цвету вершин в Maya и окрашивает их. В последствии данное освещение может использоваться в играх, а так же при обычном рендере, если освещение не должно иметь высокую детализацию. Примечание: Для использования вершинного освещения во время обычного рендера нужно воспользоваться шейдером mentalrayVertexColors, который позволяет визуализировать цвет вершин. Запекание в вершины работает гораздо быстрее запекания в текстуру, так как запекание в цвет вершин происходит только в каждой вершине. Например, FG лучи будут испускаться не из всей поверхности, а только из вершин. То есть шейдер вызывается и просчитывается только в каждой вершине. При этом промежуточный результат будет интерполироваться. Поэтому надо быть осторожными с текстурами на объектах, которые имеют какие-то небольшие контрастные участки, например, если в текстуре черная точка попадает прямо на вертекс, то вертекс окрасится в черный цвет, и в результате мы получим достаточно большое черное пятно. И, соответственно, чем детальнее разбита у нас геометрия, тем детальнее мы получим результат.

Запекание в цвет вершин со средней тесселяцией геометрии ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

Запекание в цвет вершин с более высокой тесселяцией геометрии Запекая в цвет вершин, следует обратить особое внимание на ребра, а точнее на то, сглажены они или нет. Для гладкого результата все неострые ребра должны быть сглажены, то есть даже если ребра лежат в одной плоскости и визуально не видно, что они не сглажены, например, на ровной поверхности. Нужно оставить ребра острыми только там, где это действительно нужно. Для того чтобы выявить такие ситуации, настоятельно рекомендую включить режим отображения ребер Soft/Hard - все сглаженные ребра будут отображаться пунктиром. Эту опцию можно включить в Window=>Settings/Preferences= >Preferences=>Disptay=>Polygons. Также для работы с полигонами рекомендую всегда включать опцию Border Edges и установить Border Width в значение 2, это так же поможем выявить некоторые проблемы с геометрией. Чтобы увидеть действие этих параметров, следует перезапустить Maya или открыть сцену заново, в противном же случае эффект будет виден только на вновь созданных объектах. Далее рассмотрим параметры Vertex Bake Set’a: Bake Color - запекать цвет, то есть rgb. Если эта опция выключена, то цвет не будет записываться, а если на поверхности уже есть цвет в вертексах, то он останется нетронутым. Bake Alpha - запекать альфу. Работает аналогично Bake Color. Scale Rgba - глобальный множитель вертекс колора. Clamp Min - все, что ниже значения Min Color и Min Alpha, будет обрезано. Clamp Max - все, что выше значения Max Color и Max Alpha, будет обрезано Теоретически, по умолчанию Max Color должен был быть белым. Color Blending - режим, отвечающий за наложение вертекс колора. Например, когда у вас на объекте уже есть цвет, записанный в вертексы, в этом случае он может быть: переписан (Overwride), добавлен (Add), вычтен (Subtract), поделен (Divide) или усреднен (Average). Alpha Blending - все то же самое, что и в случае с Color Blending, только применительно к альфе. Filter Size - размер фильтрации (размытие) цвета вершин. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Для удобного включения и выключения отображения цвета вершин во вьюпорте можно воспользоваться Level Tools.

Так же Level Tools будет полезен и в ряде других случаев. Примечание: Level Tools - это набор полезных скриптов, предназначенных специально для игровой индустрии. Level Tools можно свободно скачать на сайте компании Alias.

НАПИСАНИЕ ШЕЙДЕРОВ (Рендеринг в продакшне)

Рендеринг (в контексте трехмерной графики)- процесс получения двумерной картинки трехмерной сцены, рендер - собственно команда или опять же процесс. Наиболее адекватный перевод слова рендеринг - визуализация. Одни и те же данные о трехмерной сцене можно визуализировать разными способами и/или разными алгоритмами. Собственно, специальные программы, осуществляющие визуализацию, называются рендерерами. Таких рендереров много - Mental Ray, Vray, Maxwell, Prman и так далее... Как правило, основной задачей рендереров является получение фотореалистичной картинки, то есть максимально приближенной к фотографии, однако, рендереры, тем не менее, имеют возможность отклониться от физических законов и создавать так называемые не фотореалистичные или стилизованные изображения в соответствие с поставленными художественными задачами. Обилие рендереров (или программ для рендера) объясняется, с одной стороны, развивающимися вычислительными алгоритмами, с другой - оптимизацией этих алгоритмов под определенный круг задач (архитектурная визуализация, промышленный дизайн, спецэффекты в кино и телевидении). Рендереры в наиболее общем понятии - это независимые программы (стэндэлон), которые используют свой собственный формат файлов исходных данных, включающие в себя описание геометрии, камеры, источников света, свойств визуализируемых поверхностей (шэйдеров) и так далее...mi-файлы для Mental Ray, rib -файлы для PRman и т.д. и т.п. Пакеты трехмерной графики часто могут быть использованы в качестве графического интерфейса для подготовки необходимых данных для рендереров. В таком случае такие пакеты должны иметь возможность экспортировать созданные с их помощью трехмерные сцены в файлы соответствующих форматов и далее использовать выбранный (стэндэлон) рендерер для непосредственной визуализации. Рендереры так же могут быть в виде подключаемых модулей или plugin’ов для 3d-программам. В таком случае генерации промежуточного файла не происходит, и для нечного пользователя в меню рендереров появляется дополнительная строка: render with (отметим, что hi-end пакеты трехмерной графики, как правило, имеют свои собственные -родные» рендереры (native render)). Поскольку пакеты трехмерной графики и рендереры создаются зачастую разными ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. коллективами разработчиков, то вполне естественно, что возможности рендеринга при помощи plugin’a уже, чем возможности оригинального стэндэлон рендерера с тем же названием. В крупных компаниях с большим числом сотрудников рендеринг выделяется в отдельную ветвь производства со своим штатом специалистов, что позволяет более полно использовать возможности культивируемого в этой компании рендерера и более эффективно решать производственные задачи. Мне хотелось бы немного написать о различиях между понятием “продакшен рендер” и просто плагин для рендера. Обычно начинающие пользователи, используя какой-нибудь рендер (часто просто плагин для рендера), который быстро считает Global lllumi-nation, уверены, что это лучший рендер и ничего больше не надо. Мол, он рендерит мне красивую картинку - и все хорошо. Может, для домашнего пользователя это и достаточно, но для реального продакшена умение рендерить красивый GI стоит чуть ли не на последнем месте, хотя это не значит, что рендер не должен этого уметь. Главным аспектом при выборе рендера для серьезного производства обычно является гибкость, расширяемость, широта возможностей и программируемость рендера. Разумеется, к домашним пользователям и маленьким фирмам, где всего 3 человека, это практически не имеет никакого отношения, они часто выбирают рендер, руководствуясь принципом, что рендер должен быть простым в настройке и делать все сам красиво без сложных настроек и тем более без вмешательства программистов. Наверное, не надо объяснять, что это правило никак не подходит для реального производства, так как любое ограничение рендера выльется в серьезные ограничения и проблемы в работе, потому как задачи в серьезном производстве, как правило, гораздо масштабнее. Разумеется, не стоит забывать, что рендер так же выбирается и исходя из характера решаемых задач. А так как в больших компаниях на серьезном производстве решается очень много разнообразных задач и проблем, то рендер должен соответствовать этим требованиям и, грубо говоря, должен “уметь все”. В маленьких же компаниях чаще всего круг решаемых задач достаточно узок и специфичен, поэтому можно выбирать рендер, который подходит лучше для текущих задач. Итак, что же отличает серьезный рендер от простого плагина для рендера: • Рендер - это, как правило, отдельная программа (stand alone), имеющая возможность работать автономно и запускаться и управляться из командной строки. То есть рендер не должен зависеть ни от какого 3D софта. • Как правило, рендер работает на разных платформах, например, обычно это Windows, Linux и Mac. � • Рендер должен иметь возможность написания тендеров и расширения стандартных возможностей.

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


Работаем с Mentalray .............................................................................................................................................................................

Для чего нужно писать шейдера? Причин написания шейдера может быть много. 1. Такого шейдера просто нет и его нужно написать. Это наиболее частая и классическая причина, по которой пишут шейдера. Например, представим ситуацию, что нам нужен шейдер стекла, все, которые имеются, нас не устраивают по своим возможностям - в этом случае можно просто написать такой шейдер, который нам нужен. Или часто бывает, что mental ray поддерживает какую-то возможность, но она никак не реализована в 3d пакете, тогда так же часто может помочь написание шейдера. 2. Упрощение работы. Например, в Maya какую то задачу можно выполнить, собрав сложный shading network из 15 нод. Ту же задачу можно выполнить, написав простой шейдер, который сделает все то же самое, но лишь одной нодой и более элегантно, гибко и просто, ну то есть именно как вам надо. Одна нода всегда будет понятнее и проще, например, все нужные настройки, который могли быть разбросаны по всему нетворку, будут в одном месте и называться, как полагается. (Тут отчасти может помочь написание phenomenon) 3. Ускорение просчета. Например, у вас имеется сложный Shading Network, скорость рендера которого вас не устраивает. Вы можете переписать его, серьезно оптимизировав код. У меня, например, был случай, когда шейдинг нетворк, который я собрал, считался очень долго. Это был какой то слоеный шейдер, где я смешивал несколько других шейдеров. Так как каждый из этих слоев просчитывал освещение независимо друг от друга, то получалось, что освещение и тени соответственно просчитывались столько раз, сколько было слоев, что, в принципе, не нужно. Я просто взял и объединил это все в один шейдер, который всего один раз просчитывал освещение и использовал во всех слоях. В итоге я получил увеличение скорости рендера на 30%, а картинка не изменилась. И все это заняло у меня минут 30. Выигрыш на скорости визуализации всей анимации был существенен.

Что для этого нужно?

Шейдера для ментал рея пишутся на С, при желании можно писать на C++, разницы нет. А так как азы программирования сейчас изучаются практически во всех технических (и не только технических) вузах, то минимальные знания чаще всего уже имеются, в крайнем случае, можно купить любую книгу по C++, после прочтения которой вы будете иметь представление о программировании. При этом глубоких знаний С и не требуется, более того не обязательно знать C++ (классы и тп), для написания шейдеров достаточно таких элементарных знаний, как что такое: функция, структура, переменная и указатель, для начала этого вполне хватит. Если вы имеете какой-либо опыт програ��мирования, это будет совсем не лишним. Итак для написания шейдеров нам потребуется среда разработки, например, Mi-crosoft Visual Studio.NET2003. Именно эту среду я бы рекомендовал всем начинающим, так Действительно мощное и удобное средство.

Подготовка и настройка проекта

Создаем новый проект File->New->Project. Выбираем Win32 Console Project, задаем имя проекта, например,”my_mr_shaders”, и директорию, жмем ОК.

............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

В Application Settings ставим опцию DLL, чуть ниже ставим Empty Project.

Жмем Finish. Все, наш проект готов. Теперь заходим в директорию нашего проекта и создаем там папку “include”. Идем в директорию, где установлена Maya “..\Maya7.0\devkit\mentalray\indude\” и копируем все файлы из этой директории в папку include нашего проекта. Эти заголовочные файлы обязательно нужны для проекта. В частности, для всех шейдеров нужен файл shader.h - в нем объявлены все функции и типы переменных, все же остальные файлы не обязательны для простых шейдеров, но лучше скопировать сразу все, чтобы потом не возникало проблем. После чего создаем в нашем проекте папку lib, куда скопируем все содержимое папки “..\ Maya7.0\devkit\mentalray\lib\nt\”. Файл shader.lib обязателен для всех шейдеров, а файл mayabase. lib нужен только в том случае, если вы планируете писать шейдера, привязанные непосредственно к Maya, например, шейдер с использованием майского Light Linker’a. Если вы используете mayabase. lib, то ваш шейдер будет нуждаться в библиотеке .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. mayabase.dll при рендере. Примечание. Все эти файлы можно не копировать в проект, а просто указать их местонахождение в проекте. Однако, скопировав эти файлы, в результате мы получаем локальную копию проекта, которая не зависит от местоположения Maya и вообще ее наличия на машине. Такой проект легко переносится, не теряя своей функциональности, например, вы сможете работать с этим проектом и дома, и на работе. Создаем новый файл Fi le -> New- > File... типа *.срр, назовем его, например, my_con-stant. Теперь в нашем проекте появится новая закладка в свойствах проекта “C/C++”. Вот там и нужно будет кое-что подправить. Нужно еще немного настроить проект и подключить те файлы, которые мы копировали. Для этого заходим в свойства проекта и в закладке C/C++->Additional Include Directories указываем “.\include” (если вы не копировали *.h файлы в проект, то укажите тут полный путь до “c:\Program Files\Alias\Maya7.0\devkit\mentalray\include”). Теперь заходим в закладку Linker->Additional Dependencies и указываем там “.\ lib\shader.lib” (соответственно, если вы не копировали “.lib файлы локально в проект, то указываем тут полный путь до них “c:\Program Files\Alias\Maya7.0\devkit\mentalray\lib\nt\ shader.lib”). В свойствах проекта, в закладке C/C++->Code Generation->Runtime Library выбираем “Multi-threaded Debug DLL (/MDd)” для Debug режима и “Multi-threaded DLL (/MD)” для Release соответственно. Теперь следует все то же самое проделать и для Release режима компиляции. Следующий шаг не обязателен, но его желательно проделать, чтобы избежать следующего warning’a при компиляции шейдера: LINK : warning LNK4098: FAULTLIB: library

defaultlib

‘MSVCRT’

conflicts with use of other libs; use /NODE-

В свойствах проекта в поле Linker->lgnore Specific Library нужно прописать следующее: libc.lib;libcmt.lib;msvcrt.lib;libcd.lib;libcmtd.lib для Debug режима (Multithreaded Debug DLL (/MDd) ) libc. lib; libcmt. lib ; libcd. lib ; libcmtd. lib ;msvcrtd. lib для Release режима (Multithreaded DLL (/MD)) Подробнее об этой проблеме и зачем все это нужно делать, можно узнать по этому адресу: msdn.microsoft.com/library/default.asp?url=/library/en-us/wcepbguide5/ html/wce50errLinkerToolsWarningLNK4098.asp

http://

Поздравляю! Ваш проект полностью готов к работе. ............................................................................................................................................................................. Ледин Павел


.............................................................................................................................................................................

Первый шейдер

Настроив проект, приступаем непосредственно к написанию первого шейдера. Открываем созданный ранее файл my_constant.cpp и вписываем туда следующий код: #pragma once #include <math.h> #include “shader.h” typedef struct { miColor color; }my constant_t; extern “c” { DLLEXPORT int my_constant_version(void) {return(l);} DLLEXPORT miBoolean my_constant(miColor *result, miState *state, my_constant_t *paras) { *result = *mi_eval_color(&paras->color); return(miTRUE); } } Это код самого простого constant шейдера, который возвращает заданный цвет вне зависимости от освещения. Constant, как ни странно, может оказаться достаточно полезным и часто используемым шейдером. Подробнее суть кода будет описана чуть ниже, а сейчас просто компилируем код, чтобы увидеть его в работе. На выходе должен получиться my_mr_shaders.dll, это и есть функциональная часть нашего шейдера. Следующим шагом нам необходимо будет создать файл с названием my_mr_shad-ers.mi. Для этого воспользуйтесь вашим любимым текстовым редактором, например: Notepad, WordPad, Textpad или UltraEdit и т.п., но только не Word. Я бы рекомендовал использовать именно Textpad или UltraEdit, так как это наиболее продвинутые и удобные текстовые редакторы, но это дело вкуса. Набираем следующий текст и сохраняем его как my_mr_shaders.mi declare shader color “my_constant” ( color “color” ) version 1 apply material #: nodeid 666055 end declare

#:

default 1.0 1.0 1.0

Готово. Осталось подключить получившийся шейдер к Maya и протестировать. Для этого надо вначале установить шейдер. Копируем “my_mr_shaders.mi” в папку: c:\Program Files\AUas\Maya7.0\mentalray\include\ А файл “my_ mr_shaders.dll” в папку: c:\Program Files\AUas\Maya7.0\mentalray\lib\ После чего нам потребуется отредактировать файл maya.rayrc, чтобы Maya знала, откуда грузить шейдер, для этого нужно добавить в него следующие строки: link “{MAYABASE}/lib/my_mr_shaders. {DSO}” mi “ {MAYABASE} /include/my_mr_shaders. mi “ .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. Запускаем Maya. Следует обратить внимание, что после загрузки Maya в Script Editor не должно быть никаких ошибок и предупреждений. Если все хорошо, то там должно быть что-то вроде: // // // // // //

parsing С:/Program Files/Alias/Maya7.0/mentalray/include/oontoar.mi generating Maya nodes... parsing Ci/Program Files/Alias/Maya7.0/mentalray/include/my_mr_shaders.mi generating Maya nodes... parsing С: /Program Files/Alias/Maya7.0/mentalray/include/paint.mi generating Maya nodes...

Это говорит о том, что mi файл написан правильно, и в нем нет синтаксических ошибок. Теперь посмотрим, что у нас получилось. Создаем любой объект, например, сферу, открываем Hypershade, жмем Create->mental ray Materials->My_constant и назначаем его на созданный объект и, затаив дыхание, жмем кнопку рейдер.

После того как рендер завершен, следует заглянуть в Output Window на предмет наличия ошибок и тп. Если таковые имеются, то следует проверить код или то, правильно ли установлен шейдер. Теперь, когда мы имеем полностью рабочий шейдер, я расскажу немного о деталях кода. typedef struct { miColor color; }my_constant_t; Это структура параметров шейдера. Ее элементы должны совпадать с параметрами, указанными в mi файле, как по порядку, так и по количеству и типу данных. Название структуры можно использовать любое. extern “C” { DLLEXPORT int my_constant_version(void) {return (1) ;} DLLEXPORT miBoolean my_constant (miColor *result, miState *state, my_constant_t *paras) { *result = *mi_eval_color (Sparas->color) ; return (miTRUE) ; } } ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Если вы пишите на C++, то вы должны использовать декларацию extern “c” для всех внешних функций, чтобы они могли линковаться с кодом, написанным на С. Без этого шейдер откомпилируется нормально, но не будет работать во время рендера. Если вы пишите свой код на С, то extern “С” использовать не требуется (как это, например примерах шейдеров идущих в стандартной поставке). Далее мы видим две функции, которые являются обязательными для шейдера Первая, как видно из кода, просто возвращает версию шейдера. Версия должна быть та же, что указана в mi файле. Иначе во время рендера получим warning о несовпадении версий. Функция должна называться shadername_ version(). Вторая функция является главной функцией шейдера, по сути, это и есть сам шейдер. В качестве первого параметра в функцию передается miColor “result указатель на результат просчета шейдера. Примечание: Если ваш шейдер должен возвращать не miCotor, то просто пишем тут нужный тип возвращаемого значения, например miScalar *result, или тот тип, какой вам нужен, можно использовать даже структуру. Вторым параметром передается miState *state, это указатель на структуру, в которой хранится вся информация о точке пересечения, которая может понадобиться для просчета шейдера, например normal, point, direction, options и тд. И третьим параметром в функцию передается указатель на структуру, в которой хранятся параметры шейдера my_constant_t *paras. Имя данной функции - это и есть имя шейдера. Помимо этих функций, в шейдере могут быть еще две другие не обязательные функции - shadername_ init() и shadername_exit(). Функция _init() выполняется всего однажды, когда шейдер вызывается первый раз. В ней можно вычислять, например, данные, которые не меняются в процессе рендера. Например, в _init функции можно создать и вычислить какие-нибудь статичные данные, которые потом использовать во всех вызовах шейдера. Функция _exit() выполняется один раз, после того как шейдер вызывается в последний раз. В данной функции можно, например, удалять данные, созданные в _init() функции. Итак, рассмотрим сам код функциональной части шейдера. Как видно, он очень простои. *result = *mi_eval_color (&paras->color) ; Функция mi_eval_color() просто зачитывает параметр шейдера, в данном случае соlor , и возвращает указатель на его значение. В зависимости от типа параметра, нужно использовать разные функции: mi_ eval_color(), mi_eval_scalar() и mi_eval_boolean(). Как видно из кода, в качестве результата используется значение, взятое из параметра шейдера, то есть как бы из GUI. Можно, например не считывать значение, а просто указать его явно, например, так: result->r result->g result->b result->a

= = = =

0.7; 0.8; 0.3; 1.0;

При удачном выполнении шейдера функция должна возвращать miTRUE.

Освещение

Далее мы рассмотрим, как сделать так, чтобы шейдер реагировал на свет, то есть имел диффузную составляющую. Для этого создадим в проекте новый фаил my_lambert. срр, в который впишем следующий код. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. #pragma once #include <math.h> #include “shader.h” typedef struct { miColor int int miTag }my_lambert_t;

diffuse; int

i_light; n_light ; light[1] ;

mode;

extern “С” { DLLEXPORT int my_lambert_version (void) {return (1);} DLLEXPORT miBoolean my_lambert (miColor *result, miState *state, my_lambert_t *paras) { miTag *light; int n_l, i_l, mode, n, samples; miColor color, sum; miColor*diff; miVector dir ; miScalar dot_nl; result->r = result->g = resulfc->b = result->a = 0; diff = mi_eval color(*paras->di£fuse); mode = *mi_eval_integer (&paras->mode) ; n_l = *mi_eval_integer (&paras->n_light); i_l = *mi_eval_integer (&paras->i—light); light = mi_eval_tag(paras->light) + i_l; if

(mode ==1) mi__inclusive_lightlist(&n_l, &light, state); else if (mode == 2) mi_exclusive_lightlist (&n_l, &light, state); for (n=0; n < n_l; n++, light++) { sum.r = sum.g = sum.b = 0; samples = 0; while (mi_sample_light(&color, &dir, &dot_nl, state, *light, &samples)) { sum.r += dot nl * diff->r * color.r; sum.g += dot_nl * diff->g *color.g; sum.b += dot_nl * diff->b * color.b; } if (samples){ result->r += sum.r / samples; result->g += sum.g / samples; result->b += sum.b / samples; } } result->a = 1; return (miTRUE); } }............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. Подправим наш файл my_mr._shaders.mi, добавив туда следующие строки: declare shader color “my_lambert” ( color integer “mode”, array light ) version 1 apply material #: nodeid 666056 end declare

“diffuse”,

#: default 0.8 0.8 0.8

“lights”

Откомпилим и подключим шейдер, как было описано выше. В результате должен получиться обычный Iambert шейдер, код которого мы изучим дальше. По началу код может показаться непростым, но на самом деле все не так сложно. Рассмотрим его более подробно. Рассмотрим код с самого верха - с описания структуры параметров шейдера. Всего шейдер имеет 3 параметра. Первый - ‘diffuse’ - это просто цвет поверхности. Далее идет ‘mode’. Он связан с третьим параметром и отвечает за линковку источников света влияет на то, какие источники света будут освещать шейдер. Третий параметр ‘light’ хранить массив источников света. В зависимости от параметра ‘mode’, источники света, указанные в массиве ‘light’, будут либо освещать, либо не освещать шейдер. Надо отметить, что для реализации массива требуется 3 переменных: ‘n_light’размер массива, то есть количество его элементов, ‘Might’ - индекс или смещение по массиву ‘light’ - тип элементов массива. Подробнее о реализации параметров шейдера типа массив можно прочитать в документации. Далее, после создания нужных переменных и зачитывания параметров, идут функции, формирующие окончательный список источников света, которые влияют на шейдер. if (mode == 1) mi_inclusive_lightlist(&n_l, &light, state); else if (mode == 2) mi_exclusive_lightlist(&n_l, &light, state) ; В итоге указатель ‘light’ хранит в себе полный список источников света, которые нам нужны для просчета. for

(n=0; n < n_l;

n++,

light++) {...}

Ниже начинается цикл, в котором и происходит сам процесс освещения. Шейдер пробегается по всем источникам света и вызывает следующую функцию, которая уже семплирует источник света (вызывает лайт шейдер). while (mi_sample_light(&color, &dir, &dot_nl, state, *light, &samples)) Если это Area Light, то функция будет вызвана столько раз, сколько семплов в данном источнике. Если это простой источник света, то функция вызовется всего один раз. mi_ sample_light возвращает несколько разных значений: цвет света ‘color’, направление к источнику света ‘dir’, результат скалярного произведения ‘dir’ и нормали объекта ‘dot_ nl’ и количество семплов текущего источника света. В принципе, это практически все, что может понадобиться для просчета освещения в данной точке. Дальше используем полученные данные. Именно этот фрагмент, когда влияет на то, как шейдер реагирует на свет. .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. sum.r += dot_nl * diff->r * color.r; sum.g += dot_nl * diff->g * color.g; sum.b += dot_nl * diff->b * color.b; Цвет объекта умножается на цвет света и потом перемножается с dot_.nl, что и создает диффузное освещение. Если семплов было несколько, то надо будет разделить получившееся значение на значение samples. Далее вызывается функция mi_compute_irradiance для просчета ненаправленного (indirect) освещения (Final Gather, Global Illumination и Caustic). Данная функция нужна только в том случае, если шейдер должен реагировать на indirect освещение. Если нам понадобится блик, нужно будет добавить следующие строки внутри функции mi_sample_light, и шейдер превратится из lambert’a в phong: s = mi_phong_specular(expo, state, &dir); if (s > 0.0) { sum.r += s * spec->r * color.r; sum.g += s * spec->g * color.g; sum.b += s * spec->b * color.b; } Разумеется, понадобится добавить необходимые параметры и переменные. Полный кол можно посмотреть на диске или в наборе примеров шейдеров, поставляющихся вместе с ментал реем (файл basephong.c). И так можно наращивать наш шейдер далее, пока он не обзаведется всеми нужными для нас функциями и параметрами. Среди всего можно добавить Reflection, Refraction Ambient и т.д. О возможностях и функциях, которые можно добавить, можно узнать в документации.

Написание mi файлов

С написанием самого кода мы немного разобрались и получили вполне работоспособные шейдера, но как мы помним, шейдер состоит из двух файлов *.dll и *.mi. Вот о создании mi файлов мы поговорим далее. Вообще, что такое mi файл для шейдера? Это файл, в котором содержится декларация самого шейдера, его параметров и.т.п. Mi файл является как бы связующим звеном между рендером и 3d пакетом, или даже юзером. Именно по этому файлу Maya определяет, что это за тип шейдера, что он возвращает и какие у него параметры. По сути, до самого рендера Maya вообще не загружает *.dll, то есть самого шейдера, а черпает всю информацию только из *.mi файлов. ............................................................................................................................................................................. Ледин Павел


............................................................................................................................................................................. В качестве примера рассмотрим декларацию шейдера my_phong: declare shader color “my_phong” (

2

color “diffuse”, color “specular”, scalar “exponent”,

#: shortname “dif” default 0.8 0.8 0.8 #: shortname “spe” default 0.5 0.5 0.5 #: shortname “exp” default 50. min 0. max 10000. softmax 0 0

.

integer “mode” , #: shortname “mo” min 0 max 2 array light “lights” #: shortname “lig”

) version 1 apply material #: nodeid 666057 end declare

Декларация шейдера начинается со слов ‘declare shader’ и заканчивается ‘end de- clare’. Второй строкой идет тип возвращаемого значения и название шейдера. Как мы видим, данный шейдер возвращает color. В принципе, шейдер может возвращать любое значение и даже структуру. Название шейдера my_phong, точнее, это название функции, которую mental ray будет искать в подгружаемых *.dll. Далее идет перечисление параметров, тип и название. Потом следует версия шейдера. Именно это значение должна возвращать функция my_phong_version(), иначе получим предупреждение о несовпадении версий во время рендера. После чего следует строка apply material, говорящая, что это материал. Шейдера могут быть различных типов, например: texture, shadow, light и тд. Причем можно указать несколько категорий, например, так: apply material, texture. И последней строкой идут таинственные символы: #: nodeid 666057. Сразу оговорюсь, данная строка не имеет никакого отношения непосредственно к mental ray, именно поэтому она закомментарена символом ‘#’, то есть она нужна и видна только для Maya. Номер nodeid нужен Maya для идентификации различных нод, вообще это относится не только к шейдерам, в Maya каждая тип ноды имеет свой номер. Номера не должны совпадать. Если вы занимаетесь серьезной разработкой и хотите закрепить за собой какие-то айдишники, то вам нужно будет обратиться в службу поддержки, где вам выделят персональный диапозон номеров. В принципе, можно использовать любой номер, но нужно следить за возможными конфликтами. Например, может случиться так, что вы выбрали наугад какой-то номер, допустим, у вас он работает нормально без конфликтов, но тут вышла новая версия Maya, где добавились новые ноды, и возможно у вас теперь появятся проблемы. Так же возможны проблемы со сторонними плагинами, которые тоже могут конфликтовать с вашими no- deid. Поэтому тут нужно быть осторожными и лучше не использовать номера наугад. Разработчики выделили диапозон “для тестирования” от 0x0000000 до 0x0007ffff (от 0 до 524287), который гарантирует, что эти номера никогда не будут конфликтовать с Майскими нодами. Но при этом все же возможен конфликт с не совсем официальными плагинами или другими шейдерами. Этот диапозон может использовать каждый. Если не указывать никакой nodeid, то шейдер будет работать, но при загрузке Maya напишет предупреждение: // Warning: (Mayatomr.Nodes) : Node “my_phong” has no ID, assigning a temporary ID. Scene should be saved as .ma (ASCII). // Это обозначает, что шейдеру будет назначен временный ID, проблема в том, что одному и тому же шейдеру в разных ситуациях могут быть назначены разные временные номера, что может привести к разным проблемам. Теперь же вернемся немного назад к комментариям напротив параметров. Это так же Майские параметры, которые сам mental ray не видит. Возьмем строку: .............................................................................................................................................................................


Работаем с Mentalray ............................................................................................................................................................................. #:

shortname

“dif” default 0.8 0.8

0.8

Слово shortname обозначает короткое имя параметра. Данное имя будет использоваться Maya во время сохранения сцены. Чтобы лучше понять, что я имею ввиду, можно создать простую сцену с несложным шейдинг нетворком, сохранить ее в *.та, после чего открыть ее в текстовом редакторе и посмотреть, как там записаны коннекшены и значения параметров. Если короткое имя не указано, то Maya будет использовать для именования параметров в *.гпа и *.mb файлах что-то вроде “s01”, “s02”, “s03” и тд. , где число - это номер параметра (начиная сверху). Наверное, не сложно догадаться, что при таком подходе любое изменение количества параметров или просто при их перестановке старая сцена (сохраненная со старым шейдером) может просто потерять все коннекшены. Например, вы разрабатываете шейдер, который уже активно используется в производстве, и вот вам захотелось добавить новый параметр, вы это делаете, открываете старую сцену и видите, что все связи съехали или просто пропали. Чтобы этого не происходило, нужно добавлять новые параметры в самый конец, но это не всегда возможно (иногда это может выглядеть не очень красиво с точки зрения интерфейса), поэтому лучше всего использовать короткие имена. Тогда Maya при сохранении сцены будет использовать именно их. Рекомендую с самого начала придумать короткие имена для всех параметров, чтобы потом было меньше проблем. Но что же делать, если у вас уже есть сцена, которая была сохранена без использования коротких имен? На этот случай можно открыть сцену со старым шейдером и пересохранить ее с опцией “Use Full Names for Attributes and Nodes”.

После чего сцена должна открыться целой и невредимой, с новой версией шейдера, разумеется, если вы не переименовывали параметры. После слова shortname у нас идет слово default, как вы, наверное, могли догадаться, - это значение параметра по умолчанию. Если этого не указывать, то при создании нового шейдера все параметры всегда будут равны нулю. Если кто-нибудь помнит, именно так выглядели все шейдера в Maya 5.0, обнуленные и черные. Понять, какое значение нужно поставить, чтобы шейдер заработал, было временами очень сложно, поэтому не пренебрегайте правильными значениями параметров по умолчанию. Так же у параметра могут иметься дополнительные служебные слова, например, min 0.0 max 100.0 говорит о том, что параметр не может быть меньше нуля и больше 100. Слова softmin и softmax отличаются от min и max тем, что они лишь ограничивают ползунок, но при желании параметр можно установить за пределы этих границ, вбив значение в поле вручную. Если ни мягкие, ни жесткие границы не установлены, то в интерфейсе у параметра вообще не появится ползунок. Ну вот, кажется, все основные аспекты мы рассмотрели. Для шейдера еще также можно нарисовать иконку и сделать AETempleate для более красивого GUI, но это уже не так важно и на работу самого шейдера никак не влияет. Думаю, в этом при необходимости вы разберетесь самостоятельно. Для того чтобы самостоятельно изучать дальше, вам потребуется изучить уже написанные шейдера, например, хотя бы те, что идут в поставке с mental ray, уверяю вас, там есть что посмотреть, ну или искать в Интернете шейдера, распространяемые с исходным кодом, такие тоже имеются. Удачи! .............................................................................................................................................................................


Команда EMIT .............................................................................................................................................................................

Автор: Забелин Владимир

Команда EMIT Частицы - один из наиболее интересных и полезных объектов MAYA для создания всевозможных спецэффектов: взрывов, дымов, фейерверков, стай рыб, птиц и т.д., и т.п. Частицы используются там, где нужно получить большое, порой гигантское, число объектов, управляемых статистическими или физическими законами. Частицы и случайные числа - горошины из одного стручка. При работе с частицами мы, как правило, руководствуемся общими для всей системы законами и правилами. Вот источник (emitеr), вот поле (например, гравитация), вот коллизирующая поверхность, и вот результат - Ниагарский водопад - смотри и наслаждайся. Как в футболе: правила игры и количество игроков одно и тоже, но каждая игра, тем не менее, не похожа на все предыдущие и вызывает фантастический интерес у миллионов зрителей. Но есть ряд задач и эффектов, которые требуют более точного, избирательного контроля над местом, временем и количеством порождаемых частиц. Волшебное, лучистое мерцание сказочного неба, или искры, высекаемые камнем, катящимся по гранитным ступенькам - вот примеры, которые не поддаются простому, «лобовому» решению с помощью обобщенных статистических законов. Если, конечно, не пользоваться услугами команды emit.

............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

Команда emit.

Немного о терминологии. Чтобы не очень путаться в дальнейшем, мы будем говорить «множество частиц» или «система частиц», подразумевая «объект типа частица» - particle object - это объект MAYA, который мы видим в окне Outliner. И этот объект состоит из отдельных элементов - «частиц». Если использовать аналогию из нашей повседневной жизни, то пылевое облако - это «множество частиц», а отдельная пылинка - это «частица». Команда emit очень проста: она просто добавляет одну частицу в существующее множество частиц. И всё. Если, конечно, не считать, что при добавлении новой частицы мы можем абсолютно точно определить не только место возникновения новой частицы , но и значения любых других имеющихся у нее атрибутов: цвета, размера, скорости и так далее. Именно эта особенность делает ее столь полезной. А теперь несколько примеров. Установим частоту проигрывания 25 кадров в секунду

и скорость проигрывания анимации - «проигрывать каждый кадр» (Play every frame)

.............................................................................................................................................................................


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

1. Создаем локатор (Create -> Locator). Укоротим его имя, переименовав просто в L. spaceLocator

-name L -р 0

0

0;

2. Сдвинем локатор по оси X на 5 единиц. setAttr L.translateX 5;

3. Поставим два ключа на перемещение по оси Y: первый ключ - со значением 0 в первом кадре и второй - со значением 8 в 125 кадре. setKeyframe -time l -value 0 L.translateY; setKeyframe -time 125 -value В L.translateY;

4. Зададим нашим ключам тип интерполяции flat (Tangents -> Flat) и поведение анимационной кривой на бесконечности - oscillate (Curves -> Post Infinity -> Oscillate)

5. Сгруппируем локатор сам с собой (Edit -> Group) и переименуем полученную группу в LRotate. При использовании команды group с опциями по умолчанию, опорная точка (pivot) вновь созданной группы окажется в начале координат. group -name LRotate L; xform -os -piv 0 0 0;

6. Поставим пару ключей на атрибут поворота группы LRotate вокруг оси Y: первый со значением 0 в первом кадре, второй - со значением 360 в 33 кадре. setKeyframe -time 1 -value 0 LRotate.rotateY; setKeyframe -time 36 -value 360 LRotate.rotateY; 7. Зададим новым ключам тип интерполяции linear (Tangents -> Linear) и поведение анимационной кривой на бесконечности так же linear (Curves -> Post Infinity -> Linear)

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. Итак, основа для наших дальнейших экспериментов создана. Если мы проиграем созданную анимацию, задав приличное время анимации (кадров в 1000), то увидим, как локатор «наматывает» спирали вокруг невидимого цилиндра. (Сцена emit01.mb) Теперь подцепим локатору «хвост» - след, который он будет оставлять по пути своего движения. Самый простой путь - прикрепить к локатору источник частиц (emiter) и быстренько получить самый примитивный результат.

Поработав с параметрами источника, атрибутами частиц и добавив воздействие полей (турбулентность, гравитация и тому подобное), можно добиться очень натурального огненного или дымного следа. Но как быть, если нас интересует не хаос, а упорядоченность? Не натуральность, а искусственность?

8. Создадим пустое множество частиц, которое назовем trackParticl.es. Это можно сделать командой. particle -name trackParticles;

В окне Outliner появится объект trackParticles, но он пока не содержит ни единое частицы.

9. Теперь мы будем порождать в каждом кадре по одной частице точно в текущем положении

локатора L. Для этого откроем Expression Editor и создадим следующее выражение, назвав его trackExpression

.............................................................................................................................................................................


Команда EMIT ............................................................................................................................................................................. //Находим текущее положение локатора L в мировой системе координат float $LPos[] ; $LPos=’pointPosition -w L’; // Добавляем одну частицу к множеству частиц trackParticles // в текущем положении локатора L emit -object trackParticles -position ($LPos[0])

($LPos[l])

($LPos[2]);

Проиграем анимацию. Локатор оставляет четкий спиральный след из точек. Чтобы лучше видеть результат, в разделе Render Attributes редактора атрибутов множества частиц изменим тип отображения (Particle Render Type) с Points на Spheres и уменьшим радиус возникших сфер до 0.25

У нас должна получиться примерно такая картинка

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. Самое время скептически настроенному читателю задать законный вопрос: «А разве с помощью источника частиц нельзя получить точно такой же результат?». Конечно можно, но наберемся терпения - все лучшее еще впереди. Усложним вид следа локатора, добавив к каждой сфере по пять сферок поменьше - сверху, снизу, сзади и две по бокам. Этим дополнительным сферам уготована судьба, отличная от центральных, поэтому для них создадим новое множество частиц.

10. Создаем пустое множество частиц с именем crossParticles командой particle -name crossParticles; Сразу изменим тип их отображения на Spheres и зададим их радиус 0.15 - чуть меньше, чем у центральных сфер.

11. В окне Expression Editor находим выражение trackExpression. Оно должно быть единственным выражением в сцене, но чтобы его обнаружить, в меню окна Expression Editor выберите пункт меню Select Filter -> By Expression Name. Отредактируем найденное выражение, введя в него алгоритм порождения дополнительных частиц. Теперь оно будет выглядеть следующим образом: //Находим текущее положение локатора L в мировой системе координат float $LPos[]; $LPos=’pointPosition -w L’; // Добавляем одну частицу к множеству частиц trackParticles / / в текущем положении локатора L emit -object trackParticles -position ($LPos[0]) ($LPos[l]) ($LPos[2]); // Расстояние от оси Y до локатора float $radius=5.; // Расстояние между центральной и боковыми сферами float $dist=0.45; // Вспомогательные переменные float $kIn, $kOut, $kBack; SkIn=($radius - $dist)/$radius; $kOut =($radius + $dist)/$radius; $kBack=$dist/$radius; //Добавляем пять частиц к множеству частиц crossParticles emit -object crossParticles -position ($LPos[O]) ($LPos[l]+$dist) ($LPos[2]) -position ($LPos[0]) ($LPos[l]-$dist) ($LPos[2]) -position ($kIn*$LPos[0]) <$LPos[l]) ($kIn*$LPos[2]) -position ($kOut*$LPos[01) ($LPos[l]) (Sk0ut*$LPos[2]) -position <$LPos[0)-$kBack*LPos[2]) ($LPos[l]) ($LPoS[2]+$kBack*$LPos[0]); .............................................................................................................................................................................


Команда EMIT .............................................................................................................................................................................

12. Сейчас все наши частицы бессмертны. Исправим эту «несправедливость», изменив в редакторе

атрибутов в секции Lifespan Attributes атрибут lifespanMode с Live forever на Constant и задав атрибуту lifespan значение 3

Проделаем эту безжалостную операцию для обоих множеств частиц: и для trackParticles и для crossParticles. Проиграем получившуюся анимацию. За локатором теперь тянется довольно-таки затейливый хвост.

(Сцена emit02b.mb). Самое время внести в сцену немного красок. Использование команды emit для рождения частиц не делает их ни в коей мере «дефектными». Если множество частиц подчинялось каким-то правилам рождения (creation expression) или правилам жизни (runtime expression), или у него имелись атрибуты со специфическими свойствами - неважно стандартные или экзотические, то каждая частица будет обладать полным набором ............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. свойств, характерных для своего множества, независимо от того, родилась ли она «in vit-ro» - с помощью команды emit, или другим, более «естественным» способом. Цвет частиц из crossParticles мы определим атрибутом самого множества частиц, и он будет однним и тем же для всех частиц. Цвет частиц из trackParticles будем определять индивидуально для каждой частицы и передавать его частицам с помощью той же функции emit. Сделаем этот цвет зависимым от угла поворота локатора

13.

Добавим атрибут цвета для множества частиц crossParticles. Поскольку мы собирались «покрасить» все частицы из crossParticles в один цвет, то при добавлении атрибута цвета выберем опцию Add Per Object Attribute

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

значения; colorRed = 1, colorGreen = 1, colorBlue =0. Такой выбор значений сделает наши частицы желтыми.

.............................................................................................................................................................................


Команда EMIT .............................................................................................................................................................................

15. Поскольку каждой частице из trackParticles мы будем задавать значения цвета

индивидуальноьно, то при добавлении атрибута цвета множеству частиц trackParticles следует выбирать опцию Add Per Particles Attribute.

16. Вновь в окне Expression Editor разыщем выражение trackExpression и отредактируем повую команду emit, с помощью которой порождаются частицы из tracParticles. Значение Зарождающихся частиц определим, исходя из текущего значения угла поворота группы LRotate. В окончательном виде наше выражение примет вид: //Находим текущее положение локатора L в мировой системе координат float $LPos[]; $LPos=’pointPosition -w L’; float $hue; vector $curColor; // Вычисляем цвет частиц $hue=LRotate.rotateY/360. - trunc(LRotate.rotateY/360.) ; $curColor=hsv_to_rgb ( <<$hue, 1, 1>> ); // Добавляем одну частицу к множеству частиц trackPartides // в текущем положении локатора L emit -object trackPartides -position ($LPos[0]) ($LPos[l]) ($LPos[2]) -attribute rgbPP -vectorValue ($curColor.x) ($curColor.y) ($curColor.z); // Расстояние от оси Y до локатора float $radius=5.; ............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. // Расстояние между центральной и боковыми сферами float $dist=0.45; // Вспомогательные переменные float $kIn, $kOut, $kBack; $kIn= ($radius - $dist) /$radius ; $kOut =($radius + $dist)/$radius; $kBack=$dist/$radius; //Добавляем пять частиц к множеству частиц crossParticles emit -object crossParticles -position ($LPos[0]) ($LPos[l]+$dist) ($LPos[2]) -position ($LPos[0]) ($LPos[l]-$dist) ($LPos[2]) -position ($kIn*$LPos[0]) ($LPos[l]) ($kIn*$LPos [2]) -position ($kOut*$LPos[0]) ($LPos[1]) ($kOut*$LPos[2]) -position ($LPos[0])-$kBack*LPos[2])($LPos [1] )($LPos [2] +$kBack*SLPos [0]); Теперь наша сцена выглядит значительно веселее. Проиграв анимацию, мы увидим примерно такую картинку:

(Сцена emit02c.mb). Если все, что мы делали до этого шага, можно было бы тем или иным способом реализовать и без применения команды emit, то в заключительном эффекте без нее обойтись невозможно. (Правда, «невозможно» - это слишком категоричное слово, когда речь идет о MAYA). Итак, сейчас мы усложним жизнь и смерть наших частиц следующим образом. Нам бы хотелось, чтобы частицы из trackParticles «умирали» не так «бессловесно», напротив, они должны заканчивать свое существование всплеском искр. Причем искры будут того же цвета, что и погибающая частица. Частицы же из crossParticles умирать будут по-прежнему, без дополнительных эффектов, но зато в процессе своей жизни в случайном порядке испускать веер искр во всех направлениях. Искры логично сделать желтыми, под цвет самих частиц. .............................................................................................................................................................................


Команда EMIT .............................................................................................................................................................................

17. Для реализации обоих эффектов нам потребуется еще одно множество частиц, которое логично называть sparkParticles. particle -name sparkParticles ; Сразу добавим нашим частицам цвет. Поскольку искры будут разного цвета, то при добавлении атрибута цвета нужно выбрать опцию Add Per Particle Attribute, как и в пункте 15. Оба эффекта - и искристость желтых сфер, и феерическая смерть центральных, решаются по одному принципу: с помощью правил, выполняемых в процессе жизни (runtime expressions), в которых будет присутствовать команда emit, с помощью которой мы легко определим место возникновения и цвет искр - это положение и цвет порождающей искры частицы. Скорость и направление разлета искр вычислим как случайно распределенный по сфере вектор. Останется определить момент появления искр.

18. Откроем окно редактора атрибутов множества частиц crossParticles и в секции Per Particle (Ar-

ray) Attribute для атрибута position создадим выражение, исполняемое в период существования (Runtime Expression). Напомним, что для этого нужно щелкнуть правой клавишей мыши в поле атрибута и в появившемся меню выбрать Runtime Expression, либо выбрать узел crossParticleShape, вызвать окно Expression Editor и убедиться, что в строке partice выбрано положение переключателя Runtime. // Вероятность испускания искр float $р=0.005; // Число искр int $sparkNumber=10; //Скорость искр float $sparkVelocity=2 ; vector $pPosition, $pVeloeity; if (rand(l) < $p) { $pPosition = position; for ($i=0; $i < $sparkNumber; $i++) { $pVelooity = sphrand( $sparkVelocity ) ; emit -object sparkParticles -position ($pPosition.x) ($pPosition.y) ($pPosition.z) -attribute velocity -vectorValue ($pVelocity. x) ($pVelocity.y) ($pVelocity.z) -attribute rgbPP -vectorValue (colorRed) (colorGreen) (colorBlue); }; } ; Обратим внимание на условие испускания искр. В каждом кадре для каждой частицы вычисляется значение случайной равномерно распределенной на отрезке [0,1] величины (rand(1)), которое сравнивается с «пороговым» значением $р. Выполнение неравенства rand(1)<$p и является условием появления искр у каждой конкретной частицы. В нашем случае вероятность «искрения» равна 0.005 - всего лишь полпроцента! Проиграем анимацию. Кошмар! Полная каша. Вместо желаемых искр полетели какие-то желтые точки. На самом деле все не так страшно, как может показаться на первый взгляд. Чтобы добиться приемлемого результата, нужно лишь немного поработать с атрибутами “искр” - частиц из sparkParticles: изменить способ их визуализации и сократить время жизни. ............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

19. Откроем редактор атрибутов для множества частиц sparkParticles. В секции Lifespan Attribute изменим атрибут lifespanMode с Live forever на Random range и зададим для атрибута lifespan значение 0.2, а для lifespanRandom - значение 0.05. Далее. В секции Render Attributes изменим атрибут particleRenderType с Points на Streak. Добавим атрибуты для нового типа визуализации частиц, щелкнув по кнопке Add Attributes For Current Render Type, и увеличим значение атрибута tailSize до 20.

Проиграем анимацию. Уже удовлетворительно. Теперь добавим выброс искр в . момент «смерти» частиц из trackParticles. На самом деле, выполнить выражение (Runtime expression) в момент или после смерти частицы невозможно. Вместе с исчезновением частицы исчезает и вся информация о ней: положение в пространстве, цвет и так далее Поэтому любое выражение можно выполнить только пока частица «жива». Ну что ж. Мы создадим выражение для частицы, условием выполнения которого будет последний кадр ее жизни. То есть когда разность между сроком ее жизни (lifespan) и возрастом (age) станет не больше одного кадра -1 /25 секунды (В самом начале мы договорились о том, что работаем в системе PAL - 25 кадров в секунду.)

20. Как и в пункте 18, создадим выражение, исполняемое в период существования (Runtime Expression), но на этот раз для частиц trackParticles: // Число искр int $sparkNumber=50; //Скорость искр float $sparkVelocity=3; vector $pPosition, $pColor, $pVelocity; if ((lifespan-age)<=0.04) { $pPosition — position; $pColor=rgbPP; for ($i=0; $i < $sparkNumber; $i++) { $pVelocity = sphrand( $sparkVelocity); emit -object sparkParticles -position ($pPosition.x) ($pPosition.y) ($pPosition.z) -attribute velocity .............................................................................................................................................................................


Команда EMIT .............................................................................................................................................................................

};

};

-vectorValue ($pVelocity.x) (SpVelocity .y) ($pVelocity.z) -attribute rgbpp -vectorValue ($pColor.x) ($pColor.y) ($pColor.z);

Проиграем анимацию. С чувством глубокого удовлетворения отметим, что цель Достигнута.

Все заявленные эффекты в наличии. И отметим, что не было использовано ни единого источника частиц (emitter). Писанины, правда, хватило бы на небольшой рассказ, но это справедливая плата за полный контроль над происходящими в сцене событиями. Фейерверки, мерцание сказочного неба, блестки “волшебной” пыли, бенгальские свечи - вот далеко не полный перечень эффектов, в создании которых будет полезна команда emit.

Столкновение твердых тел.

Второй пример на ту же тему. Искры при столкновении твердых тел. Когда мы имеем дело с частицами, то определить, что будет происходить при их столкновениях с поверхностью разрешения коллизий, довольно легко - достаточно лишь задать некоторое (не очень большое) количество опций в диалоговом окне Particle Collision Events (Particles -> Particle Collision Events...). Все действия, необходимые для реализации этих событий (collision event), MAYA выполнит самостоятельно: и отследит сам факт столкновения, и определит его координаты, и «убьет» (если нужно) ударившуюся частицу и так далее. В случае столкновения (или коллизии) твердых тел (rigid body) все немного сложнее. Существуют, конечно, обходные пути (мы помним, что в MAYA любую задачу можно решать разными способами). Например, твердое тело можно «обернуть» эластичной оболочкой (soft body) и всю ответственность за действия при столкновениях возложить на частицы, являющиеся неотъемлемой частью этой эластичной оболочки. Метод известный и надежно работающий, причем не требующий от пользователя никаких особых познаний в MEL-программировании. Правда, выбор событий, происходящих при столкновении, невелик, и приходится «утяжелять» сцену дополнительной геометрией и системой частиц со всеми вытекающими отсюда последствиями в виде увеличения времени динамической симуляции. Поэтому мы рассмотрим наиболее общий метод - без создания дополнительных объектов. ............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

1.

Создаем полигональный куб с опциями “по умолчанию” (Create -> Polygon Primitives ->Cube). Переименуем его просто в cube. PolyCube -n cube;

2. Увеличим его размер по всем осям в 3 раза scale -r 3 3 3 cube;

3. «Заморозим» трансформации и удалим историю для построенного куба, выполнив ify -> Freeze Transformations и Edit -> Delete by Type -> History.

команды Mod-

makeIdentity -apply true -t 1 -r 1 -s 1 cube; delete -ch cube;

4.

Превратим наш куб в активное твердое тело (Soft/ Rigid Bodies -> Create Active Rigid Body), переименуем узел rigidBody1 в activeRigidBody и увеличим атрибут bounciness до 0.8 и dynamicFriction до 0.6 select -r cube; rigidBody -паше activeRigidBody -active -dynamicFriction 0.5 -bounciness 0.8;

5. Добавим в нашу сцену поле гравитации, действующее на куб. Для этого, выделив cube, выполним

команду Fields -> Gravity. Уменьшим значение атрибута magnitude гравитационного поля (которое по умолчанию получило имя gravity-Field 1) до 5. gravity -position 0 0 0 -magnitude 5; connectDynamic -f gravityField1 cube; Если сейчас проиграть сцену, то мы увидим кубик, падающий вниз под действием силы тяжести. Добавим в нашу сцену поверхность, о которую кубик мог бы ударяться. Это будет обыкновенная полигональная плоскость с атрибутами пассивного твердого тела.

6.

Создаем полигональную плоскость (Create -> Polygonal Primitives ->Plane). Переименуем ее в plane. Существенно увеличим ее размеры, отмасштабироеав по горизонтальным осям в 35 раз, и, так же как и раньше, «заморозим» трансформации и удалим историю ее создания. polyPlane -name plane; scale -r 35 1 35; makeIdentity -apply true -t 1 -r 1 -s 1 plane; delete -ch plane;

7. Преобразуем плоскость в пассивное твердое тело (Soft/Rigid Bodies -> Create Passive Rigid Body),

вновь появившийся узел rigidBody1 переименуем в passiveRigidBody. Добавим нашей плоскости упругости, увеличив значение атрибута PasstveRigidBody.bounciness до 0.8 select -r plane; rigidBody -name passiveRigidBody -passive -bounciness 0.8;

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

сцене немного живости. Значения translateY=16, rotateX=35, rotateY= -30, rotateZ=25 - неплохой ............................................................................................................................................................................. выбор.


Команда EMIT .............................................................................................................................................................................

(Сцена emit3a.mb) Проиграем сцену. Как и ожидалось, куб падает на плоскость, несколько раз отскакивает от нее с уменьшающейся амплитудой и, в конце концов, останавливается. На все движение понадобится около 500 кадров. Теперь займемся содержательной частью - добавим искры, которые будут возникать в местах столкновения куба и плоскости. В роли «искр», как и в предыдущем примере, будут выступать частицы, которые мы будем порождать с помощью команды emit. Осталось только определить время и место их возникновения. Заодно потребуем, чтобы каждый удар порождал искры своего индивидуального цвета. Поскольку мы будем использовать команду emit, то реализовать такой эффект будет нетрудно, практически «даром». В случае же, если бы мы воспользовались другими методами, например, на основе вспомогательного эластичного тела (soft body), подобного контроля над цветом возникающих частиц добиться было бы гораздо труднее. Итак, время и место. Вся динамика рассчитывается при помощи специального функционального узла - солвера (rigid body solver), «решателя», который создается автоматически, как только мы создаем первое твердое тело. И первым делом мы должны дать задание солверу, который носит имя rigidSolver, отслеживать возникновение коллизий.

9. В редакторе атрибутов узла rigidSolver в разделе Rigid SolverStates включим опцию Contact Data.

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. setAttx rigidSolver.contactData 1; Теперь в процессе работы солвера будут вырабатываться данные о коллизиях твердых тел между собой. Для каждого твердого тела информация о коллизиях носит, естественно, индивидуальный характер и становится доступной через локальные атрибуты каждого твердого тела. Нам понадобятся contactCount и contactPosition - соответственно число и координаты коллизий в данный момент времени. Как только значение атрибута con- tactCount становится отличным от нуля, то это означает наличие коллизий рассматриваемого тела с другим телом (или другими телами). В этом случае в contactPosition (а это массив!) заносятся координаты всех произошедших столкновений. Но прежде чем вводить в действие механизм обработки коллизий, необходимо создать «искры» систему частиц, которые будут порождаться в точках соприкосновения куба и плоскости. Часть свойств этой системы частиц мы определим «изнутри» - с помощью начальных выражений (creation expression) - это будут направление и скорость их движения - а часть, такие как цвет и место возникновения, будем определять «извне» - в теле команды emit.

10. Создаем систему частиц с привычным именем sparkParticles и, как и в предыдущем примере, добавим ей атрибут цвета с опцией per particles:

particle -name sparkParticles; addAttr -longName “rgbPP” -dataType vectorArray sparkParticlesShape; addAttr -longName “rgbPPO” -datatype vectorArray sparkParticlesShape;

11.

Теперь самое время добавить в сцену немного «искр». Откроем Expression Editor и создадим вот такое выражение, которое назовем sparkExpression: int $i,$j; vector $sparkColor; float $hue; float ScurrContactPos[3]; int $sparkNum=30; if ( activeRigidBody.contactcount>0 ) for ($i=0; $i< activeRigidBody.contactCount; $i++) { $currContactPos=’getAttr activeRigidBody.contactPosition[$i]’; $hue=rand(l); $sparkColor=hsv_to_rgb( << $hue, 1, 1 >> ); for ($j=0; $j< $sparkNum; $j++) emit -o sparkParticles -position ($currContactPos[0]) ($currContactPos[l]) ($currContactPos[2]) -attribute rgbPP -vectorValue ($sparkColor.x) ($sparkColor.y) ($sparkColor.z); }; Как все выше написанное должно работать? Попробуем разобраться. Выполнение условия (activeRigidBody.contactCount >0) означает, что коллизия произошла. На самом деле, точек контакта кубика и плоскости может быть несколько (кубик может упасть вершиной вниз, а может и целой гранью), и в каждой точке контакта должны появиться «искры». Поэтому дальше - цикл по количеству точек контакта. Для каждой такой точки определяем ее координаты (где произошло столкновение): $currContactPos=’getAttr activeRigidBody.contactPosition[$i]”; Следующие две строки - просто определение цвета искр, которые появятся в месте удара, и затем порождение 30 искр (переменная SsparkNumber «отвечает» за число порождаемых частиц) в нужном месте и с нужным цветом. Если проиграть анимацию, то при внимательном рассмотрении можно увидеть разноцветные .............................................................................................................................................................................


Команда EMIT ............................................................................................................................................................................. точки, появляющиеся в местах касания кубика плоскости. Не впечатляет. Все-таки «искры» должны разлетаться веером в разные стороны. Наверно, на них тоже должна действовать сила тяжести. Да и выглядеть они должны скорее в виде черточек, а не точек. Все эти недостатки легко поправить, ведь главного результата мы уже добились: появление частиц в местах коллизии кубика и плоскости.

12. Определим начальные скорость и направление движения рождающихся частиц с помощью

правила рождения или начального выражения (creation expression). Для этого, как и раньше, откроем редактор атрибутов для sparkParticles и в секции Per Particle (Array) Attributes в поле velocity из меню, появившегося при нажатии правой клавиши мыши, выберем Creation Expression... Теперь введем несколько строк: float $magVeloexty=10; vector $initVelocity; $initVelooity=$magVeloeity*sphrand (1) ; if ($initvelocity.y<0) $initVelocity=<<$initVelocifcy.x, -$initVelocity.y , $initVelocity.z >>; velocity=$initVelocity ; К сожалению, выражение получилось длинным, хотя действие оно выполняет простое - создает вектор, равномерно распределенный по верхней полусфере радиуса SmagVelocity. Дело в том, что мы не имеем возможности в выражениях напрямую использовать компоненты вектора скорости, например, на запись velocity.y Maya выдаст ошибку: // Error: Attribute not found or variable missing ‘$’: velocity.y //, поэтому приходится использовать вектор-«посредник» $initVelocity.

13. Вернемся в редактор атрибутов для sparkParticles и изменим время жизни и способ визуализации частиц. В разделе Lifespan Attributes заменим Lifespan Mode с Live forever на Random Range, атрибутам lifespan и lifespanRandom имеет смысл задать небольшие значения, например по 0.5 обоим.

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. setAttr sparkParticlesShape. lifespanMode 2; setAttr sparkParticlesShape.lifespan 0.5; setAttr sparkParticlesShape.lifespanRandom 0.5;

14. В разделе Render Attribute изменим renderParticleType с Point на Streak. Добавим атрибуты для

этого визуализации частиц этого типа (Add Attributes For Current Render Type) и изменим значение появившегося атрибута tailSize на 5. setAttr sparkParticlesShape.particleRenderType 6; setAttr sparkParticlesShape.tailSize 5.0; Проиграем анимацию (файл emit03c.mb). Действительно, при каждом ударе кубика о плоскость в точке контакта возникает сноп разноцветных «искр-. Но вот незадача! «Искры» продолжают возникать и после того, как кубик прекратит подпрыгивать и прочно утвердится на поверхности. С точки зрения наших выражений, все правильно. Кубик остановился, четыре вершины нижней грани находятся в постоянном контакте с плоскостью и солвер в каждом кадре честно сообщает нам о четырех имеющихся коллизиях. Что и вызывает такой неиссякаемый фонтан частиц. С точки зрения нашего житейского опыта, все происходящее абсолютно неприемлемо. Подковы скачущей лошади высекают искры из гранитной мостовой, но когда эта же лошадь спокойно стоит, никаких искр, конечно, быть не должно. Изменить законы физики в окружающем нас мире мы вряд ли сможем, так что попробуем подкорректировать нашу сцену, чтобы приблизить ее к реальности. Исправления эти невелики. Для появления «искр» мало просто факта столкновения тел, необходимо еще учесть, чтобы вершина«контактер» двигалась с приличной мгновенной скоростью. Измерение мгновенной скорости вершины - задача несложная, но громоздкая, поэтому вычислим что-нибудь попроще, например, скорость активного твердого тела в момент коллизии.

15. Откроем Expression Editor (Window -> Animation Editors -> Expression Editor) и найдем выражение sparkExpression (возможно, придется воспользоваться пунктом меню Select Filter -> By Expression Name) и подкорректируем его следующим образом: int $i,$j; vector $sparkColor; float $hue; float $currContactPos[3]; int $sparkNum=30; float $magVelocity; float $minVelocity=0.8 ; $magVelocity=mag (<<activeRigidBody.velocityX, activeRigidBody.velocityY, activeRigidBody.velocityZ >>) ; if (( activeRigidBody. contactCount>0 ) && ($magVelocity>$minVelocity)) for ($i=0; $i< activeRigidBody.contactCount; $i++){ $currContactPos=’getAttr activeRigidBody.contactPosition[$i]’ ; $hue=rand(l); $sparkColor=hsv_to_rgb{ << $hue, 1, 1 >> ); for (Sj=0; $j< $sparkNum; $j++) emit -o sparkParticles -position ($currContactPos[0]) ($currContactPos [l]) ($currContactPos [2]) -attribute rgbPP -vectorValue ($sparkColor.x) ($sparkColor.y) ($sparkColor.z); }; Собственно, нового добавилось немного. С помощью функции mag вычисляем скалярную величину скорости активного твердого тела ($magVelocity) и сравниваем получившееся значение с «пороговым» значением скорости $minVelocity, которое в нашему примере принимается равным 0.8. И...все! (Файл emit03d.mb) .............................................................................................................................................................................


Команда EMIT ............................................................................................................................................................................. Проиграем получившуюся анимацию. Кубик скачет по плоскости, во все стороны летят брызги, которые пропадают с остановкой куба - все заявленные эффекты налицо, причем никаких дополнительных объектов в сцене нет.

Вот, собственно, и все. Надеемся, что команда emit окажется полезным дополнением к широкому арсеналу ваших собственных методов, технологий и приемов, и ваш «словарный запас» стал на однодва слова богаче.

............................................................................................................................................................................. Забелин Владимир


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

Автор: Король Геннадий

UV маппинг вместе с Unfold UV’s

Общаясь на форумах, следя за вопросами людей, я заметил что многие пользователи Maya обратили недостаточно внимания на нововведение 7-ои версии Maya - Unfold Tool. Действительно, на первый взгляд этот инструмент может показаться сырым и мало полезным возможно, поэтому многие пользователи после 5 минут знакомства с ним обычно возвращаются к использованию своих любимых скриптов или чего хуже - стандартных инструментов. Ввиду того, как такой мощный инструмент был незамечен пользовательской общественностью, я решил написать эту статью. В ней мы попытаемся проанализировать основные принципы работы с этим инструментом, и на конкретных примерах рассмотрим его использование вместе с другими инструментами UV маппинга в Maya. Итак, начнем!

............................................................................................................................................................................. Король Геннадий


.............................................................................................................................................................................

Готовимся к работе Прежде всего нам нужно каким-то образом проверять растяжки текстуры на 3D модели. Я обычно использую 2 текстуры, или более точно - материала. Один из них классический “шахматный” узор. Он позволяет относительно быстро выявлять места растяжек на развертке прямо в окне проекции. Второй материал - Blinn с созданной в Photoshop черно-белой пятнистой текстурой на bump канале. С его помощью можно как на рендере, так и в окне проэкции немного подругому оценить качество маппинга. А именно отловить мелкие растяжки, которые смотрятся сносно на “шахматной” текстуре, но могут сильно подпортить качество Bump текстуры, не говоря уже об использовании микро displacement. . Для создания шахматного “узора” я использовал встроенную в Maya процедурную текстуру Checker. Поначалу я пытался пользоватся процедурной текстурой именно для цветового канала “шахматного” материала, но, к сожалению, процедурный Checker часто имеет проблемы с отображением в окне проэкции. Текстура “замыливается” и/или теряет равномерность. Особенно это происходит при относительно высоких значениях Repeat UV у texture placement ноды текстуры. Поэтому вместо процедурной текстуры я настоятельно советую использовать растровые (File texture) изображения. Как только вы подобрали приятный для глаза цвет “шахматного узора” (желательно с низким контрастом - важно уменьшить напряжение для глаз), процедурный Checker можно “забэйкать” в растровую текстуру. Для этого выделяем геометрию вместе с ее shader’OM и в Hypershade выполняем Edit -> Convert To File Texture(Maya Software). В опциях желательно установить Antialias-ing, и разрешение выходной текстуры повыше - хотябы 512x512. Формат выходного изображения лучше использовать без сжатия, я обычно использую BMP. Остальные опции можно оставить как на рисунке; далее жмем Convert. Maya автоматически создаст новый shader со сконвертированной текстурой на канале цвета и назначит его объекту.

Теперь можно увеличивать Repeat UV у растровой текстуры, тем самым уменьшая размер “шахматных” клеточек, не имея никаких проблем с отображением в окне 3d вида. Полученную текстуру можно сохранить в любимой папке для дальнейшего использования вместе с UV текстурированием. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

Вторая - “пятнистая”, малоконтрастная текстура для Bump канала второго материала Делается относительно просто. В Photoshop начните с нового файла, желательно высокого разрешения (например, 1280*1280), некачественность текстуры может помешать объективной оценке качества UV развертки. Для начала “зальем”(Paint Bucket Tool, Normal mode, opacity 100%) текстуру 50% серым цветом. Затем сверху “заливаем” еще paз(Paint Bucket Tool), но в этот раз более темным цветом, в режиме Dissolve, прозрачность подбираем по вкусу. Хорошую “пятнистость” дают значения в интервале 9-13%. Я так же сделал красно-черную версию этой текстуры с Увеличенным контрастом для color канала материала. Это добавит контраст Bump карте во время рендеринга и также позволит использовать эту текстуру в окне проекции.

Одна из особенносей Maya, которая может изрядно мешать при оценке качества развертки, - это wireframe, который по умолчанию рисуется на выделенных/ подсвеченых(hilited) объектах. К счастью, в Maya есть возможность его отключить: Settings/ references -> Preferences -> Display --> WireFrame on Shaded - none. Так как выключать/ включать wireframe во время работы приходится довольно часто, неэффективно каждый раз окрывать окно опций и выставлять нужные значения. Поэтому и в этой статье не ошлось без маленького MEL скрипта, позволяющего переключать режим рисования wire-frame с none на full (выключать/включать), и наоборот: ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. string $CurVal = ‘displaypref -q -wsa’; if ($CurVal = “none”) displayPref -wsa “full”; else if ($CurVal = “full”) displayPref -wsa “none”; Для удобства я назначил этот скрипт на горячую клавишу alt+4. Теперь, после базовой настройки рабочей среды, приступим к самому процесс текстурирования.

Текстурим простейший объект

Для ознакомления с базовыми принципами работы с Unfold UV попробуем помощью развернуть простейший объект - бублик (по научному - торус). В чистой сцене создадим примитив Create --> Polygon Primitives --> Torus. По умолчанию Maya генерирует текстурные координаты для примитивов. Для чистоты эксперимента уберём автогенерацию координат для нашего бублика. Зайдём в опции polyTorus ноды в АЕ (Attribute Editor) и снимем галочку Texture в настройках Poly Texture History. Первое, с чем нам нужно определиться, - это расположение текстурных швов на будущей модели. Так как на нашей модели пока нет никаких UV координат, начнём с применения простейшей планарной проекции (Planar Mapping) по оси Y сверху на модель Polygon UV -> Planar Mapping, ставим ось (Mapping Direction) в Y Axis и нажимаем Proiect. Цель этого начального мапинга - обеспечить цельность UV текстуры, то есть полное отсутствие швов на развёртке, так как мы определим их вручную. Для определения разрезов/швов я выбрал внутренний продольный edge loop и один поперечный. Теперь с помощью этих выделенных рёбер “разрежем” развёртку: Polygon UV - Cut UV’s или в UV texture editor: Polygons --> Cut UV’s.

Швы определены, и все готово к использованию Unfold UV. Открываем Polygons (Poly-gon UV) --> Unfold UV’s Options. Для начала воспользуемся настройками по умолчанию: В окне инструмента выбираем Edit -> Reset Settings. Закладка Global Consistency непосредственно влияет на конечную форму развёртки, и о ней в деталях мы поговорим немного позже. Для начала выставим значение Solver Weighting в 0.0. Таким образом, мы дадим инструменту немного “развернуть” нашу текущую развёртку, которая очень неравномерна и имеет кучу перекрывающихся (overlapping) UV. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

Одной из самых полезных опций Unfold UV’s инструмента является возможность “пригвоздить” выделенные UV и производить развёртку вокруг них. Ставим галочку Pin Selected в настройках инструмента. Pin UV Border пока оставим выключенной. Теперь выберем UV вокруг которых мы бы хотели произвести “разворачивание” маппинга. На этом этапе важно выбрать те области развёртки, которые имеют относительно правильные пропорции. так как текстура накладывалась пленарной проекцией сверху, перпендикулярные к оси проекции области модели имеют наиболее правильные пропорции. Я выбрал 3 вершинки (2 фактических ребра) сверху модели на противоположной части шва (смотрите картинку), то есть в центре будущей развёртки. Будьте осторожны, чтобы не выделить UV на нижней стороне модели. В окошке Unfold UV жмём долгожданный Apply.

Результат далёк от совершенства, но обратите внимание: теперь мы имеем дело с относительно равномерной развёрткой без перекрывающихся текстурных координат (overlapping UV’s), выровнять которую не составит большого труда. Далее я выделил 2 центральных вершинки на левом и правом швах, немного растянул их в стороны scale инструментом и подвинул вверх, ближе к общему центру развёртки. В окне Unfold UV снова жмём Apply. Развёртка станет ровнее, но Unfold пока что не учитывает длины рёбер во время вычислений. Отменяем последний Unfold и увеличиваем Solver Weighting. Особенных рекомендаций для этого значения нет. Я обычно начинаю с более низкого значения и увеличиваю его по мере необходимости. По большому счету эта часть работы с Unfold UV напоминает игру с настройками. Мы изменяем их немного, смотрим на результат, изменяем ещё немного, и так далее до достижения желаемых результатов. Значения ползунка Face Area определяют отношение степеней влияния площадей полигонов и длин рёбер на форму результирующей развёртки. Значения, близкие к 0, означают больший вес к площадям полигонов, тогда как значения, близкие к 1, дают больший вес длинам рёбер. Как и в случае с Solver Weighting атрибутом, сложно давать определённые рекомендации по использованию тех или иных значений для этого параметра. Я обычно ............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. начинаю со значения 0.5 и увеличиваю/уменьшаю его в зависимости от того, что лучше работает в конкретном случае. Для нашего торуса я остановился на использовании Solver Weighting - 0.31 и FaceArea-Edge Length - 0.71.

На данном этапе нужно выровнять боковые ряды UV точек, так как эти ряды принадлежат к одному и тому же edge loop’y. Выравнивать можно несколькими способами В идеале очень важно сохранить созданные Unfold UV длины UV рёбер, чтобы использовать эти ряды как основу для последующих unfold’ов. При использовании стандартных scale tool или align to min/max в UV Texture editor, UV просто выстроятся в ровную линию, и вся драгоценная информация о правильных пропорциях потеряется. В данном случае это не столь важно, так как торус имеет равномерную топологию. В общем, для таких целей желательно использовать Straighten UV Border tool, и в этом мы убедимся во время развёртки модели головы. Выравниваем боковые (левый и правый) крайние ряды точек относительно их минимума/максимума и используем их как опору для следующего unfold’a. В этот раз наиболее ровный результат дали очень близкие к 1 значение Solver Weighting: 0.99, и низкие значения FaceArea: - 0.2.

Теперь выровняем верхний и нижний крайние ряды точек. Тут важно выравнивать их относительно максимума/минимума боковых рядов, иначе можно растянуть края боковых рядов, “испортив” развёртку в этих местах. То есть верхний ряд выравнивается относительно своего минимума (самой нижней UV), нижний ряд - относительно своего максимума (самой высокой UV). Теперь ещё раз применим Unfold, только на этот раз вместо использования Pin Selected воспользуемся Pin UV Border, так как теперь мы хотим использовать все границы развёртки в качестве опоры. Для воздействия на всю модель можно либо выделить все UV модели, либо выделить одно ребро и применить инструмент, что во многих случаях более удобно. На этот раз хорошо подошли средние значения Solver Weighting и Face Area: - 0.5 для обоих. Если развёртка получилась грубоватой в некоторых местах, можно воспользоваться Relax UV и разгладить ее, используя UV Border как опору. Я заметил, что количество итераций Relax UV не просто влияет на скорость разглаживания, но и даёт разные результаты. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s ............................................................................................................................................................................. То есть двойное применение Relax с од��ой итерацией даст результат, отличный от одноразового применения с двумя итерациями. С релаксом главное - не переборщить, так как его алгоритм намного “слабее” Unfold’овского и может очень быстро свести на нет большинство проделанной работы. Я обычно применяю релакс с одной итерацией несколько раз до достижения оптимальных результатов.

Полученный результат можно продолжать улучшать - можно, например, выровнять область рядом с поперечным швом. Надеюсь, на данном этапе вам понятен сам принцип работы с инструментом и его возможности. Нам за довольно короткое время и достаточно просто удалось развернуть объект замысловатой формы, при этом большая часть рабочего процесса свелась к игре с настройками инструмента. Инструмент работал за нас, что не В может не радовать. Теперь, когда мы разобрались с основами, перейдём к более сложному примеру - развёртке человеческой головы.

“Разворачиваем модель головы”

В этой части урока нам предстоит маппинг вот такой вот модели головы. За модель отдельное спасибо моему другу Thomas Mahler. Эта модель была выбрана за сложные формы, обилие морщин и большой нос “картошкой”, традиционно представляющий сложности для качественного текстурирования.

............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Сначала разделим модель на отдельные объекты для мапинга. Хоть Mava и предоставляет возможность работать с развёрткой одного объекта, состоящего из нескольких UV кусков (shells), нет возможности ограничить воздействие многих инструментов на конкретный шелл. Таким образом, если мы не хотим, чтобы Unfold UV или Relax UV воздействовали на мапинг уха во время работы с лицом персонажа, нам придется каждый раз выделять области, на которые мы не хотим воздействовать, и использовать Pin Unselected для Relax UV. Подобная задача ещё больше усложняется при использовании Unfold UV инструмента. Поэтому я предпочитаю разрезать модель на отдельные объекты мапить каждый по отдельности, а затем объединять все в цельную модель. Таким образом, можно избежать многих неприятных ошибок вроде изменения мапинга уха при настройке носа и так далее. Для начала отделим уши от основной модели головы. Можно выделить нужные полигоны на ухе и воспользоваться Edit Polygons —> Extract с включённой опцией Separate Extracted Faces. Но во многих случаях гораздо удобнее резать модель по шву, заданному конкретными рёбрами. Для данной цели я использую скрипт “SplitEdge 2.0”. (Скрипт можно бесплатно скачать с бесценного сайта www. highend3d.com) Скрипт разрезает геометрию по выделенным рёбрам, после чего нам только остаётся применить Polygons --> Separate, чтобы разделить модель на отдельные куски (shells). При выборе шва желательно взять наименее заметную связку рёбер, при этом позволяющую наиболее просто произвести развёртку для отдельных кусков. Итак, выделяем ребра, определяющие будущий шов на текстуре, разрезаем их с помощью SplitEdge. Разделить модель можно с помощью Polygons --> Separate.

В принципе, уши можно было бы затекстурить слитно с головой, сильно уменьшая масштаб их развёртки относительно лица. Такой мапинг проще и подходит в случаях, когда на уши планируется поместить минимум текстурной информации, в основном цветовой. Такой подход может также весьма сносно сработать при использовании всевозможных SSS фейков, основанных на текстурных координатах. В этом уроке мы выполним более качественную отдельную развёртку для ушей. Как и в случае с развёрткой торуса, для начала нужно дать базовый бесшовный маппинг и определить на нем швы. Можно пойти этим путём, сделав планарную проекцию в профиль, затем разрезав развёртку в местах будущих швов. Но в случае со сложной формой, такой как модель головы, желательно как можно более точно сохранить пропорции будущих краёв развёртки (губы и глаза) и пропорции самой сетки. Чем меньше сильных искажений будет перед использованием Unfold UV’s, тем качественнее получится финальная развёртка. В нашем случае наиболее оптимальный вариант даёт цилиндрическая проекция. С одной стороны, она даст наиболее равномерный результат, с другой - автоматически определит нужные нам в данном случае швы. Итак, применим Polygon UV’s --> Cylindrical Mapping. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

В моем случае проекция добавила мне ненужные швы чуть выше лба. Исправим это, выделив ребра лишнего шва и выполнив Polygons - Move and Sew UV’s. Затем выделим два дополнительных ребра и сделаем Polygons - Cut UV’s -таким образом немного удлинним оригинальный шов по направлению к лицу.

Практически все швы обозначены, остался только шов, идущий от низа подбородка к шее. Выделим соответственные ребра и снова выполним Polygons - Cut UV’s.

............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Швы обозначены, все готово к применению Unfold UV’s. Нужно быть осторожными во время этой операции, чтобы сохранить основные пропорции глаз и рта. Я выделил вертикальный ряд UV в центре от начала лобового шва и до начала шва подбородка. Для того чтобы “закрепить” области глаз и рта, я добавил к выделению их края развёртки При выделении этих мест очень полезной может оказаться команда “То Shell Border” доступная в marking menu по Ctrl + клик правой кнопки мыши в UV Texture Editor. Она позволяет выделять края UV кусков (shells) компоненты которых выделены в данный момент. После этого можно быстро рамкой исключить ненужные края из выделения. Также очень пригождается возможность сохранять текущее выделение в Quick Select Set (Create --> Sets -:> Quick Select Set..). Чтобы вызвать его, можно либо ввести его имя в окошке находящимся рядом с кнопками Render View и IPR на панели Status Line, либо выделить его в Outlinear и в меню по правой кнопке выбрать Select Set Members. Для начала я применил Unfold UV с Solver Weighting - 0, используя эти выделенные области как опору. Далее можно попробовать увеличивать это значение для Достижения более равномерных результатов. В моем случае увеличение Solver Weighting не дало существенных улучшений, а при высоких значениях только добавило искажений. Также можно попробовать раздвинуть краевые UV глаз в стороны, таким образом дав Unfold больше места для развёртки области носа.

Совсем не плохо для 5 минут работы, не так ли? На данном этапе у нас есть несколько очевидных проблем: неравномерность масштаба текстуры в районе шеи, небольшая неравномерность в области глаз, и сильные растяжки на носу. И если с первыми двумя проблемами легко справится, выделяя разные области развёртки и играя с параметрами Solver Weighting, то растяжки на носу исправить не удастся. Дело в том, что наш персонаж имеет очень крупный нос “картошкой”, и на текущей развёртке Unfold’y попросту негде “развернутся”. Как и в случае с торусом надо дать инструменту сделать правильные пропорции. Для начала внесём равномерность в области шеи и глаз. Я выделил ювшки лица и использовал их как опору для Unfold UV. Выделенные ЮВ можно отмасштабировать чтоб более точно подогнать масштаб перед применением Unfold’a. В моем случае подошли высокие значения Solver Weighting - 0.8 и средние значения Face Area/Edge Length - 0.6. Теперь чтобы внести общую равномерность в развёртку можно применить Unfold с низкими значениями Solver Weighting - 0.1, использовав Pin UV Border вместо Pin Seleted. Так как форма шва ушей нам не особо важна, можно не использовать его как опору. Для этого можно выделить все края развёртки с помощью Convert To Shell Border, а затем убрать ювшки швов ушей из выделения. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

Кроме небольших растяжек в области швов ушей и носа с такой развёрткой уже можно работать. Если персонаж второстепенный, или на текстуру носа не планируется поместив много детальной информации то на данном этапе можно и остановиться. Растяжки пор кожи можно исправить на самой текстуре. А при использовании программ как ZBrush, Body Paint, или даже родного Artisian, можно без проблем использовать подобную развёртку. Чтобы проверить насколько ужасные растяжки у нас на носу можно воспользоваться заготовленной пятнистой текстурой. Но мы в данном уроке предположим что развёртка нужна высокого качества и попробуем исправить существующие проблемы. Так же это поможет нам освоить несколько важных приёмов при работе с Unfold UV’s. Чтобы дать больше места для развёртки носа, избавимся от левой половины модели Выделим все левые грани и нажмём delete. Теперь развернём модель, используя края рта и несколько прилежащих к ним точек и края глаза как опору. В этом случае хорошо сработали высокие значения Solver Weighting = 0.9 и средние значения FaceArea/ EdgeLength = 0.51. Полученную развёртку можно немного подровнять знакомым приемом Unfold UV’s с низким Solver Weight, используя основные края развёртки в качестве опоры.

............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. Теперь, после того как Unfold UV’s посчитал правильные длины текстурных рёбер на центральном шве, нужно выровнять этот шов по вертикальной оси. Ни в коем случае нельзя делать это при помощи стандартных scale или align to max/min инструментов Иначе вся ценная информация о длинах рёбер, из-за чего, собственно говоря, весь сыр-бор, потеряется. К счастью в Maya существует замечательный инструмент - Straighten UV Border, позволяющий выравнивать края развёртки, сохраняя относительные длины между рёбрами. Выделим UV, принадлежащему центральному шву модели и применим Polygons —> Straighten UV Border. Обязательно ставим Curvature в 0, что обеспечит нам выравнивание под ровную линию, Preserve Length Ration в 1 - именно этот параметр отвечает за сохранение длин рёбер при выравнивании. Blend Original Shape позволяет на подобие blend shap’a морфировать выровненные края в их форму до выравнивания. Этот параметр поставим на 0, так как мы не хотим ни малейшего воздействия от предыдущей формы на выровненный край.

Теперь осталось только выровнять эти края вдоль вертикальной оси. Удобнее] всего сделать это при помощи rotate UV’s инструмента, выбрав одну из крайних точек как опору.

.............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s ............................................................................................................................................................................. Данный ряд точек послужит центром развёртки. Я выделил ряд крайних точек рта и придвинул их ближе ко шву, так как рот будет одной из опор при использовании Unfold. Пока не стоит обращать внимание на сильные искажения текстуры по центру - Unfold обо всем позаботится. Вернём левую половинку модели: Polygons - Mirror Geometry. Осталось также зеркально отобразить и развёртку головы. Чтобы выбрать все UV, принадлежащие к левой части модели, можно выделить одну UV на левой стороне и по Ctrl правой кнопке --> То Shell. Теперь нужно точно отмасштабировать эти UV относительно центра развёртки. Перейдём в инструмент scale UV’s, зажав клавишу d, перенесём точку опоры на одно из левых краевых рёбер развёртки. Выполним приблизительное масштабирование и отменим его (ctri-z). Теперь откроем Script Editor и скопируем отменённую команду из окна History. В моем случае это была команда: polyEditOV -pu 0.481473

-pv 0.534273

-su -0.999223 -sv 1;

Теперь просто изменим флаг -su (Scale U) на -1, выполним команду.

Таким образом, можно выполнять точные трансформации без манипуляторов. Все, что теперь остаётся - это выделить вертикальный ряд рёбер в центре модели и сшить их: Polygons --> Sew UV’s. Пришло время для последних штрихов. В качестве опоры я использовал краевые точки рта, глаз и 6 точек в центре на проблемном месте - носу. Подошли высокие значения Solver Weighting - 0.9 и средние Face Area/Edge Length -0.5. После этого я применил “расслабляющий” Unfold, с 0.3 Solver Weighting и Face Area/Edge Length без изменений.

............................................................................................................................................................................. Король Геннадий


............................................................................................................................................................................. В моем случае в районе ноздрей и швов перекрывались UV. Эти проблемы спокойно решились выделением перекрывающихся областей и применением RelaxUV с одной итерацией несколько раз.

Теперь займёмся развёрткой ушей персонажа. Начнём с Планерной проекции по оси X. Плоскость проекции можно немного развернуть, чтобы как можно точнее выровнять её относительно плоскости модели уха. Теперь выделяем основные части модели с наиболее удачными пропорциями и используем их как опору для развёртки. На этих этапах, как обычно, хорошо подошли высокие значения SolverWeighting - 0.9 и средние значения Face Area/Edge Length.

На этом этапе важно дать инструментам, чтобы развернуть перекрывающиеся UV внешних и внутренних частей уха. В моем случае также образовались перекрытия в районе ушного отверстия. В этот раз можно просто вручную отмасштабировать краевые точки ушного отверстия и придвинуть их поближе к центру развертки, дав инструменту больше Места. Следующий Unfold должен устранить все перекрытия. Ну, и напоследок, я выделил точки развертки в центре ушной раковины и произвел Unfold вокруг них. Затем, как всегда, “расслабляющий” проход для усиления общей равномерности. Также не забываем про старый добрый Relax UV’s, который иногда помогает выровнять несколько резкие формы, созданные Unfold UV’s. .............................................................................................................................................................................


UV маппинг вместе с Unfold UV’s .............................................................................................................................................................................

Теперь копируем модель уха, отображаем её по оси X Соединяем с моделью головы и сшиваем краевые ребра. Обязательно выключаем опцию Texture, чтобы инструмент не шил также и текстурные координаты.

Ну, вот и все! Существующую развёртку можно продолжать улучшать Можно воспользоваться новым Lattice инструментом и растянуть область носа для более равномерного масштаба текстуры. Дальше применим Unfold для наведения общего порядка на развёртке. Надеюсь, после прочтения этого урока инструмент Unfold UV пополнит ваш арсенал инструментов для качественного UV маппинга за весьма короткое время. Спасибо за внимание, удачи! ............................................................................................................................................................................. Король Геннадий


“Обьемные” спрайты в Maya .............................................................................................................................................................................

Автор: Забелин Владимир

“Объемные” спрайты в Maya Когда речь идет об анимации или визуализации большого числа объектов, существенную помощь в решении такого класса задач могут оказать частицы. Во-первых, управление поведением частиц практически не зависит от их числа - поля и экспрешены одинаково хорошо управляются и с сотнями и с десятками тысяч частиц. Во-вторых, при работе с частицами естественным образом сочетаются законы порядка и хаоса, что идеально подходит для создания разного рода толп, потоков, лесных массивов и так далее... Технология инстансирования (то есть замещения частиц трехмерными объектами) и визуализация частиц в виде спрайтов выглядит весьма привлекательным средством для решения подобного рода задач. Инстансирование позволяет на место каждой частицы поместить трехмерный объект. Эта технология упрощает анимацию большого числа объектов, но тем не менее достаточно дорога в вычислительном плане, ведь в результате инстансирования возникает огромное число реальных объектов, справиться с которыми на рендере не всегда удается. Есть и ряд других ограничений, но о них мы говорить не будем.

............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

“Объемные” спрайты в Maya Автор: Забелин Владимир

Вступление Спрайт - это просто двумерная картинка, которой замещается частица, с одной очень важной особенностью : она всегда повернута «лицом» к камере, иными словами нормаль картинки всегда нацелена на камеру. Спрайты не требуют создания геометрии, что означает чрезвычайную экономию памяти в сценах с использованием спрайтов. Более того, для визуализации спрайтов используется хардверный рендер, то есть возможности видеокарты, а центральный процессор оказывается загруженным лишь задачей вычисления местоположения и некоторых других атрибутов порождающих спрайты частиц.

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

Задача 1. Неподвижные объекты и движущаяся камера Итак, приступим. Создадим лесной массив и прогуляемся по нему камерой. Для решения поставленной задачи нам .во-первых, понадобятся изображения дерева с разных ракурсов, которые мы будем использовать в качестве последовательности спрайтов, и во вторых мы должны будем правильно определить правило использования номера картинки в зависимости от взаимного расположения каждого конкретного спрайта и камеры. Создадим в Maya трехмерный объект - дерево, например такое, или воспользуемся одной из готовых м��делей. .............................................................................................................................................................................


“Обьемные” спрайты в Maya .............................................................................................................................................................................

Далее нам нужно сделать панорамные снимки нашего дерева под разными углами. Замечание. Неискушенный пользователь может обнаружить -большую красную кнопку» - Sprite Wizard - с помощью которой легко задать наиболее распространенные способы использования спрайтов - в частности, будет ли использоваться последовательность или одна картинка, задать начальный номер спрайта для каждой последовательности и так далее... В сущности, с помощью Sprite Wizard ‘а генерируются большие creation и run-time экспрешены, так сказать, на все случаи жизни. Но нас будут интересовать задачи, выходящие за рамки стандартных, поэтому мы откажемся от использования Sprite Wizard а и будем работать со спрайтами напрямую. Итак, создадим камеру - camera1, с помощью которой мы отрендерим необходимые в дальнейшем спрайты. Существенным моментом будет задание нашей камере значения Film Aspect Ratio равного 1, для создания квадратных картинок.

Позиционируем камеру фронтально по отношению к нашему дереву, передвинем pivot камеры в начало координат (а именно начало координат представляет визуальный центр его дерева) и проанимируем вращение камеры вокруг вертикальной оси сделав полный круг вокруг нашего объекта (поворот на 360 градусов по оси Y), скажем, за 180 кадров. ............................................................................................................................................................................. Забелин Владимир


.............................................................................................................................................................................

frame-0

frame-45

frame-90

frame-135

Отрендерив анимацию мы получим 180 «фотографий» нашего дерева с шагом поворота камеры в 2 градуса. Замечание. Отметим, что в нашей ситуации нужно именно поворачивать камеру вокруг объекта, таким образом на полученных нами «фотографиях» будет правильное распределение теней, соответствующее динамической камере и неподвижному объекту, а не наоборот. Замечание. Документация настоятельно рекомендует использовать для последовательности спрайтов нотификацию вида nате.#, поэтому не будем рисковать и соответствующим образом зададим атрибуты в Common Tab панели Render Glo bals: File Name prefix - tree Frame/Animation Ext - name.# Start Frame - 0 End Frame - 179 Width - 256 Height -256

На этом подготовительную часть работы можно считать законченной и теперь мы можем перейти к решению содержательной части задачи, а именно созданию собственно трехмерной сцены. Итак, создадим новую сцену и в ней с помощью команды: particle -11 -30 0 -30 -ur 30 0 30 -grs 3 -с 1

;

массив частиц 21x21 с расстоянием между частицами в 3 единицы. По умолчанию созданная система частиц получит имя particle1. Откроем attribute editor для particle1 и зададим тип визуализации частиц Sprites. Добавим атрибуты, сспецифические для этого типа .............................................................................................................................................................................


............................................................................................................................................................................. визуализации (Add Attribute For Current Render Type). Увеличим значения атрибутов Sprite Scale X и Sprite Scale Y до З. Пометим атрибут Depth Sort.

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

Создаем новый материал lambert (по умолчанию он получит имя lambert2, так как материал lambert1 по умолчанию присутствует в любой сцене). На color, transparency и incadenscence «навешиваем» файловую текстуру - созданную нами последовательность картинок исходного дерева

Забелин Владимир

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. После выбора имени файла (а это будет tree.0) в ноде file1 не забудем отметить атрибут Use Image Sequence и Use Interactive Sequence Caching. Имеет смысл заменить стандартный экспрешен, ассоциируемый с атрибутом Image Number, на пару ключей (time=0 -> imageNumber=0) и (time=179-> imageNumber=179) - это поможет избежать неприятного сообщения, о том что Maya не может найти текстуру с номером больше 179.

В разделе Interactive Sequence Caching Options зададим 0 для Sequence Start и 179 для Sequence End. Присвоив созданный материал нашим спрайтам, мы наконец увидим нечто, похожее на лес:

.............................................................................................................................................................................


“Обьемные” спрайты в Maya ............................................................................................................................................................................. камеры. Этот алгоритм, естественно будет зависеть от камеры и должен быть per-particle алгоритмом (взаимное расположение частиц и камеры естественно различно для разных частиц). Создадим камеру - скорее всего по умолчанию она получит имя camera1. Добавим к particleShape1 Три дополнительных атрибута camX, camY и camZ типа float и передадим на них translateтрибуты вновь созданной камеры - теперь наши частицы легко смогут получать информацию о том, где находиться камера: addAtr -In addAtr -In addAtr -In connectAtr connectAtr connectAtr

camX camY camZ -f -f -f

-keyable -keyable -keyable cameral.tx cameral.ty cameral.tz

true -at double Iparticlell particleShapel; true -at double Iparticlell particleShapel; true -at double Iparticlell particleShapel; particleShapel.camX; particleShapel.camY; particleShapel.camZ;

Добавим нашей системе частиц per-particle атрибут spriteNumPP - именно он будет определять номер кадра текстуры, который будет показываться каждым спрайтом (в атрибут эдиторе для particleShapel в закладке Add Dynamic Attribute выбираем General, далее в открывшемся окне в закладке Particle ищем spriteNumPP).

Run-time expression для номера используемого частицей спрайта не сложен и основывается на велечине угла между направлениями оси Z и проекцией вектора, соединяющего местоположение частицы и камеры на плоскость XY. Собственно, это целая часть от половины такого угла, измеренного в градусах.

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. В конечном виде сам runtime expression выглядит следующим образом: float $pos [] =position; vector $axis,$vect; $axis=<<0,0,1>> ; $vect=<< ($pos [0] - camX) ,0, ($pos[2]-camZ)>>; float $angle; $angle=rad_to_deg(angle($axis,$vect)); if ($vect.x<0) $angle=360-$angle; spriteNumPP=floor ($angle/2 .) +1; Комментарии. Вектор $axis - направление оси 2. Вектор $vect - это пресловутая проекция вектора, соединяющего местоположение частицы и камеры на плоскость XZ. Для определения угла используется функция angle (следует помнить, что, во-первых, функция angle возвращает значение угла в радианах, а не в градусах, и во-вторых, angle возвращает минимальный из двух возможных углов между векторами). Нумерация спрайтов всегда начинается с 1, независимо от нумерации используемых файлов, поэтому в последней строке после вычисления целой части к результату прибавляется единица. Чтобы не было сбоев в поведении нашего «леса» в первом кадре не забудем копию написанного выше выражения присвоить нашим частицам и в качестве creation expression. Теперь можно «побродить» камерой по получившемуся «лесу», наслаждаясь полученным результатом.

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

1. Добавим нашей системе частиц per-particle атрибут цвета - rgbPP. 2. Определим значение этого атрибута с помощью creation expression, например: rgbPP=<<rand(l) ,

3.

rand(l) ,

rand(l)>>;

Поварьируем значения атрибутов Color Gain и Color Offset файловой ноды текстуры наших спрайтов.

.............................................................................................................................................................................


“Обьемные” спрайты в Maya .............................................................................................................................................................................

Результат покажется несколько неожиданным, но по зрелому размышлению вполне закономерным: индивидуальный цвет частиц rgbPP смешивается с цветом текстуры в пропорциях, задаваемых значениями атрибутов Color Gain и Color Offset:

Таким образом, деревья в лесу приобрели индивидуальность. Остается лиш заметить, что значение индивидуального цвета частиц rgbPP может быть связано, например, с расстоянием до камеры, что позволит создать эффект воздушной перспективы, атмосферы, тумана и так далее. Задача 2. Неподвижная камера и движущиеся объекты. Описанную выше технологию можно применить и к созданию большого числа движущихся объектов - колонна войск, стадо бегущих животных, толпы людей и так далее. Однако нужно иметь ввиду два существенных отличия: во-первых, чтобы получить правдивый по освещенности результат, при «изготовлении» текстур спрайта придется вращать сам объект, а не камеру вокруг объекта; во-вторых, при каждом угле поворота объекта по отношению к камере необходимо будет отрендерить не одну картинку, а весь цикл анимации, то есть количество текстурных файлов, необходимых для создания толны анимируемых объектов будет существенно больше, чем в предыдущем примере. Давайте создадим толпу шагающих циркулей:

............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. Естественно, нам понадобиться создать базовый объект (циркуль) и проанимировать его, создав цикл ходьбы. (Конечно, читатель вправе проявить все свои творческие способности и фантазию при создании и анимации базового объекта). В моем примере цикл ходьбы (один двойной шаг) циркуля составил 20 кадров по времени и 20 единиц сетки по пространству:

Замечу, что цикл ходьбы удобнее создавать в пространстве, а не на месте, так легче избежать возможного проскальзывания «ног» нашего циркуля при любом характере движения (нейтральная походка, хромота, бег вприпрыжку и так далее). Следующий шаг - преобразование движения в пространстве в бесконечный цикл ходьбы на месте. В зависимости от устройства персонажа на этом этапе могут возникнуть разные ньюансы, но общий принцип такой: группируем проанимированный объект и сдвигаем группу в направлении, противоположном движению. В нашем случае на перемещение группы с движущимся циркулем необходимо поставить 2 ключа : О в нулевом кадре и -20 в 20-м. Интерполяция между ключевыми кадрами - линейная. Забегая вперед замечу, что в дальнейшем, когда мы «наклеим» фазы движения циркуля как текстуру на равномерно движущийся спрайт, то «спрайтовый» циркуль так же будет «шагать» без проскальзывания. Задав анимционным кривым и нашего объекта и его группы соответсвующее поведение после последнего ключа (post infinity) cycle или cycle with offset легко получить бесконечный цикл на месте шагающего циркуля. Определим материалы нашему объекту, поставим свет, создадим камеру и расположим ее фронтально по отношению к нашему шагающему чуду по аналогии с предыдущим примером чтобы получить набор картинок - полный комплект фаз движения циркуля под различными углами к камере. Напомню, что в отличие от предыдущего примера поворачивать нужно шагающий на месте циркуль вокруг своей оси, а не камеру вокруг него. Ограничимся поворотом на 180 ( а не на 360 градусов) с шагом 2 градуса. При каждом угле поворота нам необходимо будет отрендерить полный набор фаз движения (20 картинок). Итого 90 позиций угла поворота (0, 2, 4,..., 178) да по 20 изображений на каждую позицию - нам предстоит создать 1800 картинок. Немало.... Естественно задать базовое имя последовательности что-нибудь типа circul, и использовать нумерацию наших картинок в формате circul.####, то есть cirul.0000-circul.0019 - это цикл движения нашего циркуля под углом к камере в 0 градусов, circul.0020 - curcul.0039 - тот же цикл но под углом в 2 градуса и так далее... .............................................................................................................................................................................


“Обьемные” спрайты в Maya .............................................................................................................................................................................

После того, как «титанический» труд по созданию необходимого набора спрайтов будет завершен, можно приступать к созданию самой сцены. «Толпу шагающих циркулей» можно создавать любым способом, но один из самых простых - создать поток частиц с помошью имеющейся в maya технологии surface flow - создание потока частиц вдоль поверхности. Итак, создадим NURBS-плоскость, подвигаем контрольные точки этой плоскости для придания поверхности s-образной формы и создадим поток частиц вдоль этой поверхности (в меню Dynamics выбираем Effects -> Create Surface Flow ). В результате у нас получиться такая сцена:

Далее проделаем ряд действий, аналогичных с теми, что мы выполнили в предыдущем примере, а именно: • Создадим камеру, из которой мы будем наблюдать за нашей «толпой циркулей». По умолчанию она получит имя camera1. Расположим ее желаемым образом (примерно горизонтально, чтобы наши спрайты выглядели естественно) • У shape’а наших частиц ( а по умолчанию это будет particleShape1) срздадим три дополнительных атрибута camX, camY, camZ типа float и свяжем с ними атрибуты tanslateX, translated, translateZ нашей камеры camera1. Теперь частицы «знают», где находиться камера. ............................................................................................................................................................................. Забелин Владимир


............................................................................................................................................................................. • Выберем тип визуализации частиц «sprites»? создадим материал типа lambert на основе заготовленной последовательности текстур circul.#### и присвоим этот материал спрайтовым частицам. • Добавим частицам предопределенный атрибут spriteNumPP. Теперь определим, какой именно номер спрайта должен использоваться каждой частицей. Выражение для spriteNumPP будет очень похоже на выражение из предыдущего примера, с учетом небольших отличий - номер высвечиваемого спрайта будет складываться из номера фазы цикла движения (на основе возраста частицы) и угла между вектором I скорости частицы и вектором, соединяющим местоположение частицы и камеры (поскольку | объекты имеют обыкновение двигаться «лицом» вперед, то определяющим должен быть 1 именно угол между скоростью частицы и направлением на камеру). В окончательном виде выражение для spriteNumPP выглядит так (заметим, что, как и прежде, это будет и runtime I expression и creation expression): float $vel [3]=velocity; float $angle; $angle=rad_to_deg(angle(<<$vel[0],0,$vel[2]>>,<<(camX-$pos[0]),0,(camZ-$pos[2])>>)); spriteNumPP=floor(20*(age*25./20.-floor(age*25/20)))+20*floor($angle/2)+l; Успешно выполнив вышеописанные действия и запустив проигрывание анимации мы, тем не менее, обнаружим как минимум два несоответствия полученного результата здравому смыслу (или как сейчас модно говорить два «бага»): во-первых, циркули парят на разной высоте над нашей поверхностью; и, во-вторых, скорость поступательного движения циркулей не соответствует длине шага, создается ощущения движения с проскальзывай ием. Можно, конечно, сделать вид, что это не «баги»,а «фичи», и завершить на этом работу со сценой, но лучше, конечно, эти несоответствия устранить. Исходная модель циркуля имела высоту 15 единиц и за 20 кадров «проходила» 20 единиц сетки. Значит соотношение скорости ( расстояние, который циркуль проходит за 1 секунду = 25 кадром) к его высоте равно (25/20*20)/15=5/3, то есть примерно 1.67. Спрайт со scaleX=scaleY=1 - это квадратная картинка размером в одно деление сетки, но, может оказаться, что собственно картинка циркуля занимает не всю область спрайта, поэтому при вычислении соотношение скорости движения спрайта к его размеру необходимо ввести поправку на величину Н - высоту содержательной части картинки циркуля к размеру спрайта (Например, в моем случае соотношение между скоростью движения спрайта и его размером составило 1.4):

.............................................................................................................................................................................


“Обьемные” спрайты в Maya ............................................................................................................................................................................. Далее. Скорость движения потока частиц (surface flow) задается , к сожалению, не напрямую, а опосредовано - через время ее жизни (lifespan). Именно за это время частица преодолевает путь от одного края поверхности до противоположного вдоль соответствующей изопармы. В нашем простом примере все изопармы поверхности имеют одинаковую длину, которую можно измерить с помощью инструмента Arc Length Tool. У меня результаты измерения составили чуть больше 60 единиц. Тогда, задав время жизни частиц равное 10 получаем для spriteScaleX=spriteScaleY= (расстояние)/(время жизни) (соотношение между скоростью и размером спрайта) = 60/10/1.4 = 4.3 Для поверхности с длиной пробега частиц около 60 ,со временем жизни частиц 10 и размером спрайта 4.3 ходьба циркулей должна получаться без проскальзывания. Так и происходит. (В ваших примерах эти числа естественно могут быть другими, но если вычисления проделаны аккуратно, то движение без проскальзывания вам гарантировано). Итак, для того чтобы наши циркули ходили без проскальзывания размер спрайта должен быть жестко связан со скоростью движения частиц, большие спрайты должны двигаться быстрее, маленькие - медленнее, можно разнообразить размер спрайтов (правда, придется соответствующим образом изменять и скорость движения частиц) например, вот так: • • •

у наших частиц установим значение атрибута lifespanMode в LifespanPP only; добавим частицам предопределенные атрибуты spriteScaleXPP и spriteScaleYPP; в creation expression добавим следующие строки:

float $length = 60; float $coeff =1.4; lifespanPP=rand(2,20); spriteXPP=spriteScaleYPP=$length/lifespanPP/$coeff; Мы уже почти закончили, остался лишь небольшой ньюанс. Наши разнообразные по размеру циркули замечательно шагают, но делают они это где угодно, но не по дороге. Чтобы вернуть их на дорогу ( которая лежит в плоскости OXZ) необходимо позаботиться о том чтобы Y координата наших спрайтов всегда имела значение spriteScalePP*(0.5 -h) (см. рис.) Этого легко добиться, добавив и к creation expression и к runtime after dynamics expression следующие строки (в моем случае величина «зазора» h получилась равной 0.05): float $h=0.05; float $position[3] = position; position = <<$position[0], spriteScaleXPP*(0.5 -$h),$position[2]>>; При желании спрайтам можно добавить вариации по цвету так же как мы это делали в предыдущем примере. Вот и все.

Заключение

Рассмотренная выше технология «объемных» спрайтов, конечно, не претендует на оригинальность, идея чрезвычайно проста и лежит на поверхности, однако, несмотря на ее простоту и даже очевидность имеет целый ряд преимуществ. Конечно, это в первую очередь скорость рендера, не зависящая от сложности базовой модели и позволяющая за секунды получать изображения с десятками и сотнями тысяч объектов. Есть, конечно, и довольно серьезные недостатки - в первую очередь это незаурядные проблемы с тенями, отражениями и взаимодействиями с остальными элементами сцены. Гиганское количество необходимых текстур, невозможность регулировать длину цикла ходьбы, сомнительный результат в случае крупных и сверхкрупных планов. Одно слово -спрайты - со всеми их достоинствами и недостатками. Но для общих планов альтернативы скорее всего нет. ............................................................................................................................................................................. Забелин Владимир


Autodesk Maya Masterclasses