【发布时间】:2020-02-12 08:09:18
【问题描述】:
我正在学习 LearnOpenGL.com 上的教程,但我对矩阵的顺序感到困惑。
Transformations 章节讲述:
矩阵乘法不可交换,这意味着它们的顺序很重要。当矩阵相乘时,最右边的矩阵首先与向量相乘,因此您应该从右到左读取乘法。建议在组合矩阵时首先进行缩放操作,然后是旋转,最后是平移,否则它们可能(负面)相互影响。例如,如果您先进行平移然后缩放,则平移向量也会缩放!
所以如果我没记错的话,顺序是Translate * Rotate * Scale * vector_to_transform。
但紧接着下一章,在计算 LookAt 矩阵时,乘法顺序被翻转了。这是来自网站的代码sn-p:
// Custom implementation of the LookAt function
glm::mat4 calculate_lookAt_matrix(glm::vec3 position, glm::vec3 target, glm::vec3 worldUp)
{
// 1. Position = known
// 2. Calculate cameraDirection
glm::vec3 zaxis = glm::normalize(position - target);
// 3. Get positive right axis vector
glm::vec3 xaxis = glm::normalize(glm::cross(glm::normalize(worldUp), zaxis));
// 4. Calculate camera up vector
glm::vec3 yaxis = glm::cross(zaxis, xaxis);
// Create translation and rotation matrix
// In glm we access elements as mat[col][row] due to column-major layout
glm::mat4 translation = glm::mat4(1.0f); // Identity matrix by default
translation[3][0] = -position.x; // Third column, first row
translation[3][1] = -position.y;
translation[3][2] = -position.z;
glm::mat4 rotation = glm::mat4(1.0f);
rotation[0][0] = xaxis.x; // First column, first row
rotation[1][0] = xaxis.y;
rotation[2][0] = xaxis.z;
rotation[0][1] = yaxis.x; // First column, second row
rotation[1][1] = yaxis.y;
rotation[2][1] = yaxis.z;
rotation[0][2] = zaxis.x; // First column, third row
rotation[1][2] = zaxis.y;
rotation[2][2] = zaxis.z;
// Return lookAt matrix as combination of translation and rotation matrix
return rotation * translation; // Remember to read from right to left (first translation then rotation)
}
在代码sn-p的末尾,矩阵计算为rotation * translation,即使矩阵要乘以,
gl_position = projection * lookAt * model * vec4(vertexPosition, 1.0);
作为列主矩阵必须预先乘以向量。
请帮助我理解这一点。
【问题讨论】:
-
没有正确的顺序 - 您总是按照最适合您的问题的顺序应用矩阵(参见例如one of my previous answers)。 LookAt 矩阵有点特殊,因为它有点逆。这可能是代码使用
rotation * translation的原因。但这始终取决于您如何得出公式。如果你计算翻译的方式有点不同,你也可以使用translation * rotation。 -
@NicoSchertler 所以只是视图矩阵是一个特例?根据您的回答,最终结果应该是相同的。但是当我翻转订单时,我得到了不同的结果。
-
如果你想翻转订单,你需要一个不同的翻译矩阵。
-
好的!我想我明白了要点。我错过了一个重要的细节:视图矩阵不应该缩放东西。所以它只是一个矩阵来旋转和平移模型矩阵。为此,应以特定方式组合矩阵。正如您所提到的,视图矩阵是一种特殊情况。请参阅Transformations 章节的
Combining Matrices部分。
标签: c++ opengl matrix transformation glm-math