Render.ru

Вопрос по анимации в Wire Parameters

Рейтинг
2
#1
Есть вращающаяся шестеренка 1, в 25 кадре к ней прилегает вторая шестеренка, вращение передается через wire parameters. Возникает неприятная ситуация в момент начала анимации - вторя шестеренка в 25 кадре делает резкий рывок и только затем плавно вращается вместе с 1ой шестеренкой.

В wire parameters прописан такой скрипт
Код:
if slidertime > 24 then Y_Rotation else 0
Я понимаю что рывок второй шестеренки происходит из-за того что она копирует вращение первой шестеренки, но как передать вращение одной шестеренки к другой без этого рывка?
По идее надо вычесть текущее вращение второй шестеренки_Y из текущего вращения первой шестеренки_Y и после этого увеличивать значение_Y, но мне не хватает знаний MaxScript. Буду рад любой помощи
 

LastJedi

Знаток
Рейтинг
27
#2
Если вращение после 25 кадра полностью устраивает, то чтобы не было рывка, нужно изменить ориентацию ведомой шестерни до начала вращения. То есть, до 25-го кадра вторая шестерня должна иметь поворот не 0, а в точности такой же, как первая шестерня в 25-ом кадре.
Добиться этого можно следующим выражением:
Код:
if slidertime > 24 then Y_Rotation else at time 25 $[Имя первой шестерни].rotation.y_rotation
 
Симпатии: xCube
Рейтинг
2
#3
LastJedi
Спасибо, способ хороший, но в моем случае это не подошло, тк во время анимации шестеренка отключается и подключается не один раз. Нужно именно чтоб 2ая шестеренка из текущего положения начинала вращаться вслед за первой в определенном кадре.
 

LastJedi

Знаток
Рейтинг
27
#4
Тогда вот так:
Код:
if currentTime > 24f then Y_Rotation - degToRad (at time 25f $[Имя первой шестерни].rotation.y_rotation) else 0.0
 
Симпатии: xCube
Рейтинг
2
#5
Огромное спасибо! Работает отлично, сам бы низа что не додумался. Надо начинать учить Max Script в свободное время, все чаще попадаю в ситуацию когда без него просто никак задачу не решить.
Нарыл вот этот ресурс http://www.scriptattack.com/theory/theory.html может есть еще что нибудь полезное? Буду признателен за ссылки.
 
Рейтинг
2
#6
В процессе применения этой методики возникла странная ситуация, я немного дописал код
Код:
if currentTime > 261f then Y_Rotation*0.6 - degToRad (at time 262f $Point_OUT.rotation.y_rotation+5.0) else degToRad(-5.0)
И шестеренка начинает себя странно вести в 262 кадре. Поясню подробней в 261 кадре у шестиренки вращение равно (90.0, -5.0, 180.0), а в 262 становится (-90.0, 41.0, -0.0). Но я же работаю только с осью Y почему так происходит? можно ли это исправить?
Еще не понятно откуда берется 41.0? ведь судя по анимации шестеренка должна повернуться максимум на 2 градуса
 

LastJedi

Знаток
Рейтинг
27
#7
Это проблема не скрипта, а вполне штатное поведение углов Эйлера.

Если в процессе анимации шестерёнка совершает только вращения относительно оси Y, а по остальным осям повороты не нужны, то есть простое решение — перед настройкой анимации расположите шестерёнку в начальном («нулевом») положении, и сделайте Reset Transform (на панели Hierarchy). В результате все углы обнулятся и дальнейшая анимация будет влиять только на вращение относительно одной оси.

Если же в процессе анимации шестерня совершает пространственные повороты, то решение будет сложнее…
 
Последнее редактирование:
Симпатии: xCube
Рейтинг
2
#8
Большое спасибо! помогло! Но заметил еще одну неприятную особенность. Если у первой шестернки в 262 кадре значение поворота больше 90 градусов то вторая шестеренка начинает резко поворачиваться в этом 262 кадре.
Например если у первой шестеренки с261 по 262 кадра значение меняется с 101.265 до 108.001 то у второй скачет с 10.0 до 46.003, в споследующих кадрах уже вращается синхронно с первой.
скрипт при этом такой
Код:
if currentTime > 261f then Y_Rotation - degToRad (at time 262f $Cylinder001.rotation.y_rotation-10.0) else  degToRad(10.0)
 

