Added calculation to determine change in root translation when retargeting - needs cleanup/optimization
This commit is contained in:
@@ -15,27 +15,35 @@ scene = bpy.context.scene
|
|||||||
# dictionary of mapping
|
# dictionary of mapping
|
||||||
# this is currently manuall input'ed, but will
|
# this is currently manuall input'ed, but will
|
||||||
# be created from a more comfortable UI in the future
|
# be created from a more comfortable UI in the future
|
||||||
bonemap = { "LeftFoot": ("DEF_Foot.L","DEF_Toes.L"),
|
bonemap = { "Head": "Head",
|
||||||
"LeftUpLeg": "DEF_Thigh.L",
|
"Neck": "Head",
|
||||||
"Hips": "DEF_Hip",
|
"Spine1": "Chest",
|
||||||
"LowerBack": "DEF_Spine",
|
"Spine2": "Chest",
|
||||||
"Spine": "DEF_Torso",
|
"Spine3": "Chest",
|
||||||
"Neck": "DEF_Neck",
|
"Spine": "Torso",
|
||||||
"Neck1": "DEF_Neck",
|
"Hips": "root",
|
||||||
"Head": "DEF_Head",
|
"LeftUpLeg": "Thigh.L",
|
||||||
"LeftShoulder": "DEF_Shoulder.L",
|
"LeftUpLegRoll": "Thigh.L",
|
||||||
"LeftArm": "DEF_Forearm.L",
|
"LeftLeg": "Shin.L",
|
||||||
"LeftForeArm": "DEF_Arm.L",
|
"LeftLegRoll": "Shin.L",
|
||||||
"LeftHand": "DEF_Hand.L",
|
"LeftFoot": "Foot.L",
|
||||||
"RightShoulder": "DEF_Shoulder.R",
|
"RightUpLeg": "Thigh.R",
|
||||||
"RightArm": "DEF_Forearm.R",
|
"RightUpLegRoll": "Thigh.R",
|
||||||
"RightForeArm": "DEF_Arm.R",
|
"RightLeg": "Shin.R",
|
||||||
"RightHand": "DEF_Hand.R",
|
"RightLegRoll": "Shin.R",
|
||||||
"RightFoot": ("DEF_Foot.R","DEF_Toes.R"),
|
"RightFoot": "Foot.R",
|
||||||
"RightUpLeg": "DEF_Thigh.R",
|
"LeftShoulder": "Shoulder.L",
|
||||||
"RightLeg": "DEF_Shin.R",
|
"LeftArm": "HiArm.L",
|
||||||
"LeftLeg": "DEF_Shin.L"}
|
"LeftArmRoll": "HiArm.L",
|
||||||
|
"LeftForeArm": "LoArm.L",
|
||||||
|
"LeftForeArmRoll": "LoArm.L",
|
||||||
|
"RightShoulder": "Shoulder.R",
|
||||||
|
"RightArm": "HiArm.R",
|
||||||
|
"RightArmRoll": "HiArm.R",
|
||||||
|
"RightForeArm": "LoArm.R",
|
||||||
|
"RightForeArmRoll": "LoArm.R" }
|
||||||
|
|
||||||
|
root = "root"
|
||||||
# creation of a reverse map
|
# creation of a reverse map
|
||||||
# multiple keys get mapped to list values
|
# multiple keys get mapped to list values
|
||||||
bonemapr = {}
|
bonemapr = {}
|
||||||
@@ -76,7 +84,10 @@ def createIntermediate():
|
|||||||
empty.name = perf_bone.name+"Org"
|
empty.name = perf_bone.name+"Org"
|
||||||
empty = bpy.data.objects[perf_bone.name+"Org"]
|
empty = bpy.data.objects[perf_bone.name+"Org"]
|
||||||
offset = perf_bone.vector
|
offset = perf_bone.vector
|
||||||
scaling = perf_bone.length / inter_bone.length
|
if inter_bone.length == 0 or perf_bone.length == 0:
|
||||||
|
scaling = 1
|
||||||
|
else:
|
||||||
|
scaling = perf_bone.length / inter_bone.length
|
||||||
offset/=scaling
|
offset/=scaling
|
||||||
empty.location = inter_bone.head + offset
|
empty.location = inter_bone.head + offset
|
||||||
empty.keyframe_insert("location")
|
empty.keyframe_insert("location")
|
||||||
@@ -147,7 +158,7 @@ def createIntermediate():
|
|||||||
|
|
||||||
for t in range(1,150):
|
for t in range(1,150):
|
||||||
scene.frame_set(t)
|
scene.frame_set(t)
|
||||||
inter_bone = inter_bones["DEF_Hip"]
|
inter_bone = inter_bones[root]
|
||||||
retargetPerfToInter(inter_bone)
|
retargetPerfToInter(inter_bone)
|
||||||
|
|
||||||
return inter_obj,inter_arm
|
return inter_obj,inter_arm
|
||||||
@@ -191,8 +202,73 @@ def retargetEnduser():
|
|||||||
|
|
||||||
for t in range(1,150):
|
for t in range(1,150):
|
||||||
scene.frame_set(t)
|
scene.frame_set(t)
|
||||||
end_bone = end_bones["DEF_Hip"]
|
end_bone = end_bones[root]
|
||||||
bakeTransform(end_bone)
|
bakeTransform(end_bone)
|
||||||
|
|
||||||
|
#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.
|
||||||
|
def copyTranslation(perfFeet):
|
||||||
|
endFeet = [bonemap[perfBone] for perfBone in perfFeet]
|
||||||
|
perfRoot = bonemapr[root][0]
|
||||||
|
locDictKeys = perfFeet+endFeet+[perfRoot]
|
||||||
|
perf_bones = performer_obj.pose.bones
|
||||||
|
end_bones = enduser_obj.pose.bones
|
||||||
|
|
||||||
|
def tailLoc(bone):
|
||||||
|
return bone.center+(bone.vector/2)
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
locDict = {}
|
||||||
|
for key in locDictKeys:
|
||||||
|
locDict[key] = []
|
||||||
|
|
||||||
|
for t in range(scene.frame_start,scene.frame_end):
|
||||||
|
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]))
|
||||||
|
|
||||||
|
# now we take our locDict and analyze it.
|
||||||
|
# we need to derive all chains
|
||||||
|
|
||||||
|
locDeriv = {}
|
||||||
|
for key in locDictKeys:
|
||||||
|
locDeriv[key] = []
|
||||||
|
|
||||||
|
for key in locDict.keys():
|
||||||
|
graph = locDict[key]
|
||||||
|
for t in range(len(graph)-1):
|
||||||
|
x = graph[t]
|
||||||
|
xh = graph[t+1]
|
||||||
|
locDeriv[key].append(xh-x)
|
||||||
|
|
||||||
|
# now find the plant frames, where perfFeet don't move much
|
||||||
|
|
||||||
|
linearAvg = []
|
||||||
|
|
||||||
|
for key in perfFeet:
|
||||||
|
for i in range(len(locDeriv[key])-1):
|
||||||
|
v = locDeriv[key][i]
|
||||||
|
hipV = locDeriv[perfRoot][i]
|
||||||
|
endV = locDeriv[bonemap[key]][i]
|
||||||
|
if (v.length<0.1):
|
||||||
|
#this is a plant frame.
|
||||||
|
#lets see what the original hip delta is, and the corresponding
|
||||||
|
#end bone's delta
|
||||||
|
if endV.length!=0:
|
||||||
|
linearAvg.append(hipV.length/endV.length)
|
||||||
|
if linearAvg:
|
||||||
|
avg = sum(linearAvg)/len(linearAvg)
|
||||||
|
print("retargeted root motion should be "+ str(1/avg)+ " of original")
|
||||||
|
|
||||||
|
|
||||||
inter_obj, inter_arm = createIntermediate()
|
inter_obj, inter_arm = createIntermediate()
|
||||||
retargetEnduser()
|
retargetEnduser()
|
||||||
|
copyTranslation(["RightFoot","LeftFoot"])
|
||||||
Reference in New Issue
Block a user