- Removed control-shape deformation bones from the spine rig (no longer necessary thanks to the new "custom shape at" feature).
- Various improvements to the mouth rig, including a corrective shape key for mouth-open.
- The new method of generating into the same armature object every time wasn't copying pose bone data in the process, such as rotation mode and transform locks.
This commit is contained in:
Nathan Vegdahl 2010-01-26 11:17:41 +00:00
parent 5fe3524ab1
commit fb8d6b9f7a
3 changed files with 73 additions and 87 deletions

@ -231,10 +231,31 @@ def generate_rig(context, obj_orig, prefix="ORG-", META_DEF=True):
obj.selected = True
scene.objects.active = obj
# Copy over the pose_bone custom properties
# Copy over the pose_bone properties
for bone in obj_orig.pose.bones:
bone_gen = obj.pose.bones[bone.name]
# Rotation mode and transform locks
bone_gen.rotation_mode = bone.rotation_mode
bone_gen.lock_rotation = tuple(bone.lock_rotation)
bone_gen.lock_rotation_w = bone.lock_rotation_w
bone_gen.lock_rotations_4d = bone.lock_rotations_4d
bone_gen.lock_location = tuple(bone.lock_location)
bone_gen.lock_scale = tuple(bone.lock_scale)
# Custom properties
for prop in bone.keys():
obj.pose.bones[bone.name][prop] = bone[prop]
bone_gen[prop] = bone[prop]
# Copy over bone properties
for bone in obj_orig.data.bones:
bone_gen = obj.data.bones[bone.name]
# B-bone stuff
bone_gen.bbone_segments = bone.bbone_segments
bone_gen.bbone_in = bone.bbone_in
bone_gen.bbone_out = bone.bbone_out
# Create proxy deformation rig
# TODO: remove this

@ -119,8 +119,11 @@ def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='EDIT')
eb = obj.data.edit_bones
bb = obj.data.bones
pb = obj.pose.bones
jaw = definitions[1]
# Options
req_options = ["mesh"]
for option in req_options:
@ -210,6 +213,16 @@ def deform(obj, definitions, base_names, options):
eb[dlip7].bbone_segments = 8
eb[dlip8].bbone_segments = 8
# Jaw open bones
jopen1 = copy_bone_simple(obj.data, jaw, "MCH-"+base_names[jaw]+".track1", parent=True).name
eb[jopen1].connected = False
eb[jopen1].head = eb[jaw].tail
eb[jopen1].tail = eb[jopen1].head + Vector(0, 0, eb[jaw].length/4)
jopen2 = copy_bone_simple(obj.data, jopen1, "MCH-"+base_names[jaw]+".track2").name
eb[jopen2].parent = eb[jaw]
bpy.ops.object.mode_set(mode='OBJECT')
# Constraints
@ -255,8 +268,7 @@ def deform(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='OBJECT')
# Left side
# Left side shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".L.spread"
@ -278,10 +290,8 @@ def deform(obj, definitions, base_names, options):
# Set up the variable
var.type = "ROTATION_DIFF"
#var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip4
#var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip5
@ -291,7 +301,7 @@ def deform(obj, definitions, base_names, options):
mod.coefficients[0] = -rotdiff_l / (pi-rotdiff_l)
mod.coefficients[1] = 1 / (pi-rotdiff_l)
# Right side
# Right side shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".R.spread"
@ -313,10 +323,8 @@ def deform(obj, definitions, base_names, options):
# Set up the variable
var.type = "ROTATION_DIFF"
#var.targets[0].id_type = 'OBJECT'
var.targets[0].id = obj
var.targets[0].bone_target = lip1
#var.targets[1].id_type = 'OBJECT'
var.targets[1].id = obj
var.targets[1].bone_target = lip8
@ -325,7 +333,38 @@ def deform(obj, definitions, base_names, options):
if rotdiff_r != pi:
mod.coefficients[0] = -rotdiff_r / (pi-rotdiff_r)
mod.coefficients[1] = 1 / (pi-rotdiff_r)
# Jaw open corrective shape key
for mesh_name in meshes:
mesh_obj = bpy.data.objects[mesh_name]
shape_key_name = "COR-" + base_names[definitions[4]] + ".jaw_open"
# Add/get the shape key
shape_key = addget_shape_key(mesh_obj, name=shape_key_name)
# Add/get the shape key driver
fcurve = addget_shape_key_driver(mesh_obj, name=shape_key_name)
driver = fcurve.driver
# Get the variable, or create it if it doesn't already exist
var_name = base_names[definitions[4]]
if var_name in driver.variables:
var = driver.variables[var_name]
else:
var = driver.variables.new()
var.name = var_name
# Set up the variable
var.type = "LOC_DIFF"
var.targets[0].id = obj
var.targets[0].bone_target = jopen1
var.targets[1].id = obj
var.targets[1].bone_target = jopen2
# Set fcurve offset
mod = fcurve.modifiers[0]
mod.coefficients[0] = 0.0
mod.coefficients[1] = 1.0 / bb[jaw].length
return (None,)
@ -446,7 +485,7 @@ def control(obj, definitions, base_names, options):
bpy.ops.object.mode_set(mode='OBJECT')
# Add eye close action if it doesn't already exist
# Add mouth open action if it doesn't already exist
action_name = "mouth_open"
if action_name in bpy.data.actions:
open_action = bpy.data.actions[action_name]
@ -464,6 +503,7 @@ def control(obj, definitions, base_names, options):
open_driver_path = pb[lip1].path_to_id() + '["open_action"]'
# Constraints
# Jaw open tracker stretches to jaw tip
@ -475,7 +515,7 @@ def control(obj, definitions, base_names, options):
con.volume = 'NO_VOLUME'
# Head lips to jaw lips
influence = [0.0, 0.1, 0.5, 0.25, 0.0]
influence = [0.02, 0.15, 0.5, 0.25, 0.0]
con = pb[hlip1].constraints.new('COPY_TRANSFORMS')
con.target = obj

