这个答案可能比需要的要长得多。如果您已经了解了大部分矩阵数学,请跳至底部 2 段左右。
从查看一维问题开始可能是最简单的。在一维中,我们在一条线上有点。我们可以缩放它们,也可以翻译它们。考虑三点i,j,k和变换矩阵M.
M = [ s t ]
[ 0 1 ]
i = [1] j = [-2] k = [0]
[1] [ 1] [1]
j k i
─┴──┴──┴──┴──┴─
-2 -1 0 1 2
当我们乘以M,我们得到:
i' = Mi = [ s t ][ 1] = [ s+t ]
[ 0 1 ][ 1] [ 1 ]
j' = Mj = [ s t ][-2] = [-2s+t]
[ 0 1 ][ 1] [ 1 ]
k' = Mk = [ s t ][ 0] = [ t ]
[ 0 1 ][ 1] [ 1 ]
所以如果我们赋值给s and t,然后我们对一维“三角形”进行各种变换。缩放会改变“点”之间的距离,而纯平移会相对于原点移动它们,同时保持间距不变:
s=1 t=0 s=2 t=1 s=1 t=2
j k i j k i j k i
─┴──┴──┴──┴──┴─ ─┴──┴──┴──┴──┴─ ─┴──┴──┴──┴──┴─
-2 -1 0 1 2 -3 -1 1 3 5 0 1 2 3 4
值得注意的是,转换的顺序至关重要。这些一维变换规模和then翻译。如果您要先平移,那么“点”距原点的距离将不同,因此缩放因子会对它产生不同的影响。因此,变换通常保存在单独的矩阵中,以便顺序清晰。
如果我们上升到二维,我们得到矩阵N:
[1 0 tx][ cos(a) sin(a) 0][sx 0 0] [ sx*cos(a) sx*sin(a) tx ]
N =[0 1 ty][-sin(a) cos(a) 0][ 0 sy 0]=[-sy*sin(a) sy*cos(a) ty ]
[0 0 1 ][ 0 0 1][ 0 0 1] [ 0 0 1 ]
这个矩阵将1)缩放一个点sx,sy, 2)将点绕原点旋转a度,然后3将点翻译为tx,ty。请注意,该矩阵是在以下假设下构造的:点表示为列向量,并且乘法将如下进行Np。正如 datenwolf 所说,如果您想使用点的行向量表示但应用相同的变换,您可以转置所有内容并交换顺序。这是矩阵乘法的一般性质:(AB)^T = (B^T)(A^T).
也就是说,我们可以讨论对象、世界和眼睛坐标方面的变换。如果眼睛位于世界的原点,向下看世界的负 z 轴,+x 向右,+y 向上,物体(一个立方体)位于向下 10 个单位 -z(以 z 为中心)轴),沿世界 x 的宽度为 2,沿 z 的深度为 3,沿世界 y 的高度为 4。然后,如果立方体的中心是对象的局部参考系,并且其局部轴可以方便地与世界轴对齐。那么物体坐标中盒子的顶点就是[+/-1,+/-2,+/-1.5]^T
。近、上、右(从眼睛的角度来看)顶点有物体坐标 [1,2,1.5]^T
, in 世界坐标,同一个顶点是[1,2,-8.5]^T
(1.5-10=-8.5)。由于眼睛的位置、指向的方向,以及我们以与 OpenGL 相同的方式定义眼睛的事实,该顶点具有相同的眼睛坐标 as 世界坐标。因此,让我们移动并旋转眼睛,使眼睛x is 右(rt)和眼睛的y is up和眼睛的-z is look(lk)眼睛位于[eyeright(ex) eyeup(ey) eyelook(ez)]^T
。由于我们希望将对象坐标转换为眼睛坐标(这意味着我们将眼睛视为原点),因此我们将取这些转换的逆并将它们应用到对象顶点(在它们转换为世界坐标之后)。所以我们会有:
ep = [WORLD_TO_EYE]*[OBJECT_TO_WORLD]*wp;
更具体地说,对于我们感兴趣的顶点,我们将有:
[ rt.x rt.y rt.z 0][1 0 0 -ex][1 0 0 0 ][ 1 ]
[ up.x up.y up.z 0][0 1 0 -ey][0 1 0 0 ][ 2 ]
[-lk.x -lk.y -lk.z 0][0 0 1 -ez][0 0 1 -10][1.5]
[ 0 0 0 1][0 0 0 1 ][0 0 0 1 ][ 1 ]
为了方便起见,我将眼睛旋转影响的平移分开。其实写了这么多,可能这就是我比较困惑的地方。您给出的矩阵将旋转然后平移。我假设眼睛的平移是在世界坐标中。但正如您在问题中所写的那样,它实际上是在眼睛坐标中执行翻译。我也曾否定过lk因为我们已经将眼睛定义为向下看负 z 轴,但为了制作标准旋转矩阵,我们希望使用正值。
不管怎样,我可以继续下去,但这也许已经回答了你的问题。
继续:
进一步解释一下上面的内容,将眼睛的变换分成两个部分也使得找到逆矩阵变得更容易。很容易看出,如果翻译tx将眼睛相对于世界上的物体移动到某个位置,我们可以通过移动世界上的所有东西来保持眼睛和世界上的点之间相同的相对位置-tx并保持眼睛静止。
同样,考虑默认定义的眼睛方向right, up, and look向量:
[1] [0] [ 0]
d_rt=[0] d_up=[1] d_lk=[ 0]
[0] [0] [-1]
创建一个将这三个向量指向新方向的旋转矩阵很容易。我们只需将三个新轴对齐rt, up, lk(作为列向量):
[rt.x up.x -lk.x 0]
[rt.y up.y -lk.y 0]
[rt.z up.z -lk.z 0]
[ 0 0 0 1]
很容易看出,如果对 d_rt、d_up 和 d_lk 进行增广并乘以上面的矩阵,就会得到rt, up, and lk分别回来。所以我们已经应用了我们想要的转换。为了实现正确的旋转,三个向量必须正交。这实际上只是基础的改变。因此,我们可以通过转置该矩阵来非常方便地找到该矩阵的逆矩阵。这就是我上面所做的。如果将该转置矩阵应用于世界坐标中的所有点并使眼睛保持静止,则这些点将相对于眼睛保持相同的位置,就好像眼睛旋转了一样。
例如:
分配(在世界坐标中):
[ 0] [0] [-1] [-2] [1.5]
rt=[ 0] up=[1] lk=[ 0] eye=[ 0] obj=[ 0 ]
[-1] [0] [ 0] [ 1] [-3 ]