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

一、提要
        视图变换是3D图形中的一个很重要的概念,需要一些抽象的思维去理解。说完概念之后我们会写一个自旋转的地球的例子来帮助理解。

 
二、照相机比喻
在《OpenGL Programming Guide 》中将所有的3D变换统一到一个有意思的现实世界模型,照相机比喻。
 
1.确定照相机的位置的过程对应于“视图变换”(Viewing Transformations)
 
2.确定物体位置的过程对应于“模型变换”(Modeling Transformations)
 
3.确定照相机放大倍数的过程对应于“投影变换”(Projection Transformations)
 
4.确定照片大小的过程对应于“视口变换”(Viewport Transformations)

 
            之前我们有解释过一个函数:gluPerspective,它的作用就类似于设置摄像机的参数。
  今天我们要重点了解的是:
 
  void gluLookAt(    GLdouble      eyeX,
       GLdouble      eyeY,
       GLdouble      eyeZ,
       GLdouble      centerX,
       GLdouble      centerY,
       GLdouble      centerZ,
       GLdouble      upX,
       GLdouble      upY,
       GLdouble      upZ);
       一共有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
 

                
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值