四元数的增量应用
Incremental application of Quaternion
我正在尝试弄清楚如何以多个增量应用旋转,
到一个动态的方向(即 我不能使用 slerp)。
详情:
我有一个 3D 对象 space,其方向可以用四元数 Q
来描述。
当此对象旋转时,它会从另一台服务器接收定期更新,
它定义了真正的方向。例如,在时间t1
,对象的方向
是 Q1
,并收到更新,指出正确的方向应该是 K1
。
我不能简单地将Q1
替换为K1
,因为视觉效果会不流畅,
所以我宁愿通过 10 个步骤从 Q1
逐渐更正到 K1
。
另外,我不能使用 slerp,因为 Q1
不是静态的。相反,我想
导出一个增量修正,我称之为 dK
,直到下一次服务器更新
到了。
现在我通过以下方式导出 dK
:
delK = K1 * Q1.conjugate()
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);
我正在尝试弄清楚如何以多个增量应用旋转, 到一个动态的方向(即 我不能使用 slerp)。
详情:
我有一个 3D 对象 space,其方向可以用四元数 Q
来描述。
当此对象旋转时,它会从另一台服务器接收定期更新,
它定义了真正的方向。例如,在时间t1
,对象的方向
是 Q1
,并收到更新,指出正确的方向应该是 K1
。
我不能简单地将Q1
替换为K1
,因为视觉效果会不流畅,
所以我宁愿通过 10 个步骤从 Q1
逐渐更正到 K1
。
另外,我不能使用 slerp,因为 Q1
不是静态的。相反,我想
导出一个增量修正,我称之为 dK
,直到下一次服务器更新
到了。
现在我通过以下方式导出 dK
:
delK = K1 * Q1.conjugate()
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);