Создание мускульного примитива
1. Введение
Здравствуйте. В этом уроке мне бы хотелось рассказать о создании мускульного примитива в XSI. Однако, позвольте начать с небольшого вступления.
Вот все говорят, дескать, XSI-XSI. Якобы это один из самых лучших пакетов для персонажной анимации. Ну и я так думал. И в один прекрасный солнечный день (это был четверг), решил: "А почему бы не заригить перса в XSI!" Думал я, конечно, по-другому, но суть в этом. Хотелось не просто взять стандартного Двуногого и прискинить его. Нет. Хотелось сделать риг как можно более комплексным, в том числе и с мышцами. Нетерпеливый читатель наверное уже весь извелся, так ему хочется узнать, что же произошло. А произошло следующее. Нет в XSI мышц. Вот так вот все просто. Нет, и все тут. В Максе есть (благодаря модулю CAT), в Майе есть (встроенные), а в лучшем пакете для персонажей - нет.
Предупрежу сразу. Не надо после прочтения этих строк бросать изучение XSI и переходить на Blender. Может быть имеет смысл поискать в глобальной компьютерной сети (сиречь тырнете) наработки других людей. Не может же быт так, чтобы вообще не было мышц. Наработки нашлись. И все они попадали под две категории. Первая - датировались 2004-2005-м годом и на современных версиях программы не работали. Вторая - на youtub-е и vimeo показывают видеоролики, как хорошо ведут себя их мышцы, но самого аддона или скриптика не дают.
Ну раз так, то надо просто сделать свои мышца самостоятельно. И я стал смотреть, а как же можно самому сделать мускулы. Да еще такие, чтобы они обладали как можно большим числом фишек (читай, поддерживали вторичные деформации и динамику). Разобравшись понял: совершенно правильно, что в XSI нет встроенных мышц. Они просто не нужны. Каждый сам с удовольствием их сделает себе такими, какими хочет. Настоящий урок как раз и описывает один из вариантов создания мускул.
Да, еще одно замечание, прежде чем мы перейдем к делу. Делать будем стандартными средствами XSI без использования ICE. Последнее время у многих людей (в том числе и ксишников) наблюдается тенденция отождествления самого пакета и его модуля ICE. Иногда считается, что если не использован ICE, то это не раскрыт весь потенциал пакета. Возможно так и есть, но мы будем решать маленькую локальную задачу, для которой не надо больших мощностей. Вполне будет достаточно стандартных expression-ов. Более того, тот метод, которым мы будем пользоваться, можно применить на версии любой XSI, начиная с 5-ой (возможно и еще раньше), и даже, проведя аналогии, реализовать в Максе или Майе. В конец концов есть еще две причины не использовать ICE:
- И это главная причина. Автор (то есть я) совсем не знает ICE. Вернее знает, но не ахти как. Впрочем, очень хочет выучить и использовать по мере надобности.
- ICE сам по себе, и ICE Kinematics в частности, чрезвычайно нестабильно работают. Это отмечают все, кому приходится использовать те или иные модули. Вроде бы все правильно, ан нет, ошибку выдает. Перезапустил программу - нет ошибки. Зачем нам такие сложности?
2. Постановка задачи
Давайте опишем, какими свойствами должен обладать мускульный примитив.
- Должна быть реализована возможность создания мышц разных размеров и форм. Или даже так: создали мышцу, а потом меняем ее внешний вид, а она при этом остается мышцей и сохраняет все свои параметры.
- Поддержка динамики двух видов. Мускульная динамика - реагирование на сжатие-растяжение с возможностью регулировать коэффициент сжатия. Динамика движения - инерционность тела мускула. Если резку выбросить ногу, руку или голову вперед, мускулы еще некоторое время колеблются. Вот это и есть динамика движения.
- Окно с параметрами, в котором мы могли бы включать или отключать те или иные функции, изменять параметры самого мускула и вообще, чувствовать себя Творцом.
Дополнительно хотелось бы отметить следующую возможность, которую мы также будем реализовывать. Это касается принципа создания самого примитива в целом. В XSI, как и во многих других редакторах, есть возможность писать скрипты. В частности можно скриптами создавать модели, редактировать их и вообще, чувствовать себя Творцом. Поэтому при создании нашего мускульного примитива мы будем записывать на бумажку все команды, которые используем. В дальнейшем можно будет повторить процесс создания мускула не по действиям, а просто набрав линейную последовательность команд и выполнив ее.
Итак, хватит введений и отступлений, пора работать.
3. Построение модели и первых зависимостей
Первым делом создаем два нуля (объект null является аналогом dummy в максе. Имеет самый минимум свойств). Как именно создаем - не важно, можно продублировать один, либо создать оба. Растаскиваем их немного в стороны (рис. 1). Это будут самые важные нули, по крайней мере на протяжении урока. Они будут соответствовать началу и концу мускульного примитива. Вообще, это будут единственные два элемента, которые определяю положение мускула в пространстве.
Рис. 1. Два нуля
Теперь открываем редактор скриптов. Сделать это можно, нажав на кнопку внизу окна программы (как правило). Открывается окно редактора скриптов, в котором я красным отметил те команды, которые создают наши первые два объекта (рис. 2). Эти команды мы должны все дружно переписать на бумажку. При переписывании обращайте особое внимание на число запятых. Их должно быть 9 или 10 и они должны быть разделены пробелами. Также стоит заметить, что с самого начала язык скриптов надо выставить на VBScript, хотя это и не принципиально. На разных языках команды выглядят немного по-разному.
Рис. 2. Окно Script Editor
Теперь давайте создадим модель. Для этого выделяем оба объекта, идем в Edit - Model - New Model (Рис. 3). Не забываем переписывать на бумажку соответствующую скриптовую команду. Здесь надо пояснить, что такое модель. С одной стороны модель - это ни что иное, как просто сгруппированные объекты. С другой стороны модель можно экспортировать, импортировать, дублировать (чувствовать себя Творцом), и все связи внутри модели будут сохраняться. Удобная вещь. Например, сделали одного персонажа или иголку, сохранили, как модель, а потом во все проекты, где персонаж шьет иголкой, вставляем сохраненную модель. И она уже будет настроена и работать так, как изначально задумывалось.
Рис. 3. Создание модели
Переименовываем модель (команду пишем на бумажку), клавишей 8 открываем окно Explorer (не Виндовского, конечно же, а XSI-шного). В нем отображается иерархия текущей сцены. Она содержит камеру, скрытый источник света (они нам не интересны) и нашу модель (рис. 4).
Рис. 4. Окно Explorer
Переименовываем два созданных нуля в модели на Start и End и меняем их тип на сферы. Для этого выделяем объекты, нажимаем Enter, в появившемся окне выбираем в меню Icon пункт Rings. Далее создаем еще три дополнительных нуля, которые равномерно (на глаз) расставляем посередине (рис. 5). Не забываем все команды записывать на бумажку! Поясним смысл трех промежуточных объектов. В самом общем виде мускул представляет собой сосиску, которая утолщается к центру и сужается к концам. Вот мы и создали пять позиций (начало, конец и три промежуточных), в которых мы будем определять толщину сосиски-мускула. К середине толщина будет самая большая, к концам - самая маленькая.
Рис. 5. Start, End и три нуля между ними
Добавляем промежуточные нули в модель и переименовываем их. Имена можно выбрать произвольные (например, Бравый или ТолькоВперед), но лучше назвать объекты StartCenter, Center и CenterEnd в соответствии с их предполагаемым местоположением. К настоящему времени вся наша исчирканная бумажка должна содержать следующие команды:
GetPrim "Null"
Duplicate "null", , 2, 1, 1, 0, 0, 1, 0, 1, , , , , , , , , , , 0
SelectObj "null", , True
Translate , -4, 0, 0, siAbsolute, siPivot, siObj, siX, , , , , , , , , , 0
SelectObj "null1", , True
Translate , 4, 0, 0, siAbsolute, siPivot, siObj, siX, , , , , , , , , , 0
SelectObj "null,null1", , True
CreateModel
SetValue "Model.Name", "Muscle01"
SelectObj "Muscle01.null"
SetValue "Muscle01.null.Name", "Start"
SelectObj "Muscle01.null1"
SetValue "Muscle01.null1.Name", "End"
SelectObj "Muscle01.Start", , True
AddToSelection "Muscle01.End", , True
SetValue "Muscle01.Start.null.primary_icon,Muscle01.End.null.primary_icon", Array(2, 2)
GetPrim "Null"
DeselectAll
GetPrim "Null"
DeselectAll
GetPrim "Null"
SelectObj "null"
Translate , -1.40788473987383, 0, 0, siRelative, siView, siObj, siXYZ, , , , , , , , , , 0
SelectObj "null2"
Translate , 1.50359955626831, 0, 0, siRelative, siView, siObj, siXYZ, , , , , , , , , , 0
SelectObj "null"
ToggleSelection "null1"
ToggleSelection "null2"
CopyPaste "null", , "Muscle01", 1
CopyPaste "null1", , "Muscle01", 1
CopyPaste "null2", , "Muscle01", 1
SelectObj "Muscle01.null"
SetValue "Muscle01.null.Name", "StartCenter"
SelectObj "Muscle01.null1"
SetValue "Muscle01.null1.Name", "Center"
SelectObj "Muscle01.null2"
SetValue "Muscle01.null2.Name", "CenterEnd"
Хватит заниматься бирюльками, переходим к серьезным вещам. Надо сделать так, чтобы три промежуточных объекта находились всегда между Strt и End на равных расстояниях друг от друга. Выделяем объект StartCenter, жмем Ctrl+k. Открывается окно, в котором безобидно прописаны все текущие параметры локальных трансформаций выбранного объекта. Нас интересует раздел Position (рис. 6).
Рис. 6. Окно локальных трансформаций
Правой клавишей жмем на зеленый квадратик рядом с позицией объекта по оси x и в выскакивающем меню выбираем Set Expression (рис. 7).
Рис. 7. Set Expression
Появляется окно Expression Editor. В нем написано, что положение объекта по оси x является константой (указано какой. В моем случае это -1,407885. В Вашем это может быть другое число). Идея в том, чтобы положение нашего объекта по оси x вычислять по формуле. Формула простая: все растояние между Start и End делится на 4 равных отрезка. Поэтому к Start объект StartCenter должен быть приближен в доли 3/4, а к объекту End всего лишь в доли 1/4. В словах вечно такая путаница.
Как писать формулу (это спрашивает нетерпеливый читатель). Наверху окна Expression Editor есть две кнопки: Function и Param. Нажав на Function, мы выбираем, какие функции применять, нажав на Param, мы выбираем к каким свойствам объекта применять функции (Рис. 8). Нам надо добраться до положения объекта Start по оси x. Жмем Function - Node - this model. Тем самым указываем на модель, в которой содержится наш объект, в данном случае StartCenter. Нам повезло, в той же модели содержится объект Start. Жмем Param - Start (Рис. 9). Ну и дальше добираемся до нужного свойства: сначала добавляем kine (категория всех трансформаций объекта), затем добавляем local (локальные трансформации), наконец добавляем posx (местоположение по оси x). В принципе всю строку this_model.Start.kine.local.posx можно было написать вручную (рис. 10).
Рис. 8. Список Function
Рис. 9. Список Param
Рис. 10. Добрались до положения по оси x
Ну и все, умножаем написанную строчку на 3/4, добавляем то же самое, только с объектом End, умноженное на 1/4. Жмем Validate, чтобы проверить, все ли правильно написали (если неправильно, то в сером поле сверху напишется, в какой строке ошибка) и потом Apply, чтобы наконец положение по оси x рассчитывалось по написанной формуле (рис. 11).
Рис. 11. Полная формулы для положения по оси x
Копируем все, что написали, создаем выражение для положения по оси y и вставляем туда скопированное. Заменяем posx на posy (рис. 12). И снова Apply. Повторяем то же самое для положения по оси z. Теперь у нас объект StartCenter находится всегда на прямой между объектами Start и End и отстоит от Start на расстояние, равное 1/4 длины отрезка Start-End. Вот так-то! Здесь мы вовсю использовали те сведения из геометрии, которые учителя стараются поместить в головы учащихся в школах и на первых курсах ВУЗов.
Рис. 12. Заменяем posx на posy
Не забываем следить за окном Script Editor и выписывать новые появившиеся команды. Далее повторяем всю процедуру по заданию местоположения объекта для нуля Center. Только формула будет уже немного другой. Так как объект должен быть расположен точно посередине, то его местоположение по оси x определяется формулой (this_model.Start.kine.local.posx + this_model.End.kine.local.posx)/2 (рис. 13). Для осей y и z формулу исправляем самостоятельно, демонстрируя понимание обсуждаемого предмета.
Рис. 13. Положение Center
Последний в этом параграфе шаг - определяем местоположение промежуточного нуля CenterEnd. Формула та же самая, что и для StartCenter, только надо поменять местами 3/4 и 1/4. Проверяем, что все нули движутся правильно, двигая Start и End и наблюдая, как промежуточные объекта равномерно растягиваются между ними (рис. 14).
Рис. 14. Проверка местоположения промежуточных нулей
Проверяем, что написано к текущему моменту на бумажке. В добавок к тому, что было написано ранее, должны появиться следующие команды:
AddExpr "Muscle01.StartCenter.kine.local.posx"
SetExpr "Muscle01.StartCenter.kine.local.posx", "this_model.Start.kine.local.posx * (3/4) + this_model.End.kine.local.posx * (1/4)"
AddExpr "Muscle01.StartCenter.kine.local.posy"
SetExpr "Muscle01.StartCenter.kine.local.posy", "this_model.Start.kine.local.posy * ( 3 / 4 ) + this_model.End.kine.local.posy * ( 1 / 4 )"
AddExpr "Muscle01.StartCenter.kine.local.posz"
SetExpr "Muscle01.StartCenter.kine.local.posz", "this_model.Start.kine.local.posz * ( 3 / 4 ) + this_model.End.kine.local.posz * ( 1 / 4 )"
AddExpr "Muscle01.Center.kine.local.posx"
SetExpr "Muscle01.Center.kine.local.posx", "(this_model.Start.kine.local.posx + this_model.End.kine.local.posx) / 2"
AddExpr "Muscle01.Center.kine.local.posy"
SetExpr "Muscle01.Center.kine.local.posy", "(this_model.Start.kine.local.posy + this_model.End.kine.local.posy) / 2"
AddExpr "Muscle01.Center.kine.local.posz"
SetExpr "Muscle01.Center.kine.local.posz", "(this_model.Start.kine.local.posz + this_model.End.kine.local.posz) / 2"
AddExpr "Muscle01.CenterEnd.kine.local.posx"
SetExpr "Muscle01.CenterEnd.kine.local.posx", "this_model.Start.kine.local.posx * (1/4) + this_model.End.kine.local.posx * (3/4)"
AddExpr "Muscle01.CenterEnd.kine.local.posy"
SetExpr "Muscle01.CenterEnd.kine.local.posy", "this_model.Start.kine.local.posy * (1/4) + this_model.End.kine.local.posy * (3/4)"
AddExpr "Muscle01.CenterEnd.kine.local.posz"
SetExpr "Muscle01.CenterEnd.kine.local.posz", "this_model.Start.kine.local.posz * (1/4) + this_model.End.kine.local.posz * (3/4)"
стр.2>>