【问题标题】:What is the correct order of Transformations when calculating Matrices in OpenGL?在OpenGL中计算矩阵时正确的变换顺序是什么?
【发布时间】: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


【解决方案1】:

好的!再次阅读整章后,我错过了一个关键细节。视图矩阵通常不缩放对象。它只是一个矩阵,用于旋转和平移模型矩阵,以模拟眼睛进入世界。 LearnOpenGL.com 的This chapter 有一个关于组合矩阵的块解释,它展示了如何组合平移和旋转矩阵以及lookAt 函数的实现方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多