您可以编写全局姿势覆盖:
bonePose = skel.get_bone_global_pose(id)
bonePose = bonePose.rotated(axis, angle)
skel.set_bone_global_pose_override(id, bonePose, 1.0)
第三个参数amount 是一个权重。如果为 0,则保持原样,如果为 1.0,则替换它。中间的值是插值。还有第四个可选参数persistent,它指定它是否应该在下次更新骨架时保持姿势覆盖(它应该使用更新的姿势计算插值)。
如果这对你有用,那就太好了。
回答问题对我来说更有趣的是,如果没有set_bone_global_pose_override,如何做到这一点。 将此视为学术练习。
骨骼的全局姿势是父级的全局姿势乘以骨骼的姿势。让我们表达一下:
b.global_pose = parent.global_pose * b.pose
其实如果有自定义pose的话就是:
b.global_pose = parent.global_pose * b.custom_pose * b.pose
如果有休息姿势,那就是:
b.global_pose = parent.global_pose * b.rest_pose * b.custom_pose * b.pose
而且我们要修改全局pose,但是只能控制自定义pose和pose。
其实没有理由去修改pose,因为对pose应用一个transform就相当于设置一个自定义pose。
现在,问题是我们可以设置什么自定义姿势X,因此它相当于将变换T 应用于全局姿势:
T * b.global_pose = parent.global_pose * b.rest_pose * X * b.pose
求解 X。提醒:变换乘法不可交换。
首先在两侧应用父级全局姿势的反转(它们在右侧取消):
inverse(parent.global_pose) * T * b.global_pose = b.rest_pose * X * b.pose
然后是双方的其余姿势:
inverse(b.rest_pose) * inverse(parent.global_pose) * T * b.global_pose = X * b.pose
然后两边都按倒置的姿势:
inverse(b.rest_pose) * inverse(parent.global_pose) * T * b.global_pose * inverse(b.pose) = X
这就是我们需要如何计算新的自定义姿势。代码是这样的:
var inverse_rest = skel.get_bone_rest(id).affine_inverse()
var parent = ske.get_bone_parent(id)
var inverse_parent_global = Transform.IDENTITY
if parent != -1:
inverse_parent_global = skel.get_bone_global_pose(parent).affine_inverse()
var global_pose = skel.get_bone_global_pose(id)
var inverse_pose = skel.get_bone_pose(id).affine_inverse()
var t = Transform.IDENTITY.rotated(axis, angle) # the operation you want to do
var x = inverse_rest * inverse_parent_global * t * global_pose * inverse_pose
skel.set_bone_custom_pose(id, x)
或者如果你想设置姿势而不是自定义姿势(假设自定义仍然是身份转换):
var inverse_rest = skel.get_bone_rest(id).affine_inverse()
var parent = ske.get_bone_parent(id)
var inverse_parent_global = Transform.IDENTITY
if parent != -1:
inverse_parent_global = skel.get_bone_global_pose(parent).affine_inverse()
var global_pose = skel.get_bone_global_pose(id)
var t = Transform.IDENTITY.rotated(axis, angle) # the operation you want to do
var x = inverse_rest * inverse_parent_global * t * global_pose
skel.set_bone_pose(id, x)