@ -168,8 +168,7 @@ def main(obj, bone_definition, base_names, options):
#child.parent = mt.pelvis_e # was mt.ribcage
# The first bone in the chain happens to be the basis of others, create them now
ex = bone_class_instance(obj, ["pelvis", "pelvis_copy", "ribcage", "ribcage_hinge", "ribcage_copy", "spine_rotate"])
df = bone_class_instance(obj, ["pelvis", "ribcage"]) # DEF-wgt_pelvis, DEF-wgt_rib_cage
ex = bone_class_instance(obj, ["pelvis_copy", "ribcage_hinge", "ribcage_copy", "spine_rotate"])
ex.pelvis_copy_e = copy_bone_simple(arm, mt.pelvis, base_names[mt.pelvis]) # no parent
ex.pelvis_copy = ex.pelvis_copy_e.name
@ -186,33 +185,15 @@ def main(obj, bone_definition, base_names, options):
ex.spine_rotate_e.connected = False
ex.spine_rotate_e.parent = ex.pelvis_copy_e
df.pelvis_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % base_names[mt.pelvis])
df.pelvis = df.pelvis_e.name
df.pelvis_e.translate(Vector(spine_chain_segment_length * 2.0, - spine_chain_segment_length, 0.0))
ex.pelvis_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % base_names[mt.pelvis])
ex.pelvis = ex.pelvis_e.name
ex.pelvis_e.translate(Vector(0.0, - spine_chain_segment_length, 0.0))
ex.pelvis_e.connected = False
ex.pelvis_e.parent = ex.pelvis_copy_e
# Copy the last bone now
child = spine_chain[-1]
df.ribcage_e = copy_bone_simple(arm, child.name, "DEF-wgt_%s" % base_names[mt.ribcage])
df.ribcage = df.ribcage_e.name
df.ribcage_e.translate(Vector(spine_chain_segment_length * 2.0, - df.ribcage_e.length / 2.0, 0.0))
ex.ribcage_copy_e = copy_bone_simple(arm, mt.ribcage, base_names[mt.ribcage])
ex.ribcage_copy = ex.ribcage_copy_e.name
ex.ribcage_copy_e.connected = False
ex.ribcage_copy_e.parent = ex.ribcage_hinge_e
ex.ribcage_e = copy_bone_simple(arm, child.name, "MCH-wgt_%s" % base_names[mt.ribcage])
ex.ribcage = ex.ribcage_e.name
ex.ribcage_e.translate(Vector(0.0, - ex.ribcage_e.length / 2.0, 0.0))
ex.ribcage_e.parent = ex.ribcage_copy_e
spine_chain = [child.name for child in spine_chain]
# We have 3 spine chains
@ -300,7 +281,6 @@ def main(obj, bone_definition, base_names, options):
# refresh pose bones
mt.update()
ex.update()
df.update()
mt_chain.update()
ex_chain.update()
rv_chain.update()
@ -308,34 +288,6 @@ def main(obj, bone_definition, base_names, options):
# Axis locks
ex.ribcage_copy_p.lock_location = True, True, True
# df.pelvis_p / DEF-wgt_pelvis
con = df.pelvis_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = ex.pelvis
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
con = df.pelvis_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = ex.pelvis
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
# df.ribcage_p / DEF-wgt_rib_cage
df.ribcage_p.lock_location = True, True, True
con = df.ribcage_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = ex.ribcage
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
con = df.ribcage_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = ex.ribcage
con.owner_space = 'LOCAL'
con.target_space = 'LOCAL'
con = ex.ribcage_hinge_p.constraints.new('COPY_ROTATION')
con.name = "hinge"
con.target = obj
@ -356,35 +308,10 @@ def main(obj, bone_definition, base_names, options):
mod.coefficients[0] = 1.0
mod.coefficients[1] = -1.0
con = ex.spine_rotate_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = ex.ribcage_copy
# ex.pelvis_p / MCH-wgt_pelvis
con = ex.pelvis_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = mt_chain.spine_01
con.owner_space = 'WORLD'
con.target_space = 'WORLD'
con = ex.pelvis_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = mt_chain.spine_01
con.owner_space = 'WORLD'
con.target_space = 'WORLD'
# ex.ribcage_p / MCH-wgt_rib_cage
con = ex.ribcage_p.constraints.new('COPY_LOCATION')
con.target = obj
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
con.head_tail = 0.0
con = ex.ribcage_p.constraints.new('COPY_ROTATION')
con.target = obj
con.subtarget = getattr(mt_chain, mt_chain.attr_names[-1])
# ex.pelvis_copy_p / rib_cage
con = ex.ribcage_copy_p.constraints.new('COPY_LOCATION')
con.target = obj
@ -543,8 +470,6 @@ def main(obj, bone_definition, base_names, options):
getattr(ex, attr + "_b").layer = layer
for attr in ex_chain.attr_names:
getattr(ex_chain, attr + "_b").layer = layer
for attr in df.attr_names:
getattr(df, attr + "_b").layer = layer
for attr in rv_chain.attr_names:
getattr(rv_chain, attr + "_b").layer = layer