4
$\begingroup$

I have a bezier curve that I created in Inkscape and I want to convert it to an armature, where ecah node fo the curve is connected by a bone. See example below:

enter image description here

Is there a way to do this in Blender automatically?

$\endgroup$
6
$\begingroup$

Can also do this straight from the curves bezier points.

Test script, select the curve in object mode. Note for cyclic curves cannot create a circular parent structure for bones, eg the first bone can't have the last bone as a parent. AFAIK.

import bpy
context = bpy.context
scene = context.scene
curve_obj = context.object
curve = curve_obj.data

arm = bpy.data.armatures.new("BezArmature")
arm_obj = bpy.data.objects.new("BezArmature", arm)
scene.objects.link(arm_obj)

scene.objects.active = arm_obj
bpy.ops.object.mode_set(mode='EDIT')
mw = curve_obj.matrix_world
arm_obj.matrix_world = mw
for spline in curve.splines:
    points = [bp.co for bp in spline.bezier_points]
    if spline.use_cyclic_u:
        points.append(points[0])
    parent = None
    for i in range(len(points)-1):
        bone = arm.edit_bones.new("Bone")
        bone.head = points[i]
        bone.tail = points[i+1]
        bone.parent = parent
        bone.use_connect = True
        parent = bone
bpy.ops.object.mode_set(mode='OBJECT')

enter image description here

$\endgroup$
  • $\begingroup$ Just want to add note: script doesn't work in local viewport mode $\endgroup$ – Lambdadelta Oct 11 '17 at 15:42
  • $\begingroup$ @Lambdadelta yes.. barmy a bmesh for armatures would be handy, Local mode it creates the armature object, but no bones. Getting the view3d area to toggle local / global view is a bit out of the scope of the Q IMO.. Thanks for the heads up tho, good to know. $\endgroup$ – batFINGER Oct 12 '17 at 19:15
2
$\begingroup$

I created a script which solves your problem, first it cycles through all edges and finds an edge loop, then it creates bones along the vertices' positions.

import bpy

def CreateBoneChainFromVertices(switch_direction = False):
    scn = bpy.context.scene
    if (None ==scn.objects.active):
        return
    obj = scn.objects.active
    if (obj.type != 'MESH'):
        return
    bpy.ops.object.mode_set(mode='OBJECT')

    edgesA = []
    edgesB = []
    for i in range(len(obj.data.edges)):
        ver = obj.data.edges[i].vertices
        edgesA.append(ver[0])
        edgesB.append(ver[1])

    chain = []
    chain.append(edgesA[0])
    while(True):
        current = chain[len(chain)-1]
        if current in edgesA:
            idx = edgesA.index(current)
            next = edgesB[idx]
            del edgesA[idx]
            del edgesB[idx]
            chain.append(next)
        elif current in edgesB:
            idx = edgesB.index(current)
            next = edgesA[idx]
            del edgesA[idx]
            del edgesB[idx] 
            chain.append(next)
        else:
            if (chain[0] in edgesA) or (chain[0] in edgesB):
                chain = list(reversed(chain))
            else:
                break
    if switch_direction:
        chain = list(reversed(chain))

    amt = bpy.data.armatures.new(obj.name + "_vBones")
    rig = bpy.data.objects.new(obj.name + '_vRig', amt)
    scn.objects.link(rig)
    scn.objects.active = rig
    scn.update()

    print(chain, "here we go")
    bpy.ops.object.editmode_toggle()
    for i in range(0, len(chain) - 1):
        bone = amt.edit_bones.new(str(i + 1))
        bone.head = obj.data.vertices[chain[i]].co
        bone.tail = obj.data.vertices[chain[i + 1]].co
    for i in range(0, len(amt.edit_bones) - 1):
        amt.edit_bones[i + 1].parent = amt.edit_bones[i]
        amt.edit_bones[i + 1].use_connect = True
    bpy.ops.object.editmode_toggle()

# optional parameter: (bool) switch direction
CreateBoneChainFromVertices(True)

The object has to be a mesh object. If it is not a mesh object, convert it. Alt+C > To Mesh

If you have more than one edge loop, split them into separate parts. P > By loose parts

Select the object, paste the script into the text editor and click on Run Script.

enter image description here

$\endgroup$
  • $\begingroup$ Thanks for the script! It works although I noticed that if I rescale the curve I have to apply the scale before running the script. $\endgroup$ – hellocatfood Dec 11 '16 at 19:56

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.