пятница, 10 июня 2016 г.

Вращение колес посредством maxscript.

Данный скрипт предназначен для анимации сразу большого массива колес!

Если Вам надо заригить колеса в одном авто, лучше пройти по ссылкам ниже.  Данный случай постараюсь рассмотреть позже.

Для корректной работы колесам необходимо применить ResetXForm.

Также, в зависимости от способа копирования колес (mirror или instance с разворотом), возможно понадобится отдельно настраивать вращение для левых и правых колес (по часовой стрелке или против).

Сразу про недостатки:
- покадровая анимация
- морока с настройкой колес
- наверняка можно оптимизировать, но такая задача не ставилась. Главное, что более менее корректно работал. 

---------------------------------------------------------------
-- tested in 3DMax 2014
try destroyDialog WheelAnimator catch()

global arrFrontWheel, arrBackWheel, arAllData = #()

--function
fn sumArData ar = (
    sum = 0
    for i in ar do  sum+=i
    sum
    )
   
fn wheelRotationFlipZ_180 arW fb = if arW.count != 0 do for i in arW do if fb then rotate i (angleaxis 180 [0,0,1]) else rotate i (angleaxis -180 [0,0,1])

    -- arWheel - array wheels, wheelRadius - value, theAxis - axis rotation(1 - "X" or 2-"Y"), AngFlip - clockwise(counterclockwise) (true or false)   
fn wheelWriteDataAnimation arW wheelRadius theAxis AngFlip FB = (
                if arWeel.count != 0 do(
                    arAllData = #()
                    for w in arW do(
                        case FB of(
                            ("FrontWheel"): (
                                            local arTransform = #(), arAng = #()
                                            --weelRadius
                                            if wheelRadius == 0 do wheelRadius =  (w.max.z - w.min.z)/2.0
                                            --delete old keys
                                            sliderTime =  animationRange.start
                                            deleteKeys w #allKeys
                                            --write data
                                            for t = animationRange.start to animationRange.end do (
                                                    at time t (
                                                            p0 = at time t w.position; p1 = at time (t+1) w.position;
                                                            dif = p1-p0; len = Length(dif); vec = normalize dif; v2 = normalize (cross vec [0,0,1]);
                                                           
                                                            theAng = (if AngFlip then 1 else -1)*(180.0*len)/(wheelRadius*pi) -- AngFlip +1 or -1
                                                            append arAng theAng; ang = sumArData arAng;
                                                           
                                                            cm = if theAxis == 1 then matrix3 v2 vec (cross v2 vec) p0 else matrix3 vec v2 (cross vec v2) p0
                                                            append arTransform ((rotateXmatrix ang)*cm)
                                                        )  -- end at time j
                                                    ) -- end for j = AnimStart to AnimEnd do
                                            append arAllData #(w, arTransform)
                                )
                            ("BackWheel"):(
                                            local arTransform = #(), arAng = #()
                                            --weelRadius
                                            if wheelRadius == 0 do wheelRadius =  (w.max.z - w.min.z)/2.0
                                            --delete old keys
                                            sliderTime =  animationRange.start
                                            deleteKeys w #allKeys
                                            --write data
                                            for t = animationRange.start to animationRange.end do (
                                                    at time t (
                                                            p0 = at time t w.position; p1 = at time (t+1) w.position;
                                                            dif = p1-p0; len = Length(dif); vec = normalize dif; v2 = normalize (cross vec [0,0,1]);
                                                           
                                                            theAng = (if AngFlip then 1 else -1)*(180.0*len)/(wheelRadius*pi) -- AngFlip +1 or -1
                                                            append arAng theAng; ang = sumArData arAng;
                                                           
                                                            cm = w.transform
                                                            append arTransform ((rotateXmatrix ang)*cm)
                                                        )  -- end at time j
                                                    ) -- end for j = AnimStart to AnimEnd do
                                            append arAllData #(w, arTransform)
                                )
                            )
                        )
                    )--end if arWeel.count != 0
    )
   
