Риггинг автомобиля на основе реактора 3ds Max

В данном уроке мы рассмотрим процесс создания модели, имитирующей динамику автомобиля (иначе говоря car rigging), а также напишем скрипт на языке MaxScript для управления созданной моделью. Описанный car rigging основан на стандартной максовской утилите reactor. В уроке использован Autodesk 3ds Max 2009. Урок рассчитан на базовое знание построения геометрических объектов и работы с reactor в 3ds Max.
Функциональные возможности элементов reactor, а также основы языка MaxScript в данном уроке не рассматриваются.

Итак, для начала нужно пояснить, что наша модель - это кузов, колеса, подвеска и механизм поворота передних колес. Кузов с подвеской соединен инертно, подвеска с колесами - жестко. К передним колесам подсоединен механизм поворота, к задним колесам подсоединен мотор (у нас заднеприводный автомобиль))).

1. Создание элементов автомобиля

Создаем 1 бокс 4х1,5м - кузов. Создаем 4 цилиндра радиусом 0,4м (32 sides) - колеса. Создаем 6 боксов 0,2м - 4 бокса подвеска, 2 бокса - механизм поворота. Все просто)).

Кузов - body (1шт)
Колеса - wheels (4шт)
Элементы подвески - axis (4шт)
Элементы механизма поворота - rudder (2шт)
Располагаем, центруем и получаем примерно такой результат.

Для избежания ошибок, которые могут возникнуть в дальнейшем при работе с reactor, необходимо отцентровать все внутренние координаты объектов (pivot) и направить их в соответствии с основными координатами 3ds Max.

2. Создание и назначение элементов reactor

Кузов - подвеска
Как было написано ранее кузов с подвеской должен соединяться инертно, т.е. пружинить. Выберем элемент reactor Spring (пружина), далее назначаем в опциях пружины (вкладка модификаторов): Spring properties -> Objects -> Parent - body, Spring properties -> Objects -> Child - соответствующая подвеска (axis). Нажимаем Spring properties -> Objects -> Align Spaces To: Child Body, щелкаем по Spring в разделе модификаторов, раскрываем содержимое, выбираем Parent Space и мышкой тянем конец пружины вдоль оси Z примерно до середины кузова (body) по высоте. Нажимаем Spring properties -> Dynamic properties -> Rest Length ->set, чтоб зафиксировать положение пружины.
При этом верхний и нижний конец пружины расположены друг над другом!

Повторяем действия для каждого элемента подвески (всего 4 пружины). Но наличие одних только пружин недостаточно для устойчивой конструкции, поэтому применим реактор Prismatic Constraint для вертикального взаимодействия кузова с подвеской, то есть инертные движения кузова будут осуществляться только по вертикали, что и обеспечивает Prismatic Constraint. Выберем элемент reactor Prismatic Constraint, далее назначаем в опциях элемента (вкладка модификаторов): Properties -> Parent - body, Properties -> Child - соответствующая подвеска (axis). Нажимаем Properties -> Align Spaces To: Child Body. Нажимаем Properties -> Limited. Устанавливаем Min Limit -0,2m, Max Limit 0,2m.

Повторяем действия для каждого элемента подвески (всего 4 элемента Prismatic Constraint). Результат должен выглядеть как на рисунке. Если оси Prismatic Constraint не совпадают с изображенными на рисунке, необходимо щелкнуть по Prismatic в разделе модификаторов, раскрыть содержимое, выбрать Parent Space и Child Space и вручную развернуть оси.

Подвеска - механизм поворота
Пришло время подсоединить к подвеске механизм поворота колес (rudder). Колеса должны поворачиваться в горизонтальной плоскости, для этого используем reactor Hinge Constraint. Выберем элемент reactor Hinge Constraint, далее назначаем в опциях элемента (вкладка модификаторов): Properties -> Parent - axis, Properties -> Сhild - соответствующий "поворотник" (rudder). Нажимаем Properties -> Align Spaces To: Child Body. Ставим галочку Properties -> Limited.

