Введение в написание скриптов на Питоне для Блендера 2.5x. Примеры кода - страница 11
>
> bpy.ops.object.mode_set(mode='OBJECT')
> ob.location=origin
> # Установка Эйлерова режима вращения (Euler ZYX)
> bpy.ops.object.mode_set(mode='POSE')
> pbase = ob.pose.bones['Base']
> pbase.rotation_mode = 'ZYX'
> ptip = ob.pose.bones['Tip']
> ptip.rotation_mode = 'ZYX'
> # Вставка 26 ключевых кадров для двух вращений FCurves
> # Последний ключевой кадр будет вовне дипазона анимации
> for n in range(26):
> pbase.keyframe_insert(
> 'rotation_euler',
> index=0,
> frame=n,
> group='Base')
> ptip.keyframe_insert(
> 'rotation_euler',
> index=2,
> frame=n,
> group='Tip')
> # Получение FCurves из вновь созданного действия
> action = ob.animation_data.action
> fcus = {}
> for fcu in action.fcurves:
> bone = fcu.data_path.split('"')[1]
> fcus[(bone, fcu.array_index)] = fcu
> # Модификация ключевых точек
> baseKptsRotX = fcus[('Base', 0)].keyframe_points
> tipKptsRotZ = fcus[('Tip', 2)].keyframe_points
> omega = 2*math.pi/250
> for n in range(26):
> t = 10*n
> phi = omega*t
> kp = baseKptsRotX[n]
> kp.co = (t+1,phi+0.7*math.sin(phi))
> kp.interpolation = 'LINEAR'
> kp = tipKptsRotZ[n]
> kp.co = (t+1, -3*phi+2.7*math.cos(2*phi))
> kp.interpolation = 'LINEAR'
> # Вычисление путей для поз костей
> bpy.ops.pose.select_all(action='SELECT')
> bpy.ops.pose.paths_calculate()
> return
>if __name__ == "__main__":
> run((10,0,0))
> bpy.ops.screen.animation_play(reverse=False, sync=False)
Эта программа создает сложное движение, последовательно назначая родителем несколько пустышек от одной к следующей, и назначая простое вращение для каждой из них.
>#----------------------------------------------------------
># File epicycle.py
>#----------------------------------------------------------
>import bpy
>import math from math
>import pi
>def createEpiCycle(origin):
> periods = [1, 5, 8, 17]
> radii = [1.0, 0.3, 0.5, 0.1]
> axes = [0, 2, 1, 0]
> phases = [0, pi/4, pi/2, 0]
> # Добавление пустышек
> scn = bpy.context.scene
> empties = []
> nEmpties = len(periods)
> for n in range(nEmpties):
> empty = bpy.data.objects.new('Empty_%d' % n, None)
> scn.objects.link(empty)
> empties.append(empty)
> # Назначение каждой пустышке родителя последовательно
> for n in range(1, nEmpties):
> empties[n].parent = empties[n-1]
> empties[n].location = (0, radii[n-1], 0)
> # Вставка двух ключевых кадров для каждой пустышки
> for n in range(nEmpties):
> empty = empties[n]
> empty.keyframe_insert(
> 'rotation_euler',
> index=axes[n],
> frame=0,
> group=empty.name)
> empty.keyframe_insert(
> 'rotation_euler',
> index=axes[n],
> frame=periods[n],
> group=empty.name)
> fcu = empty.animation_data.action.fcurves[0]
> print(empty, fcu.data_path, fcu.array_index)
> kp0 = fcu.keyframe_points[0]
> kp0.co = (0, phases[n])
> kp0.interpolation = 'LINEAR'
> kp1 = fcu.keyframe_points[1]
> kp1.co = (250.0/periods[n], 2*pi + phases[n])
> kp1.interpolation = 'LINEAR'
> fcu.extrapolation = 'LINEAR'
> last = empties[nEmpties-1]
> bpy.ops.mesh.primitive_ico_sphere_add(
> size = 0.2,
> location=last.location)
> ob = bpy.context.object
> ob.parent = last
> empties[0].location = origin
> return
>def run(origin):
> createEpiCycle(origin)
> bpy.ops.object.paths_calculate()
> return
>if __name__ == "__main__":
> run((0,0,0))
> bpy.ops.screen.animation_play(reverse=False, sync=False)
Эта программа добавляет арматуру с одной управляющей костью и двумя управляемыми костями. Вращение Конца (tip) по Z управляется позицией по X управляющей кости. Вращение Базы (base) по Z управляется как позицией по Y, так и вращением по Z управляющей кости.
>#----------------------------------------------------------
># File driver.py
>#----------------------------------------------------------