Анимация пружины с помощью костей в 3dsMAX

1. Зачем это надо?

Вполне логичный вопрос. Тем более что в 3dsMAX'е имеются уже для этих целей соответствующий объект, который так и называется Spring (англ. - пружина). Создать ее можно из меню Create > Dynamic s > Spring или выбрав на командной панели (Command Panel) закладку Create > кнопка Geometry > в выпадающем списке Dynamics Objects > Spring.

Этот стандартный объект имеет немало параметров, отвечающих за форму (длинна, ширина, количество витков, сечение) и за метод построения концов пружины (End Point Method). Все это благополучно анимируется, а при выборе End Point Method > Bound to Object Pivots концы пружины можно привязать к конкретным объектам в сцене, тогда анимировать придется только эти объекты (если они еще не были заанимированы), а пружина уже будет самостоятельно изменять свою длину и местоположение в сцене.

Но если пружина необходима абсолютно другого сечения, чем те, которыми располагает стандартный объект: круглое, прямоугольное и D-образное? Или уже есть готовая модель пружины со своим набором материалов, текстур, текстурных координат? Или же пружину эту надо отэкспортить вместе с анимациями в какой-либо движок (Engine), а он совсем не знает о существовании такого замечательного объекта как Spring, и понимает только Skin-анимацию? Короче говоря, существуют такие ситуации, когда вопрос «Зачем это надо?» не возникает.

2. Устройство пружины

В более общем случае пружину можно разделить на три части:

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

3. Анимация деформируемой части

Для начала будет удобно скрыть недеформируемые части пружины(перейти в режим редактирования полигонов, выделить соответствующие недеформированным частям и скрыть Edit Geometry > Hide Selected):

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

Для того чтоб избежать подобных неприятностей понадобится модификатор Skin и две кости(Bones). При чем, абсолютно не важно ни количество витков пружины, ни форма сечения, ни разность между углами относительно оси пружины, в которых начинается первый виток и заканчивается второй. Важно правильно расположить кости:

  • они должны быть параллельны пружине;
  • первая кость должна начинаться строго в нижней части сечения первого(нижнего) витка и заканчиваться в нижней части последнего витка;
  • вторая кость должна начинаться строго в верхней части сечения первого витка и заканчиваться в верхней части последнего витка.

Войти в режим создания костей можно из меню Create > Systems > Bones IK Chain или из командной панели(Command Panel) закладка Create > кнопка Systems > в выпадающем списке Standard > Bones:

При создании костей необходимо использовать привязки для правильного расположения. Создание первой кости:

И второй:

Для удобства кости можно отодвинуть от оси пружины, чтоб они не находили друг на друга; завершающие косточки – удалить(в них нет необходимости):

Первая кость будет называться bone_down, вторая – bone_ up. Модификатор Skin назначается на саму пружину, в его параметры(Parameters) добавить созданные кости Bones > Add:

Дальше необходимо настроить коэффициенты влияния костей на вершины сетки пружины по следующим правилам:

  • на точки, расположенные в нижней части любого сечения пружины, будет влиять только первая кость bone_down;
  • на точки, расположенные в верхней части любого сечения пружины, будет влиять только вторая кость bone_up;
  • на промежуточные точки коэффициент влияния первой кости bone_down будет равен отношению удаленности точки от верхнегокрая сечения к толщине сечения, второй кости bone_up – отношению удаленности точки от нижнего края сечения к толщине.

Для данного примера:

  • толщина сечения равна 5;
  • желтые точки расположены в нижней части сечения: коэффициенты влияния bone_down = 1.0, bone_up = 0.0;
  • красные точки расположены в верхней части сечения: bone_down = 0.0, bone_up = 1.0;
  • синие точки удалены от нижнего края сечения на 1, от верхнего – на 4: bone_down = 1/5 = 0.2, bone_up = 4/5 = 0.8;
  • зеленые точки удалены от нижнего края на 4, от верхнего – на 1: bone_down = 4/5 = 0.8, bone_up = 1/5 = 0.8.

Для назначения коэффициентов влияния костей на вершины в свитке параметров модификатора Skin нажать кнопку Edit Envelopes, в группе Select напротив Vertices поставить галочку и в группе Weight Properties нажать кнопку Weight Tool (на кнопке нарисован гаечный ключ), после чего появиться дополнительное окно с одноименным названием:

