101 lines
3.6 KiB
Python
101 lines
3.6 KiB
Python
|
|
import bpy
|
|
from mathutils import Quaternion, Matrix, Vector, Euler
|
|
from math import pi
|
|
|
|
from hifi_tools.armature.skeleton import structure as base_armature
|
|
|
|
|
|
def correct_scale_rotation(obj, rotation):
|
|
current_context = bpy.context.area.type
|
|
bpy.context.area.type = 'VIEW_3D'
|
|
# set context to 3D View and set Cursor
|
|
bpy.context.space_data.cursor_location[0] = 0.0
|
|
bpy.context.space_data.cursor_location[1] = 0.0
|
|
bpy.context.space_data.cursor_location[2] = 0.0
|
|
bpy.context.area.type = current_context
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
bpy.ops.object.select_all(action='DESELECT')
|
|
obj.select = True
|
|
bpy.context.scene.objects.active = obj
|
|
bpy.ops.object.origin_set(type='ORIGIN_CURSOR')
|
|
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
|
obj.scale = Vector((100, 100, 100))
|
|
str_angle = -90 * pi/180
|
|
if rotation:
|
|
obj.rotation_euler = Euler((str_angle, 0, 0), 'XYZ')
|
|
bpy.ops.object.transform_apply(location=False, rotation=True, scale=True)
|
|
obj.scale = Vector((0.01, 0.01, 0.01))
|
|
if rotation:
|
|
obj.rotation_euler = Euler((-str_angle, 0, 0), 'XYZ')
|
|
|
|
|
|
def navigate_armature(data, current_rest_node, world_matrix, parent, parent_node):
|
|
name = current_rest_node["name"]
|
|
bone = data.get(name)
|
|
if(bone):
|
|
bone.rotation_mode = "QUATERNION"
|
|
destination_matrix = current_rest_node["matrix_local"].copy()
|
|
inv_destination_matrix = destination_matrix.inverted()
|
|
matrix = bone.matrix
|
|
if parent:
|
|
parent_matrix = parent.matrix.copy()
|
|
parent_inverted = parent_matrix.inverted()
|
|
parent_destination = parent_node["matrix_local"].copy()
|
|
else:
|
|
parent_matrix = Matrix()
|
|
parent_inverted = Matrix()
|
|
parent_destination = Matrix()
|
|
smat = inv_destination_matrix * \
|
|
(parent_destination * (parent_inverted * matrix))
|
|
bone.rotation_quaternion = smat.to_quaternion().inverted()
|
|
for child in current_rest_node["children"]:
|
|
navigate_armature(data, child, world_matrix,
|
|
bone, current_rest_node)
|
|
else:
|
|
bone = parent
|
|
for child in current_rest_node["children"]:
|
|
navigate_armature(data, child, world_matrix, bone, parent_node)
|
|
|
|
|
|
def retarget_armature(options):
|
|
|
|
armature = bpy.context.object
|
|
if armature != None and armature.type == "ARMATURE":
|
|
# Center Children First
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
|
|
# Make sure to reset the bones first.
|
|
bpy.ops.object.transform_apply(
|
|
location=False, rotation=True, scale=True)
|
|
bpy.ops.object.mode_set(mode='POSE')
|
|
bpy.ops.pose.select_all(action='SELECT')
|
|
bpy.ops.pose.transforms_clear()
|
|
bpy.ops.pose.select_all(action='DESELECT')
|
|
|
|
print("---")
|
|
|
|
# Now lets do the repose to rest
|
|
world_matrix = armature.matrix_world
|
|
bones = armature.pose.bones
|
|
for bone in base_armature:
|
|
navigate_armature(bones, bone, world_matrix, None, None)
|
|
print("Iterating Bones")
|
|
|
|
# Then apply everything
|
|
if options['apply']:
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
correct_scale_rotation(armature, True)
|
|
|
|
for child in armature.children:
|
|
correct_scale_rotation(child, False)
|
|
|
|
print("Set", armature, " active")
|
|
bpy.context.scene.objects.active = armature
|
|
|
|
bpy.ops.object.mode_set(mode='OBJECT')
|
|
|
|
else:
|
|
#Judas proofing:
|
|
print("No Armature, select, throw an exception")
|
|
raise Exception("You must select an armature to continue")
|