1、关于坐标系统
OpenGL D3D WPF
右手坐标系 左手坐标系 右手坐标系
OpenGL默认坐标系统是右手坐标系,即X轴向右,Y轴向上,Z轴由屏幕内侧指向屏幕外侧。而Direct 3D既支持左手坐标系统又支持右手坐标系统,默认采用左手坐标系,即Z轴向内。WPF是D3D的托管封装,不过与D3D不同,为了和大多数图形应用一致,它也采用了右手坐标系统。
2、齐次坐标
“齐次坐标表示是计算机图形学的重要手段之一,它既能够用来明确区分向量和点,同时也更易用于进行仿射(线性)几何变换。”—— F.S. Hill, JR
没有齐次坐标,同样用三个分量表示,我们无法区分一个变量是点和向量。有了齐次坐标,我们还可以表示无穷远点(w接近0)。
在普通坐标(Ordinary Coordinate)和齐次坐标(Homogeneous Coordinate)之间进行转换规则:
(1)从普通坐标转换成齐次坐标时
如果(x,y,z)是个点,则变为(x,y,z,1);
如果(x,y,z)是个向量,则变为(x,y,z,0)
(2)从齐次坐标转换成普通坐标时
如果是(x,y,z,w),则知道它是个点,变成(x/w,y/w,z/w); 一个普通坐标,有对应的一组齐次坐标,其中w不为0
如果是(x,y,z,0),则知道它是个向量,仍然变成(x,y,z)
以上是通过齐次坐标来区分向量和点的方式。从中可以得知,对于平移T、旋转R、缩放S这3个最常见的仿射变换,平移变换只对于点才有意义,因为普通向量没有位置概念,只有大小和方向。而旋转和缩放对于向量和点都有意义,你可以用类似上面齐次表示来检测。从中可以看出,齐次坐标用于仿射变换非常方便。
3、向量左乘右乘&矩阵变换左乘右乘
3.1向量左乘右乘
矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”。OpenGL存储方式是列优先,D3D是行优先。
线代:a11,a12,a13,a14 d3d : a11,a12,a13,a14 GL: a11,a21,a31,a41
a21,a22,a23,a24 a21,a22,a23,a24 a12,a22,a32,a42
a31,a32,a33,a34 a31,a32,a33,a34 a13,a23,a33,a43
a41,a42,a43,a44 a41,a42,a43,a44 a14,a24,a34,a44
矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)。
这个规则取决于向量Vector的存储形式,即行向量还是列向量。如果是列向量,如OpenGL
向量表示成v=(x1,x2,…xn)T,矩阵变换即如下所示,为向量左乘
|a11 a12 ... a1n | |x1| |x1'|
|a21 a22 ... a2n | |x2| |x2'|
|... |* |...| = |... |
|am1 am2 ... amn | |xn| |xm'|
Direct3D 采用行主序存储, 向量表示成v=(x1,x2,…xn),矩阵变换即如下所示,为矩阵右乘
|a11 a21 ... am1 |
|a12 a22 ... am2 |
|x1 x2...,xn|* |... | = | x1' x2'... ,xm'|
|a1n a2n ... amn |
同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同,opengl向量左乘,D3D和wpf向量右乘。
3.2矩阵变换左乘右乘
由上文,D3D是矩阵右乘,
projected vertex coord = VertexPosition * MatrixModelWorld * MatrixWorldView *MatrixViewProjection
则当前变换矩阵CTM=MatrixWorldView *MatrixViewProjection*MatrixViewProjection
变换矩阵也是右乘,与习惯一致。
而OpenGL则是左乘,如下
projected vertex coord = MatrixViewProjection* MatrixWorldView * MatrixModelWorld * VertexPosition ;
则当前变换矩阵CTM= MatrixViewProjection* MatrixWorldView * MatrixModelWorld
对于opengl的变换,OpenGL的API 如glRotate、glTranslate 、glScale 、glMultMatrixf(m) 都是CTM右乘新的矩阵,所以操作顺序要反过来,记住在程序中最后指定的矩阵是最先被执行的操作
如:中心点为(1.0, 1.0, 1.0)的模型, 绕自身z方向旋转90° ,应该先按向量(-1.0,-1.0,-1.0)平移到原点,然后旋转90度,最后移回中心点(1.0, 1.0, 1.0)
4、点、向量、法向量的变换
Points p =(x,y,z,1)M
Direction vectors v=(x,y,z,0)M
Normal vectors n=(x,y,z,0)M-1T
至于法向量的变换为什么是逆的转置,可见下面的推导http://blog.csdn.net/Nhsoft/archive/2004/06/23/22998.aspx
5、WPF的矩阵变换
WPF的camera、Visual3DModel类等隐藏了具体的变换矩阵,只提供了一个属性:Transform,记录相对于初始状态的变化矩阵,所以交互时需要自己计算得到各种变换矩阵,这些计算可以使用3DTools中的MathUtils类。此外,为了从其他平台如Direct3D移植代码,WPF还提供了MatrxiCamera这样的类,这样可以自己定义视图和投影矩阵。