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/leg/deform.py')
-rw-r--r--rigify/rigs/biped/leg/deform.py263
1 files changed, 263 insertions, 0 deletions
diff --git a/rigify/rigs/biped/leg/deform.py b/rigify/rigs/biped/leg/deform.py
new file mode 100644
index 00000000..bb6b6f39
--- /dev/null
+++ b/rigify/rigs/biped/leg/deform.py
@@ -0,0 +1,263 @@
+#====================== 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, has_connected_children
+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:
+ """ A leg deform-bone setup.
+
+ """
+ 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 2 connected bones
+ leg_bones = [bone] + connected_children_names(self.obj, bone)[:2]
+
+ if len(leg_bones) != 2:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+ # Get the foot and heel
+ foot = None
+ heel = None
+ for b in self.obj.data.bones[leg_bones[1]].children:
+ if b.use_connect == True:
+ if len(b.children) >= 1 and has_connected_children(b):
+ foot = b.name
+ else:
+ heel = b.name
+
+ if foot is None or heel is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+ # Get the toe
+ toe = None
+ for b in self.obj.data.bones[foot].children:
+ if b.use_connect == True:
+ toe = b.name
+
+ if toe is None:
+ raise MetarigError("RIGIFY ERROR: Bone '%s': incorrect bone configuration for rig type." % (strip_org(bone)))
+
+ self.org_bones = leg_bones + [foot, toe, heel]
+
+ # Get rig parameters
+ self.use_thigh_twist = params.use_thigh_twist
+ self.use_shin_twist = params.use_shin_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_thigh_twist:
+ thigh1 = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0] + ".01")))
+ thigh2 = 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:
+ thigh = copy_bone(self.obj, self.org_bones[0], make_deformer_name(strip_org(self.org_bones[0])))
+
+ # Create forearm bones
+ if self.use_shin_twist:
+ shin1 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".01")))
+ shin2 = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1] + ".02")))
+ stip = copy_bone(self.obj, self.org_bones[1], make_mechanism_name(strip_org(self.org_bones[1] + ".tip")))
+ else:
+ shin = copy_bone(self.obj, self.org_bones[1], make_deformer_name(strip_org(self.org_bones[1])))
+
+ # Create foot bone
+ foot = copy_bone(self.obj, self.org_bones[2], make_deformer_name(strip_org(self.org_bones[2])))
+
+ # Create toe bone
+ toe = copy_bone(self.obj, self.org_bones[3], make_deformer_name(strip_org(self.org_bones[3])))
+
+ # Get edit bones
+ eb = self.obj.data.edit_bones
+
+ org_thigh_e = eb[self.org_bones[0]]
+ if self.use_thigh_twist:
+ thigh1_e = eb[thigh1]
+ thigh2_e = eb[thigh2]
+ utip_e = eb[utip]
+ else:
+ thigh_e = eb[thigh]
+
+ org_shin_e = eb[self.org_bones[1]]
+ if self.use_shin_twist:
+ shin1_e = eb[shin1]
+ shin2_e = eb[shin2]
+ stip_e = eb[stip]
+ else:
+ shin_e = eb[shin]
+
+ org_foot_e = eb[self.org_bones[2]]
+ foot_e = eb[foot]
+
+ org_toe_e = eb[self.org_bones[3]]
+ toe_e = eb[toe]
+
+ # Parent and position thigh bones
+ if self.use_thigh_twist:
+ thigh1_e.use_connect = False
+ thigh2_e.use_connect = False
+ utip_e.use_connect = False
+
+ thigh1_e.parent = org_thigh_e.parent
+ thigh2_e.parent = org_thigh_e
+ utip_e.parent = org_thigh_e
+
+ center = Vector((org_thigh_e.head + org_thigh_e.tail) / 2)
+
+ thigh1_e.tail = center
+ thigh2_e.head = center
+ put_bone(self.obj, utip, org_thigh_e.tail)
+ utip_e.length = org_thigh_e.length / 8
+ else:
+ thigh_e.use_connect = False
+ thigh_e.parent = org_thigh_e
+
+ # Parent and position shin bones
+ if self.use_shin_twist:
+ shin1_e.use_connect = False
+ shin2_e.use_connect = False
+ stip_e.use_connect = False
+
+ shin1_e.parent = org_shin_e
+ shin2_e.parent = org_shin_e
+ stip_e.parent = org_shin_e
+
+ center = Vector((org_shin_e.head + org_shin_e.tail) / 2)
+
+ shin1_e.tail = center
+ shin2_e.head = center
+ put_bone(self.obj, stip, org_shin_e.tail)
+ stip_e.length = org_shin_e.length / 8
+
+ # Align roll of shin2 with foot
+ align_roll(self.obj, shin2, foot)
+ else:
+ shin_e.use_connect = False
+ shin_e.parent = org_shin_e
+
+ # Parent foot
+ foot_e.use_connect = False
+ foot_e.parent = org_foot_e
+
+ # Parent toe
+ toe_e.use_connect = False
+ toe_e.parent = org_toe_e
+
+ # Object mode, get pose bones
+ bpy.ops.object.mode_set(mode='OBJECT')
+ pb = self.obj.pose.bones
+
+ if self.use_thigh_twist:
+ thigh1_p = pb[thigh1]
+ if self.use_shin_twist:
+ shin2_p = pb[shin2]
+ foot_p = pb[foot]
+
+ # Thigh constraints
+ if self.use_thigh_twist:
+ con = thigh1_p.constraints.new('COPY_LOCATION')
+ con.name = "copy_location"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = thigh1_p.constraints.new('COPY_SCALE')
+ con.name = "copy_scale"
+ con.target = self.obj
+ con.subtarget = self.org_bones[0]
+
+ con = thigh1_p.constraints.new('DAMPED_TRACK')
+ con.name = "track_to"
+ con.target = self.obj
+ con.subtarget = utip
+
+ # Shin constraints
+ if self.use_shin_twist:
+ con = shin2_p.constraints.new('COPY_ROTATION')
+ con.name = "copy_rotation"
+ con.target = self.obj
+ con.subtarget = foot
+
+ con = shin2_p.constraints.new('DAMPED_TRACK')
+ con.name = "track_to"
+ con.target = self.obj
+ con.subtarget = stip