LastJedi

Знаток
Рейтинг
27
#9
Да, есть такая беда, я как-то не учёл…
Проблема возникает из-за того, что $Cylinder001.rotation.y_rotation может возвращать значение угла отличное от Y_Rotation . Тому есть своя причина, не буду тут сейчас углубляться в теорию, а то получится слишком длинно.

Исправить можно следующим образом:
Rich (BB code):
if currentTime > 261f then Y_Rotation - degToRad (at time 262f $Cylinder001.rotation.controller.y_rotation - 10.0) else degToRad (10.0)
 
Симпатии: xCube
Рейтинг
2
#10
Я ваш должник ) Сколько же грабель я собрал прежде чем удалось сделать казалось бы простую вещь, как оказалось были в этой связке и другие шестеренки у которых не был сброшен Transform, они тоже плохо влияли на анимацию.
Осталось сделать размыкание шестеренки в определенном кадре.
Я попробовал дописать код
Код:
if currentTime > 261f and currentTime < 380f then Y_Rotation - degToRad (at time 262f $Point1_up.rotation.controller.y_rotation) else
if currentTime < 380f 0 else
$Shift_Collar_-_Scaled.rotation.controller.y_rotation
Конечно же компилятору как всегда что-то не нравится, не понимаю как можно сделать вложенную конструкцию If else?
 

LastJedi

Знаток
Рейтинг
27
#11
В данном случае не нравится, как минимум, отсутствие then во второй строчке.
Rich (BB code):
if currentTime < 380f then 0 else
А $Shift_Collar_-_Scaled, это что за объект?
 
Симпатии: xCube
Рейтинг
2
#12
Да верно, then забыл прописать, спасибо, теперь работает это конструкция.
$Shift_Collar_-_Scaled это и есть та шестеренка на которую воздействую через WireParameters этим скриптом
А строкой
Код:
$Shift_Collar_-_Scaled.rotation.controller.y_rotation
пытаюсь сказать программе что значение угла поворота шестеренки теперь берется у самой себя, ведь по идее она должна перестать вращаться?
Кстати компилятор не хочет принимать эту строку пишет Unknown property: "rotation" in undefined как только я не пробовал
 

LastJedi

Знаток
Рейтинг
27
#13
Эта ошибка означает, что есть где-то опечатка в имени объекта. То есть, $Shift_Collar_-_Scaled не определён (undefined), и, соответственно, у него нет свойства "rotation".

Но даже если это исправить, такой код не заработает. Вы получите другое сообщение об ошибке: Illegal self-reference in controller script, т.к. такая запись указывает, что новое значение должно быть равно самому себе, а оно до окончания выполнения скрипта ещё не определено.

Правильным будет такой вариант:
Rich (BB code):
if currentTime > 261f and currentTime < 380f then Y_Rotation - degToRad (at time 262f $Point1_up.rotation.controller.y_rotation) else
if currentTime < 380f then 0 else
degToRad (at time 379f $Shift_Collar_-_Scaled.rotation.controller.y_rotation)
 
Симпатии: xCube
Рейтинг
2
#14
Наконец все получилось! Спасибо!
Кстати в имени Shift_Collar_-_Scaled ошибки не было, но переименование этой шестеренки помогло, видимо само имя какое-то кривое было.
 

LastJedi

Знаток
Рейтинг
27
#15
Кстати в имени Shift_Collar_-_Scaled ошибки не было, но переименование этой шестеренки помогло, видимо само имя какое-то кривое было.
А, ну да)) Я и не обратил внимания. Там же «-». А для MAXScript это минус — операция вычитания. Он пытался выполнить действие:
$Shift_Collar_ - _Scaled.rotation.controller.y_rotation, и, естественно, ничего не получалось, ведь и объекта $Shift_Collar_ не существовало и переменной _Scaled со свойствами .rotation.controller.y_rotation тоже))
 
Сверху