Уроки: 3ds Max

Динамика четырехтактного двигателя

Идея написания данного урока пришла после проекта включающего в себя четырехтактный, двухцилиндровый мотор.

Главная задача состоит в том, чтобы заставить одну деталь (а именно «коленчатый вал») управлять всеми остальными, тогда анимируя только вал, мы анимируем весь мотор.

В процессе выполнения задачи, для управления положением и вращением объектов, будем пользоваться Expression Controller.

Expression Controller дает возможность описать параметры объекта математическими и некоторыми логическими формулами.

Рассмотрим окно Expression Controller.

В поле Create Variables обозначаются переменные (скалярные и векторные), в этом уроке будем пользоваться только скалярными.

Созданные переменные показаны в поле Scalars, им можно присвоить конкретное значение (Assign to Constant) или значение параметра

какого-нибудь объекта (Assign to Controller).

Поле Description содержит описания и комментарии.

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

Иными словами выражение должно стоять на месте где подразумевается параметр предмета (в случае задавания положения объекта [выражение для X , выражение для Y , выражение для Z]).

Для выражений важно написание каждой буквы, поэтому чаще сверяйтесь с написанием, посмотрев его в Function List.

Кнопки Save и Load сохраняют и загружают выражения с переменными.

Debug показывает нынешние значения переменных и выражений.

Evaluate применяет выражение к объекту.

Close закрывает окно.

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

Вот движущиеся детали нашего двигателя:

Коленчатый вал

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

Важно чтоб контроллер вращения вала был Euler XYZ. К тому же проще всего будет расположить вал на нулевых координатах.

Шатун

Длину этой детали необходимо знать (для этого можно воспользоваться измерителем дистанции или рулеткой).

Точнее расстояние от Pivot Point до места, где поршень крепится к шатуну, при анимации поршня это будет иметь значение.

Pivot point шатуна важно расположить в месте где он должен крепится к валу. Лучше всего чтобы место крепления шатуна находилось прямо над Pivot Point вала (при начальном его положении) тогда поворот вала будет описывать поворот оси шатуна.

Далее его можно привязать к валу, но я использовал Position Expression Controller.

Для этого в панели Motion выбираем контроллер позиции и жмем Assign Controller, где выбираем Position Expression.

В поле выражений вписываем такое:

[0,

StartX+r*cos(-radToDeg(a)+Starta),

StartY+r*sin(-radToDeg(a)+Starta)]

Данное выражение означает присвоить положение:

X=0

Y=StartX+r*cos(a+Starta)

Z=StartY+r*sin(a+Starta)

Что задает положение шатуна относительно вала.

Далее надо задать скалярные переменные a, r, StartX и StartY вписав каждое имя в Create Variables и нажав Create.

Где a – угол поворота коленчатого вала. Ей мы присвоим значение вращения вала, для этого выбираем переменную и, нажав на Assign to Controller,

выбираем Коленчатый вал -> Transform -> Rotation -> Y_Rotation (например).

Здесь важно заметить, что операции с углами в Expression Controller проходят в градусах,

а значения в Euler XYZ в радианах, поэтому при использовании переменной, которой присвоено значение

вращения вала, необходимо преобразовывать ее значение в градусное с помощью команды -radToDeg(a), МИНУС потому, что отсчет угла там идет с другой стороны.

r – расстояние от Pivot Point шатуна до оси вала.

StartX, StartY – положение вала, в плоскости перпендикулярной оси вращения (когда она смотрит на нас).

Starta – Угол, на который отклонено место крепления шатуна.

Также можно загрузить мое, уже готовое, выражение, нажав кнопку Load (Важно помнить, что при загрузке выражений, переменным не присвоено никаких значений, придется присвоить их самим): Шатун

Теперь назначаем вместо контроллера вращения Look-At Constraint, сделав это через панель Motion.

Как цель выбираем поршень.

Поршень

