首先明确一点,我们在程序中,opengl的变换的代码是从上往下写的,但实际变换是从下往上进行的。在空间(坐标系)中的变换也是从下往上依次是:模型空间->世界空间->视觉空间->裁剪空间--->屏幕。
再明确两个坐标:视觉坐标相对于观察者的视角而言,可以视为绝对的屏幕坐标,通常作为参考坐标系使用
再利用opengl 进行3d绘制时,就会使用笛卡尔坐标系,如果不进行任何坐标变换,使用的坐标系和视觉坐标系相同
世界坐标:物体进行模型变换后,便进入了世界空间,在这里可以对物体进行模型变换,各个物体之间的相互位置关系也在这里确定
1。视图变换:视图变换是应用到场景中的第一种变换,移动了当前的工作坐标系,允许我们把观察点放在我们希望的任何位置,所有后续变换都会基于新调整的坐标系进行。
2。模型变换:用于操纵模型和其中的特定对象,有旋转、平移、缩放,旋转平移连续使用时每次变换都与最后的变换结果有关,先平移后旋转和先旋转后平移的结果往往不同。模型变换讲物体变换到世界空间中,在世界空调间中进行移动旋转和缩放的变换,这些变换都可以看成在移动世界坐标系
例如glTranslatef(10,0,0);可以看成是将世界坐标系左移了10个单位,然后进行绘制。
3。模型视图:把上述两者变换进行组合,成为一个单独的矩阵,即模型视图矩阵,如果直接进行视图模型变换,加载视图模型矩阵,那么我们就省略跳过世界坐标系,直接进入到视觉坐标系中,在变换中我们经常直接加载视图模型矩阵:
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
这样其实得到的坐标已经是视觉坐标系的坐标了,不是世界坐标系中的,这点要牢记。
在这之后可以进行glulookat()函数操作(记住实际是从下往上)
- gluLookat(eye,look,up);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(10,0,0);
- glScalef(A,A,A);
- glRotatef(Θ, 0,0,1)
- DrawObject() ;
4。投影变换:定义视景体并创建了裁剪平面,制定一个完成的场景如何投影到屏幕上的最终图像,有正投影和透视投影两种
5。视口变换:上述变换后得到一个场景的二位投影,用视口变换映射到屏幕某处的物理窗口上。这里其实是硬件的事情,opengl的事情只到投影变换,一个场景就算绘制完成了。
- glViewport(0,0,width,height);//设置视口(视窗)大小
- glMatrixMode(GL_PROJECTION));
- glLoadIdentity();
- gluPerspective(fov,aspect,near,far);
- gluLookat(eye,look,up);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(10,0,0);
- glScalef(A,A,A);
- glRotatef(Θ, 0,0,1)
- DrawObject() ;