四元数的增量应用

Incremental application of Quaternion

我正在尝试弄清楚如何以多个增量应用旋转, 到一个动态的方向(即 我不能使用 slerp)。

详情: 我有一个 3D 对象 space,其方向可以用四元数 Q 来描述。 当此对象旋转时,它会从另一台服务器接收定期更新, 它定义了真正的方向。例如,在时间t1,对象的方向 是 Q1,并收到更新,指出正确的方向应该是 K1

我不能简单地将Q1替换为K1,因为视觉效果会不流畅, 所以我宁愿通过 10 个步骤从 Q1 逐渐更正到 K1。 另外,我不能使用 slerp,因为 Q1 不是静态的。相反,我想 导出一个增量修正,我称之为 dK,直到下一次服务器更新 到了。

现在我通过以下方式导出 dK

  1. delK = K1 * Q1.conjugate()
  2. dk = delK / 10

在第 2 步实际发生的是,我将 delK 转换为轴+角度表示, 然后将角度除以 10。然后我转换回四元数。

问题 1:上述方法在数学上是否正确?

问题 2: 我看到一些情况 dk 不是一个小的修正并且可能在相反的方向上旋转。可能是什么原因造成的。

这是为了在 JavaScript incheon 中实现客户端预测。

您可以将 10 步方法替换为 "slerp towards" 解决方案:

Q = slerp(Q, Q1, 1 - Math.pow(smoothingRatio, deltaTime)

此解决方案将以独立于帧速率的方式将 Q 推向 Q1,并允许 Q1 是动态的。经过 1 秒的插值后,"distance" 到 Q1 的剩余分数将为 smoothingRatio。阅读更多 here.

如果每次更新的旋转角度大于 180 度,那么最近的旋转轴将与服务器上的不同。一个天真的解决方案是更频繁地发送更新,或者限制对象的旋转速度。

如果您要随更新一起发送 angular 速度,您可以进行更好的客户端预测,并可能绕过 "opposite direction" 问题。这个想法是沿着上次更新中发送的 angular 速度继续旋转四元数。

Cannon.js中的Quaternion#integrate函数实现了四元数积分,您可以使用。

// Rotate Q along the angular velocity provided in the last update
Q = Q.integrate(angularVelocity, deltaTime, Vec3.ZERO);