Список примеров

Управление Biped с помощью Dummy

Содержание

Описание задачи

Выполняется анимация движения Biped, его рук и ног.
Воспроизводится сцена фигурного катания на льду.

Для перемещения Biped выполняется его группировка. Группа подчиняется помощнику Dummy:

bipObj = biped.CreateNew 70 90 [0, 0, 70] gr = group bipObj
dum0 = dummy pos:[-100, 0, 0]
gr.parent = dum0

Движением группы gr управляет контроллер Path_constraint:

pc = path_constraint()
gr.position.controller = pc

Путь, по которому движется Biped, показан на рис. 1.

Путь Biped

Рис. 1. Путь движения Biped

Путь создается следующим кодом:

s = splineShape()
addNewSpline s
nP = 25
nP2 = 2 * nP
nPP = nP * nP
--1
for i = -nP to nP do addKnot s 1 #smooth #curve [i, sqrt (nPP - i * i), 35]
--2
for i = -nP to nP do addKnot s 1 #smooth #curve [i + nP2, -sqrt (nPP - i * i), 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [nP2 - i, sqrt (nPP - i * i), 35]
--3
for i = -nP to nP do addKnot s 1 #smooth #curve [nP - sqrt (nPP - i * i), -i - nP, 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [nP + sqrt (nPP - i * i), i - nP, 35]
--4
for i = -nP to nP do addKnot s 1 #smooth #curve [-sqrt (nPP - i * i) + nP, i + nP, 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [sqrt (nPP - i * i) + nP, nP - i, 35]
--1
for i = -nP to nP by 1 do addKnot s 1 #smooth #curve [-i, -sqrt (nPP - i * i), 35]
s.Rotation.Z_Rotation = 180
updateShape s
-- Path for Path_constraint controller
pc.path = s

В процессе движения Biped по пути выполняется анимация перемещения его плечевых и бедровых костей.
Ссылки на них получаются следующим кодом:

LCalf = biped.GetNode bipObj 5 link:2
RCalf = biped.GetNode bipObj 6 link:2
LForearm = biped.GetNode bipObj 1 link:3
RForearm = biped.GetNode bipObj 2 link:3

Структуру Biped можно посмотреть на Программирование контроллеров Biped.
Перемещение плечевых и бедровых костей двуногого выполняется функцией oneStep:

fn oneStep mvLCalf mvRCalf mvLForearm mvRForearm = (
    actionMan.executeAction 972555510 "40015"
    move LCalf mvLCalf
    move RCalf mvRCalf
    move LForearm mvLForearm
    move RForearm mvRForearm
    select #(LCalf, RCalf, LForearm, RForearm)
)

Поворот Biped выполняется в результате изменения свойства Z_Rotation помощника Dummy, например:

dum0.Rotation.Z_Rotation = -180

В некоторых случаях для поворота помощника и, следовательно, Biped употребляется функция oneRot:

fn oneRot ang = (
    actionMan.executeAction 972555510 "40015"
    select #(LCalf, RCalf, LForearm, RForearm)
    dum0.Rotation.Z_Rotation = ang
)

Модель льда формируется следующим кодом:

LD = standard reflectionMap:(Raytrace()) showInViewport:true reflectionMapEnable:true
ice = box length:2000 width:2000 height:20 pos:[0, 0, -20]
ice.Material = LD

Замечание. Приводимый далее код нужно запускать дважды. После первого запуска генерируется ошибка, но при этом определяются все необходимые объекты, которые используются при повторном запуске.

Реализация

Весь MaxScript-код программы:

