将 OpenGL 4x4 矩阵转换为旋转角度
Posted
技术标签:
【中文标题】将 OpenGL 4x4 矩阵转换为旋转角度【英文标题】:Convert OpenGL 4x4 matrix to rotation angles 【发布时间】:2011-07-29 08:23:56 【问题描述】:我在 OpenGL 中提取模型矩阵 glGetFloatv (GL_MODELVIEW_MATRIX, (float*)x)
并希望从生成的 4x4 矩阵中提取 x、y 和 z 轴旋转。我怎样才能做到这一点 ? 谢谢!
【问题讨论】:
看看这个 SOQ ***.com/questions/1766284/… 谢谢,我尝试在其中应用脚本,但结果并不正确。例如。我设置为 OpenGL xyz rot = [80,80,80],链接中的脚本返回 [-85,70,-85]。知道为什么会这样吗?谢谢! 旋转的顺序非常重要...xyz 可能必须应用 zyx(也许)通常它们被称为欧拉角en.wikipedia.org/wiki/Euler_angles 并明智地应用了航向-俯仰-滚动 欧拉角的坏事(或一件坏事)是,每个人都使用不同的约定(轴及其顺序)并隐含地假设他的约定是标准,所以你应该经常仔细检查,您和其他人正在使用 12 种可能的约定中的哪一种。 【参考方案1】:首先您应该知道,称为欧拉角的 x、y、z 轴旋转存在严重的数值问题。他们也不是明确的。因此,要么存储旋转角度和旋转轴,从而有效地变相形成四元数,要么坚持使用完整的旋转矩阵。
从旋转矩阵中找到四元数称为特征值问题。从技术上讲,您正在确定旋转矩阵的特征向量,它是轴,大小表示角度。
【讨论】:
我之所以喜欢它,是因为我将角度存储在 3 个变量中,并且在我的 OpenGL 绘制函数中,我对这些角度执行 3x glRotate。现在我想在这 3 个轴之一上进一步旋转,所以我使用了额外的时间 glRotate,并将矩阵重新发送到系统以重新存储我的新旋转角度。有更好的方法吗? @Laurent Crivello:请不要将旋转存储为欧拉角,因为混乱和疯狂等着你。而是将旋转存储为单个四元数。通过乘以该四元数来应用进一步的旋转。将四元数转换为旋转矩阵很简单,可以使用 glMultMatrix 将其应用于 OpenGL 矩阵堆栈。此外,您不应该将 OpenGL 误认为是一个数学库; OpenGL-3 删除了所有矩阵操作函数,要求用户自己跟踪矩阵。这是为了让人们远离你正在做的事情。 所以基本上我不应该将我的 x,y,z 作为单独的角度保留在数组中并使用 glRotate 命令,而是保留一个 3x3 旋转矩阵并将其乘以当前矩阵,对吗?跨度> @Laurent Crivello:是的,要么那样,要么使用四分之一。【参考方案2】:我正在编写一个类似于 CAD 的应用程序,所以我理解您的问题,我们“在业务中”知道欧拉角对于线性变换有多糟糕 - 但最终用户发现它们比矩阵或四元数更直观。
对于我的应用程序,我解释了 Ken Shoemake 的精彩算法,它是支持任意旋转顺序的极少数算法之一。它来自 93 年,所以它是纯 C 代码——不适合胆小的人!
http://tog.acm.org/resources/GraphicsGems/gemsiv/euler_angle/
【讨论】:
【参考方案3】:这样的东西应该会给你你所追求的。
final double roll = Math.atan2(2 * (quat.getW() * quat.getX() + quat.getY() * quat.getZ()),
1 - 2 * (quat.getX() * quat.getX() + quat.getY() * quat.getY()));
final double pitch = Math.asin(2 * (quat.getW() * quat.getY() - quat.getZ() * quat.getY()));
final double yaw = Math.atan2(2 * (quat.getW() * quat.getZ() + quat.getX() * quat.getY()), 1 - 2 * (quat.getY()
* quat.getY() + quat.getZ() * quat.getZ()));
当我使用 SLERP 在从 2 个 4x4 矩阵(即相机在 2 个 3D 点之间移动)导出的 2 个四元数之间进行插值时,我将其用作实用函数来打印相机角度。
【讨论】:
感谢您的回答。但是我的四元数是一个 4x4 矩阵,其中第一个 3x3 用于旋转。但是我无法在您的代码中检索 mat[0-1-2 / 4-5-6 / 8-9-10] 和 getX、Y、Z 或 W 之间的映射。对我有什么提示吗?谢谢! 如果您使用 Java 和 vecmath 库,您可以通过Quat4d quaternion = new Quat4d(); quaternion.set(yourMatrix);
创建一个四元数。以上是关于将 OpenGL 4x4 矩阵转换为旋转角度的主要内容,如果未能解决你的问题,请参考以下文章