Повторяем действия для следующего элемента механизма поворота (всего 2 Hinge Constraint). Результат должен выглядеть как на рисунке. Если оси Hinge Constraint не совпадают с изображенными на рисунке, необходимо щелкнуть по Hinge в разделе модификаторов, раскрыть содержимое, выбрать Parent Space и Child Space и вручную развернуть оси.

Поворот колес
Колеса, а именно элементы механизма поворота (rudder) будут поворачиваться под воздействием reactor Motor. Добавим два мотора к левому и правому "поворотнику" (rudder). Выберем элемент reactor Motor, далее назначаем в опциях элемента (вкладка модификаторов): Properties -> Rigid Body - соответствующий rudder, Rotation Axis - Z

Созданные Hinge Constraint обеспечивают движение "поворотников" только в горизонтальной плоскости, поэтому ось Motor должна быть направлена вверх по оси Z, чтобы поворотники могли беспрепятственно поворачиваться.

Соединение колес
Передние колеса соединяем с механизмом поворота, а задние с подвеской. Для этого используем Car-Wheel Constraint. Для передних колес в Car-Wheel Constraint (вкладка модификаторов): Properties -> Parent - соответствующий "поворотник" (rudder), Properties -> Child - соответствующее колесо (wheel), для задних Parent - соответствующий элемент подвески (axis). Нажимаем Car-Wheel Constraint -> Properties -> Align Spaces To: Child Body

Результат должен выглядеть как на рисунке. Если оси Car-Wheel Constraint не совпадают с изображенными на рисунке, необходимо щелкнуть по Car-Wheel Constraint в разделе модификаторов, раскрыть содержимое, выбрать Parent Space и Child Space и вручную развернуть оси.

Основной мотор
Задние колеса будут поворачиваться под воздействием reactor Motor. Добавим два мотора к левому и правому заднему колесу. Выберем элемент reactor Motor, далее назначаем в опциях элемента (вкладка модификаторов): Properties -> Rigid Body - wheel, Rotation Axis - X. Ось Motor должна быть направлена по оси X
И Motor и Car-Wheel Constraint имеют стрелки направления вращения! При создании модели требуется обратить внимание, чтобы направления стрелок вращения Motor и Car-Wheel не противоречили друг другу!

3. Настройка RBCollection и CSolver

Итак, модель автомобиля создана, элементы реактора на своих местах, теперь пора "оживить" наше авто. Создадим плоскость (пол или поверхность, на которой будем испытывать авто) ниже автомобиля, так чтоб был небольшой просвет между колесами и плоскостью.

Добавим в сцену Rigid Body Collection и назначим rigid bodies. Для этого выделим RBCollection и во вкладке модификаторов RBCollection Properties -> add. В появившемся окне выбираем кузов, колеса, элементы подвески, элементы механизма поворота колес (имеются ввиду геометрические объекты, а не элементы reactor!!!) и обязательно добавляем созданную поверхность.

Далее переходим во вкладку Utilities, выбираем reactor и настраиваем reactor как на рисунке (подразумевается метрическая система измерения!).

Открываем вкладку reactor -> Collisions нажимаем Define collision pairs. В появившемся окне необходимо отключить все взаимодействия (collisions) между элементами сцены, оставив только их взаимодействие с полом. Во вкладке Properties указажите массу объектов: Кузов - 50
Колеса - 10
Элементы подвески - 10
Элементы механизма поворота - 10
Пол - 0
Friction (трение) везде - 1
Simulation Geometry - Concave Mesh

Добавим в сцену Constraint Solver и назначим constraints. Для этого выделим CSolver и во вкладке модификаторов RBCollection Properties -> RBCollection укажем созданную RBCollection1. Нажмем Properties -> add. В появившемся окне выбираем CarWheel, Prismatic, Hinge.
Обязательно установим Deactivation Threshold на 0!

