推导正交投影变换

-正在学习OPENGL阅读了Twinsen编写的技术博客,收益颇多,特此转载

http://blog.csdn.net/popy007/article/details/4126809


前我们在《深入探索透视投影变换》以及《深入探索透视投影变换(续)》中研究了OpenGLD3D以及M3G的透视投影变换的原理以及生成方法。这些方法在当前的主流图形API中得到了普遍使用。但关于投影应用,还有一类经常使用的投影方式需要我们深入理解——正交投影,我们在本篇文章里面研究它(这里假设读者已经看过前两篇文章,并理解了绝大多数的理论,因为正交投影比透视投影的推导关系简单得多,因此我们的推导会非常得快,如果读者有任何的不解,请参考前两篇文章或者通过email联系我)。

在具体研究之前我觉得有必要把平面投影的分类简单介绍一下,目的是为了让大家有一个总体的认识,从而更好的理解这个知识体系。请看下图:

 

      

平面投影分为平行投影和透视投影两种类型,后者我们在前两篇文章中介绍了。平行投影则是具有矩形观察体的投影方式(透视投影则是视锥观察体),它不会根据物体离视点的远近缩放物体(透视投影则会)。平行投影可以分成侧投影和正交投影两种类型。这两种类型如何区分呢?我们继续看图吧:

上图中,v是投影平面,n是它的法线。p和q是平面外两点,p’和q’分别是它们在平面上的投影点。q的投影方向向量为Q =单位化(q’-q),而p的投影方向向量为P = 单位化(p’-p),其中Q不平行于n而P平行于n,则q的投影叫做侧投影,而p的投影叫做正交投影。正交投影是我们今天的研究对象。

实际上上面对平面投影的分类还可以继续向下细分,比如透视投影可以分为一灭点、二灭点以及三灭点透视投影。侧投影则可以继续分为散点侧投、斜二轴侧投等等。而正交投影则可以分成轴侧投影以及多视点正交投影等等。如果读者对此感兴趣,可以参考相关的图形学教程。

接下来我们研究正交投影。分别介绍OpenGL、D3D以及M3G的。我们的环境约定(左右手坐标系、行列向量乘法、CVV范围)仍然尊重相应API自己的设置。

OpenGL正交投影变换

    下图是OpenGL的右手坐标系中观察空间的情形,我们看到的是正交投影的矩形观察体,原点是相机位置,n是近裁剪平面到相机平面的距离,f是远裁剪平面到相机平面的距离。p是观察体中的一个点,p’是它投影之后的点。

投影之后我们有关系:

因为是正交投影,没有统一的投影射线目标点,因此投影之后的x和y不会变,而z则永远地变成了-n,跑到了投影平面上(我们让投影平面和近裁剪平面重合),它已经没用了,则我们用这个没用的信息保存z(为了之后片元操作的时候用),写为:

从而在z方向上构建 CVV,使得当z在近裁剪平面的时候,az+b=-1,而z在远裁剪平面的时候az+b=1(OpenGL的CVV的z范围是[-1,1],我已经说了三遍了,如果读者感到迷惑不解,强烈建议把前两篇文章理解)。我们算出a和b

然后我们就通过当前的结果反推正交投影矩阵版本一

 

 

接着把x和y建立成CVV情形(简单的线性插值)

 

 

反推正交投影矩阵版本二(最终版本)

 

 

 

则右边的那个矩阵就是OpenGL的正交投影矩阵,它可以通过glOrtho创建出来。如果你读过并理解了之前两篇文章,你会觉得我的推导越来越简洁利落了:)OpenGL的解决了,下面是D3D的。

D3D正交投影变换

    下图是D3D左手坐标系中观察空间的情形。因为是左手坐标系,因此近裁剪平面在z = n平面,而远裁剪平面在z = f平面。

 

投影之后,有                                                                                                    

 

用第三个没用的信息保存z,写为

 

使得(D3D的CVV的z范围是[0, 1])

反推正交投影矩阵版本一

对x和y进行CVV线性插值

 

 

分两种情况讨论(如果读者对此不清楚,请参考第二篇文章《深入探索透视投影变换(续)》):

(1)       投影平面居中,销掉两边的1/2,然后反推正交投影矩阵

 

 

后面那个矩阵就是相应正交投影矩阵,这个也是D3DXMatrixOrthoLH方法所使用的情况。

 

(2)       一般情况,投影平面不一定居中,直接通过投影结果反推正交投影矩阵

 

 

后面那个矩阵就是相应的正交投影矩阵,这个也是D3DXMatrixOrthoOffCenterLH方法所使用的情况。好了,D3D的也介绍完毕,接下来是M3G的。

 

M3G正交投影变换

M3G是对OpenGL的封装,因此环境和OpenGL的相同,我们从对x和y的插值来看

 

 

M3G只使用居中的投影平面,因此可以销掉两边的1/2,得到

 

 

