I have the following code to construct a bezier curve, an armature, and then hook them together, unfortunately it does not accomplish my mission
import bpy
def create_armed_spline(scn, resolution):
curve = bpy.data.curves.new("dingus", 'CURVE')
spline = curve.splines.new('BEZIER')
spline.bezier_points.add((resolution+1)*2)
half_thick = 0.1
for i in range(resolution+1):
p1 = spline.bezier_points[i]
x1 = i / (resolution)
p1.co = [x1, half_thick, 0]
p2 = spline.bezier_points[2 * resolution + 1 - i]
p2.co = [x1, -half_thick, 0]
if (i>0):
x2 = (i - 1 / 3) / (resolution)
p1.handle_left = [x2, half_thick, 0]
p2.handle_right = [x2, -half_thick, 0]
else:
p1.handle_left = [x1, half_thick/3, 0]
p2.handle_right = [x1, -half_thick/3, 0]
if i<resolution:
x3 = (i + 1 / 3) / resolution
p1.handle_right = [x3, half_thick, 0]
p2.handle_left = [x3, -half_thick, 0]
else:
p1.handle_right = [ x1, half_thick/3, 0]
p2.handle_left = [ x1, -half_thick, 0 ]
spline.use_cyclic_u=True
co = bpy.data.objects.new("dingus", curve)
#
arm = bpy.data.armatures.new("dingus")
ao = bpy.data.objects.new("dingus armature", arm)
co.parent = ao
scn.objects.link(ao)
scn.objects.link(co)
#
if 'OBJECT'!=bpy.context.mode:
bpy.ops.object.mode_set(mode='OBJECT')
scn.objects.active = ao
bpy.ops.object.mode_set(mode='EDIT')
bone_size = 0.1
for i in range(resolution+1):
x1 = i/resolution
add_bone_set(arm, "%d"%i, [x1, half_thick])
if (i>0):
x2 = (i - 1 / 3) / resolution
#add_bone_set(arm, "lh%d"%i, [x2, half_thick])
if (i<resolution):
x3 = (i+1/3)/resolution
#add_bone_set(arm, "rh%d"%i, [x3, half_thick])
bpy.ops.object.mode_set(mode='OBJECT')
for i in range(2):
hook_spline_to_armature(scn, co, ao, i, [0,1,0], "left %d"%i)
hook_spline_to_armature(scn, co, ao, 2*resolution+1-i, [0, 1, 0], "right %d"%i)
#
return co, ao
def hook_spline_to_armature(scn, curve, ao, idx, parts, bone_name):
mod = curve.modifiers.new("hook %d %r%r%r"%(idx,parts[0], parts[1], parts[2]), 'HOOK')
mod.object = ao
mod.subtarget = bone_name
mod.falloff_type='NONE'
scn.objects.active = curve
bpy.ops.object.mode_set(mode='EDIT')
for k in range(len(curve.data.splines[0].bezier_points)):
bp = curve.data.splines[0].bezier_points[k]
bp.select_control_point = (k==idx) and parts[1] != 0
bp.select_left_handle = (k==idx) and parts[0] != 0
bp.select_right_handle = (k==idx) and parts[2] != 0
bpy.ops.object.hook_assign(modifier=mod.name)
bpy.ops.object.mode_set(mode='OBJECT')
def add_bone_set(arm, idx, co):
bone_size = 0.1
b0 = arm.edit_bones.new("center %s" % idx)
b0.head = [co[0], 0, 0]
b0.tail = [co[0], 0, bone_size]
b1 = arm.edit_bones.new("right %s" % idx)
b1.head = [co[0], -co[1], 0]
b1.tail = [co[0], -co[1], bone_size]
b1.parent = b0
b2 = arm.edit_bones.new("left %s" % idx)
b2.head = [co[0], co[1], 0]
b2.tail = [co[0], co[1], bone_size]
b2.parent = b0
return b0, b1, b2
def maybe_purge(scn, name):
obj = bpy.data.objects.get(name)
if obj is None:
return
obj.name = "discard"
try:
scn.objects.unlink(obj)
except:
pass
def mission1(scn):
if 'OBJECT'!=bpy.context.mode:
bpy.ops.object.mode_set(mode='OBJECT')
maybe_purge(scn, "dingus")
maybe_purge(scn, "dingus armature")
spline, arm = create_armed_spline(scn, 1)
#
mission1(bpy.context.scene)
What I do get is a deformed bezier curve which appears to have no mathematical relationship to the armature it is hooked to.
How do I fix my python code so it properly hooks the bezier control points to the bones of the armature?