Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'rigify/rigs/biped/arm/deform.py')
-rw-r--r--rigify/rigs/biped/arm/deform.py230
1 files changed, 230 insertions, 0 deletions
diff --git a/rigify/rigs/biped/arm/deform.py b/rigify/rigs/biped/arm/deform.py
new file mode 100644
index 00000000..2a7b3109
--- /dev/null
+++ b/rigify/rigs/biped/arm/deform.py
@@ -0,0 +1,230 @@
+#====================== 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 LICENSE BLOCK ========================
+
+import bpy
+from math import acos, degrees
+from mathutils import Vector, Matrix
+from rigify.utils import MetarigError
+from rigify.utils import copy_bone, flip_bone, put_bone
+from rigify.utils import connected_children_names
+from rigify.utils import strip_org, make_mechanism_name, make_deformer_name
+
+
+def align_roll(obj, bone1, bone2):
+ bone1_e = obj.data.edit_bones[bone1]
+ bone2_e = obj.data.edit_bones[bone2]
+
+ bone1_e.roll = 0.0
+
+ # Get the directions the bones are pointing in, as vectors
+ y1 = bone1_e.y_axis
+ x1 = bone1_e.x_axis
+ y2 = bone2_e.y_axis
+ x2 = bone2_e.x_axis
+
+ # Get the shortest axis to rotate bone1 on to point in the same direction as bone2
+ axis = y1.cross(y2)
+ axis.normalize()
+
+ # Angle to rotate on that shortest axis
+ angle = y1.angle(y2)
+
+ # Create rotation matrix to make bone1 point in the same direction as bone2
+ rot_mat = Matrix.Rotation(angle, 3, axis)
+
+ # Roll factor
+ x3 = x1 * rot_mat
+ dot = x2 * x3
+ if dot > 1.0:
+ dot = 1.0
+ elif dot < -1.0:
+ dot = -1.0
+ roll = acos(dot)
+
+ # Set the roll
+ bone1_e.roll = roll
+
+ # Check if we rolled in the right direction
+ x3 = bone1_e.x_axis * rot_mat
+ check = x2 * x3
+
+ # If not, reverse
+ if check < 0.9999:
+ bone1_e.roll = -roll
+
+
+class Rig:
+ """ An FK arm rig, with hinge switch.
+
+ """
+ def __init__(self, obj, bone, params):
+ """ Gather and validate data about the rig.
+ Store any data or references to data that will be needed later on.
+ In particular, store references to bones that will be needed, and
+ store names of bones that will be needed.
+ Do NOT change any data in the scene. This is a gathering phase only.
+
+ """
+ self.obj = obj
+ self.params = params
+
+ # Get the chain of 3 connected bones
+ self.org_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(self.org_bones) != 3:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': input to rig type must be a chain of 3 bones." % (strip_org(bone)))
+
+ # Get rig parameters
+ self.use_upper_arm_twist = params.use_upper_arm_twist
+ self.use_forearm_twist = params.use_forearm_twist
+
+ def generate(self):
+ """ Generate the rig.
+ Do NOT modify any of the original bones, except for adding constraints.
+ The main armature should be selected and active before this is called.
+
+ """
+ bpy.ops.object.mode_set(mode='EDIT')
+
+ # Create upper arm bones
+ if self.use_upper_arm_twist:
+ uarm1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+ uarm2 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".02")))
+ utip = copy_bone(self.obj, self.org_bones[0], make_mechanism_name(strip_org(self.org_bones[0] + ".tip")))
+ else:
+ uarm = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+ # Create forearm bones
+ if self.use_forearm_twist:
+ farm1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
+ farm2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
+ ftip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
+ else:
+ farm = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))
+
+ # Create hand bone
+ hand = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ org_uarm_e = eb[self.org_bones[0]]
+ if self.use_upper_arm_twist:
+ uarm1_e = eb[uarm1]
+ uarm2_e = eb[uarm2]
+ utip_e = eb[utip]
+ else:
+ uarm_e = eb[uarm]
+
+ org_farm_e = eb[self.org_bones[1]]
+ if self.use_forearm_twist:
+ farm1_e = eb[farm1]
+ farm2_e = eb[farm2]
+ ftip_e = eb[ftip]
+ else:
+ farm_e = eb[farm]
+
+ org_hand_e = eb[self.org_bones[2]]
+ hand_e = eb[hand]
+
+ # Parent and position upper arm bones
+ if self.use_upper_arm_twist:
+ uarm1_e.use_connect = False
+ uarm2_e.use_connect = False
+ utip_e.use_connect = False
+
+ uarm1_e.parent = org_uarm_e.parent
+ uarm2_e.parent = org_uarm_e
+ utip_e.parent = org_uarm_e
+
+ center = Vector((org_uarm_e.head + org_uarm_e.tail) / 2)
+
+ uarm1_e.tail = center
+ uarm2_e.head = center
+ put_bone(self.obj, utip, org_uarm_e.tail)
+ utip_e.length = org_uarm_e.length / 8
+ else:
+ uarm_e.use_connect = False
+ uarm_e.parent = org_uarm_e
+
+ # Parent and position forearm bones
+ if self.use_forearm_twist:
+ farm1_e.use_connect = False
+ farm2_e.use_connect = False
+ ftip_e.use_connect = False
+
+ farm1_e.parent = org_farm_e
+ farm2_e.parent = org_farm_e
+ ftip_e.parent = org_farm_e
+
+ center = Vector((org_farm_e.head + org_farm_e.tail) / 2)
+
+ farm1_e.tail = center
+ farm2_e.head = center
+ put_bone(self.obj, ftip, org_farm_e.tail)
+ ftip_e.length = org_farm_e.length / 8
+
+ # Align roll of farm2 with hand
+ align_roll(self.obj, farm2, hand)
+ else:
+ farm_e.use_connect = False
+ farm_e.parent = org_farm_e
+
+ # Parent hand
+ hand_e.use_connect = False
+ hand_e.parent = org_hand_e
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ if self.use_upper_arm_twist:
+ uarm1_p = pb[uarm1]
+ if self.use_forearm_twist:
+ farm2_p = pb[farm2]
+ hand_p = pb[hand]
+
+ # Upper arm constraints
+ if self.use_upper_arm_twist:
+ con = uarm1_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = uarm1_p.constraints.new('COPY_SCALE')
+ con.name = "copy_scale"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = uarm1_p.constraints.new('DAMPED_TRACK')
+ con.name = "track_to"
+ con.target = self.obj
+ con.subtarget = utip
+
+ # Forearm constraints
+ if self.use_forearm_twist:
+ con = farm2_p.constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = hand
+
+ con = farm2_p.constraints.new('DAMPED_TRACK')
+ con.name = "track_to"
+ con.target = self.obj
+ con.subtarget = ftip
+