Rig Tracing Experiment

I wrote a script that generates a curve by tracing out an armature. I’m not sure where to go with this idea but I figure the results were interesting enough to share. What do you guys think?


import bpy
"""
bones_and_splines.py
by cotejrp1

DESCRIPTION: 
fun script for messing around with bone data and splines.
STATUS: 
Traces out a curve for an armature with multiple links.
"""

def add_spline(bone_chain, crv):
    # gather the data into an appropriate list.
    bone_data = []
    for bone in bone_chain:
        loc = bone.head_local
        bone_data.extend((loc.x, loc.y, loc.z))

    loc = bone_chain[-1].tail_local
    bone_data.extend((loc.x, loc.y, loc.z))

    # construct the spline itself.
    spline = crv.splines.new(type="BEZIER")
    num_points = len(bone_chain)
    spline.bezier_points.add(num_points)
    spline.bezier_points.foreach_set("co", bone_data)
    for point in spline.bezier_points:
        point.handle_left_type = "AUTO"
        point.handle_right_type = "AUTO"


def get_bone_chain(arm):
    bone_chain = []

    for bone in arm.bones:
        bone_chain.append( bone )
        if len( bone.children ) != 1:
            yield bone_chain
            bone_chain = []


scn = bpy.context.scene

# assumed that an armature is selected here.
arm = bpy.context.active_object.data
crv = bpy.data.curves.new("crv", type="CURVE")
crv_ob = bpy.data.objects.new("crv_ob", crv)
scn.objects.link(crv_ob)

for bone_chain in get_bone_chain(arm):
    add_spline(bone_chain, crv)


hi, i really like the concept behind this.
thanks.

those paper may help you get an idea of what you can achieve
http://www-ljk.imag.fr/Publications/Basilic/com.lmc.publi.PUBLI_Article@1172c0fd434_486320/index_en.html

http://www-ljk.imag.fr/Publications/Basilic/com.lmc.publi.PUBLI_Inproceedings@117681e94b6_486daa/index_en.html

http://www-ljk.imag.fr/Publications/Basilic/com.lmc.publi.PUBLI_Inproceedings@117681e94b6_113895d/index_en.html

http://www-ljk.imag.fr/Publications/Basilic/com.lmc.publi.PUBLI_Phdthesis@117681e94b6_951a2/index_en.html

Finally came back around on this one. I decided the best thing to do was simply to generate a curve that traces out the armature and then parent it. That much I could get to work so I made an add-on out of it. So yeah, instant curve-based character based on a naked armature. I might offer up polyline and nurb options on this too. What do you guys think?


# arm_curve.py (c) 2011 Phil Cote (cotejrp1)
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ***** END GPL LICENCE BLOCK *****


bl_info = {
    'name': 'Armature Curve',
    'author': 'Phil Cote, cotejrp1, (http://www.blenderaddons.com)',
    'version': (0,1),
    "blender": (2, 6, 0),
    "api": 41098,
    'location': '',
    'description': 'Generates a curve character based on an existing armature',
    'warning': '', # used for warning icon and text in addons panel
    'category': 'Add Curve'}

import bpy
from pdb import set_trace

def add_spline(bone_chain, crv):
    # gather the data into an appropriate list.
    bone_data = []
    for bone in bone_chain:
        loc = bone.head_local
        bone_data.extend((loc.x, loc.y, loc.z))

    loc = bone_chain[-1].tail_local
    bone_data.extend((loc.x, loc.y, loc.z))

    # construct the spline itself.
    spline = crv.splines.new(type="BEZIER")
    num_points = len(bone_chain)
    spline.bezier_points.add(num_points)
    spline.bezier_points.foreach_set("co", bone_data)
    for point in spline.bezier_points:
        point.handle_left_type = "AUTO"
        point.handle_right_type = "AUTO"

def get_bone_chain(arm):
    bone_chain = []

    for bone in arm.bones:
        bone_chain.append( bone )
        if len( bone.children ) != 1:
            yield bone_chain
            bone_chain = []

def make_arm_curve(arm_ob):
    crv = bpy.data.curves.new("crv", type="CURVE")
    crv_ob = bpy.data.objects.new("crv_ob", crv)
    
    for bone_chain in get_bone_chain(arm_ob.data):
        add_spline(bone_chain, crv)
    
    return crv_ob

def bind_curve_to_arm(arm_ob, crv_ob):
    crv_ob.parent = arm_ob
    crv_ob.parent_type="ARMATURE"
    

class CurveArmatureOp(bpy.types.Operator):
    '''Tooltip'''
    bl_idname = "curve.armature_curve"
    bl_label = "Curve Armature"

    @classmethod
    def poll(cls, context):
        ob = context.active_object
        if ob == None:
            return False
        if ob.type != 'ARMATURE':
            return False 
        return True


    def execute(self, context):
        scn = bpy.context.scene
        arm_ob = bpy.context.active_object
        crv_ob = make_arm_curve(arm_ob)
        scn.objects.link(crv_ob)
        bind_curve_to_arm(arm_ob, crv_ob)
        return {'FINISHED'}

class CurveArmaturePanel(bpy.types.Panel):
    bl_label = "Curve Armature"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_context = "objectmode"
    
    def draw(self, context):
        scn = context.scene
        layout = self.layout
        layout.column().operator("curve.armature_curve")

def register():
    bpy.utils.register_class(CurveArmatureOp)
    bpy.utils.register_class(CurveArmaturePanel)


def unregister():
    bpy.utils.unregister_class(CurveArmatureOp)
    bpy.utils.unregister_class(CurveArmaturePanel)


if __name__ == "__main__":
    register()

cant you show a video of the process