Создание мускульного примитива

1. Введение

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

Вот все говорят, дескать, XSI-XSI. Якобы это один из самых лучших пакетов для персонажной анимации. Ну и я так думал. И в один прекрасный солнечный день (это был четверг), решил: "А почему бы не заригить перса в XSI!" Думал я, конечно, по-другому, но суть в этом. Хотелось не просто взять стандартного Двуногого и прискинить его. Нет. Хотелось сделать риг как можно более комплексным, в том числе и с мышцами. Нетерпеливый читатель наверное уже весь извелся, так ему хочется узнать, что же произошло. А произошло следующее. Нет в XSI мышц. Вот так вот все просто. Нет, и все тут. В Максе есть (благодаря модулю CAT), в Майе есть (встроенные), а в лучшем пакете для персонажей - нет.

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

Ну раз так, то надо просто сделать свои мышца самостоятельно. И я стал смотреть, а как же можно самому сделать мускулы. Да еще такие, чтобы они обладали как можно большим числом фишек (читай, поддерживали вторичные деформации и динамику). Разобравшись понял: совершенно правильно, что в XSI нет встроенных мышц. Они просто не нужны. Каждый сам с удовольствием их сделает себе такими, какими хочет. Настоящий урок как раз и описывает один из вариантов создания мускул.

Да, еще одно замечание, прежде чем мы перейдем к делу. Делать будем стандартными средствами XSI без использования ICE. Последнее время у многих людей (в том числе и ксишников) наблюдается тенденция отождествления самого пакета и его модуля ICE. Иногда считается, что если не использован ICE, то это не раскрыт весь потенциал пакета. Возможно так и есть, но мы будем решать маленькую локальную задачу, для которой не надо больших мощностей. Вполне будет достаточно стандартных expression-ов. Более того, тот метод, которым мы будем пользоваться, можно применить на версии любой XSI, начиная с 5-ой (возможно и еще раньше), и даже, проведя аналогии, реализовать в Максе или Майе. В конец концов есть еще две причины не использовать ICE:

  1. И это главная причина. Автор (то есть я) совсем не знает ICE. Вернее знает, но не ахти как. Впрочем, очень хочет выучить и использовать по мере надобности.
  2. ICE сам по себе, и ICE Kinematics в частности, чрезвычайно нестабильно работают. Это отмечают все, кому приходится использовать те или иные модули. Вроде бы все правильно, ан нет, ошибку выдает. Перезапустил программу - нет ошибки. Зачем нам такие сложности?

2. Постановка задачи

Давайте опишем, какими свойствами должен обладать мускульный примитив.

  1. Должна быть реализована возможность создания мышц разных размеров и форм. Или даже так: создали мышцу, а потом меняем ее внешний вид, а она при этом остается мышцей и сохраняет все свои параметры.
  2. Поддержка динамики двух видов. Мускульная динамика - реагирование на сжатие-растяжение с возможностью регулировать коэффициент сжатия. Динамика движения - инерционность тела мускула. Если резку выбросить ногу, руку или голову вперед, мускулы еще некоторое время колеблются. Вот это и есть динамика движения.
  3. Окно с параметрами, в котором мы могли бы включать или отключать те или иные функции, изменять параметры самого мускула и вообще, чувствовать себя Творцом.

Дополнительно хотелось бы отметить следующую возможность, которую мы также будем реализовывать. Это касается принципа создания самого примитива в целом. В 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>>
749 0 850 20
10
2011-02-01
>>ICE сам по себе, и ICE Kinematics в частности, чрезвычайно нестабильно работают. Это отмечают все, кому приходится использовать те или иные модули. Вроде бы все правильно, ан нет, ошибку выдает. Перезапустил программу - нет ошибки. Зачем нам такие сложности? Это откуда такой бредовый вывод сделан ? практически все глюки айса самого по себе связаны с криворучием; с кинематикой чуть сложнее, она действительно не стабильна, но только если не следовать некоторым правилам грубо говоря, которые не описаны в хелпе, по которым нет (совсем нихрена даже у пиндосов) материалов, и которые можно вывести только путем исследования сцены с ригом кролика из оф.поставки ксюхи, так что тут впринципе можно согласиться на счет чрезвычайной глючности, но на айс в целом гнать не надо 5\4, потому что опять таки, писать столько экспрешенов - это е**** на отличненько когда есть айс
2011-02-01
А что - хорошо. 5/5. Правда осилил только короткую версию урока. Да, описал бы кто технологию ICE рига кролика.
2011-02-01
http://vimeo.com/6203991
2011-02-01
На ICE не гоню, но на ICE Kinematics, да и то только в силу неграмотности. Экспрешенов так-то пишется не много, они ведь либо чрезвычайно просты, либо повторяются. Хотя, может это когда делаешь кажется просто и раз-два, а стороннему человеку кажется эвон как накручено.
2011-02-03
отличный урок! уже прикидываю как перенести на макс (с ходу вроде всё есть, не матюкать - лулзов и опыта ради) 5/5! небольшие замечания: админам/программистам render.ru - код выделять тегом и под кат прятать хорошо бы - возможность сделать обтекание картинки текстом (многие ведь небольшие, будет компактнее и читабельнее - глаза скакать не будут так) Ангелу - анимашки (gif) - видео (труба или вимео) - творцом замучил! ;) - код в кнопку запихивать как-то некрасиво ИМХО (есть же external file, который может лежать в сети для всей команды) - стоит дополнение к статье сделать - именование уникальное, скрытие (не что-то типа Hide, а кардинальное, чтобы для блАндинок пользователей), метод создания по двум точкам (кликом по костям возможно или по нуллам) и прочие ништячки до полноценного продукта Креатив гениален, автор Молодец! Пиши ещё! ;)
2011-02-03
Автор молодец, кстати, примерно по такой же технологии, в любом пакете можно мускулы сделать, меняются лишь названия модификаторов. Но, все-таки, их отсутствие в XSI, это скорее минус.
2011-02-05
Урок простенький, тем не менее - 5/5
2011-02-13
Вопрос по уроку только один... а это вот в начале к чему было? "Предупрежу сразу. Не надо после прочтения этих строк бросать изучение XSI и переходить на Blender." |:-X
2011-04-05
А я то думал, что знаю XSI.... Записывайте меня в чайники! [smile=01]
2012-04-14
А че так сложно то, памоему есть гораздо проще способ создать мышцу в ксях... а тут прям целая "Война и мир" написана.
RENDER.RU