[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [1694] trunk/py/scripts/addons/rigify: Rigify:

Nathan Vegdahl cessen at cessen.com
Thu Mar 10 10:18:10 CET 2011


Revision: 1694
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=1694
Author:   cessen
Date:     2011-03-10 09:18:09 +0000 (Thu, 10 Mar 2011)
Log Message:
-----------
Rigify:
Clean-up of the IK/FK snapping code.  Should be much more maintainable now.

Also changed rig id generation.  Rig id's now consist of a random
alphanumeric string 8 characters long, with the smallest 8 digits of seconds
since the epoc (in hex) at the time of rig generation appended on the end.
This results in a 16-character string that is ludicrously unlikely to
have any collisions between rigs.  36^8 * 16^8, with the 16^8 being very well
distributed over time.  Ah... paranoia.

Modified Paths:
--------------
    trunk/py/scripts/addons/rigify/generate.py
    trunk/py/scripts/addons/rigify/rig_ui_template.py
    trunk/py/scripts/addons/rigify/ui.py

Modified: trunk/py/scripts/addons/rigify/generate.py
===================================================================
--- trunk/py/scripts/addons/rigify/generate.py	2011-03-10 06:01:25 UTC (rev 1693)
+++ trunk/py/scripts/addons/rigify/generate.py	2011-03-10 09:18:09 UTC (rev 1694)
@@ -52,8 +52,11 @@
 
     """
     t = Timer()
-    rig_id = random_string(12)  # Random so that different rigs don't collide id's
 
+    # Random string with time appended so that
+    # different rigs don't collide id's
+    rig_id = random_string(8) + str(hex(int(time.time())))[2:][-8:].rjust(8, '0')
+
     # Initial configuration
     mode_orig = context.mode
     rest_backup = metarig.data.pose_position

Modified: trunk/py/scripts/addons/rigify/rig_ui_template.py
===================================================================
--- trunk/py/scripts/addons/rigify/rig_ui_template.py	2011-03-10 06:01:25 UTC (rev 1693)
+++ trunk/py/scripts/addons/rigify/rig_ui_template.py	2011-03-10 09:18:09 UTC (rev 1694)
@@ -24,17 +24,21 @@
 rig_id = "%s"
 
 
-def get_pose_matrix_in_other_space(mat, pbs):
-    """ Returns the transform matrix relative to pbs's transform space.
-        In other words, you could take the matrix returned from this, slap
-        it into pbs, and it would have the same world transform as mat.
-        This is with constraints applied.
+#########################################
+## "Visual Transform" helper functions ##
+#########################################
+
+def get_pose_matrix_in_other_space(mat, pose_bone):
+    """ Returns the transform matrix relative to pose_bone's current
+        transform space.  In other words, presuming that mat is in
+        armature space, slapping the returned matrix onto pose_bone
+        should give it the armature-space transforms of mat.
     """
-    rest_inv = pbs.bone.matrix_local.inverted()
+    rest_inv = pose_bone.bone.matrix_local.inverted()
 
-    if pbs.parent:
-        par_inv = pbs.parent.matrix.inverted()
-        par_rest = pbs.parent.bone.matrix_local.copy()
+    if pose_bone.parent:
+        par_inv = pose_bone.parent.matrix.inverted()
+        par_rest = pose_bone.parent.bone.matrix_local.copy()
 
         smat = rest_inv * (par_rest * (par_inv * mat))
     else:
@@ -43,135 +47,130 @@
     return smat
 
 
-def get_local_matrix_with_constraints(pose_bone):
-    """ Returns the local matrix of the given pose bone, with constraints
-        applied.
+def get_local_pose_matrix(pose_bone):
+    """ Returns the local transform matrix of the given pose bone.
     """
     return get_pose_matrix_in_other_space(pose_bone.matrix, pose_bone)
 
 
-def set_pose_rotation(pb, mat):
-    """ Sets the pose bone's rotation to the same rotation as the given matrix.
-        Matrix should be given in local space.
-    """
-    q = mat.to_quaternion()
-
-    if pb.rotation_mode == 'QUATERNION':
-        pb.rotation_quaternion = q
-    elif pb.rotation_mode == 'AXIS_ANGLE':
-        pb.rotation_axis_angle[0] = q.angle
-        pb.rotation_axis_angle[1] = q.axis[0]
-        pb.rotation_axis_angle[2] = q.axis[1]
-        pb.rotation_axis_angle[3] = q.axis[2]
-    else:
-        pb.rotation_euler = q.to_euler(pb.rotation_mode)
-
-
-def set_pose_scale(pb, mat):
-    """ Sets the pose bone's scale to the same scale as the given matrix.
-        Matrix should be given in local space.
-    """
-    pb.scale = mat.to_scale()
-
-
-def set_pose_translation(pb, mat):
+def set_pose_translation(pose_bone, mat):
     """ Sets the pose bone's translation to the same translation as the given matrix.
-        Matrix should be given in local space.
+        Matrix should be given in bone's local space.
     """
-    if pb.bone.use_local_location == True:
-        pb.location = mat.to_translation()
+    if pose_bone.bone.use_local_location == True:
+        pose_bone.location = mat.to_translation()
     else:
         loc = mat.to_translation()
 
-        rest = pb.bone.matrix_local.copy()
-        if pb.bone.parent:
-            par_rest = pb.bone.parent.matrix_local.copy()
+        rest = pose_bone.bone.matrix_local.copy()
+        if pose_bone.bone.parent:
+            par_rest = pose_bone.bone.parent.matrix_local.copy()
         else:
             par_rest = Matrix()
 
         q = (par_rest.inverted() * rest).to_quaternion()
-        pb.location = loc * q
+        pose_bone.location = loc * q
 
 
-def fk2ik_arm(obj, fk, ik):
-    """ Matches the fk bones in an arm rig to the ik bones.
+def set_pose_rotation(pose_bone, mat):
+    """ Sets the pose bone's rotation to the same rotation as the given matrix.
+        Matrix should be given in bone's local space.
     """
-    pb = obj.pose.bones
+    q = mat.to_quaternion()
 
-    uarm = pb[fk[0]]
-    farm = pb[fk[1]]
-    hand = pb[fk[2]]
+    if pose_bone.rotation_mode == 'QUATERNION':
+        pose_bone.rotation_quaternion = q
+    elif pose_bone.rotation_mode == 'AXIS_ANGLE':
+        pose_bone.rotation_axis_angle[0] = q.angle
+        pose_bone.rotation_axis_angle[1] = q.axis[0]
+        pose_bone.rotation_axis_angle[2] = q.axis[1]
+        pose_bone.rotation_axis_angle[3] = q.axis[2]
+    else:
+        pose_bone.rotation_euler = q.to_euler(pose_bone.rotation_mode)
 
-    uarmi = pb[ik[0]]
-    farmi = pb[ik[1]]
-    handi = pb[ik[2]]
 
-    uarmmat = get_pose_matrix_in_other_space(uarmi.matrix, uarm)
-    set_pose_rotation(uarm, uarmmat)
-    set_pose_scale(uarm, uarmmat)
-    bpy.ops.object.mode_set(mode='OBJECT')
-    bpy.ops.object.mode_set(mode='POSE')
+def set_pose_scale(pose_bone, mat):
+    """ Sets the pose bone's scale to the same scale as the given matrix.
+        Matrix should be given in bone's local space.
+    """
+    pose_bone.scale = mat.to_scale()
 
-    farmmat = get_pose_matrix_in_other_space(farmi.matrix, farm)
-    set_pose_rotation(farm, farmmat)
-    set_pose_scale(farm, farmmat)
+
+def match_pose_translation(pose_bone, target_bone):
+    """ Matches pose_bone's visual translation to target_bone's visual
+        translation.
+        This function assumes you are in pose mode on the relevant armature.
+    """
+    mat = get_pose_matrix_in_other_space(target_bone.matrix, pose_bone)
+    set_pose_translation(pose_bone, mat)
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.mode_set(mode='POSE')
 
-    handmat = get_pose_matrix_in_other_space(handi.matrix, hand)
-    set_pose_rotation(hand, handmat)
-    set_pose_scale(hand, handmat)
+
+def match_pose_rotation(pose_bone, target_bone):
+    """ Matches pose_bone's visual rotation to target_bone's visual
+        rotation.
+        This function assumes you are in pose mode on the relevant armature.
+    """
+    mat = get_pose_matrix_in_other_space(target_bone.matrix, pose_bone)
+    set_pose_rotation(pose_bone, mat)
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.mode_set(mode='POSE')
 
 
-def ik2fk_arm(obj, fk, ik):
-    """ Matches the ik bones in an arm rig to the fk bones.
+def match_pose_scale(pose_bone, target_bone):
+    """ Matches pose_bone's visual scale to target_bone's visual
+        scale.
+        This function assumes you are in pose mode on the relevant armature.
     """
-    pb = obj.pose.bones
+    mat = get_pose_matrix_in_other_space(target_bone.matrix, pose_bone)
+    set_pose_scale(pose_bone, mat)
+    bpy.ops.object.mode_set(mode='OBJECT')
+    bpy.ops.object.mode_set(mode='POSE')
 
-    uarm = pb[fk[0]]
-    farm = pb[fk[1]]
-    hand = pb[fk[2]]
 
-    uarmi = pb[ik[0]]
-    farmi = pb[ik[1]]
-    handi = pb[ik[2]]
-    pole = pb[ik[3]]
+##############################
+## IK/FK snapping functions ##
+##############################
 
-    # Hand position
-    handmat = get_pose_matrix_in_other_space(hand.matrix, handi)
-    set_pose_translation(handi, handmat)
-    set_pose_rotation(handi, handmat)
-    set_pose_scale(handi, handmat)
-    bpy.ops.object.mode_set(mode='OBJECT')
-    bpy.ops.object.mode_set(mode='POSE')
+def match_pole_target(ik_first, ik_last, pole, match_bone, length):
+    """ Places an IK chain's pole target to match ik_first's
+        transforms to match_bone.  All bones should be given as pose bones.
+        You need to be in pose mode on the relevant armature object.
+        ik_first: first bone in the IK chain
+        ik_last:  last bone in the IK chain
+        pole:  pole target bone for the IK chain
+        match_bone:  bone to match ik_first to (probably first bone in a matching FK chain)
+        length:  distance pole target should be placed from the chain center
+    """
+    a = ik_first.matrix.to_translation()
+    b = ik_last.matrix.to_translation() + ik_last.vector
 
-    # Pole target position
-    a = uarm.matrix.to_translation()
-    b = farm.matrix.to_translation() + farm.vector
+    # Vector from the head of ik_first to the
+    # tip of ik_last
+    ikv = b - a
 
-    # Vector from the head of the upper arm to the
-    # tip of the forearm
-    armv = b - a
-
-    # Create a vector that is not aligned with armv.
+    # Create a vector that is not aligned with ikv.
     # It doesn't matter what vector.  Just any vector
     # that's guaranteed to not be pointing in the same
-    # direction.
-    if abs(armv[0]) < abs(armv[1]) and abs(armv[0]) < abs(armv[2]):
+    # direction.  In this case, we create a unit vector
+    # on the axis of the smallest component of ikv.
+    if abs(ikv[0]) < abs(ikv[1]) and abs(ikv[0]) < abs(ikv[2]):
         v = Vector((1,0,0))
-    elif abs(armv[1]) < abs(armv[2]):
+    elif abs(ikv[1]) < abs(ikv[2]):
         v = Vector((0,1,0))
     else:
         v = Vector((0,0,1))
 
-    # cross v with armv to get a vector perpendicular to armv
-    pv = v.cross(armv).normalized() * (uarm.length + farm.length)
+    # Get a vector perpendicular to ikv
+    pv = v.cross(ikv).normalized() * length
 
     def set_pole(pvi):
+        """ Set pole target's position based on a vector
+            from the arm center line.
+        """
         # Translate pvi into armature space
-        ploc = a + (armv/2) + pvi
+        ploc = a + (ikv/2) + pvi
 
         # Set pole target to location
         mat = get_pose_matrix_in_other_space(Matrix().Translation(ploc), pole)
@@ -182,50 +181,99 @@
 
     set_pole(pv)
 
-    # Get the rotation difference between the ik and fk upper arms
-    q1 = uarm.matrix.to_quaternion()
-    q2 = uarmi.matrix.to_quaternion()
+    # Get the rotation difference between ik_first and match_bone
+    q1 = ik_first.matrix.to_quaternion()

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list