基于四元数的 3D 相机应该累积四元数还是欧拉角?

Posted

技术标签:

【中文标题】基于四元数的 3D 相机应该累积四元数还是欧拉角?【英文标题】:Should Quaternion based 3D Cameras accumulate Quaternions or Euler angles? 【发布时间】:2010-09-24 01:37:52 【问题描述】:

所以我编写了一个面向新程序员的基于四元数的 3D 相机,因此他们非常容易集成和开始使用。

在我开发它时,起初我会将用户输入作为欧拉角,然后根据该帧的输入生成一个四元数。然后,我将获取相机的四元数并将其乘以我们为输入生成的四元数,理论上这应该只是将输入旋转添加到相机旋转的当前状态,然后一切都会变得又胖又快乐。让我们称之为:累积四元数,因为我们只存储和添加四元数。

但我注意到这种方法存在问题。我使用它的次数越多,即使我只在一个欧拉角上旋转,比如 Yaw,它也会在一些迭代中开始流血到另一个,比如 Pitch。这是轻微的,但相当不可接受。

所以我做了更多的研究,发现一篇文章说累积欧拉角更好,所以相机将其当前旋转存储为欧拉角,并且输入只是在每一帧添加到它们。然后我每帧从它们生成一个四元数,然后用来生成我的旋转矩阵。这解决了旋转渗入不正确轴的问题。

那么有任何 *** 成员对这个问题有任何见解吗?这是一种正确的做事方式吗?

【问题讨论】:

【参考方案1】:

乘以四元数会累积浮点舍入问题(即使是 45 度这样的简单角度也不准确)。这是一种复合旋转的好方法,但是每个四元数组件的精度都会随着时间的推移而下降。渗透是一个副作用,视觉上更糟糕的是你的四元数可以开始合并一个比例因子 - 为了恢复它,你必须在任何情况下重新归一化回欧拉角。定点欧拉角不会累积舍入。

重新计算每帧的四元数是最少的。我不会费心去优化它。在重新归一化以恢复准确度之前,您可能允许累积一些四元数,但这确实不值得。

【讨论】:

变换矩阵方法也是如此,将一些运算计数器添加到基于欧拉角的四元数类(仅几行)中并不费力。顺便说一句,我不建议过于频繁地进行标准化,因为它可能会影响您想要的转换效果。我通常每 64-128 次操作标准化一次 “要恢复它,无论如何你都必须重新归一化回欧拉角” - 这根本不是真的 - 比例因子可以通过采用四元数的大小【参考方案2】:

积累是一个不精确的过程。无论您使用四元数还是矩阵,累积大量增量旋转都会累积舍入误差。

我想像这样:您的代码启动并运行,但注意到在一定量的导航后,您的相机令人讨厌地倾斜 - 违反了您事先没有想到的不变量。实际上,您已经意识到您不想想要累积轮换;相反,您想做其他事情。

您可以将其视为界面设计问题,而不是数值准确性问题。基本上,人们希望相机根据俯仰、偏航和滚动进行导航,因此选择直接控制和表示角度可以避免很多问题。

这里的遗憾是四元数似乎变得多余(至少对于这种特殊用法)。不过,您仍然需要四元数 - 用原始俯仰/偏航/滚动角度进行插值可能很难看。同样,这是一个界面设计问题:您需要弄清楚在哪里需要四元数,以及如何将它们放入和取出...

【讨论】:

【参考方案3】:

我见过两者都在争论。我认为您必须处理的真正问题是相机系统的灵活性。 IMO 偏航通常在第三人称视角中更有趣(因为您将围绕角色的垂直轴旋转)。虽然您可以在第一人称视角中围绕垂直方向“偏航”,但我不确定这是否真的是一回事。

但是,我确实认为重新计算每帧的四元数有点浪费。如果您的框架接收到输入,存储最新的四元数并将它们标记为脏可能会更好?

【讨论】:

所以可能同时存储欧拉角和四元数,并且仅在需要时更新四元数,或者更好的是,存储旋转矩阵,并且仅在更新时通过新的四元数更新它。这对于物体的旋转更为重要,因为相机会经常变化。

以上是关于基于四元数的 3D 相机应该累积四元数还是欧拉角?的主要内容,如果未能解决你的问题,请参考以下文章

欧拉角万向节死锁与四元数的相关资料

3D数学基础四元数和欧拉角

3D数学基础:四元数与欧拉角之间的转换

3D计算机图形学变换矩阵欧拉角四元数

怎么把向量转化为四元数或欧拉角

3D计算机图形学变换矩阵欧拉角四元数