[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