Pivot Point поршня необходимо расположить в центре, а именно в месте крепления шатуна к поршню, это необходимо чтобы шатун «смотрел» именно на это место,

в результате нижеприведенных действий поршень будет «насажен» на шатун.

Его движение будет описывать Position Expression Controller, для этого выполняем аналогичные, предыдущему разделу, действия.

Ниже приведено объяснение выражения движения поршня:

На рисунке зеленым выделен сам поршень, красная ось его движения имеет угол наклона s.

r – расстояние от Pivot Point шатуна до оси вала.

a угол поворота вала.

с – длина шатуна, о которой я говорил на начале предыдущего раздела.

Путем несложных вычислений находим положение поршня относительно угла поворота вала:

m=c*cos(arcsin((r*sin(a-s))/c))

n=r*cos(a-s)

x=cos(s)*(m+n)

y=sin(s)*(m+n)

x=cos(s)*(c*cos(arcsin((r*sin(a-s))/c))+ r*cos(a-s))

y=sin(s)*(c*cos(arcsin((r*sin(a-s))/c))+ r*cos(a-s))

Выражение, заносимое в контроллер будет выглядеть так:

[0,

StartX+cos(s)*(c*cos(asin((r*sin(-radToDeg(a)-s+Starta))/c))+r*cos(-radToDeg(a)-s+Starta)),

StartY+sin(s)*(c*cos(asin((r*sin(-radToDeg(a)-s+Starta))/c))+r*cos(-radToDeg(a)-s+Starta))]

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

Или пользуемся готовым сохранением: Поршень

Полученную систему можно использовать в любых объектах имеющих поршень.

Следующие детали необходимы лишь для четырехтактного двигателя.

Распределительный вал

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

В четырехтактном двигателе распределительный вал делает один поворот на два поворота коленчатого вала, поэтому формула вращения для него будет выглядеть так:

a/2+Starta

Где a угол поворота вала.

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

Для задания вращения этого вала, в панели Motion, выберем поле Assign Controller->Rotation->Y_Rotation (ось Y, например), нажмем Assign Controller, где выбираем Float Expression.

В этом случае выражение задает вращение лишь по выбранной нами оси, поэтому следует задать наши две переменные и вписать выражение

a/2+degToRad(Starta)

В градусы мы угол не превращаем, потому что ответ нужен тоже в радианах.

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

Можно воспользоваться готовым файлом: Распределительный вал

Клапан

Анимация клапана является трудной задачей, я решил ее так.

Я представил головку распределительного вала как совокупность полукруга и сдвинутой вниз параболы:

На данном рисунке (слева сверху) представлен срез этой самой головки, верхняя часть-полукруг радиуса r, причем радиус равняется координате x0 параболы при пересечении с 0:

r=sqrt(y0)

Здесь и далее sqrt() – означает корень (так корень пишется и в Expression).

В этой задаче требуется найти c – расстояние от оси распределительного вала до точки прикосновения с клапаном (иными словами точку на оси движения клапана, которая будет верхней точкой клапана).

Pivot Point клапана следует разместить как раз в этой точке.

Нам известны s – угол наклона оси клапана

(на практике берите 180 минус настоящий угол, потому что картинка не совсем соответствует системе координат в максе)

a – угол поворота распределительного вала (его мы назначаем с помощью Assign to Controller).

y0 – смещение параболы вниз, не сильно большое, задайте его, так чтобы в максимальном своем смещении (как раз на кончике параболы) клапан чуть приоткрывался.

Еще нам потребуется вспомогательный угол:

b=90-s+90-a=180-s-a

Из найденного нами отрезка c мы с легкостью найдем положение точки прикосновения в координатах (относительно оси распределительного вала).

n=c*sin(s)

m=c*cos(s)

Итак полученную задачу я решил так:

c2=k2+d2

d=k2-y0

c2=k4-2*k2*y0+y02+k2

k=cos(b)*c

