【发布时间】:2018-08-23 13:10:06
【问题描述】:
我有一个 3D 场景,在沿 Y 垂直轴的高度 H 处具有无限水平面(平行于 xz 坐标)。
我想知道如何确定我的相机轴和这个平面的交点。
相机由一个视图矩阵和一个投影矩阵定义。
【问题讨论】:
-
如何定义相机及其方向?
-
@Ripi2 我有 4x4 viewMatrix 和 projectionMatrix。
我有一个 3D 场景,在沿 Y 垂直轴的高度 H 处具有无限水平面(平行于 xz 坐标)。
我想知道如何确定我的相机轴和这个平面的交点。
相机由一个视图矩阵和一个投影矩阵定义。
【问题讨论】:
这里有两个子问题:1)从相机矩阵中提取位置和视图方向。 2) 计算视线与平面的交点。
提取位置和视图方向
视图矩阵描述了点如何从世界空间转换到视图空间。 OpenGL中的view-space通常被定义为相机在原点并且朝向-z方向。
为了获得相机的位置,我们必须将视图空间的原点 [0,0,0] 转换回世界空间。从数学上讲,我们必须计算:
camera_pos_ws = inverse(view_matrix) * [0,0,0,1]
但是在查看方程时,我们会发现我们只对包含 1
的逆矩阵的第 4 列感兴趣camera_pos_ws = [-view_matrix[12], -view_matrix[13], -view_matrix[14]]
可以通过类似的计算找到相机的方向。我们知道相机在视图空间的 -z 方向上看,因此世界空间方向由下式给出
camera_dir_ws = inverse(view_matrix) * [0,0,-1,0];
同样,在查看等式时,我们会看到这仅考虑了由 2
给出的逆矩阵的第三行camera_dir_ws = [-view_matrix[2], -view_matrix[6], -view_matrix[10]]
计算交点
我们现在知道相机位置 P 和观察方向 D,因此我们必须找到沿射线 R(x,y,z) = P + l * D 的 x,z 值,其中 y 等于 H。由于只有一个未知数 l,我们可以计算出来自
y = Py + l * Dy
H = Py + l * Dy
l = (H - Py) / Dy
然后通过将 l 粘贴回射线方程来给出交点。
备注
1 索引假定矩阵存储在以列为主的线性数组中。
2 注意,逆矩阵的形式是
M = [ R T ]
0 1
,其中 R 是正交 3x3 矩阵,由下式给出
inv(M) = [ transpose(R) -T ]
0 1
【讨论】:
y = Mx = R * x + T;反转这一点,得到x = inv(M) * y = transpose(R) * (y - T)。所以inv(M)的最后一列不完全是-T,而是-transpose(R) * T。
对于一般的线平面相交,有很多答案和教程。
由于平面是水平的,因此您的情况很简单。
我想相机在C(cx, cy, cz),它看起来在T(tx, ty,tz)。
那么线camera-target可以定义为:
cx - x cy - y cz - z
------ = ------ = ------ /// These are two independant equations
tx - cx ty - cy tz - cz
对于水平面,只需要一个方程:y = H。
将这个值代入直线方程,你得到
(cx-x)/(tx-cx) = (cy-H)/(ty-cy)
(cz-z)/(tz-cz) = (cy-H)/(ty-cy)
所以
x = cx - (tx-cx)*(cy-H)/(ty-cy)
y = H
z = cz - (tz-cz)*(cy-H)/(ty-cy)
当然,如果你的摄像头也是水平线,那么ty=cy 并没有解决方案。
【讨论】:
cx, tx, cy, ty,... 是坐标,而不是向量分量。你的方程式是错误的。