# How to convert curve to armature

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:

Is there a way to do this in Blender automatically?

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.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.tail = points[i+1]
bone.parent = parent
bone.use_connect = True
parent = bone
bpy.ops.object.mode_set(mode='OBJECT')


• Just want to add note: script doesn't work in local viewport mode – Lambdadelta Oct 11 '17 at 15:42
• @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. – batFINGER Oct 12 '17 at 19:15

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.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.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.

• 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. – hellocatfood Dec 11 '16 at 19:56