4. Первая анимация

Пора ставить нашу модель на колеса! Открываем вкладку Utilities, выбираем Reactor -> Preview&Animation, указываем начальный и конечный кадр анимации (0 - 100 например) и нажимаем Preview in Window. В появившемся окне видим как модель, плавно амортизируя, опускается на пол. Ура! Большая часть задачи выполнена!! Теперь необходимо запустить моторы задних колес, а передними моторами будем регулировать "поворот руля". Все это можно делать и вручную, выделяя нужные элементы и своевременно меняя их настройки, но проще написать небольшой скрипт и упростить управление транспортным средством.

5. Немного скриптинга

Выбираем MaxScript -> New Script, появляется окно редактора MaxScript. Не буду вдаваться в особенности языка, просто опишу рассматриваемый пример. Итак, создадим окно управления, содержащее 2 раздела ("управление рулем" и "управление скоростью"). Для этого добавим в окно редактора MaxScript строки:

CarRig = newRolloutFloater "CarRig script" 300 330
addRollout rudder_control CarRig
addRollout speed_control CarRig

Раздел "управление рулем" будет контролировать угол поворота колес и скорость поворота, а также блокировку колес в прямом положении.

rollout rudder_control "rudder control" ////раздел управления рулем
(
slider wheelangle "wheel angle (right--center--left)" orient:#horizontal ticks:6 range:[-15,15,0] type:#integer ////бегунок контроля угла поворота колес
on wheelangle changed val do
(
$Hinge_r.minlimitangle = val-15 ////задаем мин и макс угол поворота колеса для
$Hinge_r.maxlimitangle = val +15 ////каждого Hinge
$Hinge_l.minlimitangle = val-15
$Hinge_l.maxlimitangle = val +15
)

slider rudderangspeed "rudder ang speed (right----center----left)" orient:#horizontal ticks:10 range:[-5,5,0] type:#integer ////бегунок контроля угловой скорости
on rudderangspeed changed val do
(
$Motor_ridder_r.angularspeed =val ////задаем угловую скорость для каждого мотора
$Motor_ridder_l.angularspeed=val
)

spinner ruddergain "rudder Gain" range:[0,10,0] type:#integer on ruddergain changed val do ////поле выбора коэфф-та нарастания/убывания угловой скорости
(
$Motor_ridder_r.gain= val
$Motor_ridder_l.gain=val
)

checkbutton straightonly "straight only" checked:false align:#left on straightonly changed state do ////кнопка движения прямо
if state == on
then
(
$Hinge_r.limitfriction = 1000
$Hinge_l.limitfriction = 1000

$Motor_ridder_r.disabled = true
$Motor_ridder_l.disabled = true
)
else
(
$Hinge_r.limitfriction = 0
$Hinge_l.limitfriction = 0

$Motor_ridder_r.disabled = false
$Motor_ridder_l.disabled = false
)
)

Раздел "управление скоростью" будет контролировать скорость авто.
rollout speed_control "speed control" ////раздел управления скоростью
(
slider speed "speed (back-stop-----forward)" orient:#horizontal ticks:8 range:[-10,30,0] type:#integer ////бегунок контроля скорости вращения задних колес
on speed changed val do
(
$Motor_r.angularspeed =val
$Motor_l.angularspeed=val
)

spinner speedgain "speed Gain" range:[0,20,0] type:#integer on speedgain changed val do ////поле выбора коэфф-та нарастания/убывания скорости авто
(
$Motor_r.gain= val
$Motor_l.gain=val
)

checkbutton stop "stop"checked:false align:#left on stop changed state do ////кнопка остановки/запуска мотора задних колес
if state == on
then
(
$Motor_r.disabled = true
$Motor_l.disabled = true
)
else
(
$Motor_r.disabled = false
$Motor_l.disabled = false
)
)


