3d模型经过世界坐标变换、相机坐标变换后,下一步需要投影变换。投影变换的目的就是要把相机空间转换到标准视图空间,在这个空间的坐标都是正规化的,也就是坐标范围都在[-1,1]之间,之所以转换到这个空间是为了后续操作更方便。

  下面的讨论都是以列向量来表示,这样在变换操作时,采用的是矩阵左乘法,如果采用的是行向量的话,那就相反,矩阵右乘法即是向量在左边乘以变换矩阵。采用哪种表示并不影响结果,只需要把该种表示下得出的变换矩阵转置一下,就是采用另外一种表示模式需要的结果。

  常见的投影有两种,正交投影和透视投影,正交投影相对来说更简单,所以先来看看正交投影。

  最简单的正交变换矩阵

                                  1 0 0 0

                                   0 1 0 0

                                   0 0 0 1

  这个正交变换是不可逆变换,变换后x和y保留,z变成了0,在实际应用中,更常见的情况是限定x、y、z在一定的范围内的进行投影变换,比如x[l,r],y[b,t],z[n,f]。那么要把这段空间中的点变换到-1和1之间,只要完成两个变换,首先把坐标轴移到中心,然后进行缩放就可以了。采用列向量的话,那就是缩放矩阵乘以平移矩阵。

    2/(r-l)     0     0    0                                1   0   0    -(r+l)/2                    2/(r-l)   0       0  -(r+l)/(r-l)

    0   2/(t-b)    0    0                x              0    1   0   -(b+t)/2          =        0     2/(t-b)  0  -(t+b)/(t-b)

    0       0   2/(f-n)  0                               0     0   1   -(n+f)/2                    0        0    2/(f-n)  -(f+n)/(f-n)

    0      0         0     1                              0     0    0         1                       0        0        0           1

  透视投影类比于我们人眼系统,看一个物体,会有远小近大的效果。在转换到相机空间后,相机是这个空间的原点,和正交投影体是一个长方体或者立方体不同,透视投影体是一个锥体被近平面截取掉头部剩下的空间。假定仍然采用上面的坐标表示。在透视投影下,空间上面的任何一点P投影到近平面上某点q,通过三角几何学我们可以得到 qx=px*n/p,y点同理。假定直接投影到近平面,则该矩阵很简单,用Ma表示下面的矩阵

1 0   0    0

0 1   0    0

0 0   1    0

0  0  1/n 0

则齐次空间某点(x,y,z ,1)被该矩阵转换后变成了 (x ,y z, z/n) ,除以z/n,则变成了(nx/z,ny/z,n ,1) 正好吻合上面的公式。

但是我们知道投影变换需要把坐标变换到-1和1之间,假定先不考虑z轴的变换,在x轴和y轴上面经过上述变换后,已经投影在近平面了,假设近平面xy在[l,r] 和[b,t]之间了,因此只需要和上面的正交投影一样,进行平移和缩放操作就可以了,平移矩阵Mb

1  0  0  -(l+r)/2

0  1  0  -(t+p)/2

0  0  1  -(f+n)/2

0  0   0     1

以及缩放矩阵Mc

2/(r-l)     0     0    0                            

0   2/(t-b)    0    0              

0       0   2/(f-n)  0               

0      0         0     1   

McXMbXMa

得到的矩阵为

2/(r-l)       0       -(r+l)/(n*(r-l))   0

0           2/(t-b)  -(t+b)/(n*(t-b))  0

0             0            j               k

0            0            1/n            0  

j  k 为未知数,这个矩阵也可以同时乘以n,则变为

2n/(r-l)      0      -(r+l)/(r-l)      0

0       2n/(t-b)   -(t+b)/(t-b)     0

0            0              j                k

0            0              1                0

为了求解 J  k,我们需要把z变换到-1 和1

因此当z=n时为-1, z=f时 为1

(j*n+k)/n= j+k/n=-1;

同理  j+k/f=1;

得到 k=2f*n/(n-f)

j=-(n+f)/(n-f)

代入上面的矩阵,就得出通用的正交变换矩阵。

而且在一般情况下  r=-l ,b=-t

因此上述矩阵可以简化为

n/r  0   0   0

0   n/t   0   0

0   0   -(n+f)/(n-f)  2f*n/(n-f)

0  0     1     0

 

n/r 和 n/t可以进一步简化成水平半视角和垂直半视角的三角函数来表示,而水平视角和垂直视角和透视窗口的宽高比有是成正比的,最终上面两行可以用宽高比和某个半视角的余切来表示。

 

这是在列向量情况下得出的投影矩阵,如果采用行向量,只需要把上面的矩阵转置一下即可。