Для удобства можно выделить все вершины и сбросить коэффициент влияния первой кости bone_ down в ноль. Коэффициенты влияния на вершины назначать лучше сразу на цепочки вершин, расположенных вдоль витков: выделить две соседние вершины и нажать кнопку Loop, выбрать кость в параметрах модификатора, затем нажать кнопку на которой изображен требуемый коэффициент(0, .1, .25, .5, .75, .9, 1) либо рядом с кнопкой Set Weight ввести требуемую величину и нажать ее:

После всех этих манипуляций должно получиться следующее:

Теперь если выделить кости bone_up и bone_down, войти в режим масштабирования, выбрать в качестве центра точки привязки объектов, то при масштабировании костей вдоль оси пружины сама пружина будет корректно сжиматься и разжиматься, при этом толщина сечения изменяться не будет:

4. Анимация недеформируемых частей пружины.

Теперь можно сделать видимыми скрытые полигоны отвечающие, за недеформируемые части. Для этого выбрать объект пружины, перейти на уровень редактирования полигонов и нажать кнопку Edit Geometry > Unhide all:

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

Первая кость будет называться bone_start, а вторая – bone_end. В настройках иерархии вращение второй косточки должно быть заблокировано Command Panel > Hierarchy > Link Info > Locks > X, Y, Z:

Для настройки первой кости понадобиться утилита Bone Tools, которая находится в меню Animation > Bone Tools... .Кость должна иметь возможность изменять свою длину (убрать галочку с Freeze Length) и при этом сохранять неизменной свою матрицу трансформаций(Stretch > None):

Кости влияющие на деформируемую чать пружины bone_down и bone_up привязываются к кости bone_start инструментом Select and Link:

В параметры(Parameters) модификатора Skin добавляются оставшиеся кости bone_start и bone_end. Для скрытых ранее недеформируемых частей пружины назначаются соответствующие коэффициенты влияния:

  • для нижней части bone_start = 1.0, все остальные кости 0.0;
  • для верхней части bone_end = 1.0, все остальные кости 0.0.

Теперь при изменении положения корневой кости bone_start за ней перемещаются вершины нижней недеформируемой части пружины(через модификатор Skin), кости bone_down и bone_end, которые изменяют положения вершин деформируемой части, и косточка bone_end, изменяющая положения вершин верхней недеформируемой части. При изменении положения косточки bone_end,за ней меняет свою ориентацию корневая кость bone_start и соответственно вся пружина, а также изменяют свое положение относительно продольной оси пружины вершины верхней недеформированой части. Осталось связать масштабирование вдоль оси пружины костей bone_down и bone_end с перемещением косточки bone_end вдоль оси пружины.

Для начало необходимо получить зависимость коэффициента масштабирования костей деформируемой части от расстояния от косточки bone_end до начала кости bone_start:

Пояснения к рисунку:

  • L – расстояние от косточки bone_end до начала кости bone_start (для начального положения L');
  • c1, c2, c3, c4 – отступы от концов костей bone_down и bone_up до краев пружины, из-за присутствия недеформируемых частей эти величины неизменны при растяжении или сжатии пружины;
  • ld и lu – длины костей bone_down и bone_up соответственно, нетрудно заметить, что они равны между собой, поэтому в дальнейшем будут обозначаться l (для начального положения l').

Необходимо найти соотношение l/l' = s, что и является коэффициентом масштабирования костей деформируемой части. Итак:

L = c1 + lu + c2 = c3 + ld + c4, c1 + c2 + l = c3 + c4 + l, следовательно c1 + c2 = c3 + c4 = C = L' - l',

L = C + l, l = L - C, l' = L' - C,

l / l' = (L - C) / (L' - C) = (L - (L' - l')) / (L' - (L' - l')) = (L - L' + l')/(L' - L' + l') = (L - L' + l') / l' = (L - L')/l' + 1.

