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

как сослаться на текущий разворот объекта?

Тема в разделе "MAXScript", создана пользователем morkovni, 5 мар 2011.

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

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    подскажите пожалуйста как в max script сослаться на текущий разворот объекта вокруг оси x по аналогии с текущим положением: $Box01.pos.x ??? я ввожу $Box01.rot.x - script ругается на неизвестный параметр "rot"
     
  2. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    $Box01.rotation.x_rotation
     
  3. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    помогите разобраться: допустим в сцене 2 объекта - box01 и box02. box01 крутится вокруг x, т.е. угол разворота меняется от нуля и до бесконечности. я хочу чтобы 2 раза за оборот box01, box02 поворачивался на 90 градусов, а остальное время оставался неподвижным.

    вот мой скрипт (x - переменная, привязанная к box01.rotation.x):


    if abs(cos(x))>0.9 then
    ($Box02.rotation.y_rotation+0.05)
    else $Box02.rotation.y_rotation

    галочку real time снял.
    по идее за каждый кадр анимации при выполнении условия cos>0.9 Box02 должен поворачиваться на 0.05 радиан, а потом останавливаться, но этого не происходит. box02 вращается постоянно и в разные стороны...
    подскажите где ошибка?
     
  4. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Допустим твой скрипт находится в контроллере box02.rotation.y (тип Float Script).
    1. Установи для контроллера box02.rotation.y тип Bezier Float.
    2. Создай еще один объект box03, установи для контроллера box03.rotation.y тип Float Script и напиши:
    Код:
    if abs(cos(x))>0.9 then 
    (rotate $Box02 (EulerAngles 0 (0.05*(180/PI)) 0)  )
    0
    где x - переменная, привязанная к box01.rotation.x
    PS. Логику задачи я не понял.
     
  5. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    суть в том чтобы привязать прерывистое вращение одного объекта к непрерывному вращению другого. abs(cos(x))>0.9 означает что первый будет вращаться только тогда, когда второй проходит угол от -25 до 25 +/- 2*PI*n и от 155 до 205 +/- 2*PI*n

    а в чем логика создания дополнительного объекта??
     
  6. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    выдает либо эту:

    >> MAXScript Script Controller Exception: -- Unable to convert: OK to type: Float <<


    либо эту ошибку:

    -- Error occurred in anonymous codeblock
    >> MAXScript Script Controller Exception: -- Type error: Call needs function or class, got: OK <<

    вот мой скрипт:

    if F>1999 then (
    if ((abs(cos(disk)))>0.9) then (
    rotate $Object100 (EulerAngles 0 (abs(sin(disk+90))) 0) ) else 0 ) else 0
     
  7. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Суть в том, чтобы не получилось циклическая зависимость. Создаю один вспомогательный объект (box03) и теперь можно с его помощью контролировать остальные объекты в сцене.
    Не нужно писать "else 0". Нужно просто в последнию строчку скрипта написать 0 (ноль), как в моем скрипте.
     
  8. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    так тоже пробовал. с else первая ошибка, без else - вторая (см. выше)
     
  9. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Давай по порядку. Ты в новой сцене создал 3 бокса box01, box02, box03 и выполнил действия которые описываются в посте 4 и появилась какая-то ошибка? Сначала нужно анимировать бокс box01 и создать ключи.
    А вариант, чтобы сразу создать ключи для контроллера box02.rotation.y Bezier Float в нужных кадрах для объекта box02 и не мучиться с этим контроллером Float Script не подходит?
     
  10. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    ключи создать будет намного сложнее, так как во-первых объектов, зависимых от первого около десяти, во-вторых вращение первого неравномерное, в-третьих поворот зависимых объектов на 90 градусов тоже неравномерный...

    да, создал 3 объекта, все как написано... переменную привязываю через Assign track, max 2010...
     
  11. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    более того, я создал новую сцену и box01, и просто в max script listener написал:
    rotate $Box01 eulerangles 0 0 1
    и получил ошибку:
    -- Argument count error: rotate wanted 3, got 5
     
  12. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Изучать MaxScript постепенно и писать простые примеры это хорошо. Конечно нужно знать немного английский язык.
    -- Argument count error: rotate wanted 3, got 5
    Перевод: Ошибка, неправильное количество аргументов: функции rotate нужно не более 3 аргумента, а было написанно 5 аргументов.
    Поэтому нужно писать eulerangles 0 0 1 в скобках.
    Правильно будет: rotate $Box01 (eulerangles 0 0 1)

    Выполни эти действия и посмотри, если работает этот простой пример:
    1. Создай новую сцену (меню File > New).
    2. Создай новый скрипт (меню MaxScript > New Script).
    3. Скопируй текст скрипта и запусти его (меню File > Evaluate All).
    4. Сделай рендер кадров с 0 до 100 или просто перемещай таймслайдер.
    Код:
    box01= Box(); box01.name="Box01"; box01.pos=[0,0,0] 
    box02= Box(); box02.name="Box02"; box02.pos=[100,0,0]
    box03= Box(); box03.name="Box03"; box03.pos=[200,0,0]
    sliderTime=0
    box01_rotation_x_c= box01.rotation.x_rotation.controller
    with animate on
    (
    at time 10 box01_rotation_x_c.value=box01_rotation_x_c.value+50
    at time 20 box01_rotation_x_c.value=box01_rotation_x_c.value+80
    at time 50 box01_rotation_x_c.value=box01_rotation_x_c.value+40
    at time 100 box01_rotation_x_c.value=box01_rotation_x_c.value+200
    )
    box03.rotation.y_rotation.controller=float_script();
    box03_rotation_y_c=box03.rotation.y_rotation.controller
    str="x=$Box01.rotation.x_rotation.controller.value"+"\n";
    str=str+"if abs(cos(x))>0.9 then "+"\n"; 
    str=str+"(rotate $Box02 (EulerAngles 0 (0.05*(180/PI)) 0))"+"\n"; 
    str=str+"0"+"\n"; 
    box03_rotation_y_c.script=str; 
    
    box02.rotation.y_rotation.controller.value=0;
     
  13. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    да, этот скрипт работает... все понял, скрипт с rotate нужно писать только в max script listener... спасибо!
     
  14. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    у меня новая проблема: box02 вращается прерывисто, но скорость его вращения не связана со скоростью вращения box01.
    т.е. в начале, когда box01 начинает вращение, скорость еще мала и возрастает, 50 градусов (когда abs(cos(x))>0.9) соответствует 6-ти кадрам анимации, соответственно box02 поворачивается 6 раз на заданный угол. а когда скорость вращения box01 возрастает, 50 градусов оборота соответствует одному кадру анимации, и box02 поворачивается только один раз на заданный угол... результат сильно не устраивает... подскажите, возможно ли привязать вращение box02 не к кадрам анимации или к перемещению таймслайдера, а к скорости вращения box01???
     
  15. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Если я правильно понял, тогда после выполнения действий из поста 12, попробуй в окне Time Configuration увеличить количество кадров в секунду FPS (Frames Per Second), например FPS=300.
     
  16. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    а разве это что-то изменит? тогда вместо 6-ти будет 600 кадров, а вместо 1-го - 100, т.е. опять же не постоянный поворот... я вот думаю если была бы возможность как-то получить значения вращения box01 на текущем и следующем кадре, то можно будет задать зависимость вращения box02 от скорости вращения box01
     
  17. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
    Есть такая возможность. Используй конструкцию: at time
    Пример: Есть 2 объекта Box01 и Box02. Оба объекта имеют котроллеры по умолчанию. Объект Box01 анимирован с помощью ключей с кадра 0 до 100. Объект Box01 вращается вокруг оси X относительно его Pivot-а в системе координат родителя. Нужно вычислить скорость объекта Box01 для каждого кадра, в котором соблюдается некоторые условия и использовать эту скорость для вращения объекта Box02 вокруг оси Y относительно его Pivot-а в системе координат родителя. Нужно создать кадры для объекта Box02 в каждом кадре. Допустим нужно вращать прерывисто объект Box02 в 2 раза медленнее чем объект Box01.
    Запусти скрипт в новой сцене:
    Код:
    box01= Box(); box01.name="Box01"; box01.pos=[0,0,0] 
    box02= Box(); box02.name="Box02"; box02.pos=[100,0,0]
    sliderTime=0
    box01_rotation_x_c= box01.rotation.x_rotation.controller
    with animate on
    (
    at time 10 box01_rotation_x_c.value=box01_rotation_x_c.value+50
    at time 20 box01_rotation_x_c.value=box01_rotation_x_c.value+80
    at time 50 box01_rotation_x_c.value=box01_rotation_x_c.value+40
    at time 100 box01_rotation_x_c.value=box01_rotation_x_c.value+200
    )
    -------------------
    for t in 1 to 100 do
    at time t
    (
    box01_rotation_x_c=$Box01.rotation.x_rotation.controller
    box02_rotation_y_c=$Box02.rotation.y_rotation.controller
    box01_rotation_x_c_value_current=box01_rotation_x_c.value
    if (abs(cos(box01_rotation_x_c_value_current))>0.9)then
    (
    at time (t-1) box01_rotation_x_c_value_previous=box01_rotation_x_c.value
    box01_speed=box01_rotation_x_c_value_current-box01_rotation_x_c_value_previous
    box02_speed=box01_speed/2
    with animate on ( box02_rotation_y_c.value=box02_rotation_y_c.value+box02_speed )
    )
    else with animate on ( box02_rotation_y_c.value=box02_rotation_y_c.value+0 )
    )
     
  18. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    спасибо, попробую. а подскажите как в макс скрипте создать двумерный массив-счетчик, A[i;j] , чтобы посчитать за сколько кадров box01 поворачивается на свои 50 градусов??
     
  19. igorznag

    igorznag Знаток

    С нами с:
    23.04.2010
    Сообщения:
    1.255
    Симпатии:
    173
    Баллы:
    65
  20. morkovni

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

    С нами с:
    25.10.2008
    Сообщения:
    192
    Симпатии:
    0
    Баллы:
    11
    извините за мою настойчивость и глупые вопросы, но может вы поможите:
    вот мой скрипт:



    A=#()
    V=0
    for i=1 to 5000 do (A=0)
    for t=2500 to 5000 do
    (
    at time t
    (disk_rot_z=$disk.rotation.z_rotation.controller.value
    if (abs(cos(disk_rot_z))>0.9) then
    ((A[t]=A[t]+1)
    V=A[t]
    ( at time (t+1)
    (disk_rot_z=$disk.rotation.z_rotation.controller.value
    if (abs(cos(disk_rot_z))>0.9) then
    (A[t+1]=(V)) else (A[t+1]=(0))
    )
    )
    ) else A[t]=0
    )
    "print(A[t]); print(t)" )

    B=#()
    for i=1 to 5000 do (B=0)
    for t=2500 to 5000 do
    (if A[t]>0 then
    (B[t]=1
    j=1
    while A[t+j]>0 do
    ((B[t]=B[t]+1)
    (j=j+1))
    ) else B[t]=0
    "print(A[t]); print(B[t]); print(t);"
    )

    for t=2500 to 5000 do
    (at time t
    (
    object100_rotation_y_c=$object100.rotation.y_rotation.controller
    if (B[t]>0) then
    ( (object100_speed=((51/(B[t]+A[t]-1)) as float))
    with animate on ( object100_rotation_y_c.value=((object100_rotation_y_c.value+object100_speed) as float) )
    )
    else with animate on (object100_rotation_y_c.value=((object100_rotation_y_c.value+0) as float))
    ); "print(t); print(A[t]); print(B[t]); print(object100_speed);"
    )



    проблема в конце, в том, что object100_speed везде получается целым, несмотря на применение as float... подскажите, как object100_speed превратить во float??
     
Модераторы: Savin Denis

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