转载+整理 - 计算机图形学 - 模型视图矩阵和投影矩阵

出处:http://blog.csdn.net/qb371/article/details/8650094

  根据原文,我将其中关于模型视矩阵和投影矩阵的比较重要的知识整理出来再加工一下,如果有什么地方看得不适合明白的话还是去看一下原文吧。

模型矩阵

我们必须考虑,当空间中点的位置会发生变化的时候,其坐标如何变化。考虑三种基本的变换:平移、旋转和缩放。

“变换”的含义就是,将点的初始位置的坐标P映射到平移、旋转、缩放后的位置坐标P’,即:

 

平移变换是最简单的变换:

 

 

旋转变换有一些复杂,先看在二维平面上的旋转变换:

Untitled-1

很容易得到:

 

x=xcosθysinθ
y=xsinθ+ysinθ

 

矩阵形式的表达更加简洁,后面大多使用这种形式:

 

 

推广到三维空间中: 
点绕z轴旋转:

 

 

点绕x轴旋转:

 

 

点绕y轴旋转:

 

 

绕指定的任意轴旋转变换是由几个绕坐标轴旋转变换和平移变换效果叠加而成的,后文会有详细叙述。

缩放变换也比较简单:

 

 

总结一下:平移变换,变换后点坐标等于初始位置点坐标加上一个平移向量;而旋转变换和缩放变换,变换后点坐标等于初始位置点坐标乘以一个变换矩阵。

 

P=P+T,P=RP,P=SP

 

齐次坐标这天才的发明,允许平移变换也表示成初始位置点坐标左乘一个变换矩阵的形式。齐次坐标使用4个分量来表示三维空间中的点,前三个分量和普通坐标一样,第四个分量为1。

 

 

平移变换巧妙地表示为:

 

 

旋转变换(以绕z轴旋转为例)和缩放变换相应为:

 

 

综上,在齐次坐标下三种基本变换实现了形式上的统一,这种形式的统一意义重大。

 

P=TP,P=RP,P=SP

 

矩阵有一个性质:

 

M(AB)=(MA)B

 

考虑一个点,先进行了一次平移变换,又进行了一次旋转变换,结合上面矩阵的性质,可知变换后的点P’为:

 

P=R(TP)=(RT)P

 

旋转矩阵和平移矩阵的乘积R·T也是一个4×4的矩阵,这个矩阵代表了一次平移变换和一次旋转变换效果的叠加;如果这个点还要进行变换,只要将新的变换矩阵按照顺序左乘这个矩阵,得到的新矩阵能够表示之前所有变换效果的叠加,将最初的点坐标左乘这个矩阵就能得到一系列变换后最终的点坐标,这个矩阵称为“模型矩阵”。一个模型矩阵乘以另一个模型矩阵得到的还是一个模型矩阵,表示先进行右侧模型矩阵代表的变换,再进行左侧模型矩阵代表的变换这一过程的效果之和,因此模型矩阵的乘法又可以认为是闭合的。 
模型矩阵之所以称之为“模型矩阵”,是因为该矩阵与点的位置没有关系,仅仅包含了一系列变换的信息。而在三维世界中,一个模型里所有的顶点往往共享同一个变换,对应同一个模型矩阵,比如抛在空中的一个木块,运转机器的一个齿轮。

之前说到,考虑一个物体绕指定轴旋转,如以下这个变换:绕着过顶点(x,y,z)方向为(a,b,c)的轴旋转角度θ,利用多个变换的叠加构建绕任意轴旋转的变换矩阵。 
首先将顶点(x,y,z)平移到原点,绕x轴旋转角度p使指定的旋转轴在x-z平面上,绕y轴旋转角度q使指定的旋转轴与z轴重合,绕指定旋转轴(也就是z轴)旋转角度θ,绕y轴旋转角度-q,绕x轴旋转角度-p,将顶点平移到向量(x,y,z),p和q的值由方向(a,b,c)决定。综上,变换矩阵为:

 

 

因此在处理围绕非坐标轴旋转的模型时,根据指定的旋转参数可以直接按照上述公式生成按照指定轴旋转的旋转矩阵,参加模型矩阵的构建。

