首页 > 解决方案 > 相机变换矩阵和视图矩阵之间的确切区别是什么(使用OpenGL和lwjgl)

问题描述

在问这个问题之前,我已经在网上阅读了很多内容,我了解到 View 矩阵只是 Camera Transformation 矩阵的逆矩阵。为了清楚起见,如果我们将相机视为一个实际实体,它像场景中的任何其他 3D 对象一样被转换(因此使用转换矩阵,首先平移,然后旋转,然后缩放对象),我们获得相机转换包含相机位置的矩阵。如果我们反转这个矩阵,我们应该得到视图矩阵,但这不是我的代码中发生的事情. 我有两种静态方法:一种在给定位置、3 个轴的旋转和一个应用于所有轴的缩放值(首先平移,然后旋转,然后缩放)的情况下创建变换矩阵,另一种创建给定相机的视图矩阵,它有一个偏航(y 轴的旋转)、一个俯仰(围绕 x 轴的旋转)和一个表示位置的 Vec3(在这里我们首先旋转相机,然后用它的负位置平移它,因为移动相机与移动周围的世界是一样的)。这是转换矩阵的代码:

public static Matrix4f createTransformationMatrix(Vector3f translation, float rx, float ry,
        float rz, float scale) {
    
    Matrix4f matrix = new Matrix4f();
    matrix.setIdentity();
    
    Matrix4f.translate(translation, matrix, matrix);
    
    Matrix4f.rotate((float)Math.toRadians(rx), new Vector3f(1, 0, 0), matrix, matrix);
    Matrix4f.rotate((float)Math.toRadians(ry), new Vector3f(0, 1, 0), matrix, matrix);
    Matrix4f.rotate((float)Math.toRadians(rz), new Vector3f(0, 0, 1), matrix, matrix);
    
    Matrix4f.scale(new Vector3f(scale, scale, scale), matrix, matrix);
    
    return matrix;
}

这是视图矩阵的代码:

public static Matrix4f createViewMatrix(Camera camera) {
    Matrix4f viewMatrix = new Matrix4f();
    viewMatrix.setIdentity();
    
    Matrix4f.rotate((float) Math.toRadians(camera.getPitch()), new Vector3f(1, 0, 0), viewMatrix, viewMatrix);
    Matrix4f.rotate((float) Math.toRadians(camera.getYaw()), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);
    
    Vector3f cameraPos = camera.getPosition();

    Vector3f negativeCameraPos = new Vector3f(-cameraPos.x, -cameraPos.y, -cameraPos.z);
    Matrix4f.translate(negativeCameraPos, viewMatrix, viewMatrix);
    
    return viewMatrix;
}

问题来了:由于我在 Youtube 上学习了如何构建这两个矩阵的教程,而我自己没有编写这段代码,所以我不明白 viewMatrix 如何是相机变换矩阵的反转。我注意到在 createViewMatrix() 中我们首先旋转然后平移(使用负位置),而在 createTransformationMatrix() 中我们首先平移然后旋转然后缩放。因此,如果我理解正确,我可以使用相机数据创建一个转换矩阵,然后将其反转以获得视图矩阵,但它不起作用。我还尝试在 createViewMatrix() 中先用正位置平移(不计算negativeCameraPos),然后旋转然后反转矩阵。结果相同:它不起作用,当我运行程序时会发生奇怪的事情(我没有 不知道如何解释它们,但它们是错误的)。我尝试了很多其他的东西,但它只适用于我提供的代码。你能给我解释一下吗请问如何先旋转然后用负相机位置平移来提供倒置的相机变换矩阵?我很抱歉冗长,但我希望你能在第一时间了解我的问题,以便你能回答我。谢谢你。

标签: javalwjglcg

解决方案


您对相机和视图矩阵的基本了解是正确的。相机通常用于描述观察者/相机在世界中的位置和方向,而视图矩阵将用于从世界空间转换到视图空间,因此它应该是相机矩阵的逆矩阵。

请注意,在矩阵数学中,应用变换的顺序有所不同:先旋转后平移不同于先平移后旋转(我们将在此处不进行等式缩放,因为您通常不会缩放相机 -缩放将通过投影矩阵完成)。

在构建相机矩阵时,您首先要旋转以设置相机方向,然后平移以设置相机位置,即您将相机视为位于 0/0/0,沿 z 轴查看(因此视图矢量将为 0/ 0/1)。旋转后,您会得到不同的归一化视图矢量,但相机仍会“坐”在 0/0/0 处。然后您转换为实际的相机位置(您可能需要额外的矩阵运算来计算该位置,但对于初学者,我会在单独的步骤中执行此操作 - 直到您做对了)。

你能解释一下如何先旋转然后用负相机位置平移来提供倒置的相机变换矩阵吗?

它不应该因为生成的视图矩阵会应用不同的方向。“负”旋转(即角度 +/- 180 度)应该可以工作。在这种情况下,您旋转矢量以指向相机(因此,如果相机围绕 y 轴旋转 45 度,则任何“指向相机”的对象都需要围绕同一轴旋转 225 或 -135 度)。

负平移是可以的,因为如果您将相机移动到世界空间中的 4/3/2,则 -4/-3/-2 的平移会将世界空间中的任何坐标移动到视图空间中。


推荐阅读