3D图形矩阵变换总结

77 篇文章 4 订阅
4 篇文章 0 订阅

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)

  1. glMatrixMode(GL_MODELVIEW);  
  2.   
  3. glLoadIdentity();  
  4.   
  5. glTranslated(1.0, 1.0, 1.0);  
  6.   
  7. glRotated(90.0, 0.0, 0.0, 1.0);  
  8.   
  9. glTranslatef(-1.0, -1.0, -1.0);  
  10.   
  11.    

glMatrixMode(GL_MODELVIEW);

glLoadIdentity();

glTranslated(1.0, 1.0, 1.0);

glRotated(90.0, 0.0, 0.0, 1.0);

glTranslatef(-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这样的类,这样可以自己定义视图和投影矩阵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值