c2=c4*cos4(b)-2*c2*cos2(b)*y0+y02+c2*cos2(b)

0=sqrt((1+2*cos2(b)*y0- cos2(b)+sqrt((cos2(b)-1)*(cos2(b)-1-4*cos2(b)*y0)))/(2*cos4(b))) - c

Решив данное уравнение относительно c, получим ответ :

с=sqrt((1+2*(cos(b)^2)*y0-(cos(b)^2)-sqrt(((cos(b)^2)-1)*((cos(b)^2)-1-4*(cos(b)^2)*y0)))/(2*(cos(b)^4)))

Где b=180-s-a

Теперь нам известны и m и n:

n=c*sin(s)

m=c*cos(s)

Теперь добавляя StartX+ m, получим нужное положение клапана по оси X.

А, отнимая StartY- n (ведь клапан движется вниз), получим положение клапана по оси Y.

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

Для решения этой проблемы воспользуемся оператором if(условие, выражение1, выражение2)

что означает следующие: оператор выполняет выражение1, если условие верно и выражение2, если условие неверно.

Поэтому мы запишем следующие if(d>0, StartX+ c*cos(s), StartX+cos(s)*r) для движения по оси X,

и if(d>0, StartY+ c*sin(s), StartX+sin(s)*r) для движения по оси Y.

Почему как условие я взял d>0 ?

Потому что d= sin(b)*c – проекция отрезка c на ось Y головки, из рисунка видно, что если это значение превышает 0 то точка прикосновения находится в районе круга, и будет задавятся выражением cos(s)*r для X, и sin(s)*r для Y.

Если ось клапана находится по другую сторону НЕОБХОДИМО поменять знак с > на <.

Теперь мы можем вывести остаточное выражение, зависящие от данных нам переменных.

Нужно заметить, что b =180+radToDeg(a)-s (помним, что угол поворота распределительного вала мы получаем в радианах, и отрицательного значения).

ИТАК, вот готовое выражение, зависящие от переменных a, s, StartX, StartY, y0:

[0,

if(

sin(180+radToDeg(a)-s)* sqrt((1+2*(cos(180+radToDeg(a)-s)^2)*y0-(cos(180+radToDeg(a)-s)^2)-
sqrt(((cos(180+radToDeg(a)-s)^2)-1)*((cos(180+radToDeg(a)-s)^2)-1-4*(cos(180+radToDeg(a)-
s)^2)*y0)))/(2*(cos(180+radToDeg(a)-s)^4)))>0,

StartX+cos(s)* sqrt((1+2*(cos(180+radToDeg(a)-s)^2)*y0-(cos(180+radToDeg(a)-s)^2)-sqrt(((cos(180+radToDeg(a)-
s)^2)-1)*((cos(180+radToDeg(a)-s)^2)-1-4*(cos(180+radToDeg(a)-s)^2)*y0)))/(2*(cos(180+radToDeg(a)-
s)^4))),StartX+cos(s)*sqrt(y0)),

if(

sin(180+radToDeg(a)-s)* sqrt((1+2*(cos(180+radToDeg(a)-s)^2)*y0-(cos(180+radToDeg(a)-s)^2)-
sqrt(((cos(180+radToDeg(a)-s)^2)-1)*((cos(180+radToDeg(a)-s)^2)-1-4*(cos(180+radToDeg(a)-
s)^2)*y0)))/(2*(cos(180+radToDeg(a)-s)^4)))>0,

StartY-sin(s)* sqrt((1+2*(cos(180+radToDeg(a)-s)^2)*y0-(cos(180+radToDeg(a)-s)^2)-sqrt(((cos(180+radToDeg(a)-s)^2)-
1)*((cos(180+radToDeg(a)-s)^2)-1-4*(cos(180+radToDeg(a)-s)^2)*y0)))/(2*(cos(180+radToDeg(a)-s)^4))), StartY
-sin(s)*sqrt(y0))]

