1. Пользоваться форумом на планшетах и телефонах стало удобнее благодаря Tapatalk

Проблемы с вращением

Тема в разделе "MAXScript", создана пользователем aaaantares, 21 июн 2010.

Модераторы: Savin Denis
  1. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Всем привет! У меня тут возник вопрос. Представьте себе два одинаковых объекта. Задача простая - нужно сделать так, чтобы при вращении одного объекта второй вращался вдвое медленнее. То есть, когда я прямо во вьюпорте поворачиваю мышкой первый объект, второй должен тут же поворачиваться на вдвое меньший угол. Все просто, когда объекты свободны - выделяешь ведомый объект, идешь на вкладку motion, выбираешь нужную ось, назначаешь Rotation Script, там создаешь переменную, и нажимаешь кнопку Assign Track. Далее в открывшемся списке выбираешь ведущий объект и трек его вращения вокруг той же оси. Все работает - потому что в данном случае я получаю в переменную угол поворота, неограниченный 360 градусами - то есть, если я ведущий объект повернул три раза, то переменная у меня примет значение 360*3=1080. Таким образом, я могу теперь просто поделить это число пополам, и ведомый объект будет поворачиваться как и должен на угол, вдвое меньший.
    Вся сложность приходит тогда, когда ведущий объект сам уже управляется каким то плагином, и у него вообще нет трека вращения вокруг интересующей оси. Обычно, я в таком случае делаю следущее: создаю три поинта, два из них линкую к ведущему объекту, один линкую к миру. Тогда, при вращении мышкой ведущего объекта я могу отследить угол, на который я поворачиваю ведущий объект - этот угол будет равен углу, образуемому тремя поинтами. Но этот угол может лежать в пределах от 0 до 360! я таким способом не могу узнать, на сколько оборотов я повернул свой ведущий объект. Если угол ведущего меняется от 0 до 360, то после деления пополам, угол поворота ведомого объекта будет меняться от 0 до 180. То есть, если я ведущий объект поверну на два оборота ровно, то по идее, ведомый объект должен повернуться на один оборот. Однако, на деле (из за того что угол его поворта не больше 180, как сказано выше) получается следущее - ведомый объект поворачивается сначала от нуля градусов до 180, а потом происходит резкий скачок назад - опять на ноль градусов - и все повторяется - поворот от нуля до 180. Вместо того, чтобы совершить полный оборот, ведомый объект два раза проходит первую половину оборота. Мои детали обладают осью симметрии второго порядка - внезапный поворот на 180 градусов проходит незаметно. Когда анимация просматривается во вьюпорте, никаких проблем и не видно - все вполне номально крутится. Но когда включается motion blur, все обнаруживается. Дело в том, что MB отслеживает положения объектов в трехмерном пространстве - и каждый кадр ведомый объект поворачивается на небольшой угол, как и должен. Но в одном кадре происходит скачок на 180 градусов - MB начинает думать, что объект крутится со страшной силой (за один кадр поворот на целых полоборота!), и размазывает его так, что ведомый объект в этом кадре становится почти невидим. Один-единственный кадр, но он портит впечатление. Был вариант заменить этот кадр соседним - но получается заметная задержка во времени, да и просто хочется разобраться, как же заставить ведомый объект крутиться как следует? Прошу прозения за многабукаф:)
     
  2. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    Для решения этой задачи нужно работать с относительным углом поворота, то есть взять дельту угла между текущим и предыдущим кадром, разделить и добавить к углу требуемого объекта. Для того чтобы можно было добавлять угол нужно использовать внешний контроллер.
     
  3. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Да, была такая идея. Но как получить значения переменных за предыдущий кадр? Большинство углов я получаю через скалярное произведение, поэтому мне достаточно знать все положения нужных поинтов. Таким образом, вопрос следущий - как через конструкцию Point.transform.Position получить радиус-вектор точки из предыдущего кадра? а еще лучше даже не из предыдущего кадра, а с предыдущего момента пересчета переменных. То есть, когда я кручу ведущий объект прямо во вьюпорте, ползунок таймлайна не меняется - я все это время стою на одном кадре. Тем не менее, пока я держу зажатой ЛКМ и двигаю мышь, положения точек пересчитываются с какой то частотой, и это отражается на тех параметрах, которые зависят от этих положений. Я не знаю, каким образом это реализовано, и вообще можно ли добраться до этих скрытых внутренних "кадров".
     
  4. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    Для этого существует модификатор at time, читаем хелп внимательно.

    Кто тебе мешает запомнить в переменной ?

    Вообще я бы советовал отказаться от интероактивности, здесь она только мешать будет, сделав утилитой которая просто пропишет ключи.
     
  5. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    а что нельзя создать переменную к которой будет прибавляться значение угла?
     
  6. Savin Denis vip

    Savin Denis Moderator Команда форума

    С нами с:
    05.05.2005
    Сообщения:
    1.633
    Симпатии:
    0
    Баллы:
    210
    Проблема не в переменной, а в том что нельзя правильно рассчитать анимацию если собьется последовательность анимации, например если слайдер отмотать назад.
     
  7. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Не спрашивайте меня зачем я поднял тему, просто скажите, как пользоваться at time так, чтобы было правильно? То есть, я смог с помощбю него найти разницу между углом поворота в текущем кадре и глом поворота в предыдущем кадре. Как теперь эту добавку добавить к углу поворота другого объекта? Вот в Delphi это было бы так: X:=X+dX. Как это записать на языке макс скрипт? Я уже готов монитор разбить!
     
  8. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    expose transform испробовал?
     
  9. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Попробовал Expose Transform. На деле оказалось, что это тоже самое что и мои три поинта, о которых я говорил в первом посте. Он выдает углы от 0 до 360 (точнее от -180 до 180, но это все можно привести к обычному от 0 до 360) и все, поэтому моя первоначальная проблема решена не будет. Но за совет спасибо, использовать Expose Transform гораздо удобнее чем тыкать на каждую вращающуюся деталь по три хелпера да потом писать скрипт, во многих случаях, где мне надо будет просто передать вращение от одной детали к другой я буду использовать теперь именно Expose Transform (Надо еще попробовать wire, но эта штука как я понял устанавливает взаимосвязь только между двумя объектами, а у меня должны быть связаны как минимум три объекта, я об этом не написал в первом посте чтобы упростить вопрос. На самом деле, угол поворота одного объекта есть половина суммы углов поворота двух других объектов, которые вращаются соверенно независимо. Это важное уточнение, потому что на вопрос, заданный в первом посте я получил в Лс исчерпывающий ответ, но как оказалось это не то что нужно).
    Но я кажется понял, о чем говорил Savin Denis, я теперь представляю как использовать относительные углы, а этот способ универсальный и точно будет работать.
     
  10. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    Так через wire parametres и надо сделать. Настроить как надо expose transform и завайрить соответствующий трек. Меня удивляет как ты знаешь некоторые вещи а некоторые которые проще, нет))
     
  11. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    А я думал что при использовании вайров не обязательно пользовать expose transform. То есть это две альтернативы - можно использовать вайры, а можно - expose transform:) Или сочетая вайры и expose transform можно организовать взаиимодействие сразу несокльких объектов? Расскажи если не трудно поподробнее:)
     
  12. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    Вот где нужен expose transform когда нет трека вращения. А wire просто связывает. Видел вопрос на 3дцентре. Насчет rotation list в курсе? Ведомому объекту назначаешь rotation list. Ему нужно 2 euler xyz. Вращения по Z одного обьекта вайришь к вращения по оси Z одного eulera xyz, а вращение по Z другого объекта к вращению по Z другого euler xyz. И ставишь 50% процентов каждому euler xyz. Могу скинуть сцену в 2010 или 2011 максе.
     
  13. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Ух ты. Сейчас попробую. Я полагал что должно быть что-то подобное но не знал где искать. Ну-ка, сейчас посмотрим на этот rotation list.
     
  14. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Попробовал, хорошая штука:) Правда проблема со скачком на пи так и остается:) Хорошо видно, если ведомый объект не симметричный. Но в большинстве случаев на этот скачок можно будет наплевать. Видимо все же придется использовать утилиту, которая пропишет ключи, и действительно отказываться от интерактивности, как собсвтенно мне сразу и посоветовал Savin Denis. Да и не сильно жалко, все равно из за довольно тяжелой геометрии все тормозило при записи сразу всей анимации прямо во вьюпорте. Утилиту эту я в принципе уже и написал. А плюс ко всему, благодаря тебе, kolts, я теперь могу все свою поинты выкинуть за ненадобностью, а их там не меньше двух десятков было:)
     
  15. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    Я вообще не понял как может быть скачок на пи. Используешь wire parametres? Ведь это просто связь. Ведомый объект отвечает сразу и кадры анимации вообще не при чем.
     
  16. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Да, я использую Wire. тут все просто - возьми три плоскости, сделай среднюю какой нибудь кривой, несимметричной чтоб была и попробуй все сделать как ты сказал. Rotation List, в нем два EulerXYZ, к одному вайришь вращение по оси З одной ведущей плоскости, к другому - вращение по оси З другой. а потом прям во вьюпорте крутишь любую из ведущих плоскостей. Ведомый объект будет поворачиваться вдвое медленнее (никаких кадров, просто глазами увидишь, так и должно быть, потому что вес-то 50), а потом внезапно резко повернется сразу на 180 градусов. Это можно заметить только если ведомый объект несимметричен, или если симметричен, но включен motion blur, это уже при рендеринге. Кстати, можнт моно какнибудь отследить этот скачок? Например, если видно что вот сейчас произойдет скачок, то в этот момент сразу вычесть эти 180 градусов, чтоб скомпенсировать. Тогда было б совсем хорошо.
     
  17. kolts

    kolts Активный участник

    С нами с:
    05.02.2008
    Сообщения:
    448
    Симпатии:
    0
    Баллы:
    17
    Не знаю почему так видимо 50 процентов так отрабатывает. Проверил увидел, что самое смешное, что на обычном кубе такое не заметно, сделал кривую плоскость и увидел скачок. Тогда проценты оставь 100, но формуле вайра напиши Z_Rotation*0.5 то есть добавь *0.5. Так скачков нет. Ну я в качестве примера использую Z. Вообще там еще есть подводный камень - гимбал лок. Если не слыхал, почитай это основы. Но если использовать ось Z то он не должен выплыть.
     
  18. aaaantares

    aaaantares Знаток

    С нами с:
    17.07.2006
    Сообщения:
    40
    Симпатии:
    1
    Баллы:
    22
    Все, наконец-то решил свою проблему:) Не обошлось без вазелина конечно (например, в некоторых случаях Expose transform выдавал нули вместо углов, и от них пришлось частично отказаться, в пользу расстановки ключей), но зато результат меня устроил:) Боялся, что при расстановке ключей со временем начнет сказываться какая нибудь ошибка округления, но надеюсь при расчетах MAX Script будет округлять до блиайшего целого, и накопления не произойдет. Под конец совсем обалдел - как оказалось запись (21/15)* и 1.4* приводит к разным результатам (проверял несколько раз). Но пора бы уе привыкнуть к такого рода проблемам.
     
Модераторы: Savin Denis

Поделиться этой страницей