接着反推出正交投影矩阵

 

 

最后那个矩阵就是M3G的正交投影矩阵,也就是Camera.setParallel所使用的形式。

结束语

以上介绍了三个API所使用的正交投影矩阵的生成方法,三者的正交投影矩阵依然可以通过视野(FOV)以及投影平面的宽高比(Aspect Ratio)来设置,这里请读者自行推导,可以参考第二篇文章《深入探索透视投影变换(续)》。

正交投影矩阵和透视投影矩阵一样可以有无穷多个,但原理相同,不同的只是环境。目前正交投影在3D引擎中有着和透视投影同样的地位,它至少是3D用户界面系统的基础。因此,有必要清晰地理解正交投影矩阵和透视投影矩阵的原理,如此才能够真正创建、修改、使用好图形引擎。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
透视投影变换矩阵的推导过程如下: 假设有一个三维点 $(X,Y,Z)$,它在相机坐标系中的坐标为 $(X_c,Y_c,Z_c)$。相机坐标系的原点为相机位置,$Z_c$ 轴指向相机朝向的反方向,$X_c$ 和 $Y_c$ 轴分别与相机的右方向和下方向对齐。 为了把相机坐标系中的点映射到图像平面上,我们需要进行透视投影变换。首先,我们将相机坐标系中的点转换为齐次坐标 $(X_c,Y_c,Z_c,1)$。然后,我们将它乘以一个投影矩阵 $P$,得到一个新的齐次坐标 $(u,v,w,1)$: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = P \cdot \begin{bmatrix} X_c \\ Y_c \\ Z_c \\ 1 \\ \end{bmatrix} $$ 其中,$u$ 和 $v$ 分别表示图像平面上的坐标,$w$ 用来进行透视除法,保证 $u$ 和 $v$ 的值在图像平面上。 投影矩阵 $P$ 可以分解为相机内参矩阵 $K$ 和相机外参矩阵 $[R|t]$ 的乘积: $$ P = K [R|t] $$ 其中,$K$ 是一个 $3 \times 3$ 的矩阵,包含了相机的内部参数,如焦距、主点等。$[R|t]$ 是一个 $3 \times 4$ 的矩阵,包含了相机的外部参数,如相机的旋转和平移。 为了推导 $P$ 的具体形式,我们可以先考虑一个简单的情况:相机坐标系的原点与图像平面重合,且相机的朝向与图像平面平行。这种情况下,投影矩阵可以表示为: $$ P = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{bmatrix} $$ 其中,$f$ 是焦距,表示相机到图像平面的距离。 当相机坐标系的原点和图像平面不重合时,我们可以使用相机外参矩阵 $[R|t]$ 来把相机坐标系的原点变换到图像平面上。具体来说,我们可以将相机坐标系的原点变换为 $(X_c',Y_c',Z_c')$,其中 $(X_c',Y_c',0)$ 是图像平面上的点。这个变换可以表示为: $$ \begin{bmatrix} X_c' \\ Y_c' \\ Z_c' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} 0 \\ 0 \\ 0 \\ 1 \\ \end{bmatrix} $$ 然后,我们可以把 $(X,Y,Z)$ 变换为 $(X',Y',Z')$,其中 $(X',Y')$ 是图像平面上的坐标。这个变换可以表示为: $$ \begin{bmatrix} X' \\ Y' \\ Z' \\ 1 \\ \end{bmatrix} = [R|t] \cdot \begin{bmatrix} X \\ Y \\ Z \\ 1 \\ \end{bmatrix} $$ 最后,我们可以将 $(X',Y',Z')$ 投影到图像平面上,得到一个新的齐次坐标 $(u,v,w,1)$。这个投影可以表示为: $$ \begin{bmatrix} u \\ v \\ w \\ 1 \\ \end{bmatrix} = K \cdot \begin{bmatrix} X'/Z' \\ Y'/Z' \\ 1 \\ \end{bmatrix} $$ 将以上三个变换组合起来,我们可以得到透视投影变换矩阵的形式: $$ P = K [R|t] = \begin{bmatrix} f_x & 0 & c_x & 0 \\ 0 & f_y & c_y & 0 \\ 0 & 0 & 1 & 0 \\ \end{bmatrix} \begin{bmatrix} r_{11} & r_{12} & r_{13} & t_1 \\ r_{21} & r_{22} & r_{23} & t_2 \\ r_{31} & r_{32} & r_{33} & t_3 \\ \end{bmatrix} $$ 其中,$f_x$ 和 $f_y$ 是 $K$ 矩阵的对角线元素,分别表示 $x$ 和 $y$ 方向上的焦距;$c_x$ 和 $c_y$ 是 $K$ 矩阵的中心点,表示图像平面上的主点;$r_{ij}$ 和 $t_i$ 是 $[R|t]$ 矩阵的元素,表示相机的旋转和平移。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值