Как и раньше, вы можете воспользоваться готовым файлом: Клапан

Ремень

Оставшейся ремень, я нарисовал сплайнами, и задав ему Bump карту, анимировал ее U offset относительно поворота коленчатого вала.

Для этого, задав карту, заходим в Wire Parameters->Наша карта->Maps->Bump->Coordinates->U_Offset, соединяем ее, таким же образом, с поворотом коленчатого вала, выбираем вал как главный (стрелочка влево), и вписываем слева такое выражение:

-Y_Rotation/2

Минус или плюс зависит от расположения ремня в пространстве (точнее его UVW Mapping), кстати я выбрал сферический,

Делитель подбирал также - чтоб он гармонично двигался вместе с ремнем. Советую просто сделать ваш Bump видимым во вьюпорте и подбирать направление и скорость движения карты.

Последней деталью двигателя, которой нам придется заняться, является свеча зажигания, а точнее ИСКРА.

Искра свечи зажигания

Искру, я сделал просто:

Провел две линии, задал им анимированный Noise, применив его ко всем вертексам кроме конечных.

В Render Effects, я задал Glow, примененный к линиям (через )

Чтобы линия и свечение виднелись, отметим линию как Renderable, а для Thikness зададим специальное выражение, с помощью Wire Parameters.

Для этого идем в Wire Parametrs->Modified Object->Line (Object)->Thickness

И, как показано на рисунке, соединяем с вращением коленчатого вала.

Теперь вписываем такое выражение:

floor(abs(0.1+sin(radToDeg(Y_Rotation)/2-90)))/20

Y_Rotation – если вал вращается по оси Y.

Тут floor() – оператор, который выдает наибольшее целое, меньшее данного числа.

abs() – модуль

Данное выражение выдает 1/20 каждый полный первый поворот вала, в ином случае оно выдает 0/20, что делает линию невидимой.

Получается, что Thickness линии = 1/20 = 0,05, каждый первый поворот вала (на начало такта Рабочего хода)

0,1 добавлено для того чтобы слегка продлить результат 1/20 (floor выдает 1), добавив, например 0,2 вы продлите искру еще на чуть-чуть.

-90 выполнено чтоб искра «попадала» точно на начало такта «Рабочего хода» (Взрыв), эта величина зависит от угла наклона цилиндра и времени когда будет проводится взрыв, поэтому проще всего будет поставить систему в положение, когда должна проходить искра, и подобрать такую величину, при которой искра виднеется (Thickness = 1/20).

Итог

Мы установили зависимость всех деталей от одной – коленчатого вала, теперь для анимации мотора (даже довольно сложного, не просто монотонного, хода) нужно только задать валу соответственное вращение и подправить его в

Curve Editor.

Итак мы научились пользоваться Expression Controller, если у вас что-то не вышло, посмотрите готовый мотор:

Motor.max

Большое спасибо и до свидания.

44277 Автор:
Актуальность: 418
Качество: 462
Суммарный балл: 880
Выбор Публики
Голосов: 46 оценки

Отзывы посетителей:

2 | След.
аватар
 
Leonidych 87 0
Автору, пять баллов! Молодец!
Я, в своё время, делал подобное но гораздо более интерактивным и доступным способом.
Найду время, обязательно напишу как сделать то же самое, без всей этой математики.
Спасибо!
аватар
 
NSasha 1 0
Это было круто! Но только для математиков!
аватар
 
furmanOFF 16 0
Большое спасибо за отзывы.

В целом я и не ожидал больших баллов, действительно, работа не слишком актуальна.
Я попытался показать, что не стоит ограничиваться предложенными инструментами, ведь выучить ту или иную программу – это не цель, это всего лишь средство.
Что я хочу сказать – развиваемся, ставим новые цели и добиваемся их, а то мы так и останемся только пользователями.
аватар
 
maxer 7 0
Уважаю людей, которые пишут такие классные уроки. Голосовать за них не будут. А учиться будут. Спасибо.
аватар
 
