OpenGL变换矩阵的顺序是反向的。

13

如果我想绕z轴旋转物体,然后再平移它,我必须执行

glm::mat4 transform;
GLfloat angle = 90f;
transform = glm::rotate(transform, angle, glm::vec3(0.0f, 0.0f, 1.0f));
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));

但它是反向运作的,先旋转后平移,因此我需要将其写成

glm::mat4 transform;
GLfloat angle = 90f;
transform = glm::translate(transform, glm::vec3(0.5f, -0.5f, 0.0f));
transform = glm::rotate(transform, angle, glm::vec3(0.0f, 0.0f, 1.0f));

这背后的数学原理是什么?为什么我必须倒序组合矩阵才能达到预期效果?


我刚刚在谷歌上搜索,也许是角度参数?https://www.opengl.org/sdk/docs/man2/xhtml/glRotate.xml - HRgiger
@HRgiger 角度与此无关 :) 请查看更新。 - lukas.pukenis
这对我来说听起来有点困惑。你先说:“我想沿着z轴旋转对象,然后平移它”。接着又说“它是倒序的,它先旋转再平移”。为什么这会是倒过来的?按照你的描述,听起来你恰好得到了你想要的结果? - Reto Koradi
@RetoKoradi 因为从逻辑上讲,我需要先旋转再平移,但是当将所有操作合并到一个变换矩阵中时,我必须反向执行这些操作,否则结果会出错。这就是让我感到困惑的地方。 - lukas.pukenis
1个回答

29
从直观角度来看,您是完全正确的:必须以人们思考它们相反的方式应用变换。原因非常简单:
在glm / OpenGL中,所有向量都被假定为列向量,因此将矩阵形式的变换(M)应用于向量t可以写成以下形式:
t' = M * t

现在假设我们首先想要翻译 (T) 然后旋转 (R)。我们现在可以分别执行每个步骤,例如:

t' = T * t       //Translate
t'' = R * t'     //Rotate result Translation

当我们想要结合两个变换时,我们在第二行中替换t'并得到:

t'' = R * (T * t) = (R * T) * t

正如您所看到的,首先应用的操作是最后写的(或更好地说是靠近向量)。同样的原则可以应用于任意数量的矩阵。

请注意,如果将向量视为行向量,则整个矩阵顺序将会改变。

 t' = t * M        //General case

让我们来看一下与上面相同的例子,但这次是使用行向量:

 t' = t * T
 t'' = t' * R

 t'' = (t * T) * R = t * (T * R)

结论:每当您考虑变换和向量时,请记住首先应用的操作必须更接近向量。

1
很好的解释!非常感谢!现在我明白了 :) - lukas.pukenis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接