2
$\begingroup$

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.

screenshot

How do I fix my python code so it properly hooks the bezier control points to the bones of the armature?

$\endgroup$
1
$\begingroup$

It appears that hook modifiers are not truly initialized when you create them. They need a bpy.ops.object.hook_reset(modifier=mod.name) to clear out some hidden state that might be leftover garbage from the heap.

| improve this answer | |
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.