在学习上,我总会是杂乱无章的学。为什么呢。我一般是在需要某个理论的时候才会去深究理论内部的各种详细机制,当然前提必须是你对这方面知识必须有一点的了解,不需要了解的足够深入。其实我想这也是读书的一种方法吧。对于看书我向来先很粗糙的浏览整书一遍,大概就只看一些概念,了解这书的主要内容 方向等。第二遍则是详细的理解内容,某些时候有些内容都是很有之后才有心去看的。
其实今天在总结这个的时候,并不是在用opengl而是在使用osg设计一个项目人物汽车车等漫游类《可能应用在手机,汽车导航上》的时候,想起总结这的。我其实是想画些图来写这份总结可能会更容易理解的.然而实在懒...
在图形学的显示流程:
三维图形->模型视图变换->投影变换->三维裁剪->视口->屏幕图形显示
三维->二维的变换,总的来理解只是三维的物体在一系列的变换之后决定了屏幕上某些像素位置的颜色值。最后这些颜色组成了一幅图画。就是我们所看到得最终屏幕二维图形了。
在大概了解这种流程之后,模型视图变换 无疑将成为决定我们所将看到的图像的轮廓。
模型视图变换 应该来讲是包含两个变换的:模型变换,视图变换。为什么将他们合在一起呢? 在照相机成像系统中 若固定相机不动移动模型会 等价于 固定模型不动移动相机。
考究如下内容:
glMatrixMode(GL_MODELVIEW);
glLoadIdentity(); //当前矩阵设置为单位矩阵
glRotatef(45.0f,0.0,0.0,1.0); //按[0.0,0.0,1.0]为轴旋转45度
glTranslatef(2.0,2.0,2.0); // 平移至 [2.0,2.0,2.0]
glBegin(...); // 画某些东西
...
...
...
glEnd();
有两种方式理解:一种是局部坐标系的理解,一种是全局坐标系的理解。
如果按照上面那些内容从上到下的理解的方式就是局部坐标系的理解。opengl变换上的实现其实是个矩阵的乘法。按照局部坐标系的理解 上面代码的变换是按照这样的顺序执行的:
先将局部坐标系绕z轴旋转45度,在将局部坐标系的原点平移至[2.0,2.0,2.0],然后在局部坐标系内画物体。
假设 旋转步骤的矩阵为R,平移部分的矩阵为T 当前矩阵为C。
new_C=old_C*R*T 这是一个矩阵右乘操作
理论上来讲 这就是一个坐标系的变换过程,R*T 这个矩阵其实就是将原先的坐标系变换到现在的坐标系,这个时候原先坐标系的点p将变换成p1,p1=(R*T)*p。
而按照全局坐标系的理解,它的变换过程则是相反的,这也是相当的好理解的.在当前世界坐标系中画好该物体之后,我必须将它移动到正确的位置。那必须得先平移物体到[2.0,2.0,2.0],然后将物体绕z轴旋转45度。这是一个相反的变换过程,然而这个与前面的是等价的 为什么?
考虑世界坐标系下点p,经过平移操作后 p11=T*p; 在经过旋转操作后 p1=R*P11=R*(T*p) 这是矩阵的一个左乘操作 先变换的在后面. 所以说new_C=(old_c*(R*(T))) 左乘 所以说这是一个等价的过程.
一般来将,我们考虑的时候总是世界坐标系考虑旋转平移等操作的.所以在写变换的时候最好的方式就是将 变换步骤一直左乘,而代码中则按左乘后结果矩阵的顺序写代码。
其次在理解以上的变换过程中模型变换的原理,我们可以很好的理解gluLookAt(eye,center,up)的视图变换的过程,现在只考虑模型不动,照相机移动的过程,且是在全局坐标系下的移动过程.
opengl默认照相机框架 是视点在原点 y轴为向上方向 z轴负方向为视线方向
gluLookAt的目的在于使得视点移动到eye位置 并看向center。
则gluLookAt的过程先平移至eye,而center->eye(center指向eye)则为z方向设为z(Zx,Zy,Zz),Up方向为y轴方向,y,z的叉积则为x轴方向.则只需将它们都旋转到位就行了
所以这个时候模型变换矩阵就为《相对于模型来讲 相机移动到eye等价于模型移动到-eye.
|Xx Xy Xz 0| |1 0 0 -eyex|
|Yx Yy Yz 0| * |0 1 0 -eyey|
|Zx Zy Zz 0| |0 0 1 -eyez|
|0 0 0 1| |0 0 0 1 |