Наша задача уже облегчена, потому что мы уже сгруппировали вершины частей тела в модуле mymesh, так что связывание их с группой вершин и соответствующей костью тривиально. Не таким тривиальным будет создание самих костей, так как их может быть много, и их нужно разместить и соединить правильным способом.
Давайте посмотрим на то, как могли бы быть осуществлены некоторые существенные элементы (полный код смотрите в creepycrawlies.py). Сначала мы должны создать арматуру и сделать её редактируемой для добавления костей:
ar = Blender.Armature.New('BugBones')
ar.autoIK = True
obbones = scn.objects.new(ar)
ar.makeEditable()
Мы можем также задать любые атрибуты, которые изменяют поведение арматуры или способ её отображения. Здесь мы просто включаем свойство autoIK, так как это сделает манипуляции хвостом нашего создания, возможно очень длинным, намного проще для аниматора.
Следующий шаг - это создание костей для каждого набора вершин. Список
for vg,vlist,parent,connected in vgroup:
bone = Blender.Armature.Editbone()
bb = bounding_box([verts[i] for i in vlist])
Для каждой кости, которую мы создаем, мы вычисляем габаритный ящик (bounding box) всех вершин в группе, на которые эта кость будет влиять. Дальше мы должны разместить кость. При способе, которым мы настраивали наше создание, все сегменты его тела вытягивались вдоль оси y, за исключением крыльев (wing) и ног (leg). Они вытягивались вдоль оси x. Мы сначала проверяем этот факт, и соответственно устанавливаем переменную
axis=1
if vg.startswith('wing') or vg.startswith('leg'):
axis = 0
Кости в составе арматуры индексируются по имени и позиции концов костей, сохраненных в их атрибутах
if parent != None :
parenty = (ar.bones[parent].head[1] +
ar.bones[parent].tail[1])/2.0
Мы вычисляем эту позицию, поскольку такие части как, например, ноги и крылья имеют родительские кости (то есть, они перемещаются вместе с родительской костью), но не подсоединены головой к хвосту. Мы разместим эти кости, начиная в центре родительской кости, и для этого нам нужна позиция родителя по y. Кости сегментов, лежащих вдоль оси y, сами позиционируются вдоль оси y, и, таким образом, имеют нулевые координаты x и z. Координаты x и z ног и сегментов крыльев берутся из их габаритных ящиков. Если кость подсоединена (connected), мы просто устанавливаем позицию её головы в копию позиции хвоста родителя (выделено ниже).
if connected:
bone.head = ar.bones[parent].tail.copy()
else:
if axis==1:
bone.head=Blender.Mathutils.Vector(0,
bb[1][0],0)
else:
bone.head=Blender.Mathutils.Vector(bb[0][1],
parenty,bb[2][1])
Положение хвоста кости рассчитывается аналогичным образом:
if axis==1:
bone.tail=Blender.Mathutils.Vector(0,bb[1][1],0)
else:
bone.tail=Blender.Mathutils.Vector(bb[0][0],
parenty, bb[2][0])
Последние шаги в создании кости - это добавление её к арматуре и установка специфичных для костей опций и всех родительских связей.
ar.bones[vg] = bone
if parent != None :
bone.parent=ar.bones[parent]
else:
bone.clearParent()
if connected:
bone.options=Blender.Armature.CONNECTED
Заметьте, что в предыдущем коде важен порядок действий: атрибут