fix: use world-space rotation via global pose override

The bone rest poses have complex non-identity rotations (e.g. LeftUpperArm
euler=(-0.161,-2.760,-2.760)). Applying local rotations on top of these
produces incorrect results. Fix by using set_bone_global_pose_override()
with world-space rotation pre-multiplied on the rest pose basis.
This commit is contained in:
2026-06-25 11:24:54 -04:00
parent 35cb2ef10c
commit 35decd65b3
+8 -4
View File
@@ -545,7 +545,7 @@ func _process(delta: float) -> void:
func _apply_procedural_animation(data: Dictionary, time: float) -> void:
## Applies procedural animation data to the skeleton at the given time.
## Uses linear interpolation between keyframe values.
## Uses global pose override to set bone transforms relative to their rest pose.
if not skeleton:
return
var tracks = data["tracks"]
@@ -577,9 +577,13 @@ func _apply_procedural_animation(data: Dictionary, time: float) -> void:
if prev_kf.has("rot") and next_kf.has("rot"):
var rot: Vector3 = lerp(prev_kf["rot"], next_kf["rot"], t)
# Convert euler angles to Quaternion for set_bone_pose_rotation
var quat = Quaternion.from_euler(rot)
skeleton.set_bone_pose_rotation(bone_idx, quat)
# Get the bone's rest global pose
var rest_global = skeleton.get_bone_global_pose(bone_idx)
# Apply rotation offset around world axes (pre-multiply)
# For locomotion: X = forward/back swing, Y = twist, Z = lateral
var world_basis = Basis(Quaternion.from_euler(rot))
var new_global = Transform3D(world_basis * rest_global.basis, rest_global.origin)
skeleton.set_bone_global_pose_override(bone_idx, new_global, 1.0, true)
elif prev_kf.has("pos") and next_kf.has("pos"):
var pos: Vector3 = lerp(prev_kf["pos"], next_kf["pos"], t)
skeleton.set_bone_pose_position(bone_idx, pos)