首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

QT与OpenGL之三维空间旋转

2012-12-20 
QT与OpenGL之三维旋转效果:由于上传大小的限制,只能制作短暂的效果。在这篇文章中,将要展现的效果是在3D场

QT与OpenGL之三维旋转

效果:

QT与OpenGL之三维空间旋转

由于上传大小的限制,只能制作短暂的效果。


在这篇文章中,将要展现的效果是在3D场景中移动位图,得到简单的动画效果。便于大家共同学习,给出全部代码:

在开始前,你应该在pro中添加

LIBS +=glut.lib glut32.lib

同时你也应该将这两个库加到QT的bin目录下。

glwidget.h

#include "glwidget.h"#include "ui_glwidget.h"#include <QtGui>#include <QtCore>#include <QtOpenGL>#include <GL/GLU.h>const int num = 50;typedef struct{    int r, g, b;    GLfloat dist;    GLfloat angle;}stars;stars star[num];GLfloat light_ambient[4]={0.5, 0.5, 0.5, 1.0};GLfloat light_diffuse[4]={1.0, 1.0, 1.0, 1.0};GLfloat light_position[4]={0.0, 0.0, 2.0, 0.0};GLWidget::GLWidget(QGLWidget *parent) :    QGLWidget(parent),    ui(new Ui::GLWidget){    ui->setupUi(this);    fullscreen = false;    rotate_angle = 0.0;    zoom = -15.0;    title = 90.0;    spin = (GLfloat)0.1;    loop = 0;    twinkle = false;    blend = false;    startTimer(5);//开启5ms定时器}//这是对虚函数,这里是重写该函数void GLWidget::initializeGL(){    setGeometry(300, 150, 500, 500);//设置窗口初始位置和大小    loadGLTextures();    glEnable(GL_TEXTURE_2D);//允许采用2D纹理技术    glShadeModel(GL_SMOOTH);//设置阴影平滑模式    glClearColor(0.0, 0.0, 0.0, 0.5);//改变窗口的背景颜色    glClearDepth(1.0);//设置深度缓存    glEnable(GL_DEPTH_TEST);//允许深度测试    glDepthFunc(GL_LEQUAL);//设置深度测试类型    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);//进行透视校正    glBlendFunc(GL_SRC_ALPHA, GL_ONE);//源像素因子采用alpha通道值,目标像素因子采用1.0    glEnable(GL_BLEND);    /*为num个星星的数组结构体赋初值*/    for(loop = 0; loop < num; loop++)        {            star[loop].angle = 0.0;            star[loop].dist = (float(loop)/num)*5.0;//星星的离中心的距离越来越远,最大距离为5,接近屏幕的距离            star[loop].r = rand()%256;            star[loop].g = rand()%256;            star[loop].b = rand()%256;        }}void GLWidget::paintGL(){    //glClear()函数在这里就是对initializeGL()函数中设置的颜色和缓存深度等起作用    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);    glBindTexture(GL_TEXTURE_2D, texture[0]);//绑定纹理目标    for(loop = 0; loop < num; loop++)        {            glLoadIdentity();            glTranslatef(0.0, 0.0, zoom);//移向屏幕里面            glRotatef(title, 1.0, 0.0, 0.0);//沿着x轴旋转了tilt度            glRotatef(star[loop].angle, 0.0, 1.0, 0.0);//每个星星沿着y轴旋转自己的角度            glTranslatef(star[loop].dist, 0.0, 0.0);            glRotatef(-star[loop].angle, 0.0, 1.0, 0.0);//将沿着y轴旋转的角度又转回去            glRotatef(-title, 1.0, 0.0, 0.0);//将沿着x轴旋转过的角度也转回去            if(twinkle)//如果星星闪烁的话                {                    glColor4ub(star[num-loop-1].r, star[num-loop-1].g, star[num-loop-1].b, 255);//采用的是对称一头那边的星星的颜色                    //将星星的纹理贴到一个小矩形上                    glBegin(GL_QUADS);                    glTexCoord2f(0.0, 0.0);                    glVertex3f(-1.0, -1.0, 0.0);                    glTexCoord2f(1.0, 0.0);                    glVertex3f(1.0, -1.0, 0.0);                    glTexCoord2f(1.0, 1.0);                    glVertex3f(1.0, 1.0, 0.0);                    glTexCoord2f(0.0, 1.0);                    glVertex3f(-1.0, 1.0, 0.0);                    glEnd();                }            /*不闪烁时*/            glRotatef(spin, 0.0, 0.0, 1.0);//星星沿z轴自转spin度            glColor4ub(star[loop].r, star[loop].g, star[loop].b, 255);//采用的是自己的颜色,完全不透明            glBegin(GL_QUADS);            glTexCoord2f(0.0, 0.0);            glVertex3f(-1.0, -1.0, 0.0);            glTexCoord2f(1.0, 0.0);            glVertex3f(1.0, -1.0, 0.0);            glTexCoord2f(1.0, 1.0);            glVertex3f(1.0, 1.0, 0.0);            glTexCoord2f(0.0, 1.0);            glVertex3f(-1.0, 1.0, 0.0);            glEnd();            spin += 0.01f;            star[loop].angle += float(loop)/num;//角度是在慢慢增大的            star[loop].dist -= 0.01f;//距离慢慢减小,被吸向了屏幕中心            if(star[loop].dist < 0)                {                    star[loop].dist += 5.0f;                    star[loop].r = rand()%256;                    star[loop].g = rand()%256;                    star[loop].b = rand()%256;                }        }}//该程序是设置opengl场景透视图,程序中至少被执行一次(程序启动时).void GLWidget::resizeGL(int width, int height){    if(0 == height)        height = 1;//防止一条边为0    glViewport(0, 0, (GLint)width, (GLint)height);//重置当前视口,本身不是重置窗口的,只不过是这里被Qt给封装好了    glMatrixMode(GL_PROJECTION);//选择投影矩阵    glLoadIdentity();//重置选择好的投影矩阵    gluPerspective(45.0, (GLfloat)width/(GLfloat)height, 0.1, 100.0);//建立透视投影矩阵    glColor4f(1.0f, 1.0f, 1.0f, 0.5f);    glBlendFunc(GL_SRC_ALPHA, GL_ONE);    glMatrixMode(GL_MODELVIEW);//以下2句和上面出现的解释一样    glLoadIdentity();}void GLWidget::keyPressEvent(QKeyEvent *e){    switch(e->key())    {        /*PageUp键为将木箱移到屏幕内部方向*/        case Qt::Key_T:        twinkle = !twinkle;        updateGL();        break;        /*B键位选择是否采用色彩融合*/        case Qt::Key_B:            blend = !blend;            if(blend)                {                    glEnable(GL_BLEND);//色彩融合和深度缓存不能同时开启                    glDisable(GL_DEPTH_TEST);                }            else                {                    glDisable(GL_BLEND);                    glEnable(GL_DEPTH_TEST);                }            updateGL();            break;        /*PageUp键为将木箱移到屏幕内部方向*/        case Qt::Key_PageUp:            zoom -= 0.2;            updateGL();            break;        /*PageDown键为将木箱移到屏幕外部方向*/        case Qt::Key_PageDown:            zoom += 0.2;            updateGL();            break;        /*Up键为加快立方体旋转的速度*/        case Qt::Key_Up:            title += 0.5;            updateGL();            break;        /*Down键为减慢立方体旋转的速度*/        case Qt::Key_Down:            title -= 0.5;            updateGL();            break;        /*F1键为全屏和普通屏显示切换键*/        case Qt::Key_F1:            fullscreen = !fullscreen;            if(fullscreen)                showFullScreen();            else            {                setGeometry(300, 150, 500, 500);                showNormal();            }            updateGL();            break;        /*Ese为退出程序键*/        case Qt::Key_Escape:            close();    }}/*装载纹理*/void GLWidget::loadGLTextures(){    QImage tex, buf;    if(!buf.load(":/images/2.bmp"))//这个时候因为debug没有在外面,所以图片文件夹就是本目录了   // if(!buf.load("../opengl_qt_nehe_07/crate.bmp"))    {        qWarning("Cannot open the image...");        QImage dummy(128, 128, QImage::Format_RGB32);//当没找到所需打开的图片时,创建一副128*128大小,深度为32位的位图        dummy.fill(Qt::green);        buf = dummy;    }    tex = convertToGLFormat(buf);//将Qt图片的格式buf转换成opengl的图片格式tex    glGenTextures(1, &texture[0]);//开辟3个纹理内存,索引指向texture[0]    /*建立第一个纹理*/    glBindTexture(GL_TEXTURE_2D, texture[0]);//将创建的纹理内存指向的内容绑定到纹理对象GL_TEXTURE_2D上,经过这句代码后,以后对                                            //GL_TEXTURE_2D的操作的任何操作都同时对应与它所绑定的纹理对象    glTexImage2D(GL_TEXTURE_2D, 0, 3, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.bits());//开始真正创建纹理数据    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理小时,采用GL_NEAREST的方法来处理                                                                      //GL_NEAREST方式速度非常快,因为它不是真正的滤波,所以占用内存非常                                                                      // 小,速度就快了    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);//当所显示的纹理比加载进来的纹理大时,采用GL_NEAREST的方法来处理}void GLWidget::timerEvent(QTimerEvent *){    updateGL();}GLWidget::~GLWidget(){    delete ui;}


热点排行