齐次坐标还有一个优点,能够区分点和向量:在普通坐标里,点和向量都是由三个分量组成的,表示位置的点坐标(2,3,4)和表示方向的向量(2,3,4)没有区别。而在齐次坐标中,第四个分量可以区分它们,点坐标的第四个分量为1,而向量坐标第四个分量为0。比如,平移一个点是有意义的,能够得到平移后的点坐标;而平移一个向量是没有意义的,方向不会因为平移而改变。

以上,我们已经了解到模型矩阵可以存储一个模型空间位置变化的信息,在生成三维动画每一帧的过程中,我们首先计算每个模型的模型矩阵,然后将最初的模型的每一顶点坐标都左乘该模型矩阵,得到这一帧表示的时刻(模型已经经过多次变换)该模型每一顶点的坐标。上面说的“帧”并不狭义地指屏幕的两次刷新时间的短暂间隔中屏幕上呈现的图像,而是指在这幅图像所描绘的整个三维空间的这个瞬间的所有顶点的位置。

来看个具体的例子:一个绕z轴匀速螺旋匀速上升的立方体,在某一帧中(即在这一帧对应的时刻t下),其向z轴正方向平移的长度和绕z轴旋转的角度分别为:

 

 

则模型矩阵(注意上文齐次坐标下的基本变换矩阵)为:

 

 

产生这一帧时,只需要计算一次模型矩阵,再将立方体中8个顶点坐标分别左乘该矩阵,就可以得到经过变换后8个顶点的坐标。当一个模型顶点数量增加到上百甚至上千个,模型变换的步骤数也增加到几十步时,模型矩阵的作用就很明显了:如果没有齐次坐标(也当然没有模型矩阵),对每个顶点都需要一步一步地变换:平移的时候加上一个向量,旋转的时候左乘一个矩阵,才能得到变换后的顶点坐标;而模型变换只需要计算一次模型矩阵(当然也是一步一步的),然后每个顶点左乘模型矩阵就可以直接得到变换后的坐标了。

 

视图矩阵

在模型矩阵中,我们关心的是空间中的点在经历变换后在世界坐标系下的位置。事实上,我们更加关心空间中的点相对于观察者的位置。最简单的方案是将观察者置于原点处,面向z轴(或x轴、y轴)正半轴,那么空间中的点在世界坐标系下的位置就是其相对于观察者的位置。 
观察者的位置和方向会变化,看上去就好像整个世界的位置和方向发生变化了一样,所以解决的方案很简单,将世界里的所有模型看作一个大模型,在所有模型矩阵的左侧再乘以一个表示整个世界变换的模型矩阵,就可以了。这个表示整个世界变换的矩阵又称为“视图矩阵”,因为他们经常一起工作,所以将视图矩阵乘以模型矩阵得到的矩阵称为“模型视图矩阵”模型视图矩阵的作用是:乘以一个点坐标,获得一个新的点坐标,获得的点坐标表示点在世界里变换,同时观察者也变换位置,观察者也变换后,点相对于观察者的位置。

视图矩阵同样也可以分为平移、旋转和缩放,视图矩阵是将观察者视为一个模型,获得的观察者在世界中变换的模型矩阵的逆矩阵(这里可以看成观察者不移动,但是世界相对观察者运动)。

观察者平移了(tx,ty,tz),视图矩阵如下,可以看出如果将视图矩阵看作整个世界的模型矩阵,相当于整个世界平移了(-tx,-ty,-tz)。

 

 

观察者绕z轴旋转了角度θ,视图矩阵如下,相当于整个世界绕z轴旋转了-θ度。

 

 

观察者在三个方向等比例缩小了s倍,视图矩阵如下,相当于整个世界放大了s倍。

 

观察者缩小的情形可能会引起困惑:如果人和猫咪的眼睛在同一个位置,人看到的世界和一只猫咪看到的世界应当是一样尺寸的,这和上述视图矩阵的情形矛盾;但是直觉告诉我,如果你喝了缩小药水,你应该会觉得整个世界在膨胀,就像视图矩阵所表现的那样。解答是这样:如果在计算机上模拟观察者喝了缩小药水的情形,在屏幕上看到整个世界是膨胀的,因为在那个虚拟的三维空间中,计算机屏幕这个“窗口”也随你(观察者)缩小。 
视图矩阵实际上就是整个世界的模型矩阵,这给我一点启发:一个模型可能由多个较小的子模型组成,模型自身有其模型矩阵,而子模型也有自己的局部模型矩阵。考虑一辆行驶中的汽车的轮胎,其模型视图矩阵是局部模型矩阵(描述轮胎的旋转)左乘汽车的模型矩阵(描述汽车的行驶)再左乘视图矩阵得到的。

 

