深入浅出3D模型的几何变换

发表于2015-04-29
评论1 2.3k浏览

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image001.jpg

在3D图形建模时,开发者最经常问的问题是,为什么一个三维空间,由顶点数据构成的模型,最后会映射在屏幕上显示。实际上,三维数据变换处理经过以下三步骤,模型-视图变换(Model-View)-》透视(Projection)-》视口变换(ViewPort)。本文从尽量简单的角度,介绍一下3D模型的显示原理

【编著】局部坐标->世界坐标->相机坐标->视口坐标->屏幕坐标

 

了解齐次坐标系

由向量导出齐次坐标系:

       首先,在三维空间的坐标系中,向量是很重要的概念,为什么需要向量?因为我们不但需要知道空间中一个点的位置,有时还需要标明方向,比如人眼的视角,物体的运动等。我们复习一下:

物理定义:向量是具有如下两条性质的量

 方向

 长度: |v|

在了解了向量之后,需要解决向量如何在坐标系中表示

在n维空间中,任意n个线性无关的向量构成空间的基,给定空间的一组基v1, v2 ,…, vn,空间中任意向量v都可以表示为

v = α1v1+ α2v2 +…+ αnvn,其中{αi}是唯一的

也就是说给定一组基(3D世界里,基就是世界坐标系或某一视角坐标系),那么该标量组{α1, α2 , …, αn}就可以表示其中的任意向量与基的关系,就解决了向量如何在坐标系中数学表示的基础。即:

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image002.png

但是这样是不足以表示点的,那么可以在基向量组中增加一个点(称为原点),从而构成一个frame

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image003.pngFrame是由(O, v1, v2 ,…, vn)确定的,在这个Frame中,每个向量可以表示为

v = α1v1+ α2v2 +…+ αnvn

每个点可以表示为

P = O + β1v1+ β2v2 +…+ βnvn

从而得到n+1维齐次坐标表示,即引入了齐次坐标系

向量:v = [α1, α2 ,…,αn, 0]T

点:P = [β1, β2 ,…, βn, 1]T

齐次坐标系:齐次坐标是所有计算机图形系统的关键,可以大大简化计算

 所有标准变换(旋转、平移、放缩)都可以应用4×4阶矩阵的乘法实现

 硬件流水线体系都设计为四维计算

 对于正交投影,可以通过w = 0保证向量,w = 1保证点

 对于透视投影,可以进行特殊的处理:透视除法

 

模型-视图变换(Model-View)-》透视(Projection)-》视口变换(ViewPort)

有了齐次坐标系,就可以讨论到底如何将模型数据最终投影到平面上并显示出来,首先看一下模型的格式,每个模型有许多组三角型顶点组成,每组顶点数据包含:

x,y,z,(vertex,顶点),x,y,z(normal,法向量,表示该顶点所在平面的方向,比如说,光照向量夹角和法向量就可以决定入射光强度), s,t(纹理坐标),顶点顺序(index,即描述每个三角型的顶点描画顺序)

这些数据将经过以下步骤进行处理

将顶点数据转换为齐次坐标系下的坐标:P = [X, Y, Z]T -》 P = [X, Y, Z, 1]T w=1

然后进行Model-View变换(把模型摆放到人眼观察的位置,常见的有平移,旋转和缩放),和透视(投影到二维平面上),再通过计算纹理坐标st在对应纹理上的颜色值,对显示屏幕进行适配(ViewPort),就可以显示三维模型到屏幕上(为了说明过程,这里简化了很多流程)。由于使用了齐次坐标系,所有这些变换都转化为对应点(向量)和一个4*4矩阵进行乘法运算。这里举例介绍每个矩阵是如何推算出来

先看Model-View变换,Model-View,可以朴素的理解为把模型摆放到一个人眼观察的方向上,因为移动相机(人眼)和移动模型,其效果是等价的,所以就合二为一为Model-View,具体包含平移,旋转和缩放等。

以平移变换为例, 将每个顶点乘以T矩阵,就可以在每个x,y,z上增加距离dx,dy,dz

p = [x, y, z, 1]T

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image004.jpgp’ = [x’, y’, z’, 1]T

d = [dx, dy, dz, 0]T

x’ = x + dx,

y’ = y + dy,

z’ = z + dz.

p’ = Tp

旋转和缩放也可以类似推出,有兴趣可以参考其它资料。通过这样的矩阵变换,我们可以把世界坐标系的模型转化到人眼的方向

然后我们就需要将模型进行投影变换,常见的是透视投影变换,透视投影变换将坐标变换到统一的立方体空间(裁剪体)内,如下图所示:

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image005.jpg

透视投影变换有什么作用呢,透视在美术上我们可以简单理解为采取通过一块透明的平面去看景物的方法,将所见景物准确描画在这块平面上,即成该景物的透视图,从上图可以看出一个正常的正方体,在经过透视变换后,在新的裁剪(-1到1的立方体)内,变成一个梯形,符合透视的效果。根据上图相似三角形,我们用几何就可以推出变换矩阵,将Model-View转换出的顶点齐次坐标,乘以该矩阵就可以完成透视变换。有兴趣可以参考相关书籍:

http://avocado.oa.com/fconv/files/201211/183bf5db25bfea7de3d43b05d1d5a905.files/image006.jpg

经过透视以后,如果新的裁剪体它的长宽就是屏幕长宽的话,那么这时候,z轴坐标就可以只用于隐藏面的消除了,xy坐标就表示出了模型在屏幕坐标显示位置,我们的变换也就到此结束了,后续的纹理贴图,通过顶点纹理坐标st,会决定xy坐标上像素点的颜色,于是我们的3D模型就在屏幕上显示出来了。

需要注意的是,这里简化了透视除法,隐藏面消除等许多过程,只是尽可能的简单描述变换过程,描述有不专业和错误的地方,欢迎讨论。

 

【本文作者】normanren(任桥)


如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引