Полный текст скрипта:
rollout rudder_control "rudder control"
(

slider wheelangle "wheel angle (right--center--left)" orient:#horizontal ticks:6 range:[-15,15,0] type:#integer
on wheelangle changed val do
(
$Hinge_r.maxlimitangle = val +15
$Hinge_l.minlimitangle = val-15
$Hinge_l.maxlimitangle = val +15
)

slider rudderangspeed "rudder ang speed (right----center----left)" orient:#horizontal ticks:10 range:[-5,5,0] type:#integer
on rudderangspeed changed val do
(
$Motor_ridder_r.angularspeed =val
$Motor_ridder_l.angularspeed=val
)

spinner ruddergain "rudder Gain" range:[0,10,0] type:#integer
on ruddergain changed val do
(
$Motor_ridder_r.gain= val
$Motor_ridder_l.gain=val
)

checkbutton straightonly "straight only" checked:false align:#left
on straightonly changed state do
if state == on
then
(
$Hinge_r.limitfriction = 1000
$Hinge_l.limitfriction = 1000

$Motor_ridder_r.disabled = true
$Motor_ridder_l.disabled = true
)
else
(
$Hinge_r.limitfriction = 0
$Hinge_l.limitfriction = 0

$Motor_ridder_r.disabled = false
$Motor_ridder_l.disabled = false
)
)

rollout speed_control "speed control"
(
slider speed "speed (back-stop-----forward)" orient:#horizontal ticks:8 range:[-10,30,0] type:#integer
on speed changed val do
(
$Motor_r.angularspeed =val
$Motor_l.angularspeed=val
)

spinner speedgain "speed Gain" range:[0,20,0] type:#integer
on speedgain changed val do
(
$Motor_r.gain= val
$Motor_l.gain=val
)

checkbutton stop "stop"checked:false align:#left
on stop changed state do
if state == on
then
(
$Motor_r.disabled = true
$Motor_l.disabled = true
)
else
(
$Motor_r.disabled = false
$Motor_l.disabled = false
)
)
-------------------------------------------------------------------
CarRig = newRolloutFloater "CarRig script" 300 330
addRollout rudder_control CarRig
addRollout speed_control CarRig

Сохраняем скрипт.

6. Двигатель, заводись!

Запускаем MaxScript -> Open Script, выбираем созданный скрипт, появляется окно управления.

Делаем нужные нам настройки, устанавливаем интервал, запускаем просмотр в окне, если все нравится, создаем анимацию (Create Animation). Для плавности движения авто требуется чтобы следующий интервал, хотя бы на один кадр захватывал предыдущий (например, 0 - 100 - авто едет прямо, 99 - 200 - авто начинает поворачивать, 199 - 250 - авто снижает скорость до нуля).

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

