Godot如何修复旋转精度错误

Godot how to fix rotation precision errors

我有一个骨架,我的程序每帧都在旋转。使用起始方向向量(骨骼位置到其尖端的起始位置)和结束方向向量(骨骼位置到其尖端的结束位置)计算旋转角度和轴。骨架的骨骼每帧从起始向量到结束向量完全旋转。对于前 70 帧,一切都很好,并且旋转正确。然而,在那之后,旋转中存在明显的错误。每一帧错误都变得越来越大,直到旋转完全错误。我认为发生这种情况是因为精度错误导致此错误累积。

在 Godot 文档中它说:

If a transform is rotated every frame, it will eventually start deforming over time. This is unavoidable.

There are two different ways to handle this. The first is to orthonormalize the transform after some time (maybe once per frame if you modify it every frame):

为了解决这个问题,我尝试了这个:

transform.orthonormalized()

这似乎没有任何改变,错误仍然存​​在。

我正在考虑使用 .look_at() 方法而不是按轴和角度旋转,但我不确定是否会出现精度错误。另外,我不确定如何在骨骼的骨骼上调用该方法。

解决此问题的最佳方法是什么?


新答案

所以你在处理物理…

让我们重新构建转换。我们可以从我们拥有的转换中提取我们需要的部分:

var start_location := transform.origin
var start_rotation := transform.basis.get_rotation_quat()
var start_scale := transform.basis.get_scale()

并且您有一个要应用的旋转,保留其他部分。所以 我认为那将是:

var new_location := transform.origin
var new_rotation := transform.basis.get_rotation_quat() * rotation
var new_scale := transform.basis.get_scale()

或者您需要输入rotation * transform.basis.get_rotation_quat()

然后我们从中构建一个转换,我相信它会像这样:

var new_transform := Transform(
    Basis(
        transform.basis.get_rotation_quat() * rotation
    ).scaled(transform.basis.get_scale()),
    transform.origin
)

而且,如果这不能消除累积的错误,这应该:

var new_transform := Transform(
    Basis(
        (transform.basis.get_rotation_quat() * rotation).normalized()
    ).scaled(transform.basis.get_scale()),
    transform.origin
)

旧答案

此答案假定您正在制作程序化动画。

创建开始和结束旋转(四元数或轴角),每一帧使用从端点开始的插值旋转创建一个新的变换。也就是说,您需要一个表示从运动开始的旋转的变换,而不是从前一帧开始的旋转。


对于插值,您可能希望使用已用时间与总时间的比率作为权重。我的意思是,您可以将动画开始后的时间除以动画必须花费的总时间。

所以,假设动画在 start_time 开始,必须用 total_time 才能完成。在current_time瞬间,你有:

elapsed_time = current_time - start_time

权重为elapsed_time/total_time,即:

(current_time - start_time)/total_time

我不知道你是如何处理时间的。但是,请注意,如果您使用 OS.get_ticks_msec() 之类的东西,它以整数形式给出毫秒数,那么当您想要 0.0 和 [=23= 之间的浮点数时,您将进行整数除法] 进行插值。所以你需要在划分之前转换为浮动。


同样,如果要将旋转应用到原始变换,请不要在每一帧应用增量旋转。相反,每一帧都将原始变换与从运动开始到当前帧的旋转相结合。

由于旋转不会基于先前的帧,因此不会累积错误。

结合上面Theraot的回答,我还发现在计算旋转轴和角度之前重置Transform有助于消除精度错误。

类似于:

skeleton.set_bone_pose(bone, Transform.IDENTITY)