|
顶点变换:
一、本地坐标系到世界坐标系
3D 程序定义一系列的数据结构来表示虚拟的游戏世界,所有的物体以一系列的顶点和三角形来表示。而定义这些物体的顶点一般以本地坐标来表示,因此,要把他们转换成虚拟世界的世界坐标系,包括三种形式的变换,平移,旋转,缩放。
1 平移比较容易,只要知道了本地坐标系的原点在世界坐标系中的位置就行了。设某个点<x0,y0,z0>是在本地坐标系中的位置,本地坐标系原点在世界坐标系中的位于为<x,y,z>则该点在世界坐标系中的位置是<x0+x,y0+y,x0+z>,用向量来表示即为 Pw = P0 + Po.
2 旋转相对要复杂一点,一般可以分解为各坐标轴施转的组合来表达,任何一个位置,都可以通过分别绕不同的轴按特定顺序旋转一点的角度来得到。当然这个顺序和绕各轴旋转的角度不是唯一的。另一方面,按不同的顺序旋转相同的角度,得到的位于也不一样。绕各个轴旋转后的坐标如下:
X轴
Yw = Y0 * cos(a) + Z0 * sin(a)
Zw = Y0 * -sin(a) + Z0 * cos(a)
Y轴
Xw = X0 * -cos(a) + Z0*sin(a)
Zw = X0 * sin(a) + Z0*cos(a)
Z轴
Xw = X0*cos(a)+Y0*sin(a)
Yw = X0*-sin(a)+Y0*sin(a)
3 缩放也比较容易,只要用坐标乘上缩放系统就行了,
Xw = X0*sx
Yw = Y0*sy
Zw = Y0*sz;
二、世界坐标系到摄像机坐标系
虚拟世界的物体,不可能一下全部投影到屏幕上,因此,要使用一个虚拟摄像机来模拟人的眼睛,只有在摄像机的可视范围的物体,才会最终绘制到屏幕上。摄像机由一个可视范围,通过定义一个视角,可以确定在水平和垂直方向的可视范围。然后再定义一个在最大可视距离和最小可视距离,从而将可视范围定义成一个封闭的六面锥体结构,叫做视锥,只有在视锥内的物体最终会被投影到屏幕上。
如何知道一个物体是否在视锥内呢?在世界坐标系要得到这个问题的答案非常困难,因此我们把物体都转换到摄像机坐标系。由上面说的本地坐标到世界坐标的转换我们可以知道,这个变换实际上就是上面的变换的逆变换。我们把摄像机坐标系当成世界坐标系,把真正的世界坐标系就相当一个本地坐标系。设摄像机位于点Pc处,那么世界坐标系在摄像机坐标系中的位置就是-Pc。设摄像机按 Y, X, Z的顺序分别转动a1,a2,a3到达当前位置,就可以用上面的公式计算出世界坐标系中的点在摄像机坐标系中的位置。
不幸的是,一般情况下,我们并不知道摄像机坐标系旋转的顺序以及角度,只知道摄像机的三个坐标轴指向的方向。那么我们到底如何计算呢?可以通过求逆阵的方法来解得。设摄像机的坐标轴在世界坐标系中的向量为u,v,n,则从摄像机坐标轴到世界坐标系的设换矩阵为M= 只要求出他的逆阵就行了。计算逆阵也很困难,而且不能保存所有的逆阵都一定存在,但是我们知道三个坐标轴是垂直,因此上面的矩阵T,是一个正交阵,而正交阵的逆阵等于他的转置矩阵,因此 M-1= 。我们再加入上面的平移变换最终得到Mwtoc =
得到摄像机坐标之后,就可以对物体进行整体的裁剪,去掉那些不在视锥里的物体。这部分以后再讲。
三、投影变换
我们最终的目的,是要将三维的顶点投影到一个2维的平面上,从摄像机的角度来说,在视锥中的物体是以透视图的形式表现的。首先,我们要选择一个投影面,为了简单起见,我们选择一个到摄像机的距离为1,与摄像机坐标系Z轴垂直的面为投影面,于是根据投影的原理:
在摄像机坐标系中的点Pc在该平面的的投影的坐标为
Xp = Pc.x/Pc.z
Yp = Pc.y/Pc.z
Zp = 1
然而为了方便起见,通常我们让Xp,Yp的取值范围为[-1,1],因此我们根把视角的大小,对Xp和Yp进行缩放,最终得到
Xp = Pc.x/Pc.z/tg(a)
Yp = Pc.y/Pc.z/tg(a)
Zp = 1
四、视口变换
由上一步的变换我们得到一个规格化的顶点,但是在进行视口变换之前,我们还有工作要做,我们定义的投影面,在水平和垂直方向上的长度是一样的,但是视口的水平和垂直方向上的长度不一定是一样的,设视口的长和宽分别为Width和Height,我们ar = Width /Height。由于我们的视角是在Y方向上定义的,因此,要对X(即Width)方向上的值作一个缩放使它是规格化的,则:Xp’ = Xp * ar,
Xp’ = Xp
最后,我们进行视口变换
Xs = Xp’*Width/2 + Width
Ys = Height - Yp’*Height (注意,窗口的Y坐标轴与我们定义的Y坐标轴的方向是相反的)。最终我们得到一个顶点在窗口上的坐标。
|
|