2011-06-25 23:50:50 +00:00
|
|
|
# ##### 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 #####
|
|
|
|
|
|
|
|
# <pep8 compliant>
|
|
|
|
|
2011-06-02 17:19:07 +00:00
|
|
|
import bpy
|
|
|
|
from mathutils import *
|
|
|
|
from math import radians, acos
|
|
|
|
|
2011-06-09 12:30:24 +00:00
|
|
|
#TODO: Only selected bones get retargeted.
|
2011-06-25 23:50:50 +00:00
|
|
|
# Selected Bones/chains get original pos empties,
|
|
|
|
# if ppl want IK instead of FK
|
|
|
|
# Some "magic" numbers - frame start and end,
|
|
|
|
# eulers of all orders instead of just quats keyframed
|
2011-06-09 12:30:24 +00:00
|
|
|
|
2011-06-02 17:19:07 +00:00
|
|
|
# dictionary of mapping
|
2011-06-25 23:50:50 +00:00
|
|
|
# this is currently manuall input'ed, but willW
|
2011-06-09 12:30:24 +00:00
|
|
|
# be created from a more comfortable UI in the future
|
2011-06-24 17:11:54 +00:00
|
|
|
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-24 17:11:54 +00:00
|
|
|
def createDictionary(perf_arm):
|
|
|
|
bonemap = {}
|
|
|
|
for bone in perf_arm.bones:
|
|
|
|
bonemap[bone.name] = bone.map
|
|
|
|
#root is the root of the enduser
|
|
|
|
root = "root"
|
|
|
|
# creation of a reverse map
|
|
|
|
# multiple keys get mapped to list values
|
|
|
|
bonemapr = {}
|
2011-06-25 23:50:50 +00:00
|
|
|
for key, value in bonemap.items():
|
|
|
|
if not value in bonemapr:
|
|
|
|
if isinstance(bonemap[key], tuple):
|
2011-06-24 17:11:54 +00:00
|
|
|
for key_x in bonemap[key]:
|
|
|
|
bonemapr[key_x] = [key]
|
|
|
|
else:
|
|
|
|
bonemapr[bonemap[key]] = [key]
|
2011-06-02 17:19:07 +00:00
|
|
|
else:
|
2011-06-24 17:11:54 +00:00
|
|
|
bonemapr[bonemap[key]].append(key)
|
2011-06-25 23:50:50 +00:00
|
|
|
return bonemap, bonemapr, root
|
2011-06-02 17:19:07 +00:00
|
|
|
# list of empties created to keep track of "original"
|
|
|
|
# position data
|
|
|
|
# in final product, these locations can be stored as custom props
|
2011-06-09 12:30:24 +00:00
|
|
|
# these help with constraining, etc.
|
2011-06-02 17:19:07 +00:00
|
|
|
|
|
|
|
#creation of intermediate armature
|
|
|
|
# the intermediate armature has the hiearchy of the end user,
|
|
|
|
# does not have rotation inheritence
|
|
|
|
# and bone roll is identical to the performer
|
|
|
|
# its purpose is to copy over the rotations
|
|
|
|
# easily while concentrating on the hierarchy changes
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def createIntermediate(performer_obj, enduser_obj, bonemap, bonemapr, root, s_frame, e_frame, scene):
|
2011-06-02 17:19:07 +00:00
|
|
|
#creates and keyframes an empty with its location
|
|
|
|
#the original position of the tail bone
|
|
|
|
#useful for storing the important data in the original motion
|
2011-06-24 17:11:54 +00:00
|
|
|
#i.e. using this empty to IK the chain to that pos / DEBUG
|
2011-06-25 23:50:50 +00:00
|
|
|
def locOfOriginal(inter_bone, perf_bone):
|
2011-07-02 18:24:05 +00:00
|
|
|
if not inter_bone.name + "Org" in bpy.data.objects:
|
2011-06-25 23:50:50 +00:00
|
|
|
bpy.ops.object.add()
|
|
|
|
empty = bpy.context.active_object
|
2011-07-02 18:24:05 +00:00
|
|
|
empty.name = inter_bone.name + "Org"
|
2011-06-27 12:48:30 +00:00
|
|
|
empty.empty_draw_size = 0.1
|
|
|
|
#empty.parent = enduser_obj
|
2011-07-02 18:24:05 +00:00
|
|
|
empty = bpy.data.objects[inter_bone.name + "Org"]
|
2011-06-25 23:50:50 +00:00
|
|
|
offset = perf_bone.vector
|
|
|
|
if inter_bone.length == 0 or perf_bone.length == 0:
|
|
|
|
scaling = 1
|
|
|
|
else:
|
|
|
|
scaling = perf_bone.length / inter_bone.length
|
|
|
|
offset /= scaling
|
|
|
|
empty.location = inter_bone.head + offset
|
|
|
|
empty.keyframe_insert("location")
|
|
|
|
|
2011-06-02 17:19:07 +00:00
|
|
|
#Simple 1to1 retarget of a bone
|
2011-06-25 23:50:50 +00:00
|
|
|
def singleBoneRetarget(inter_bone, perf_bone):
|
|
|
|
perf_world_rotation = perf_bone.matrix * performer_obj.matrix_world
|
2011-06-02 17:19:07 +00:00
|
|
|
inter_world_base_rotation = inter_bone.bone.matrix_local * inter_obj.matrix_world
|
|
|
|
inter_world_base_inv = Matrix(inter_world_base_rotation)
|
|
|
|
inter_world_base_inv.invert()
|
|
|
|
return (inter_world_base_inv.to_3x3() * perf_world_rotation.to_3x3()).to_4x4()
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
#uses 1to1 and interpolation/averaging to match many to 1 retarget
|
|
|
|
def manyPerfToSingleInterRetarget(inter_bone, performer_bones_s):
|
|
|
|
retarget_matrices = [singleBoneRetarget(inter_bone, perf_bone) for perf_bone in performer_bones_s]
|
2011-06-02 17:19:07 +00:00
|
|
|
lerp_matrix = Matrix()
|
2011-06-25 23:50:50 +00:00
|
|
|
for i in range(len(retarget_matrices) - 1):
|
2011-06-02 17:19:07 +00:00
|
|
|
first_mat = retarget_matrices[i]
|
2011-06-25 23:50:50 +00:00
|
|
|
next_mat = retarget_matrices[i + 1]
|
|
|
|
lerp_matrix = first_mat.lerp(next_mat, 0.5)
|
2011-06-02 17:19:07 +00:00
|
|
|
return lerp_matrix
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
#determines the type of hierachy change needed and calls the
|
|
|
|
#right function
|
2011-06-02 17:19:07 +00:00
|
|
|
def retargetPerfToInter(inter_bone):
|
2011-06-25 23:50:50 +00:00
|
|
|
if inter_bone.name in bonemapr:
|
2011-06-02 17:19:07 +00:00
|
|
|
perf_bone_name = bonemapr[inter_bone.name]
|
|
|
|
#is it a 1 to many?
|
2011-06-25 23:50:50 +00:00
|
|
|
if isinstance(bonemap[perf_bone_name[0]], tuple):
|
2011-06-02 17:19:07 +00:00
|
|
|
perf_bone = performer_bones[perf_bone_name[0]]
|
|
|
|
if inter_bone.name == bonemap[perf_bone_name[0]][0]:
|
2011-06-25 23:50:50 +00:00
|
|
|
locOfOriginal(inter_bone, perf_bone)
|
2011-06-02 17:19:07 +00:00
|
|
|
else:
|
|
|
|
# then its either a many to 1 or 1 to 1
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-02 17:19:07 +00:00
|
|
|
if len(perf_bone_name) > 1:
|
|
|
|
performer_bones_s = [performer_bones[name] for name in perf_bone_name]
|
|
|
|
#we need to map several performance bone to a single
|
2011-06-09 12:30:24 +00:00
|
|
|
for perf_bone in performer_bones_s:
|
2011-06-25 23:50:50 +00:00
|
|
|
locOfOriginal(inter_bone, perf_bone)
|
|
|
|
inter_bone.matrix_basis = manyPerfToSingleInterRetarget(inter_bone, performer_bones_s)
|
2011-06-02 17:19:07 +00:00
|
|
|
else:
|
|
|
|
perf_bone = performer_bones[perf_bone_name[0]]
|
2011-06-25 23:50:50 +00:00
|
|
|
locOfOriginal(inter_bone, perf_bone)
|
|
|
|
inter_bone.matrix_basis = singleBoneRetarget(inter_bone, perf_bone)
|
|
|
|
|
2011-06-02 17:19:07 +00:00
|
|
|
inter_bone.keyframe_insert("rotation_quaternion")
|
|
|
|
for child in inter_bone.children:
|
|
|
|
retargetPerfToInter(child)
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
#creates the intermediate armature object
|
|
|
|
inter_obj = enduser_obj.copy()
|
|
|
|
inter_obj.data = inter_obj.data.copy() # duplicate data
|
|
|
|
bpy.context.scene.objects.link(inter_obj)
|
|
|
|
inter_obj.name = "intermediate"
|
|
|
|
bpy.context.scene.objects.active = inter_obj
|
2011-06-02 17:19:07 +00:00
|
|
|
bpy.ops.object.mode_set(mode='EDIT')
|
2011-06-25 23:50:50 +00:00
|
|
|
#resets roll
|
2011-06-02 17:19:07 +00:00
|
|
|
bpy.ops.armature.calculate_roll(type='Z')
|
|
|
|
bpy.ops.object.mode_set(mode="OBJECT")
|
2011-06-25 23:50:50 +00:00
|
|
|
inter_obj.data.name = "inter_arm"
|
|
|
|
inter_arm = inter_obj.data
|
2011-06-02 17:19:07 +00:00
|
|
|
performer_bones = performer_obj.pose.bones
|
2011-06-25 23:50:50 +00:00
|
|
|
inter_bones = inter_obj.pose.bones
|
2011-06-02 17:19:07 +00:00
|
|
|
#clears inheritance
|
|
|
|
for inter_bone in inter_bones:
|
|
|
|
inter_bone.bone.use_inherit_rotation = False
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
for t in range(s_frame, e_frame):
|
2011-06-02 17:19:07 +00:00
|
|
|
scene.frame_set(t)
|
2011-06-17 11:47:45 +00:00
|
|
|
inter_bone = inter_bones[root]
|
2011-06-02 17:19:07 +00:00
|
|
|
retargetPerfToInter(inter_bone)
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
return inter_obj, inter_arm
|
2011-06-09 12:30:24 +00:00
|
|
|
|
|
|
|
# this procedure copies the rotations over from the intermediate
|
|
|
|
# armature to the end user one.
|
2011-06-25 23:50:50 +00:00
|
|
|
# As the hierarchies are 1 to 1, this is a simple matter of
|
2011-06-09 12:30:24 +00:00
|
|
|
# copying the rotation, while keeping in mind bone roll, parenting, etc.
|
|
|
|
# TODO: Control Bones: If a certain bone is constrained in a way
|
|
|
|
# that its rotation is determined by another (a control bone)
|
|
|
|
# We should determine the right pos of the control bone.
|
2011-06-25 23:50:50 +00:00
|
|
|
# Scale: ? Should work but needs testing.
|
|
|
|
|
|
|
|
|
|
|
|
def retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene):
|
|
|
|
inter_bones = inter_obj.pose.bones
|
2011-06-09 12:30:24 +00:00
|
|
|
end_bones = enduser_obj.pose.bones
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-09 12:30:24 +00:00
|
|
|
def bakeTransform(end_bone):
|
|
|
|
src_bone = inter_bones[end_bone.name]
|
|
|
|
trg_bone = end_bone
|
|
|
|
bake_matrix = src_bone.matrix
|
|
|
|
rest_matrix = trg_bone.bone.matrix_local
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-09 12:30:24 +00:00
|
|
|
if trg_bone.parent and trg_bone.bone.use_inherit_rotation:
|
|
|
|
parent_mat = src_bone.parent.matrix
|
|
|
|
parent_rest = trg_bone.parent.bone.matrix_local
|
|
|
|
parent_rest_inv = parent_rest.copy()
|
|
|
|
parent_rest_inv.invert()
|
|
|
|
parent_mat_inv = parent_mat.copy()
|
|
|
|
parent_mat_inv.invert()
|
|
|
|
bake_matrix = parent_mat_inv * bake_matrix
|
|
|
|
rest_matrix = parent_rest_inv * rest_matrix
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-09 12:30:24 +00:00
|
|
|
rest_matrix_inv = rest_matrix.copy()
|
|
|
|
rest_matrix_inv.invert()
|
|
|
|
bake_matrix = rest_matrix_inv * bake_matrix
|
|
|
|
trg_bone.matrix_basis = bake_matrix
|
|
|
|
end_bone.keyframe_insert("rotation_quaternion")
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-09 12:30:24 +00:00
|
|
|
for bone in end_bone.children:
|
|
|
|
bakeTransform(bone)
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
for t in range(s_frame, e_frame):
|
2011-06-09 12:30:24 +00:00
|
|
|
scene.frame_set(t)
|
2011-06-17 11:47:45 +00:00
|
|
|
end_bone = end_bones[root]
|
2011-06-09 12:30:24 +00:00
|
|
|
bakeTransform(end_bone)
|
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
#recieves the performer feet bones as a variable
|
|
|
|
# by "feet" I mean those bones that have plants
|
|
|
|
# (they don't move, despite root moving) somewhere in the animation.
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
def copyTranslation(performer_obj, enduser_obj, perfFeet, bonemap, bonemapr, root, s_frame, e_frame, scene):
|
2011-06-17 11:47:45 +00:00
|
|
|
endFeet = [bonemap[perfBone] for perfBone in perfFeet]
|
|
|
|
perfRoot = bonemapr[root][0]
|
2011-06-25 23:50:50 +00:00
|
|
|
locDictKeys = perfFeet + endFeet + [perfRoot]
|
2011-06-17 11:47:45 +00:00
|
|
|
perf_bones = performer_obj.pose.bones
|
|
|
|
end_bones = enduser_obj.pose.bones
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
def tailLoc(bone):
|
2011-06-25 23:50:50 +00:00
|
|
|
return bone.center + (bone.vector / 2)
|
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
#Step 1 - we create a dict that contains these keys:
|
|
|
|
#(Performer) Hips, Feet
|
|
|
|
#(End user) Feet
|
|
|
|
# where the values are their world position on each (1,120) frame
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
locDict = {}
|
|
|
|
for key in locDictKeys:
|
2011-06-25 23:50:50 +00:00
|
|
|
locDict[key] = []
|
|
|
|
|
|
|
|
for t in range(scene.frame_start, scene.frame_end):
|
2011-06-17 11:47:45 +00:00
|
|
|
scene.frame_set(t)
|
|
|
|
for bone in perfFeet:
|
|
|
|
locDict[bone].append(tailLoc(perf_bones[bone]))
|
|
|
|
locDict[perfRoot].append(tailLoc(perf_bones[perfRoot]))
|
|
|
|
for bone in endFeet:
|
|
|
|
locDict[bone].append(tailLoc(end_bones[bone]))
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
# now we take our locDict and analyze it.
|
2011-06-25 23:50:50 +00:00
|
|
|
# we need to derive all chains
|
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
locDeriv = {}
|
|
|
|
for key in locDictKeys:
|
|
|
|
locDeriv[key] = []
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
for key in locDict.keys():
|
|
|
|
graph = locDict[key]
|
2011-06-25 23:50:50 +00:00
|
|
|
for t in range(len(graph) - 1):
|
2011-06-17 11:47:45 +00:00
|
|
|
x = graph[t]
|
2011-06-25 23:50:50 +00:00
|
|
|
xh = graph[t + 1]
|
|
|
|
locDeriv[key].append(xh - x)
|
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
# now find the plant frames, where perfFeet don't move much
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
linearAvg = []
|
2011-06-25 23:50:50 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
for key in perfFeet:
|
2011-06-25 23:50:50 +00:00
|
|
|
for i in range(len(locDeriv[key]) - 1):
|
2011-06-17 11:47:45 +00:00
|
|
|
v = locDeriv[key][i]
|
|
|
|
hipV = locDeriv[perfRoot][i]
|
|
|
|
endV = locDeriv[bonemap[key]][i]
|
2011-06-25 23:50:50 +00:00
|
|
|
if (v.length < 0.1):
|
2011-06-17 11:47:45 +00:00
|
|
|
#this is a plant frame.
|
|
|
|
#lets see what the original hip delta is, and the corresponding
|
|
|
|
#end bone's delta
|
2011-06-25 23:50:50 +00:00
|
|
|
if endV.length != 0:
|
|
|
|
linearAvg.append(hipV.length / endV.length)
|
2011-07-02 18:24:05 +00:00
|
|
|
|
2011-06-27 12:48:30 +00:00
|
|
|
bpy.ops.object.add()
|
|
|
|
stride_bone = bpy.context.active_object
|
|
|
|
stride_bone.name = "stride_bone"
|
2011-07-02 18:24:05 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
if linearAvg:
|
2011-06-25 23:50:50 +00:00
|
|
|
avg = sum(linearAvg) / len(linearAvg)
|
|
|
|
for t in range(s_frame, e_frame):
|
|
|
|
scene.frame_set(t)
|
|
|
|
newTranslation = (tailLoc(perf_bones[perfRoot]) / avg)
|
2011-07-02 18:24:05 +00:00
|
|
|
stride_bone.location = newTranslation * enduser_obj.matrix_world
|
2011-06-24 17:11:54 +00:00
|
|
|
stride_bone.keyframe_insert("location")
|
2011-06-27 12:48:30 +00:00
|
|
|
return stride_bone
|
2011-06-24 17:11:54 +00:00
|
|
|
|
2011-06-17 11:47:45 +00:00
|
|
|
|
2011-06-26 19:54:29 +00:00
|
|
|
def IKRetarget(bonemap, bonemapr, performer_obj, enduser_obj, s_frame, e_frame, scene):
|
|
|
|
end_bones = enduser_obj.pose.bones
|
|
|
|
for pose_bone in end_bones:
|
|
|
|
if "IK" in [constraint.type for constraint in pose_bone.constraints]:
|
|
|
|
# set constraint target to corresponding empty if targetless,
|
|
|
|
# if not, keyframe current target to corresponding empty
|
|
|
|
perf_bone = bonemapr[pose_bone.name]
|
|
|
|
if isinstance(perf_bone, list):
|
|
|
|
perf_bone = bonemapr[pose_bone.name][-1]
|
2011-07-02 18:24:05 +00:00
|
|
|
end_empty = bpy.data.objects[pose_bone.name + "Org"]
|
2011-06-26 19:54:29 +00:00
|
|
|
ik_constraint = [constraint for constraint in pose_bone.constraints if constraint.type == "IK"][0]
|
|
|
|
if not ik_constraint.target:
|
|
|
|
ik_constraint.target = end_empty
|
|
|
|
else:
|
|
|
|
#Bone target
|
|
|
|
target_is_bone = False
|
|
|
|
if ik_constraint.subtarget:
|
|
|
|
target = ik_constraint.target.pose.bones[ik_constraint.subtarget]
|
|
|
|
target.bone.use_local_location = False
|
|
|
|
target_is_bone = True
|
|
|
|
else:
|
|
|
|
target = ik_constraint.target
|
|
|
|
for t in range(s_frame, e_frame):
|
|
|
|
scene.frame_set(t)
|
|
|
|
if target_is_bone:
|
|
|
|
final_loc = end_empty.location - target.bone.matrix_local.to_translation()
|
|
|
|
else:
|
|
|
|
final_loc = end_empty.location
|
|
|
|
target.location = final_loc
|
|
|
|
target.keyframe_insert("location")
|
|
|
|
ik_constraint.mute = False
|
|
|
|
|
|
|
|
|
|
|
|
def turnOffIK(enduser_obj):
|
|
|
|
end_bones = enduser_obj.pose.bones
|
|
|
|
for pose_bone in end_bones:
|
|
|
|
if pose_bone.is_in_ik_chain:
|
|
|
|
pass
|
|
|
|
# TODO:
|
|
|
|
# set stiffness according to place on chain
|
|
|
|
# and values from analysis that is stored in the bone
|
|
|
|
#pose_bone.ik_stiffness_x = 0.5
|
|
|
|
#pose_bone.ik_stiffness_y = 0.5
|
|
|
|
#pose_bone.ik_stiffness_z = 0.5
|
|
|
|
if "IK" in [constraint.type for constraint in pose_bone.constraints]:
|
|
|
|
ik_constraint = [constraint for constraint in pose_bone.constraints if constraint.type == "IK"][0]
|
|
|
|
ik_constraint.mute = True
|
|
|
|
|
2011-07-02 18:24:05 +00:00
|
|
|
|
|
|
|
def cleanAndStoreObjMat(performer_obj, enduser_obj):
|
2011-06-27 12:48:30 +00:00
|
|
|
perf_obj_mat = performer_obj.matrix_world.copy()
|
|
|
|
enduser_obj_mat = enduser_obj.matrix_world.copy()
|
2011-07-02 18:24:05 +00:00
|
|
|
zero_mat = Matrix() # Matrix(((0,0,0,0),(0,0,0,0),(0,0,0,0),(0,0,0,0)))
|
2011-06-27 12:48:30 +00:00
|
|
|
performer_obj.matrix_world = zero_mat
|
|
|
|
enduser_obj.matrix_world = zero_mat
|
|
|
|
return perf_obj_mat, enduser_obj_mat
|
|
|
|
|
2011-07-02 18:24:05 +00:00
|
|
|
|
|
|
|
def restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, stride_bone):
|
|
|
|
pose_bones = enduser_obj.pose.bones
|
|
|
|
for pose_bone in pose_bones:
|
|
|
|
if pose_bone.name + "Org" in bpy.data.objects:
|
|
|
|
empty = bpy.data.objects[pose_bone.name + "Org"]
|
2011-06-27 12:48:30 +00:00
|
|
|
empty.parent = enduser_obj
|
|
|
|
performer_obj.matrix_world = perf_obj_mat
|
|
|
|
enduser_obj.matrix_world = enduser_obj_mat
|
2011-06-26 19:54:29 +00:00
|
|
|
|
2011-07-02 18:24:05 +00:00
|
|
|
|
2011-06-24 17:11:54 +00:00
|
|
|
def totalRetarget():
|
2011-06-26 19:54:29 +00:00
|
|
|
print("retargeting...")
|
2011-06-25 23:50:50 +00:00
|
|
|
enduser_obj = bpy.context.active_object
|
|
|
|
performer_obj = [obj for obj in bpy.context.selected_objects if obj != enduser_obj]
|
|
|
|
if enduser_obj is None or len(performer_obj) != 1:
|
|
|
|
print("Need active and selected armatures")
|
|
|
|
else:
|
|
|
|
performer_obj = performer_obj[0]
|
|
|
|
perf_arm = performer_obj.data
|
|
|
|
end_arm = enduser_obj.data
|
2011-06-24 17:11:54 +00:00
|
|
|
scene = bpy.context.scene
|
|
|
|
s_frame = scene.frame_start
|
|
|
|
e_frame = scene.frame_end
|
2011-06-25 23:50:50 +00:00
|
|
|
bonemap, bonemapr, root = createDictionary(perf_arm)
|
2011-07-02 18:24:05 +00:00
|
|
|
perf_obj_mat, enduser_obj_mat = cleanAndStoreObjMat(performer_obj, enduser_obj)
|
2011-06-26 19:54:29 +00:00
|
|
|
turnOffIK(enduser_obj)
|
2011-06-25 23:50:50 +00:00
|
|
|
inter_obj, inter_arm = createIntermediate(performer_obj, enduser_obj, bonemap, bonemapr, root, s_frame, e_frame, scene)
|
|
|
|
retargetEnduser(inter_obj, enduser_obj, root, s_frame, e_frame, scene)
|
2011-06-27 12:48:30 +00:00
|
|
|
stride_bone = copyTranslation(performer_obj, enduser_obj, ["RightFoot", "LeftFoot"], bonemap, bonemapr, root, s_frame, e_frame, scene)
|
2011-06-26 19:54:29 +00:00
|
|
|
IKRetarget(bonemap, bonemapr, performer_obj, enduser_obj, s_frame, e_frame, scene)
|
2011-07-02 18:24:05 +00:00
|
|
|
restoreObjMat(performer_obj, enduser_obj, perf_obj_mat, enduser_obj_mat, stride_bone)
|
2011-06-24 17:11:54 +00:00
|
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
2011-06-25 23:50:50 +00:00
|
|
|
bpy.ops.object.select_name(name=inter_obj.name, extend=False)
|
2011-06-24 17:11:54 +00:00
|
|
|
bpy.ops.object.delete()
|
2011-06-25 23:50:50 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2011-07-02 18:24:05 +00:00
|
|
|
totalRetarget()
|