在OpenGL中计算矩阵时,变换的正确顺序是什么?

fcwjkofz  于 2022-12-23  发布在  其他
关注(0)|答案(2)|浏览(157)

我正在www.example.com上学习教程LearnOpenGL.com,我对矩阵的顺序感到困惑。
Transformations章节讲述:
矩阵乘法是不可交换的,这意味着它们的顺序很重要。当矩阵相乘时,最右边的矩阵首先与向量相乘,所以您应该从右到左阅读乘法。建议在组合矩阵时,首先进行缩放操作,然后进行旋转,最后进行平移,否则可能(负面)相互影响。例如,如果你先做平移,然后缩放,平移矢量也会缩放!
如果我没记错的话,顺序是Translate * Rotate * Scale * vector_to_transform
但在下一章中,当计算注视矩阵时,乘法的顺序被颠倒了,下面是网站上的代码片段:

// 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)
}

在代码片段的结尾,矩阵的计算公式为rotation * translation,尽管矩阵将乘以,

gl_position = projection * lookAt * model * vec4(vertexPosition, 1.0);

因为列主矩阵必须与向量预乘。
请你帮我弄明白。

yhqotfr8

yhqotfr81#

LearnOpenGL并没有解释相机变换的来源。你可以把相机变换看作是一个逆模型变换。3D数学并不关心你是把相机移向物体还是把物体移向相机。同样,如果你的物体已经被缩放到合适的“世界空间”大小,你也不需要相机来缩放它们。“内在相机参数”的缩放在投影矩阵中处理(纵横比和视野的比例)。这是在相机变换之后完成的。
所以我们把物体的点移向“摄像机”而不是摄像机移向这些点。正如我所说的,你不会把缩放留在摄像机矩阵中,因为你只想确定摄像机前面物体的方向。
将摄影机作为模型放置在世界空间中将是:

M = TR   (leave out S for above reasons)

然后反转摄影机变换-〉

C = M^-1           | M = TR
  = (TR)^-1 
  = R^-1 * T^-1    | inverse of matrix product -> flip order and invert matrices

假设R(angle)是旋转Angular angle的矩阵,T(t)是平移向量t的矩阵,则:

= R(angle)^-1 * T(t)^-1
  = R^T(angle) * T(-t)

这就是你在lookAt方法中返回的结果,R的基向量是由新坐标系的列向量建立的,然后转置(所以它们是行向量)。这是因为相机帧向量是正交的,并且是单位长度,所以得到的矩阵是正交的,这意味着它的逆矩阵是它的转置矩阵。(t)得到平移向量T(-t)(相机的眼睛位置的倒数)。希望我的解释澄清多于混淆:-)

velaa5lx

velaa5lx2#

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

相关问题