本文一些用于均参考《OpenGL编程指南(第8版)》,有兴趣的同窗能够结合一块儿看。这篇算是整合补充。编程
OpenGL采用的是相机模型,就是把视图变换操做类比为使用照相机拍摄照片的过程,具体步骤以下(这里和红宝书有一些改变):spa
在这四个步骤中,前三个都是能够用变换矩阵实现的。看完本文以后基本就能够用本身写的矩阵来代替OpenGL里面的各类变换操做了。至于为何要按照上述的顺序能够参考下面代码,有兴趣的读者能够调换一下位置试一试,其中投影变换矩阵必定要放在最左边。3d
/*Project:投影变换矩阵 View:视图变换矩阵 Model:模型变换矩阵*/ ModelViewProject = Project * View * Model;
下面须要知道一些矩阵和齐次坐标的相关知识,网上有不少资料,若是又不知道的能够提早了解下。orm
这里有必要深刻讲解一下齐次坐标的意义。假设一3维向量x,咱们对这个向量进行线性变换Tx,但不管T为任意3*3矩阵,都没法完成向量的平移操做(好比x=(0,0,0),Tx不管如何也不可能变换到(1,0,0))。这里咱们就须要用到齐次坐标,使用齐次坐标的目的也就是经过增长额外的数值来完成向量的平移操做。熟悉OpenGL的已经知道了,将三维数据植入思惟坐标空间当中就好了。就是将x=(0,0,0)转变成x=(0,0,0,1)。T也转变成4*4矩阵。对象
咱们再讨论一下齐次坐标的一个性质, 齐次坐标所表达的实际上是方向而不是位置。好比x1=(1,2,3,1)和x2=(2,4,6,2)其实在3维坐标系中表示的是同一个位置。此外,最后一个份量w越大,那么齐次坐标将处于更远的位置。当OpenGL准备显示集合体的时候,它会使用左后一个份量除之前三个份量,从而将其次坐标从新变换到3维坐标系中,所以w越大的物体也会显示的越小。w为0.0的时候,因为坐标位于无限近的位置,以致于显示可能会呈现出无限大。这个概念很是重要,由于下面投影矩阵就是利用这个概念!blog
咱们接下来讲明三个变换中具体包含哪些矩阵。对于一个顶点来讲,咱们对其先进行模型变换,在进行视图变换和投影变换。咱们将这些变换细分一下就能够获得以下代码:图片
/*S:缩放 R:旋转 T:平移*/ ModelViewProject = Project * ViewR * ViewT * ModelS * ModelR * ModelT gl_position = ModelViewProject * Vertex;
下面我就按照顺序逐一介绍一下各个矩阵,先介绍一下模型变换矩阵,这部分我就不细说了,了解的人应该很多。博客
(1)ModelT 平移矩阵it
这个矩阵算是最简单的矩阵,这里举个例子。假设咱们要将v=(x,y,z)沿x轴正方向平移2.5,具体计算以下:io
图1
(2)ModelR 旋转矩阵
这个矩阵就比较多样了,我之前的博客关于这个矩阵有很多分析,这里也很少说了。下面列出三个欧拉角对应的旋转矩阵(也是最经常使用的):
图2
(3)ModelS 缩放矩阵
这个矩阵也比较简单,只要把缩放因子factor放在矩阵的对角线上就好了。具体表达以下:
图3
这三个矩阵就组成了模型变换矩阵,根据具体需求能够随意组合平移旋转缩放矩阵,并不必定非要按照上面代码中的顺序。
下面介绍视图矩阵,咱们能够把这一步假想为设置相机或者人眼(View)的位置。设置相机通常只须要两步,首先把相机移动到固定的位置,而后把当前坐标系转化成相机坐标系。这里不像模型变换,能够屡次旋转平移,这里只须要1个平移操做和1个旋转操做通常就能够了,并且还不须要缩放。
(1)ViewT 平移矩阵
这个矩阵和ModelT正好是相反的。咱们能够这样理解,若是要在世界坐标系下的(x,y,z)位置设置相机,那么咱们把相机再移回世界坐标系原点的位移就是(-x,-y,-z)。因此咱们当以相机为坐标原点的时候,全部在原来坐标系下的物体都要加上这个负的平移份量。那么这个平移矩阵以下:
图4
(2)ViewR 旋转矩阵
咱们将原来的坐标系转变成相机坐标系,不只须要平移到相机位置,还要旋转到相机的朝向。如图5所示,咱们要将蓝色的坐标系经过旋转变换成红色的相机坐标系。因为坐标系的三个基向量都是单位化的,因此最简单的办法就是点乘。作法是点乘相机坐标系的三个基向量,具体看图6的公式。
图5
图6
其中V指向相机坐标系的y轴,U指向相机坐标系的x轴,N指向相机坐标系的z轴。
这两个矩阵就组成了视图变换矩阵,将View乘以Model获得的矩阵,在OpenGL固定管线中称为模型视图矩阵,能够经过glMatrixMode(GL_MODELVIEW)进行设置。