Answers:
简短答案
首先反转视图矩阵。然后从最后一行/列获取翻译。
长答案
推导视图矩阵内容的一种方法是,首先将摄像机视为世界上的任何其他对象,然后为其计算世界矩阵:
RightX RightY RightZ 0
UpX UpY UpZ 0
LookX LookY LookZ 0
PosX PosY PosZ 1
世界矩阵将坐标从局部空间转换为世界空间。但是在这种情况下,相机的局部空间和视图空间是相同的,因此我们也可以说此矩阵将坐标从视图空间转换为世界空间。
由于我们需要在相反方向上进行转换,因此我们必须将矩阵求逆。结果就是所谓的视图矩阵,该矩阵将坐标从世界空间转换为视图空间:
RightX UpX LookX 0
RightY UpY LookY 0
RightZ UpZ LookZ 0
-(Pos*Right) -(Pos*Up) -(Pos*Look) 1 // * = dot product
这就是您所拥有的矩阵。因此,为了从中找回相机的位置,您首先需要将其反转,然后才能从最后一行(或列,具体取决于系统)获取转换。
首先,我强烈建议将位置单独存储为向量,这将使计算变得更容易。无论如何...
[x (dot) right, y (dot) up, z (dot) look]
不是实际的视图矩阵。矩阵本身具有以下形式:
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
其中左上方的3x3矩阵表示旋转,比例等。所有相机的方向都在此完成。其余的行和列用于翻译以及一些我现在不打算讨论的其他复杂的透视图。
当您获得矩阵(假设它是4x4矩阵)时,转换将始终存储在最后一行或最后一列中,具体取决于您的矩阵类是行优先还是列优先。
您可能会感到困惑的是,您需要点积。发生的事情是简化了矩阵数学运算,在此堆栈溢出问题中还有更详细的答案:https : //stackoverflow.com/questions/349050/calculating-a-lookat-matrix
可以在这里找到解决方案,您需要对矩阵求逆并得到其转换结果:
Vector3 ViewTrans = Matrix.Invert(ViewMatrix).Translation;
Position = ViewTrans;
此处的其他答案说明了如何从相机矩阵逆获得相机位置。
如果照像机矩阵的3x3部分像通常那样只有旋转(没有缩放或剪切),则可以通过将照像机矩阵平移与照像机旋转的转置相乘来优化计算。然后,将摄影机位置乘以转换后的平移矢量乘以-1。在GLSL中,这是:
vec3 cameraPosition = -transpose(mat3(worldToCameraMatrix)) * worldToCameraMatrix[3].xyz;
要么
vec3 cameraPosition = -worldToCameraMatrix[3].xyz * mat3(worldToCameraMatrix);
如果我不想以统一的方式计算和传递相机位置,这就是我在顶点着色器中一直使用的。