Render.ru
Поддержать

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

Валерий Кварацхелия (xCube)

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

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

LastJedi

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

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
LastJedi
Спасибо, способ хороший, но в моем случае это не подошло, тк во время анимации шестеренка отключается и подключается не один раз. Нужно именно чтоб 2ая шестеренка из текущего положения начинала вращаться вслед за первой в определенном кадре.

LastJedi

Знаток
Рейтинг
27
Тогда вот так:
if currentTime > 24f then Y_Rotation - degToRad (at time 25f $[Имя первой шестерни].rotation.y_rotation) else 0.0

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
Огромное спасибо! Работает отлично, сам бы низа что не додумался. Надо начинать учить Max Script в свободное время, все чаще попадаю в ситуацию когда без него просто никак задачу не решить.
Нарыл вот этот ресурс http://www.scriptattack.com/theory/theory.html может есть еще что нибудь полезное? Буду признателен за ссылки.

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
В процессе применения этой методики возникла странная ситуация, я немного дописал код
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
Изменено: 2 #7
Это проблема не скрипта, а вполне штатное поведение углов Эйлера.

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

Если же в процессе анимации шестерня совершает пространственные повороты, то решение будет сложнее…

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
Большое спасибо! помогло! Но заметил еще одну неприятную особенность. Если у первой шестернки в 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
Да, есть такая беда, я как-то не учёл…
Проблема возникает из-за того, что [ICODE]$Cylinder001.rotation.y_rotation[/ICODE] может возвращать значение угла отличное от [ICODE]Y_Rotation [/ICODE]. Тому есть своя причина, не буду тут сейчас углубляться в теорию, а то получится слишком длинно.

Исправить можно следующим образом:
if currentTime > 261f then Y_Rotation - degToRad (at time 262f $Cylinder001.rotation.[COLOR=red]controller.[/COLOR]y_rotation - 10.0) else degToRad (10.0)

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
Я ваш должник ) Сколько же грабель я собрал прежде чем удалось сделать казалось бы простую вещь, как оказалось были в этой связке и другие шестеренки у которых не был сброшен 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
В данном случае не нравится, как минимум, отсутствие [ICODE]then [/ICODE]во второй строчке.
if currentTime < 380f [color=red]then [/color]0 else
А [ICODE]$Shift_Collar_-_Scaled[/ICODE], это что за объект?

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
Да верно, then забыл прописать, спасибо, теперь работает это конструкция.
$Shift_Collar_-_Scaled это и есть та шестеренка на которую воздействую через WireParameters этим скриптом
А строкой
$Shift_Collar_-_Scaled.rotation.controller.y_rotation
пытаюсь сказать программе что значение угла поворота шестеренки теперь берется у самой себя, ведь по идее она должна перестать вращаться?
Кстати компилятор не хочет принимать эту строку пишет Unknown property: "rotation" in undefined как только я не пробовал

LastJedi

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

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

Правильным будет такой вариант:
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
[COLOR=red]degToRad (at time 379f[/COLOR] $Shift_Collar_-_Scaled.rotation.controller.y_rotation[COLOR=red])[/COLOR]

Валерий Кварацхелия (xCube)

Пользователь сайта
Рейтинг
2
Наконец все получилось! Спасибо!
Кстати в имени Shift_Collar_-_Scaled ошибки не было, но переименование этой шестеренки помогло, видимо само имя какое-то кривое было.

LastJedi

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