-- animation wheel by array data
fn wheelAnimation =(
        if arAllData.count != 0 do(
            for w in arAllData do(
                local num = 0
                with animate on(
                    for t = animationRange.start to animationRange.end do at time t w[1].transform = w[2][num+=1]
                    )
            --deleting unnecessary keys       
            selectKeys w[1].pos.controller animationRange.start animationRange.end
            deleteKeys w[1].pos.controller #selection   
            selectKeys w[1].scale.controller animationRange.start animationRange.end
            deleteKeys w[1].scale.controller #selection   

            )--for i in arWeel do
        )--if arWeel.count != 0 do(
    )--fn weelAnimation w arW =(

--Interface
rollout WheelAnimator "WheelAnimator"
(   
group "Selection:"
(
    listbox ListFrontWheel ""  height:5
    button addToListFrontWheel "Add front wheels" width:175
    listbox ListBackWheel ""  height:5
    button addToListBackWheel "Add back wheels" width:175
    )
group "Parameters:"
    (
    spinner radW "Wheel radius:" range:[0,100000, 0] type:#float width:100 offset:[30,0] enabled:false across:2
    checkbox theAuto "Auto" checked:true align:#center offset:[10,0]
    label lbl1 "Orientation: " align:#left across:2
    radiobuttons rb1  "" labels:#("X", "Y") default:1 align:#left  offset:[-15,0] --across:2
    checkbox theFlip "Flip (turn 180 deg around Z-ax)" checked:true align:#left
    checkbox theCW "Clockwise (or not)" checked:true align:#left
        )

button theGo "Animate" width:175 height:30  align:#left  --across:2

on theAuto changed theState do(
    radW.enabled = not theAuto.state
    if radW.enabled == false do radW.value = 0
    ) 
   
on addToListFrontWheel pressed do(
    local SelFW = selection as array, ListName = #()
    arrFrontWheel = #()
    if SelFW.count != 0 then(
            for i in SelFW do (append ListName i.name; append arrFrontWheel i;)
            ListFrontWheel.items = ListName
            ) else ListFrontWheel.items = #()
     )
   
 on addToListBackWheel pressed do(
    local SelFW = selection as array, ListName = #()
    arrBackWheel = #()
    if SelFW.count != 0 then(
            for i in SelFW do(append ListName i.name; append arrBackWheel i;)
            ListBackWheel.items = ListName
            ) else ListBackWheel.items = #()
     )

on theFlip changed theState do (wheelRotationFlipZ_180 arrFrontWheel theFlip.state; wheelRotationFlipZ_180 arrBackWheel theFlip.state;)   
   
on rb1 changed state do (
    wheelWriteDataAnimation arrFrontWheel radW.value rb1.state theCW.state "FrontWheel"
    wheelAnimation()
    wheelWriteDataAnimation arrBackWheel radW.value rb1.state theCW.state "BackWheel"
    wheelAnimation()
    )
on theGo pressed do (
    wheelWriteDataAnimation arrFrontWheel radW.value rb1.state theCW.state "FrontWheel"
    wheelAnimation()
    wheelWriteDataAnimation arrBackWheel radW.value rb1.state theCW.state "BackWheel"
    wheelAnimation()
    )
on theCW changed theState do    (
    wheelWriteDataAnimation arrFrontWheel radW.value rb1.state theCW.state "FrontWheel"
    wheelAnimation()
    wheelWriteDataAnimation arrBackWheel radW.value rb1.state theCW.state "BackWheel"
    wheelAnimation()
    )
) --END rollout
createDialog WheelAnimator width:200
---------------------------------------------------------------
 

Ссылки по теме:
MAXScript Tutorials: Quaternions 1/2
Rolling Ball
111_carWheel_v0.3
3DS MAX - CG Academy - The Matrix Continued
CGTalk - Wheel rig script!
Rotating the Wheels


Если необходимо просто провращать колеса без подруливания, то это можно сделать этим скриптом:

------------------------------------------------------------
 -- tested in 3DMax 2014
try destroyDialog SimpleWheelAnimator catch()
--fn
fn swa arW wr st cw rb  = ( -- arW: array wheels [#()], wr: wheel radius[float], st: step [integer], cw: Clockwise[false-true], rb: radiobuttons [integer]
    if arW.count != 0 do(
        for w in arW do(
            deleteKeys w #allKeys
                for t = animationRange.start to animationRange.end by st do(
                    p0 = at time (t-st) w.position; p1 = at time t w.position; d = length (p1-p0); u += (if cw then 1 else -1)*180.0*d/(wr*pi);
                    case rb of(
                        (1):(addnewkey w.rotation.controller.X_Rotation.controller t).value = u
                        (2):(addnewkey w.rotation.controller.Y_Rotation.controller t).value = u
                        (3):(addnewkey w.rotation.controller.Z_Rotation.controller t).value = u
                        )
                    )
            )--for w in ws do(
        )--if ws.count != 0 do(
    )-- end fn
--Interface
rollout SimpleWheelAnimator "SimpleWheelAnimator"(  
group "Parameters:"(
    label lbl1 "Rotation axis   - " align:#left across:2; radiobuttons rb1  "" labels:#("X", "Y", "Z") default:1 align:#left    columns:3;
    checkbox theCW "Clockwise" checked:true align:#left across:2; spinner sf "Step:" range:[1,100000, 20] type:#integer width:60  align:#left;  
    spinner radW "Wheel radius:" range:[0,100000, 40] type:#float width:100 align:#left  --enabled:false across:2; checkbox theAuto "Auto" checked:true align:#center offset:[10,0]
        )
button theGo "Animate selection!" width:175 height:30  align:#left  --across:2
on theAuto changed theState do(
    radW.enabled = not theAuto.state
    if radW.enabled == false do radW.value = 0
    )
on theGo pressed do swa (selection as array) radW.value sf.value theCW.state rb1.state
on theCW changed theState do    swa (selection as array) radW.value sf.value theCW.state rb1.state
on rb1 changed state do swa (selection as array) radW.value sf.value theCW.state rb1.state
) --END rollout
createDialog SimpleWheelAnimator width:200
------------------------------------------------------------

Комментариев нет:

Отправить комментарий