glm - 将 mat4 分解为平移和旋转?

Posted

技术标签:

【中文标题】glm - 将 mat4 分解为平移和旋转?【英文标题】:glm - Decompose mat4 into translation and rotation? 【发布时间】:2013-07-28 21:19:36 【问题描述】:

出于 lerping 的目的,我需要将 4x4 矩阵分解为四元数和 vec3。 获取四元数很简单,因为您可以将矩阵传递给构造函数,但我找不到获取翻译的方法。 肯定有办法吗?

【问题讨论】:

【参考方案1】:

glm::vec3(m[3])是位置向量(假设mglm::mat4

【讨论】:

我认为有必要解释一下为什么这样有效。平移矩阵只是一个 4x4 单位矩阵,其位置在第四列(在第四行有一个 1)。在 GLM 中,mat4vec4 的 4 数组,其中每个 vec4 代表一列;数组是零索引的,所以[3] 得到第四列。然后glm::vec3(...) 将其转换为 vec3,丢弃第四个(未使用的)部分,只为您提供平移距离。【参考方案2】:

看起来 glm 0.9.6 支持矩阵分解 http://glm.g-truc.net/0.9.6/api/a00204.html

#include <glm/gtx/matrix_decompose.hpp>

glm::mat4 transformation; // your transformation matrix.
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(transformation, scale, rotation, translation, skew, perspective);

【讨论】:

该文档有点过时(即使对于当前的 v0.9.7),您需要包含 而不是 让它工作。 应该注意的是,如果你想要的只是平移向量,那么这种方法的计算效率非常低。 @kerim 下面的答案会快得多。【参考方案3】:

在 glm-0.9.8.1 版本中,您必须包含:

#include &lt;glm/gtx/matrix_decompose.hpp&gt;

使用它:

glm::mat4 transformation; // your transformation matrix.
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(transformation, scale, rotation, translation, skew,perspective);

请记住,生成的四元数不正确。 它返回它的共轭!

要解决此问题,请将其添加到您的代码中:

rotation=glm::conjugate(rotation);

【讨论】:

感谢一堆,真是奇怪的 API 你怎么知道返回的四元数是共轭的?它没有在文档中说明任何内容 您可以通过组合您选择的转换矩阵进行测试,然后执行分解以断言值。 P.S.四元数的共轭代表它的逆旋转。【参考方案4】:

我想我会发布 2019 年的更新和完整答案。信用到期,这是基于 valmo 的答案,包括 Konstantinos Roditakis 的答案中的一些项目以及我遇到的一些其他信息。

无论如何,从 0.9.9 版本开始你仍然可以使用实验矩阵分解:https://glm.g-truc.net/0.9.9/api/a00518.html

首先,我要添加的部分是因为我在其他任何地方都看不到它,除非您在以下包含之前定义以下内容,否则您将收到错误:

#define GLM_ENABLE_EXPERIMENTAL

接下来,您必须包括:

#include <glm/gtx/matrix_decompose.hpp>

最后是一个使用示例:

glm::mat4 transformation; // your transformation matrix.
glm::vec3 scale;
glm::quat rotation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(transformation, scale, rotation, translation, skew,perspective);

此外,如 Konstantinos Roditakis 的回答中所述,四元数确实不正确,可以通过应用以下方法来修复:

rotation = glm::conjugate(rotation);

【讨论】:

【参考方案5】:

抱歉迟到了。实际上,在计算四元数的 x,y,z 分量时,必须将结果 quat 共轭的原因是矩阵分量的减法顺序错误。

Here 是它应该如何的解释和示例代码。

所以基本上在glm,decompose()方法,matrix_decompose.inl文件中:

我们有:

    orientation.x = root * (Row[1].z - Row[2].y);
    orientation.y = root * (Row[2].x - Row[0].z);
    orientation.z = root * (Row[0].y - Row[1].x);

什么时候应该:

    orientation.x = root * (Row[2].y - Row[1].z);
    orientation.y = root * (Row[0].z - Row[2].x);
    orientation.z = root * (Row[1].x - Row[0].y);

还有see this impl,它看起来非常接近 GLM 中的那个,但它是正确的。

【讨论】:

【参考方案6】:

我自己制作了不需要“倾斜”和“透视”组件的分解函数。

void decomposeMtx(const glm::mat4& m, glm::vec3& pos, glm::quat& rot, glm::vec3& scale)

    pos = m[3];
    for(int i = 0; i < 3; i++)
        scale[i] = glm::length(vec3(m[i]));
    const glm::mat3 rotMtx(
        glm::vec3(m[0]) / scale[0],
        glm::vec3(m[1]) / scale[1],
        glm::vec3(m[2]) / scale[2]);
    rot = glm::quat_cast(rotMtx);

如果你也不需要缩放,可以进一步简化:

void decomposeMtx(const glm::mat4& m, glm::vec3& pos, glm::quat& rot)

    pos = m[3];
    rot = glm::quat_cast(m);

【讨论】:

以上是关于glm - 将 mat4 分解为平移和旋转?的主要内容,如果未能解决你的问题,请参考以下文章

在 GLM 中旋转、缩放和平移 2d 点

模型矩阵分解

如何从 glm::quat 和 glm::mat4 中提取偏航俯仰滚动

如何在 glRotatef 中使用 glm::mat4

相机 旋转

相机 旋转