您的位置:首页 > 编程语言 > Qt开发

Qt下的OpenGL 编程(9)3D视图变换、旋转的地球

2012-08-22 15:52 369 查看
一、提要
视图变换是3D图形中的一个很重要的概念,需要一些抽象的思维去理解。说完概念之后我们会写一个自旋转的地球的例子来帮助理解。
二、照相机比喻
在《OpenGL Programming Guide 》中将所有的3D变换统一到一个有意思的现实世界模型,照相机比喻。
1.确定照相机的位置的过程对应于“视图变换”(Viewing Transformations)
2.确定物体位置的过程对应于“模型变换”(Modeling Transformations)
3.确定照相机放大倍数的过程对应于“投影变换”(Projection Transformations)
4.确定照片大小的过程对应于“视口变换”(Viewport Transformations)
之前我们有解释过一个函数:gluPerspective,它的作用就类似于设置摄像机的参数。
今天我们要重点了解的是:
void gluLookAt(GLdoubleeyeX,
 GLdoubleeyeY,
 GLdoubleeyeZ,
 GLdoublecenterX,
 GLdoublecenterY,
 GLdoublecenterZ,
 GLdoubleupX,
 GLdoubleupY,
 GLdoubleupZ);
 一共有9个参数,还是用一台摄像机来比喻,前三个参数就是摄像机所处的位置,
中间三个参数是摄像机要对准的地方,最后三个是摄像机观察的角度(横着看,竖着看,斜着看...).
三、自旋转地球
编程的思路:首先在空间建立一个球体,然后赋予地球的材质,利用之前的动画原理使它不断地绕着轴线旋转,通过改变不同的视图,我们可以观察到地球不同的旋转方式,而模型位置没有任何改变。
主要代码:
void NeHeWidget::initializeGL()
{
//载入纹理
loadGLTextures();
// 启用阴影平滑
glShadeModel( GL_SMOOTH );
// 黑色背景
glClearColor( 0.0, 0.0, 0.0, 0.0 );
// 设置深度缓存
glClearDepth( 1.0 );
// 启用深度测试
glEnable( GL_DEPTH_TEST );
//启用纹理
glEnable( GL_TEXTURE_2D );
// 所作深度测试的类型
glDepthFunc( GL_LEQUAL );
// 告诉系统对透视进行修正
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
// 开启剔除操作效果
glEnable(GL_CULL_FACE);
// 使用平滑法线
gluQuadricNormals(mySphere, GL_SMOOTH);
// 使用纹理
gluQuadricTexture(mySphere, GL_TRUE);
// 设置球纹理映射
}
void NeHeWidget::paintGL()
{
// 清除屏幕和深度缓存
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
//移到屏幕的左半部分,并且将视图推入屏幕背后足够的距离以便我们可以看见全部的场景
//glTranslatef(0.0f,0.0f,zoom);
glRotatef( yRot, 0.0,0.0,1.0 );
glColor3f(1.0,1.0,1.0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glPushMatrix();
gluSphere(mySphere, 0.55f, 40, 40);
glPopMatrix();
//旋转速度
yRot += 0.4;
glLoadIdentity();
//gluLookAt (2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
 //gluLookAt (0.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0);
gluLookAt (2.0, 0.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0);
glFlush();
//fps的字体颜色
glColor3f(0.0f,0.0f,1.0f);
//计算FPS
calFrequency();
}
这里用到的建立球的方式是二次曲面建模,比较简单主要过程如下:
//声明一个二次曲面
GLUquadricObj *mySphere; //初始化
mySphere=gluNewQuadric();
//通过二次曲面建立球体
gluSphere(mySphere, 0.55f, 40, 40);
给二次曲面添加纹理的方法如下:
 //剔除背面
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
// 使用平滑法线
gluQuadricNormals(mySphere, GL_SMOOTH);
// 使用纹理
gluQuadricTexture(mySphere, GL_TRUE);
// 设置球纹理映射
glBindTexture(GL_TEXTURE_2D, texture[0]);
系统默认是两面贴图的,前面的两句话用于剔除我们看不到的面,节省系统开销。
但是,需要说明的是,背面剔除后,在转换视角,到背面变成正面的那一瞬间,会需要重新渲染背面,此时效率较低,事实上,这么一个简单的程序,再没有开启背面剔除时,从正面到背面的转换非常流畅,开启后,转换会有明显的小小迟缓,但是好处就是背面没有需要显示的时候是不占用资源的了,孰优孰劣,开启与否,那就只能看情况把握了。
最后的效果如下:
通过调节gluLookAt的参数,我们可以切换不同的视角。

参考资料

1.《 OpenGL Reference Manual 》, OpenGL 参考手册2.《 OpenGL 编程指南》(《 OpenGL Programming Guide 》), Dave Shreiner , Mason Woo , Jackie Neider , Tom Davis 著,徐波译,机械工业出版社3. 《win32 OpenGL编程 》 一个大牛的博客 http://blog.csdn.net/vagrxie/article/category/628716/3

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息