757 0 850 21
26
2010-09-27
Неплохой урок, особенно что касается ознакомления со скриптованием, интересны возможности 3ds max в области программирования.
2010-09-28
Сначала думал что урок слишком простой, но дочитал до скриптов и порадовался! Спасибо за урок!
2010-09-28
Урок хороший!! Вот чет маю Bugatti разносит на кусочки еще на старте )) Сначало ее колбасит лихорадочно, а как только сигает с площадки в низ, колеса с подвеской летят в разные стороны )))
2010-09-28
[quote=-=AS=-] [/quote] подкорректируйте веса подвески, колес и самого кузова
2010-09-30
Спасибо! Помогло! Сделас ее потежелей в 1.5 раза и получилось ))
2010-09-30
Запускаем MaxScript -> Open Script, выбираем созданный скрипт, появляется окно управления. после открытия скрипта ничего не появляется.. а когда жму run script вылазит ошибка..подскажите в чё проблема может быть.. 2 раза проверял. всё делал по уроку)
2010-10-01
[quote=Андрей Прохорцев] Запускаем MaxScript -> Open Script, выбираем созданный скрипт, появляется окно управления. [/quote] Для запуска скрипта нажмите MaxScript -> Run Script
2010-10-01
а когда я жму MaxScript -> Run Script.. появляется ошибка скрипта.. открывает окно управления.. но совершенно пустое
2010-10-01
аха.. с окном управления мой касяк) , а вот как ей управлять..ума не приложу
2010-10-02
Урок для меня очень полезен, так как у меня max 2011, а на нем не работает плагин madcar..но при запуске скрипта, как только я пытаюсь передвинуть любой ползунок выскакивает ошибка: MAXScript Rollout Handler Exception --Unknown property: "maxlimitangle"in undefined Что делать?(((
2010-10-03
[quote=Александр Вдовин] Unknown property: "maxlimitangle"in undefined [/quote] У меня нет 2011, поэтому читайте свой maxscript help, ищите аналогичную функцию... тут я помочь не могу
2010-10-10
У меня таже проблема Unknown property: "maxlimitangle"in undefined =(...
2010-10-11
В 2011 максе: "$Hinge_r.minlimitangle = val-15" заменить на "$Hinge_r.limitMinAngle = val - 15" и т.д. Вроде помогло. :))
2010-10-11
У меня Autodesk 3ds Max 9 ... =( Не помогло
2010-10-15
Хороший урок, надо бы его изучить и попробовать вместо скрипта использовать траекторию, по которой будет ехать автомобиль, плюс, еще и физически реалистично. Увы по траектории не получалось, никак не мог добиться хорошего результата. Здесь вроде как с амортизаторами, надеюсь будет прикольно выглядеть, когда авто едет на большой скорости и после трамплина приземлится )))
2010-11-02
ЕЕЕ! Что бы не вылезала ошибка "Unknown property: "maxlimitangle"in undefined" нужно сделать одинаковыми имена. Hinge_r назывались также в сцене, а не Hinge01. А ещё там где полный текст скрипта нехватает одной строчки. вот тут $Hinge_r.minlimitangle = val-15 (нехватает) $Hinge_r.maxlimitangle = val +15 $Hinge_l.minlimitangle = val-15 $Hinge_l.maxlimitangle = val +15 А ещё как сделать так что бы машина прямо ехала. даже когда нажимаю кнопку или ставлю колёса прямо. она в итоге всёравно начинает заварачивать. Сделал по больше скорость движения. Она стартует в пробуксовку, а потом её заносит. и как сделать так что бы машина когда стартует перед поднимался немного, а когда тормозит - прижимался?
2010-11-29
а у меня почему то машина на 3 кадре разваливается и исчезает. что делать?
2010-11-29
измените вес
2010-12-13
Дошел до этапа 4. "Первая анимация". После запуска реактора машина на одном месте буксует. В чем дело? Единственная несостыковка моего опыта и урока заключается здесь: "[b]Основной мотор. Задние колеса будут поворачиваться под воздействием reactor Motor. Добавим два мотора к левому и правому заднему колесу. Выберем элемент reactor Motor, далее назначаем в опциях элемента (вкладка модификаторов): Properties -> Rigid Body - wheel, Rotation Axis - X. Ось Motor должна быть направлена по оси X[/b]". У меня при Rotation Axis - X, ось вращения направлена вниз. Что бы направить ось вращения как на рисунке приходится выбирать параметр Rotation Axis - Z. Может быть в этом дело?
2010-12-13
С направлениями осей разобрался. Переделал. Но все равно буксует. Что не так?
2011-01-08
2 FALCON- :на сайте [url]hhttp://compart.at.ua/publ[/url] есть наглядный материал по MAXScript
2011-01-08
поправка: [url]http://compart.at.ua/publ[/url]
2011-01-31
что делать если передние колёса отваливаются?
2011-04-16
У меня пишет: Geometry is too small А когда увеличиваю объекты в рвзмере и нажимаю на кнопку "Preview in window", 3ds max вообще слетает. Может поможете?
2011-10-15
Скажите. А без скрипта можно как-то обойтись ?
2011-12-27
пасиба
RENDER.RU