投影矩阵

模型视图矩阵的作用是确定某一帧中,空间里每个顶点的坐标,而投影矩阵则将这些顶点坐标映射到二维的屏幕上,即:

 

 

最主要的有两种投影方式,正射投影和透视投影。前者用于精确制图,如工业零件侧视图或建筑物顶视图,从屏幕上就可以量测平行于屏幕的线段长度;后者用于模拟视觉,远处的物体看上去较小。下图中,空间中的同一个矩形,正射投影后仍然是矩形,而透视投影后则变成了梯形。

正射投影(投影面和相机空间):

透视投影(投影面和相机空间):

三维世界的显示中,屏幕模拟了一个窗口,你透过这个窗口观察“外面”的世界。你的屏幕是有边缘的(除非你有一个球形的房间,内壁全是屏幕),因此你仅仅能观察到那个世界的一部分,即“相机空间”。相机空间的左、右、上、下边界是受限于屏幕的边缘,同时也设定前、后边界,因为你很难看清太近或太远的东西。在正射投影中,相机空间是一个规则的立方体,而在透视投影中则是一个方台体。 
三维模型可能在不同的显示器上展现,因此投影的过程中不该将显示器参数加入进来,而是将空间中的点投影到一个规范的显示器中。另外,透视投影中的z值并不是毫无用处,它可以用来表示顶点的“深度”:如果三维空间中的两个不同顶点投影到平面上时重合了,那么将显示深度较浅的顶点。

定义一个规范的视窗区域(CCV),为x,y,z都处在区间[-1,1]之间的边长为2的立方体。x和y坐标值用来线形拉伸到到实际屏幕上,而z值存储了“深度”。而投影的过程就是将三维空间中的点从相机空间映射到CCV中。 
正射投影非常简单,直接将矩形的相机空间线形压缩到CCV中即可。采取顶视图,相机空间的左右边界为 xleft 和 xright :

Untitled-21

简单的线形成比例关系:

 

 

推广到y轴和z轴:

 

相机空间中的点经过正射投影矩阵左乘后得到的点都在CCV之中:

 

 

透视投影相对较为复杂,同样用顶视图考虑x坐标的情况:

 

 

Untitled-122

转化为齐次的方式:

 

推广到y轴:

 

 

透视投影矩阵的第三行不是我们关心的内容,只要保证不同顶点投影前后的点坐标的第三个分量z和z’的大小关系不变就可以。 
透视投影矩阵尾行是(0,0,1,0),这样就将计算得到的坐标的第四个分量赋值为z而不是1。将相机空间左乘投影矩阵后的结果不是一个CCV空间,如果你将这个空间画出来,会发现其仍然是一个方台形。这时进行“透视除法”,将上一步得到的点坐标化为第四个分量为1的标准齐次坐标:

 

 

然后我们直接取齐次坐标中的x’和y’值,并将其线形映射到屏幕上,比如点(0,0)出现在屏幕中央,点(-1,1)出现在屏幕左上角。

 

相关:这一篇关于投影矩阵的博文:http://blog.csdn.net/yanwei2016/article/details/7326180(虽然题目是模型视图矩阵变化,但大部分篇幅都在讲投影矩阵)

 

 总结:

    模型矩阵:保存了模型里面的点需要怎样运动到下一个位置(包括平移、旋转、缩放)。

    视图矩阵:保存了整个世界模型(我就这样叫它吧,包括所有的模型)相对于观察者需要做的变换,满足观察者的观察需求,也就是相当于观察者移动的操作的逆矩阵。

    投影矩阵:还不是很了解这东西。主要就是将一个三维的物体投影到二维平面所需要做的变换的矩阵。

    模型视矩阵:模型矩阵和视图矩阵的合并。

posted @ 2014-11-17 17:33  银槲  阅读(...)  评论(...编辑  收藏