I’m working on a script that takes an armature, and then creates a spline to use for an IK spline constraint, as well as a new guide armature to control the position of the spline points. The armature used for testing the script is a chain of eight bones with the first being named “Bone.001”, and each bone extruded along the Y axis, so the first bone has a head location of (0, 0, 0) and a tail location of (0, 1, 0), and so on.
The trouble is that about half of the time it places the guide bones in their corect positions. Other times, all (or at least some) of the bones will be placed at (0, 0, 0), or some of the bones will be placed 1 blender unit above where it was meant to go (e.g., placed at (0, 5, 1) instead of (0, 5, 0).
Also the spline generation part is, well, weird. Most of the time points are placed at (0, 0, 0), and all but a few points has a w value of 0. The rest of the time the points are placed randomly.
import bpyfrom mathutils import Vector
def ChangeSelectedObject(formerySelected, toBeSelected, scene):
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='OBJECT')
toBeSelected.select = True
scene.objects.active = toBeSelected
formerySelected.select = False
currentScene = bpy.context.scene
armObj = bpy.context.active_object
location = armObj.location
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='EDIT')
armData = armObj.data
numberOfBones = len(armData.edit_bones)
pointList = []#list of points
print(armData.name)
print(armData.edit_bones.keys())
pointList.append(armData.edit_bones['Bone.001'].head)
nameList = []
for i in range(1, numberOfBones + 1):#get point positions
pointList.append(armData.edit_bones['Bone.{0:03d}'.format(i)].tail)
nameList.append('Bone.{0:003d}'.format(i))
print('added point: {0}'.format(armData.edit_bones['Bone.{0:03d}'.format(i)].tail))
#create new guide armiture
guideArmData = bpy.data.armatures.new('GuideArmatureData')
guideArmObj = bpy.data.objects.new('GuideArmature', guideArmData)
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='OBJECT')
currentScene.objects.link(guideArmObj)
guideArmObj.location = location
ChangeSelectedObject(armObj, guideArmObj, currentScene)
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='EDIT')
nameList.insert(0, 'BoneParent')#place name BoneParent at the beginning of the list
for p, n in zip(pointList, nameList):
eb = guideArmData.edit_bones.new(n)
pr = p# * guideArmObj.matrix_world.inverted()
print('added bone {1} with head at {0}'.format(pr, n))
eb.head = pr
eb.tail = (pr[0], pr[1], pr[2] + 1.0)
ChangeSelectedObject(armObj, guideArmObj, currentScene)
#create spline
splineData = bpy.data.curves.new('IK_SplineData', 'CURVE')
splineObj = bpy.data.objects.new('IK_Spline', splineData)
currentScene.objects.link(splineObj)
splineObj.location = location
ChangeSelectedObject(armObj, splineObj, currentScene)
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='EDIT')
splineData.dimensions = '3D'
splineData.splines.clear()
splineData.splines.new('NURBS')
splineData.splines.active.use_endpoint_u = True
splineData.splines.active.points.add(len(pointList) - 1)
curveModifiers = []
hookNo = 0
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='OBJECT')
for bn in nameList:
mod = splineObj.modifiers.new('HookMod{0}'.format(hookNo), 'HOOK')
hookNo+=1
mod.object = guideArmObj
mod.subtarget = bn
curveModifiers.append(mod)
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='EDIT')
a = pointList
b = splineData.splines.active.points
for sp in b:
sp.select=False
print('length of nameList: {0}, pointList: {1}, curveModifiers: {2}'.format(len(nameList), len(pointList), len(curveModifiers)))
print('Contents of nameList: {0}
Contents of pointList: {1}'.format(nameList, pointList))
for pd, sp, c in zip(a, b, curveModifiers):#matrix_world
print('Spline point X; {0}, Y: {1}, Z: {2}'.format(pd[0], pd[1], pd[2]))
sp.select=True
tl = Vector((pd[0], pd[1], pd[2]))
sp.co = (tl[0], tl[1], tl[2], 1)
print('Spline co: {0}'.format(sp.co))
#bpy.ops.object.mode_set('EXEC_DEFAULT', mode='OBJECT')
bpy.ops.object.hook_assign(modifier=c.name)
bpy.ops.object.hook_reset(modifier=c.name)
#bpy.ops.object.mode_set('EXEC_DEFAULT', mode='EDIT')
sp.select=False
#add bone constraint
ChangeSelectedObject(splineObj, armObj, currentScene)
bpy.ops.object.mode_set('EXEC_DEFAULT', mode='POSE')
splineIK = armObj.pose.bones[nameList[len(nameList) - 1]].constraints.new('SPLINE_IK')
splineIK.influence = 1.0
splineIK.chain_count = numberOfBones
splineIK.target = splineObj
del pointList
del nameList
del curveModifiers
Thanks for your help.