OpenGL - 从4x4矩阵中获取本地上方向和右方向?

4

我有一个4x4的变换矩阵,是按以下方式构建的:

glm::mat4 matrix;
glm::quat orientation = toQuaternion(rotation);
matrix*= glm::mat4_cast(orientation);
matrix= glm::translate(matrix, position);
matrix= glm::scale(matrix, scale);

orientation = toQuaternion(localRotation);
matrix*= glm::mat4_cast(orientation);
matrix= glm::scale(matrix, localScale);

其中rotation、position、scale、localRotation和localScale都是vector3。根据许多不同论坛上的许多不同问题的建议,应该可以通过以下方式从生成的矩阵中提取本地方向:

right   = glm::vec3(matrix[0][0], matrix[0][1], matrix[0][2]);
up      = glm::vec3(matrix[1][0], matrix[1][1], matrix[1][2]);
forward = glm::vec3(matrix[2][0], matrix[2][1], matrix[2][2]);

在这里,所有这些方向都被标准化。然后我使用这些方向来获取视图矩阵,如下所示:

glm::lookAt(position, position + forward, up);

一切都很完美——除了一个问题:当我在场景中飞行时,右向量和上向量是完全错误的。前向方向总是准确的。当我在0,0,-1处看向0,0,0时,所有方向都是正确的。但是,当我朝不同的方向看(除了从0,0,-1看向原点的逆向),右向量和上向量就不一致了。它们既不是世界向量,也不是本地向量。它们似乎几乎是随机的。我做错了什么?如何从4x4变换矩阵中获得一致的本地上向量和本地右向量?
1个回答

9

matrix 是本地到世界的转换,而视图矩阵是世界到本地的转换,这意味着在这种情况下,matrix 是视图矩阵的逆矩阵。您当前拥有的代码仅适用于视图矩阵。只需交换行和列:

right   = glm::vec3(matrix[0][0], matrix[1][0], matrix[2][0]);
up      = glm::vec3(matrix[0][1], matrix[1][1], matrix[2][1]);
forward = glm::vec3(matrix[0][2], matrix[1][2], matrix[2][2]);

可能之所以适用于 (0, -1, 0) 是因为视图矩阵的旋转/缩放部分类似于:
1 0 0
0 0 1
0 1 0
< p > matrix 的相应部分是上述矩阵的逆矩阵,当然是相同的。尝试使用另一个方向。


哇!这确实解决了上下问题!然而,左右仍存在同样的问题。 - Skarab
1
@Skarab,这可能是一个符号问题吗?如果你把第一列的负数作为“右” ,那么如果“旋转部分”是正交的(正如它应该是的),并且“向上”和“向前”都是正确的,那么“右”必须是正确值的+或-(取决于坐标惯用约定)。 - meowgoesthedog
1
我真是太惊讶了,就是这个问题!!!!!!你太棒了!!!!!!我被卡在这个问题上已经一个星期了,我无法感谢你! - Skarab
1
非常感谢您,这让我在两天的僵局中终于迎来了突破。 - Karl Forshaw

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