欢迎来到天天文库
浏览记录
ID:15720234
大小:95.00 KB
页数:9页
时间:2018-08-05
《深入探讨透视投影坐标变换》由会员上传分享,免费在线阅读,更多相关内容在行业资料-天天文库。
1、深入探讨透视投影坐标变换写3d图形程序,就一定会做坐标变换。而谈到坐标变换,就不得不提起投影变换,因为它是所有变换中最不容易弄懂的。但有趣的是,各种关于透视变换的文档却依然是简之又简,甚至还有前后矛盾的地方。看来如此这般光景,想要弄清楚它,非得自己动手不可了。所以在下面的文章里,作者尝试推导一遍这个难缠的透视变换,然后把它套用到DX和PS2lib的实例中去。1.一般概念所谓透视投影变换,就是view空间到project空间的带透视性质的坐标变换步骤(这两个空间的定义可以参考其他文档和书籍)。我们首先来考虑它应该具有那些变换性质。很显然,它至少要保证我们在view空间中所有处于可视范围内的点
2、通过变换之后,统统落在project空间的可视区域内。好极了,我们就从这里着手——先来看看两个空间的可视区域。由于是透视变换,view空间中的可见范围既是常说的视平截体(viewfrustum)。如图,(图1)它就是由前后两个截面截成的这个棱台。从view空间的x正半轴看过去是下图这个样子。(图2)接下来是project空间的可视范围。这个空间应当是处于你所见到的屏幕上。实际上将屏幕表面视作project空间的xoy平面,再加一条垂直屏幕向里(或向外)的z轴(这取决于你的坐标系是左手系还是右手系),这样就构成了我们想要的坐标系。好了,现在我们可以用视口(viewport)的大小来描述这个可
3、视范围了。比如说全屏幕640*480的分辨率,原点在屏幕中心,那我们得到的可视区域为一个长方体,它如下图(a)所示。(图3)但是,这样会带来一些设备相关性而分散我们的注意力,所以不妨先向DirectX文档学学,将project空间的可视范围定义为x∈[-1,1],y∈[-1,1],z∈[0,1]的一个立方体(上图b)。这实际上可看作一个中间坐标系,从这个坐标系到上面我们由视口得出的坐标系,只需要对三个轴向做一些放缩和平移操作即可。另外,这个project坐标系对clip操作来说,也是比较方便的。2.推导过程先从project空间的x正半轴看看我们的变换目标。(图4)这个区域的上下边界为y’
4、=±1,而图2中的上下边界为y=±z*tan(fov/2),要实现图2到图4的变换,我们有y’=y*cot(fov/2)/z。这下完了,这是一个非线性变换,怎么用矩阵计算来完成呢?还好我们有w这个分量。注意到我们在做投影变换之前所进行的两次坐标变换——world变换和view变换,他们只是一系列旋转平移和缩放变换的叠加。仔细观察这些变换矩阵,你会发现它们其实不会影响向量的w分量。换句话说,只要不是故意,一个w分量等于1的向量,再来到投影变换之前他的w分量仍旧等于1。好的,接下来我们让w’=w*z,新的w就记录下了view空间中的z值。同时在y分量上我们退而求其次,只要做到y’=y*cot(
5、fov/2)。那么,在做完线性变换之后,我们再用向量的y除以w,就得到了我们想要的最终的y值。x分量的变换可以如法炮制,只是fov要换一换。事实上,很多用以生成投影变换矩阵的函数都使用了aspect这个参数。这个参数给出了视平截体截面的纵横比(这个比值应与viewport的纵横比相等,否则变换结果会失真)。如果我们按照惯例,定义aspect=sizeofX/sizeofY。那么我们就可以继续使用同一个fov而给出x分量的变换规则:x’=x*cot(fov/2)/aspect。现在只剩下z分量了。我们所渴望的变换应将z=Znear变换到z=0,将z=Zfar变换到z=1。这个很简单,但是等等
6、,x,y最后还要除以w,你z怎能例外。既然也要除,那么z=Zfar就不能映射到z=1了。唔,先映射到z=Zfar试试。于是,有z’=Zfar*(z-Znear)/(Zfar–Znear)。接下来,看看z’/z的性质。令f(z)=z’/z=Zfar*(z-Znear)/(z*(Zfar–Znear))。则f’(z)=Zfar*Znear/(z^2*(Zfar–Znear)),显而易见f’(z)>0。所以除了z=0是一个奇点,函数f(z)是一个单调增的函数。因此,当Znear≤z≤Zfar时,f(Znear)≤f(z)≤f(Zfar),即0≤f(z)≤1。至此,我们可以给出投影变换的表达式了。
7、x’=x*cot(fov/2)/aspecty’=y*cot(fov/2)z’=z*Zfar/(Zfar–Znear)–Zfar*Znear/(Zfar–Znear)w’=z以矩阵表示,则得到变换矩阵如下,cot(fov/2)/aspect0000cot(fov/2)0000Zfar/(Zfar-Znear)100-Zfar*Znear/(Zfar-Znear)0。做完线性变换之后,再进行所谓的“归一化”,即用w分量去除
此文档下载收益归作者所有