Motion transfer setup #1

Manually merged
Sybren A. Stüvel merged 18 commits from cgtinker/powership:motion_transfer into main 2023-06-05 12:06:15 +02:00
1 changed files with 13 additions and 26 deletions
Showing only changes of commit 7cbc8a8c40 - Show all commits

View File

@ -83,8 +83,7 @@ class PowerShipNodeTree(bpy.types.NodeTree):
nodes_before = list(node.exec_order_prerequisites())
if nodes_before:
print(
f" {len(nodes_before)} prerequisites, going there first")
print(f" {len(nodes_before)} prerequisites, going there first")
# There are nodes to execute before this one. Push them to the front of the queue.
to_visit.extendleft(reversed(nodes_before))
continue
@ -170,12 +169,10 @@ class AbstractPowerShipNode(bpy.types.Node):
self.add_execution_socket_output()
def add_execution_socket_input(self) -> None:
self.inputs.new(NodeSocketExecute.bl_idname,
NodeSocketExecute.bl_label)
self.inputs.new(NodeSocketExecute.bl_idname, NodeSocketExecute.bl_label)
def add_execution_socket_output(self) -> None:
self.outputs.new(NodeSocketExecute.bl_idname,
NodeSocketExecute.bl_label)
self.outputs.new(NodeSocketExecute.bl_idname, NodeSocketExecute.bl_label)
def add_optional_input_socket(
self, typename: str, label: str
@ -267,8 +264,7 @@ class AbstractPowerShipNode(bpy.types.Node):
"""Return the connected socket value, or None if not connected."""
input_socket = self.inputs[input_socket_name]
for link in input_socket.links:
convertedValue = expectType(
link.from_socket.default_value) # type: ignore
convertedValue = expectType(link.from_socket.default_value) # type: ignore
return convertedValue
return None
@ -400,8 +396,7 @@ class GetBoneNode(AbstractPowerShipNode):
bl_label = "Get Bone"
bl_icon = "BONE_DATA"
head_tail: bpy.props.EnumProperty(
name="Side", items=_bone_head_tail) # type: ignore
head_tail: bpy.props.EnumProperty(name="Side", items=_bone_head_tail) # type: ignore
def draw_buttons(
self, context: bpy.types.Context, layout: bpy.types.UILayout
@ -443,8 +438,7 @@ class GetBoneNode(AbstractPowerShipNode):
bone_rest_rot_scale = bone.bone.matrix_local.copy()
bone_rest_rot_scale.translation = v_nil
_, rot, scale = (
mat_world @ bone_rest_rot_scale.inverted()).decompose()
_, rot, scale = (mat_world @ bone_rest_rot_scale.inverted()).decompose()
self.outputs["Location"].default_value = arm_matrix @ loc
self.outputs["Rotation"].default_value = rot
@ -540,8 +534,7 @@ class SetControlNode(AbstractPowerShipNode):
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
control_location = self._get_optional_input_value("Location", Vector)
control_rotation = self._get_optional_input_value(
"Rotation", Quaternion)
control_rotation = self._get_optional_input_value("Rotation", Quaternion)
control_scale = self._get_optional_input_value("Scale", Vector)
control_obj = self._get_input_value("Control", bpy.types.Object)
@ -923,8 +916,7 @@ class SetCursorNode(AbstractAlwaysExecuteNode):
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
control_location = self._get_optional_input_value("Location", Vector)
control_rotation = self._get_optional_input_value(
"Rotation", Quaternion)
control_rotation = self._get_optional_input_value("Rotation", Quaternion)
cursor = depsgraph.scene.cursor
if control_location is not None:
@ -963,8 +955,7 @@ class SetBoneNode(AbstractPowerShipNode):
def execute(self, depsgraph: bpy.types.Depsgraph) -> None:
control_location = self._get_optional_input_value("Location", Vector)
control_rotation = self._get_optional_input_value(
"Rotation", Quaternion)
control_rotation = self._get_optional_input_value("Rotation", Quaternion)
control_scale = self._get_optional_input_value("Scale", Vector)
if not (control_location or control_rotation or control_scale):
@ -1008,8 +999,7 @@ class SetBoneNode(AbstractPowerShipNode):
loc, rot, scale = bone_mat_world.decompose()
case "CHANNELS":

in which case would rot not be normalized? I'd expect bone_mat_world.decompose() to return a unit quaternion. If you want to normalize the socket value, do that above with rot = control_rotation.normalized().

in which case would `rot` not be normalized? I'd expect `bone_mat_world.decompose()` to return a unit quaternion. If you want to normalize the socket value, do that above with `rot = control_rotation.normalized()`.

I think that can be removed. I was confused because the quaternion affected the scale which indicates that it's not a unit quaternion. This happened on longer bone chains - rounding the scale seemed to fix the issue so I guess it has been some floating point error.

I think that can be removed. I was confused because the quaternion affected the scale which indicates that it's not a unit quaternion. This happened on longer bone chains - rounding the scale seemed to fix the issue so I guess it has been some floating point error.
bone_rest_rot_scale.translation = v_nil
mat_rot_scale = Matrix.LocRotScale(
v_nil, rot, scale) @ bone_rest_rot_scale
mat_rot_scale = Matrix.LocRotScale(v_nil, rot, scale) @ bone_rest_rot_scale
mat_loc = Matrix.Translation(loc)
bone_mat_world = mat_loc @ mat_rot_scale
@ -1052,8 +1042,7 @@ class TwoBoneIKNode(AbstractPowerShipNode):
locator: Callable[[str, Vector], bpy.types.Object]
if self._debug:
locator = functools.partial(
self._debug_locator, scene=depsgraph.scene)
locator = functools.partial(self._debug_locator, scene=depsgraph.scene)
else:
locator = self._locator
@ -1061,11 +1050,9 @@ class TwoBoneIKNode(AbstractPowerShipNode):
target_loc = self._get_input_value("Target", Vector)
target_ob = locator("temp-ik-target", target_loc)
pole_target_loc = self._get_optional_input_value(
"Pole Target", Vector)
pole_target_loc = self._get_optional_input_value("Pole Target", Vector)
if pole_target_loc is not None:
pole_target_ob = locator(
"temp-ik-pole-target", pole_target_loc)
pole_target_ob = locator("temp-ik-pole-target", pole_target_loc)
try:
# Reuse constraint from previous run. This can be useful for