Render.ru

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

morkovni

Активный участник
Рейтинг
11
#1
подскажите пожалуйста как в max script сослаться на текущий разворот объекта вокруг оси x по аналогии с текущим положением: $Box01.pos.x ??? я ввожу $Box01.rot.x - script ругается на неизвестный параметр "rot"
 

morkovni

Активный участник
Рейтинг
11
#3
помогите разобраться: допустим в сцене 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 вращается постоянно и в разные стороны...
подскажите где ошибка?
 

igorznag

Мастер
Рейтинг
103
#4
Допустим твой скрипт находится в контроллере 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. Логику задачи я не понял.
 

morkovni

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

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

morkovni

Активный участник
Рейтинг
11
#6
выдает либо эту:

>> 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
 

igorznag

Мастер
Рейтинг
103
#7
Суть в том, чтобы не получилось циклическая зависимость. Создаю один вспомогательный объект (box03) и теперь можно с его помощью контролировать остальные объекты в сцене.
Не нужно писать "else 0". Нужно просто в последнию строчку скрипта написать 0 (ноль), как в моем скрипте.
 

morkovni

Активный участник
Рейтинг
11
#8
так тоже пробовал. с else первая ошибка, без else - вторая (см. выше)
 

igorznag

Мастер
Рейтинг
103
#9
Давай по порядку. Ты в новой сцене создал 3 бокса box01, box02, box03 и выполнил действия которые описываются в посте 4 и появилась какая-то ошибка? Сначала нужно анимировать бокс box01 и создать ключи.
А вариант, чтобы сразу создать ключи для контроллера box02.rotation.y Bezier Float в нужных кадрах для объекта box02 и не мучиться с этим контроллером Float Script не подходит?
 

morkovni

Активный участник
Рейтинг
11
#10
ключи создать будет намного сложнее, так как во-первых объектов, зависимых от первого около десяти, во-вторых вращение первого неравномерное, в-третьих поворот зависимых объектов на 90 градусов тоже неравномерный...

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

morkovni

Активный участник
Рейтинг
11
#11
более того, я создал новую сцену и box01, и просто в max script listener написал:
rotate $Box01 eulerangles 0 0 1
и получил ошибку:
-- Argument count error: rotate wanted 3, got 5
 

igorznag

Мастер
Рейтинг
103
#12
Изучать 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;
 

morkovni

Активный участник
Рейтинг
11
#13
да, этот скрипт работает... все понял, скрипт с rotate нужно писать только в max script listener... спасибо!
 

morkovni

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

igorznag

Мастер
Рейтинг
103
#15
Если я правильно понял, тогда после выполнения действий из поста 12, попробуй в окне Time Configuration увеличить количество кадров в секунду FPS (Frames Per Second), например FPS=300.
 

morkovni

Активный участник
Рейтинг
11
#16
а разве это что-то изменит? тогда вместо 6-ти будет 600 кадров, а вместо 1-го - 100, т.е. опять же не постоянный поворот... я вот думаю если была бы возможность как-то получить значения вращения box01 на текущем и следующем кадре, то можно будет задать зависимость вращения box02 от скорости вращения box01
 

igorznag

Мастер
Рейтинг
103
#17
Есть такая возможность. Используй конструкцию: 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 )
)
 

morkovni

Активный участник
Рейтинг
11
#18
спасибо, попробую. а подскажите как в макс скрипте создать двумерный массив-счетчик, A[i;j] , чтобы посчитать за сколько кадров box01 поворачивается на свои 50 градусов??
 

morkovni

Активный участник
Рейтинг
11
#20
извините за мою настойчивость и глупые вопросы, но может вы поможите:
вот мой скрипт:



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??
 
Сверху