scripterBB 11 0
В реальной работе, когда время дорого, применение маловероятно...
аватар
 
crest 7 0
Сложно, но не актуально.
аватар
 
rendermax80 -8 0
Высший пилотаж.
большинству не нравится потому что не хотят заниматься MAX серьёзно.
Поэтому и остаются на любительском уровне всю жизнь.
аватар
 
ovodav 27 0
труд сделан большой но я согласен с KuvicK ..... проще можна сделать... без расщета траектории полета в другую галактику....
аватар
 
Moon Man 37 0
Блин, я не математики, и не профессор, я просто дизайнер. Что за ядрёные формулы? Мне такое не по душе ((
аватар
 
GenPLan 5 0
Хочу выразить благодарность автору за написание данного урока. Если честно была у меня идея написать что-то похожее про манипуляторы, но опоздал.
Для полноты я бы добавил больше теории. Ребята, которые владеют ТММ (теория машин и механизмов) вполне понимают что здесь и к чему, но другие могут срезаться на первых же формулах. Сама же идея постановки сцены в максе довольно проста, но сам механизм делает работу достаточно муторной. Во избежание этого есть такая штука как Структурный Анализ Механизма. Это основы ТММ. Вы можете спросить, зачем всё мне это знать? Ответ долгий. Конечно, можно обойтись и без этого как в принципе говорили раньше. Но если вам нужна точность, правильная скорость движения каждой детали и наглядность. Или к примеру: у вас многозвенный замкнутый механизм, а нужно реализовать графически как прямую так и обратную задачу. То без таких методов задача будет громоздкой, а главное непонятной. Кто боится формул, то поверьте их все считает MathCAD.
Если кто заинтересовался данным вопросом, то я с удовольствием его освещу более подробно.
аватар
 
Banderas 2 0
а мне понравилось.....
аватар
 
Юрий Гузеев 12 0
Да!!!
Поработал от души.
Если бы все так серьёзно относились к работе с 3DS MAX, думаю, догнали бы буржуев и перегнали.
Хочу поставить 5+5, но к сожалению, после нажатия на кнопку "Проголосовать" ничего не происходит...
Это вопрос к модераторам. В чём дело???
В общем, так держать!!!
аватар
 
Vasya Dyachencko 7 0
Что могу сказать!? МУЖИК!!!!
аватар
 
const.ant 2 0
А что это всем так формулы не нравятся? Математика - это же самая лучщая наука, без нее никакого 3д бы не было... тем более что формулы не такие уж и сложные
аватар
 
Yamato 15 0
эх, начал я читать это в воскресенье утром.... и жизнь мне стала не мила.......
ЗЫ:: формулы - жесть
аватар
 
KuvicK 11 0
Для облегчения жизни в МАХе есть куча привязок, constraint'ов, IK'ев и прочего. Остается только применять.
Reactor может и будет работать, но либо очень криво, либо очень тормозно.
аватар
 
KuvicK 11 0
+ поступательные движения. Reactor'ом мягко говоря за***... мучаетесь. Пробовал
аватар
 
furmanOFF 16 0
Отвечая на предыдущие комментарии, скажу что любой способ анимации занял бы не меньше времени (на настройку и подготовку).
За исключением, конечно, reactor.
Но его я не взял, потому что искал способ анимации более «интерактивный», а reactor не дал бы мне видеть движение всех остальных деталей в процессе разработки (ведь анимация мотора - это не простое верчение по часовой или против…).
аватар
 
Русских Денис 32 0
Снимаю шляпу. :)

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

Однако техническая подкованность автора вызывает уважение. :)
аватар
 
Konstantin Tretyakoff 2 0
Я в восторге. Очень емко и без "воды". Давай еще!
2 | След.
Зарегистрируйтесь, чтобы добавить комментарий.
Эту страницу просмотрели: * уникальных посетителей