fn oneStep mvLCalf mvRCalf mvLForearm mvRForearm = (
    actionMan.executeAction 972555510 "40015"
    move LCalf mvLCalf
    move RCalf mvRCalf
    move LForearm mvLForearm
    move RForearm mvRForearm
    select #(LCalf, RCalf, LForearm, RForearm)
)
fn oneRot ang = (
    actionMan.executeAction 972555510 "40015"
    select #(LCalf, RCalf, LForearm, RForearm)
    dum0.Rotation.Z_Rotation = ang
)
delete $*
global LCalf, RCalf, LForearm, RForearm, dum0
max time start
-- Make a path
s = splineShape()
addNewSpline s
nP = 25
nP2 = 2 * nP
nPP = nP * nP
--1
for i = -nP to nP do addKnot s 1 #smooth #curve [i, sqrt (nPP - i * i), 35]
--2
for i = -nP to nP do addKnot s 1 #smooth #curve [i + nP2, -sqrt (nPP - i * i), 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [nP2 - i, sqrt (nPP - i * i), 35]
--3
for i = -nP to nP do addKnot s 1 #smooth #curve [nP - sqrt (nPP - i * i), -i - nP, 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [nP + sqrt (nPP - i * i), i - nP, 35]
--4
for i = -nP to nP do addKnot s 1 #smooth #curve [-sqrt (nPP - i * i) + nP, i + nP, 35]
for i = -nP to nP do addKnot s 1 #smooth #curve [sqrt (nPP - i * i) + nP, nP - i, 35]
--1
for i = -nP to nP by 1 do addKnot s 1 #smooth #curve [-i, -sqrt (nPP - i * i), 35]
s.Rotation.Z_Rotation = 180
updateShape s
sV = 100 / nP
scale s [sV, sV, 1]
move s [100, 0, 0]
hide s
-- Ice model
LD = standard reflectionMap:(Raytrace()) showInViewport:true reflectionMapEnable:true
ice = box length:2000 width:2000 height:20 pos:[0, 0, -20]
ice.Material = LD
-- Make a Biped
bipObj = biped.CreateNew 70 90 [0, 0, 70]
gr = group bipObj
dum0 = dummy pos:[-100, 0, 0]
gr.parent = dum0
-- Path assignment
pc = path_constraint()
gr.position.controller = pc
-- Path for Path_constraint controller
pc.path = s
--
LCalf = biped.GetNode bipObj 5 link:2
RCalf = biped.GetNode bipObj 6 link:2
LForearm = biped.GetNode bipObj 1 link:3
RForearm = biped.GetNode bipObj 2 link:3
max motion mode -- Sets Motion command mode active
animate on ( -- Acceleration
    at time 10 oneStep [0, 0, 5] [0, 0, 0] [0, 0, 10] [0, -10, 0]
    at time 20 oneStep [0, 0, -3.5] [0, 20, 0] [0, 0, 0] [0, -10, 0]
    at time 30 oneStep [0, -20, 0] [0, -10, 0] [0, 0, 0] [0, 0, 0]
    at time 40 oneStep [0, -20, 0] [0, -10, 2] [0, 0, 0] [0, 0, 0]
    -- Sliding
    at time 50 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 100 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, -60] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -180
    )
    at time 115 (
        oneStep [0, 0, 0] [0, 0, 0] [0, -20, 10] [0, 0, -10]
        dum0.Rotation.Z_Rotation = 0
    )
    -- Rotation
    at time 125 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 135 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 30, -30] [0, 0, -40]
        dum0.Rotation.Z_Rotation = -180
    )
    -- Sliding
    at time 145 oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
    at time 200 (
        move LCalf [0, -20, -60]
        move RCalf [0, 40, -40]
        move LForearm [0, 30, -40]
        move RForearm [0, 0, -40]
        oneStep [0, 0, 10] [-10, 40, 0] [30, 0, 0] [-30, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    -- Some rotations
    at time 250 oneRot 0
    at time 260 oneRot 90
    at time 270 oneRot 180
    at time 280 oneRot -90
    at time 290 oneRot 0
    at time 300 oneRot 90
    at time 310 oneRot 180
    at time 320 oneRot -90
    at time 330 oneRot 0
    at time 340 oneRot 90
    at time 350 oneRot 180
    -- Straightening
    at time 360 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 370 (
        oneStep [0, 0, -40] [0, 40, -40] [0, 0, 40] [0, 0, 40]
        dum0.Rotation.Z_Rotation = 0
    )
    at time 380 oneRot 90
    at time 390 oneRot 180
    -- Acceleration
    at time 450 (
        move $Bip001LCalf [0, -20, -60]
        move $Bip001RCalf [0, 40, -40]
        oneStep [0, 0, 10] [-10, 40, 0] [0, 30, -40] [0, 0, -40]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 460 oneRot 0
    at time 470 oneRot 90
    at time 480 oneRot 180
    at time 490 oneRot -90
    at time 510 oneRot 0
    at time 520 (
        oneRot 90
        move s [0, 0, 0]
    )
    at time 530 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 180
    )
    at time 540 (
        move LCalf [0, 0, -40]
        move RCalf [0, 40, -40]
        move LForearm [0, 0, 40]
        move RForearm [0, 0, 40]
        oneStep [0, 0, -40] [0, 0, -100] [0, 40, 0] [0, -40, 0]
        dum0.Rotation.Z_Rotation = -90
        move s [0, 0, 0]
    )
    -- Jumping
    at time 550 (
        oneStep [0, 40, 0] [0, -40, 0] [0, 0, 0] [0, 0, 0]
        move s [0, 0, 30]
    )
    at time 560 (
        oneStep [0, 40, 0] [0, -40, 0] [0, 40, 0] [0, -40, 0]
    )
    at time 570 (
        oneStep [70, 0, 0] [70, 0, 0] [70, 0, 0] [70, 0, 0]
        move s [0, 0, 30]
    )
    -- Landing
    at time 580 (
        oneStep [0, 70, 0] [0, -70, 0] [0, 30, -50] [0, -30, -50]
        move s [0, 0, -20]
    )
    at time 590 (
        oneStep [-10, -10, -40] [-20, 20, -40] [0, 30, 0] [0, -30, 0]
        dum0.Rotation.Z_Rotation =-90
        move s [0, 0, -40]
    )
    -- Rotation
    at time 600 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 0
    )
    at time 610 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, -60] [0, 0, -60]
        dum0.Rotation.Z_Rotation = 90
    )
    at time 620 oneStep [0, 0, -40] [0, 40, -40] [0, 0, 40] [0, 0, 40]
    at time 630 oneRot 90
    at time 640 oneRot 180
    at time 650 (
        move LCalf [0,-20,-60]
        move RCalf [0, 40, -40]
        oneStep [0, 0, 10] [-10, 40, 0] [0, 30, -40] [0, 0, -40]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 700 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -180
    )
    at time 750 (
        actionMan.executeAction 972555510 "40015"
        move LCalf [0, 60, 10]
        move RCalf [0, -40, -5]
        rotate RCalf (angleaxis 45 [1, 0, 0])
        move LForearm [0, 40, 0]
        move RForearm [0, -40, 0]
        select #(LCalf, RCalf, LForearm, RForearm)
        dum0.Rotation.Z_Rotation = -90
    )
    at time 800 oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
    at time 850 (
        oneStep [0, 0, -100] [0, 0, -20] [0, 0, -100] [0, 0, -100]
        dum0.Rotation.Z_Rotation = -180
    )
    at time 860 oneStep [0, 0, 0] [0, 20, 0] [70, 0, 0] [-70, 0, 0]
    at time 880 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 90
    )
    at time 890 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 0
    )
    at time 900 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 910 (
        oneStep [-20, 0, 0] [20, 0, 0] [20, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 920 (
        oneStep [-20, 0, 0] [20, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 180
        move s [0, 0, 0]
    )
    at time 930 (
        oneStep [-20, 0, 0] [20, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 90
    )
    at time 940 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 0
    )
    at time 950 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = -90
    )
    at time 960 (
        oneStep [-20, 0, 0] [20, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 180
        move s [0, 0, 60]
    )
    at time 970 (
        oneStep [-20, 0, 0] [20, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 90
    )
    at time 980 (
        oneStep [0, 0, 0] [0, 0, 0] [0, 0, 0] [0, 0, 0]
        dum0.Rotation.Z_Rotation = 0
    )
    at time 990 (
        actionMan.executeAction 972555510 "40015"
        move LCalf [0, 0, 0]
        move RCalf [0, 0, 0]
        select #(LCalf, RCalf, LForearm, RForearm)
        dum0.Rotation.Z_Rotation = -90
        move s [0, 0, -60]
    )
    at time 1000 oneStep [0, 0, -100] [0, 0, -100] [0, 0, 50] [0, 0, 50]
)
viewport.SetGridVisibility 4 false
animationRange = interval 0f 1000f
select s
playAnimation()

Источники

  1. Autodesk® 3ds Max® 2009 MAXScript Reference.
  2. Бартеньев О. В. Программирование модификаторов 3ds Max. Учебно-справочное пособие. – М.:Физматкнига, 2009. – 341 с.

Список примеров

Рейтинг@Mail.ru