[Bf-extensions-cvs] SVN commit: /data/svn/bf-extensions [3235] trunk/py/scripts/addons/ io_import_scene_mhx.py: Mhx importer v 1.12: Improved FK/IK snapping.

Thomas Larsson thomas_larsson_01 at hotmail.com
Sat Apr 7 22:06:09 CEST 2012


Revision: 3235
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-extensions&revision=3235
Author:   thomasl
Date:     2012-04-07 20:06:09 +0000 (Sat, 07 Apr 2012)
Log Message:
-----------
Mhx importer v 1.12: Improved FK/IK snapping.

Modified Paths:
--------------
    trunk/py/scripts/addons/io_import_scene_mhx.py

Modified: trunk/py/scripts/addons/io_import_scene_mhx.py
===================================================================
--- trunk/py/scripts/addons/io_import_scene_mhx.py	2012-04-07 10:58:18 UTC (rev 3234)
+++ trunk/py/scripts/addons/io_import_scene_mhx.py	2012-04-07 20:06:09 UTC (rev 3235)
@@ -26,7 +26,7 @@
 """
 Abstract
 MHX (MakeHuman eXchange format) importer for Blender 2.5x.
-Version 1.10.3
+Version 1.12.0
 
 This script should be distributed with Blender.
 If not, place it in the .blender/scripts/addons dir
@@ -39,7 +39,7 @@
 bl_info = {
     'name': 'Import: MakeHuman (.mhx)',
     'author': 'Thomas Larsson',
-    'version': (1, 11, 1),
+    'version': (1, 12, 0),
     "blender": (2, 6, 3),
     'location': "File > Import > MakeHuman (.mhx)",
     'description': 'Import files in the MakeHuman eXchange format (.mhx)',
@@ -50,9 +50,8 @@
     'category': 'Import-Export'}
 
 MAJOR_VERSION = 1
-MINOR_VERSION = 11
-SUB_VERSION = 1
-BLENDER_VERSION = (2, 6, 2)
+MINOR_VERSION = 12
+SUB_VERSION = 0
 
 #
 #
@@ -3591,252 +3590,249 @@
 
 #########################################
 #
-#   FK-IK snapping panel. 
-#   The bulk of this code was shamelessly stolen from Rigify.
+#   FK-IK snapping. 
 #
 #########################################
 
-def getParent(pb):
+def getPoseMatrix(mat, pb):
+    restInv = pb.bone.matrix_local.inverted()
     if pb.parent:
-        return pb.parent
-    #return None
-    for cns in pb.constraints:
-        if cns.type == 'CHILD_OF' and cns.influence > 0.5:
-            ob = cns.target
-            parent = ob.pose.bones[cns.subtarget]
-            return parent
-    return None            
-    
-def getPoseMatrixInOtherSpace(mat, pb):
-    rest = pb.bone.matrix_local.copy()
-    restInv = rest.inverted()
-    parent = getParent(pb)
-    if parent:
-        parMat = parent.matrix.copy()
-        parInv = parMat.inverted()
-        parRest = parent.bone.matrix_local.copy()
+        parInv = pb.parent.matrix.inverted()
+        parRest = pb.parent.bone.matrix_local
+        return restInv * (parRest * (parInv * mat))
     else:
-        parMat = Matrix()
-        parInv = Matrix()
-        parRest = Matrix()
+        return restInv * mat
 
-    # Get matrix in bone's current transform space
-    smat = restInv * (parRest * (parInv * mat))
-    return smat
+        
+def getGlobalMatrix(mat, pb):
+    gmat = pb.bone.matrix_local * mat
+    if pb.parent:
+        parMat = pb.parent.matrix
+        parRest = pb.parent.bone.matrix_local
+        return parMat * (parRest.inverted() * gmat)
+    else:
+        return gmat
 
 
-def getLocalPoseMatrix(pb):
-    return getPoseMatrixInOtherSpace(pb.matrix, pb)
+def matchPoseTranslation(pb, fkPb, auto):
+    mat = getPoseMatrix(fkPb.matrix, pb)
+    insertLocation(pb, mat, auto)
+    
 
+def insertLocation(pb, mat, auto):    
+    pb.location = mat.to_translation()
+    if auto:
+        pb.keyframe_insert("location", group=pb.name)
+    bpy.ops.object.mode_set(mode='OBJECT')
+    bpy.ops.object.mode_set(mode='POSE')
 
-def setPoseTranslation(pb, mat):
-    if pb.bone.use_local_location == True:
-        pb.location = mat.to_translation()
-    else:
-        loc = mat.to_translation()
 
-        rest = pb.bone.matrix_local.copy()
-        parent = getParent(pb)
-        if parent:
-            parRest = parent.bone.matrix_local.copy()
-        else:
-            parRest = Matrix()
+def matchPoseRotation(pb, fkPb, auto):
+    mat = getPoseMatrix(fkPb.matrix, pb)
+    insertRotation(pb, mat, auto)
+    
 
-        q = (parRest.inverted() * rest).to_quaternion()
-        pb.location = q * loc
-
-
-def setPoseRotation(pb, mat):
+def insertRotation(pb, mat, auto):    
     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]
+        if auto:
+            pb.keyframe_insert("rotation_quaternion", group=pb.name)
     else:
         pb.rotation_euler = q.to_euler(pb.rotation_mode)
-
-
-def setPoseScale(pb, mat):
-    pb.scale = mat.to_scale()
-
-def matchPoseTranslation(pb, tarPb):
-    mat = getPoseMatrixInOtherSpace(tarPb.matrix, pb)
-    setPoseTranslation(pb, mat)
+        if auto:
+            pb.keyframe_insert("rotation_euler", group=pb.name)
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.mode_set(mode='POSE')
 
-def matchPoseRotation(pb, tarPb):
-    mat = getPoseMatrixInOtherSpace(tarPb.matrix, pb)
-    setPoseRotation(pb, mat)
+
+def matchPoseReverse(pb, fkPb, auto):
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.mode_set(mode='POSE')
+    gmat = fkPb.matrix * Matrix.Rotation(math.pi, 4, 'Z')
+    offs = pb.bone.length * fkPb.matrix.col[1]    
+    gmat[0][3] += offs[0]
+    gmat[1][3] += offs[1]
+    gmat[2][3] += offs[2]    
+    mat = getPoseMatrix(gmat, pb)
+    pb.matrix_basis = mat
+    insertLocation(pb, mat, auto)
+    insertRotation(pb, mat, auto)
+    
 
-def matchPoseScale(pb, tarPb):
-    mat = getPoseMatrixInOtherSpace(tarPb.matrix, pb)
-    setPoseScale(pb, mat)
+
+def matchPoseScale(pb, fkPb, auto):
+    mat = getPoseMatrix(fkPb.matrix, pb)
+    pb.scale = mat.to_scale()
+    if auto:
+        pb.keyframe_insert("scale", group=pb.name)
     bpy.ops.object.mode_set(mode='OBJECT')
     bpy.ops.object.mode_set(mode='POSE')
 
-def matchPoleTarget(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
 
-    # Vector from the head of ik_first to the
-    # tip of ik_last
-    ikv = b - a
-
-    # 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.  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(ikv[1]) < abs(ikv[2]):
-        v = Vector((0,1,0))
-    else:
-        v = Vector((0,0,1))
-
-    # 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 + (ikv/2) + pvi
-
-        # Set pole target to location
-        mat = getPoseMatrixInOtherSpace(Matrix.Translation(ploc), pole)
-        setPoseTranslation(pole, mat)
-
-        bpy.ops.object.mode_set(mode='OBJECT')
-        bpy.ops.object.mode_set(mode='POSE')
-
-    set_pole(pv)
-
-    # Get the rotation difference between ik_first and match_bone
-    q1 = ik_first.matrix.to_quaternion()
-    q2 = match_bone.matrix.to_quaternion()
-    angle = math.acos(min(1,max(-1,q1.dot(q2)))) * 2
-
-    # Compensate for the rotation difference
-    if angle > 0.0001:
-        pv = Matrix.Rotation(angle, 4, ikv).to_quaternion() * pv
-        set_pole(pv)
-
-        # Get rotation difference again, to see if we
-        # compensated in the right direction
-        q1 = ik_first.matrix.to_quaternion()
-        q2 = match_bone.matrix.to_quaternion()
-        angle2 = math.acos(min(1,max(-1,q1.dot(q2)))) * 2
-        if angle2 > 0.0001:
-            # Compensate in the other direction
-            pv = Matrix.Rotation((angle*(-2)), 4, ikv).to_quaternion() * pv
-            set_pole(pv)
-
-
 def fk2ikArm(context, suffix):
     rig = context.object
-    print("Snap FK Arm")
-    (uparmIk, loarmIk, elbowPt, wrist) = getSnapBones(rig, "ArmIK", suffix)
-    (uparmFk, loarmFk, handFk) = getSnapBones(rig, "ArmFK", suffix)
+    auto = context.scene.tool_settings.use_keyframe_insert_auto
+    print("Snap FK Arm%s" % suffix)
+    (uparmIk, loarmIk, elbow, elbowPt, wrist) = getSnapBones(rig, "ArmIK", suffix)
+    (uparmFk, loarmFk, elbowPtFk, handFk) = getSnapBones(rig, "ArmFK", suffix)
 
-    matchPoseRotation(uparmFk, uparmIk)
-    matchPoseScale(uparmFk, uparmIk)
+    matchPoseRotation(uparmFk, uparmIk, auto)
+    matchPoseScale(uparmFk, uparmIk, auto)
 
-    matchPoseRotation(loarmFk, loarmIk)
-    matchPoseScale(loarmFk, loarmIk)
+    matchPoseRotation(loarmFk, loarmIk, auto)
+    matchPoseScale(loarmFk, loarmIk, auto)
 
     if rig["&HandFollowsWrist" + suffix]:
-        matchPoseRotation(handFk, wrist)
-        matchPoseScale(handFk, wrist)
+        matchPoseRotation(handFk, wrist, auto)
+        matchPoseScale(handFk, wrist, auto)
     return
 
 
 def ik2fkArm(context, suffix):
     rig = context.object
-    print("Snap IK Arm")
-    (uparmIk, loarmIk, elbowPt, wrist) = getSnapBones(rig, "ArmIK", suffix)
-    (uparmFk, loarmFk, handFk) = getSnapBones(rig, "ArmFK", suffix)
+    scn = context.scene
+    auto = scn.tool_settings.use_keyframe_insert_auto
+    print("Snap IK Arm%s" % suffix)
+    (uparmIk, loarmIk, elbow, elbowPt, wrist) = getSnapBones(rig, "ArmIK", suffix)
+    (uparmFk, loarmFk, elbowPtFk, handFk) = getSnapBones(rig, "ArmFK", suffix)
 
-    matchPoseTranslation(wrist, handFk)
-    matchPoseRotation(wrist, handFk)  
-    matchPoseScale(wrist, handFk)
-
-    matchPoleTarget(uparmIk, loarmIk, elbowPt, uparmFk, (uparmIk.length + loarmIk.length))
+    #rig["&ElbowFollowsShoulder" + suffix] = False
+    #rig["&ElbowFollowsWrist" + suffix] = False
+    
+    matchPoseTranslation(wrist, handFk, auto)
+    matchPoseRotation(wrist, handFk, auto)  
+    matchPoseTranslation(elbow, elbowPtFk, auto)
+    matchPoseTranslation(elbowPt, elbowPtFk, auto)
+    setInverse(rig, elbowPt)
     return
 
 
 def fk2ikLeg(context, suffix):
     rig = context.object
+    auto = context.scene.tool_settings.use_keyframe_insert_auto
     print("Snap FK Leg%s" % suffix)

@@ Diff output truncated at 10240 characters. @@


More information about the Bf-extensions-cvs mailing list