Таким образом s = (L - L')/l' + 1, где L' и l' известные величины (их можно получить используя Command Panel > Utilities > Measure. В данном примере получилось L' = 147, l' = 132:

Следующие действия проделываются для каждой кости bone_up и bone_down:

  • выделить кость отвечающую за деформируемую часть;
  • перейти Command Panel >Motion > Parameters > Assign Controller;
  • назначить Sceale контроллер ScaleXYZ;
  • назначить X Scale контроллер Float Expression;

  • появится окно настройки контроллера:

  • тут в группе Create Variables создается новая векторная переменная end_pos и назначается ей контроллер $bone_end.transform.controller.Position, теперь эту переменную можно использовать в выражении Expression, куда и вписываеться полученная ранее формула (length(end_pos) - 147) / 132 + 1, где length(end_pos) и есть расстояние от косточки bone_end до начала кости bone_start, так как переменная end_pos содержит координаты косточки bone_end относительно родительской кости bone_start.

Вот вроде и все. Теперь если выделить косточку bone_end и выбрать инструмент перемещение Move и подвигать ее должно получиться так:

5. Почему это работает.

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

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

Файл сцены для 3ds MAX 2010.

697 0 850 59
21
2009-11-02
интерсно, а главное подробно
2009-11-02
Довольно неплохо! Молодец! +
2009-11-03
Ну для анимации, движущегося автомобиля самое то...пойдет....Подход творческий...описано и разжовано...Да еще и в 2010 Maxе ....Сам урок не воспроизводил...но попробую повторить...)))
2009-11-03
Хороший метод!
2009-11-03
как мне кажется даже на примере видно что сечение пружины деформируется при растяжении и сжатии!
2009-11-03
сделал щас такое за 2 минуты ...есть намного легче способы!!!твой слишком долгий и замудреный
2009-11-03
[quote=DDDimaXXX] сделал щас такое за 2 минуты ...есть намного легче способы!!!твой слишком долгий и замудреный [/quote] Способов масса, но не костями. Это отличный пример грамотного использования Skin, там где это необходимо. AShim спасибо. Правда гораздо интереснее было-бы рассмотреть случай с гибкой пружиной, и оформить привязку в полуавтоматическом режиме скриптом. Твои скрипты, которые попадались, впечатляют.
2009-11-03
Обалденный, неординарный, серьезный урок. Прямо бальзам на душу. Держи пятерки!
2009-11-04
Спасибо за положительные отзывы :) [quote=megavitus]оформить привязку в полуавтоматическом режиме скриптом[/quote] Была такая идея, но ввиду того, что не так уж и часто приходится анимировать пружины, отпала. Тут написано много, а на самом деле все быстро делается. [quote=DDDimaXXX]есть намного легче способы[/quote] Конструктивная критика приветствуется, если есть такой способ, отвечающий задачам урока, то интересно узнать о нем.
2009-11-05
ммм.. а не легче просто использовать уже встроенные пружины (dinamics objects->spring), просто указывая два конца пружины ,ну или используя контроллеры?
2009-11-05
[quote=BM] а не легче... [/quote] хоть бы первый пункт дочитал хотя бы
2009-11-06
Хороший урок и изложено все грамотно, а то напишут хрень всякую которой в сети и так валом, автор отлично - так держать!!!
2009-11-09
хм... а смысл так сетапить пружину если можно обычнымы параметрами сплайна покрутить....??? ладно если бы делать анимацию пружины которая изгибается другое дело.....
2009-11-23
Молодец,урок супер.+
2009-12-08
Еще не пробовал сделать, но уже вдохновляет... Уж больно мне нравятся привязочки и взаимодействия... Актуально - ДА!
2010-01-18
Файл сцены подевался, нажимаю а выводит неограниченное количество символов, букв, цифр
2010-08-10
А стандартную пружину можно за 2 секунды создать.......Спрашивается.....Зачем мудрить)
2011-03-16
[quote=chilintano06] А стандартную пружину можно за 2 секунды создать.......Спрашивается.....Зачем мудрить) [/quote] Вот уж правда, ребята, да прочитайте же вы дальше названия, а потом уж судите! Отличная подробная статья, на интересное решение задачи. автору 10 баллов!
2011-09-13
[quote=1Best>|animation|+lucк] stems > в [/quote] это опера так реагирует на zip-архив. открой через другой обозреватель.
2014-12-16
Спасибо за урок! Очень пригодился. П.С. Сделал по этому принципу скрипт, который всё это автоматом делает, вроде работает - если кому нужен - пишите в ЛС (не выкладываю ссылку, потому что он ещё сыроват).
2016-05-11
Привет, отличный урок.  Один вопрос касательно последнего шага с настройкой скейла. Почему нельзя было просто создать концевые кости у первых двух и сделать position constran на последнюю кость. Эффект тотже будет и не надо париться с формулами
RENDER.RU