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

Qt中使用OpenGL进行三维场景绘制基础

2014-09-26 00:00 337 查看
OpenGL的引入

需要添加头文件:

#include<QGLWidegt>

实际上可以直接添加头文件:

#include <Qt/qgl.h>

并且需要在.pro文件中加入:

QT += opengl

使用OpenGL的基本方法

QGLWidget派生自QWidget,故绝大多数情况下QGLWidget可以像使用QWidget一样使用,只是使用OpenGL的函数替代QPainter实现绘制。通常通过子类化QGLWidget来实现OpenGLde使用,QGLWidget提供了三个虚函数用以重载来实现OpenGL的绘制:

paintGL()

l 窗口绘制函数,相当于paintEvent(),但QGLWidget依旧有只记得paintEvent()

l paintGL()只在需要重新绘制时候才会被调用,即调用updateGL()时被调用

l 在此使用OpenGL中的函数进行场景绘制,部分函数实际是QGLWidget的函数成员

resizeGL()

l 第一次调用paintGL()之前initializeGL()之后调用resizeGL()函数,窗口大小发生改变时也会调用该函数

l 在此设置视口,投影和其他与窗口不见尺寸相关的设置

initializeGL()

l 相当于注册函数,在调用paintGL()之前之辈调用一次

l 在此初始化GL环境:设置场景全局的属性,绘图描述表,定义显示列表,执行其他初始化

updateGL()

更新场景,通知调用paintGL(),在任何改变场景后调用,但自身不用实现

交互控制

鼠标和键盘时间可以通过mousePressEvent()和keyPressEvent()进行处理,与QWidget相同。要创建动画,只需启动QTimer,然后调用updateGL().

Qt: OpenGL模板

#ifndef GLWIDGET_H
#define GLWIDGET_H
#include <QtOpenGL/QGLWidget>
class GLWidget : public QGLWidget {
    Q_OBJECT
public:
    GLWidget(QWidget *parent = 0);
~GLWidget();
protected:
virtual void initializeGL();
virtual void resizeGL(int w, int h);
virtual void paintGL();
virtual void hideEvent(QHideEvent *event);
virtual void showEvent(QShowEvent *event);
virtual void timerEvent(QTimerEvent *event);
virtual void mousePressEvent(QMouseEvent *event);
virtual void mouseMoveEvent(QMouseEvent *event);
virtual void mouseReleaseEvent(QMouseEvent *event);
virtual void wheelEvent(QWheelEvent *event);
private:
int timerId;
QPoint lastPos;
GLfloat rotateX;
GLfloat rotateY;
GLfloat rotateZ;
GLfloat zoom;
void drawCube(GLfloat factorX = 1, GLfloat factorY = 1,
GLfloat factorZ = 1, GLfloat w = 1);
void drawCone(GLfloat radius = 1.0f, GLfloat height = 1,
GLuint steps = 18);
};
#endif // GLWIDGET_H
==================================[GLWidget.cpp]==================================
#include "GLWidget.h"
#include <qDebug>
#include <QTimerEvent>
#include <QMouseEvent>
#include <cmath>
GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(parent) {
setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer));
rotateX = 0.0f;
rotateY = 0.0f;
rotateZ = 0.0f;
zoom = 1.0f;
}
GLWidget::~GLWidget() {
}
void GLWidget::hideEvent(QHideEvent *eve
3ff0
nt) {
this->killTimer(this->timerId);
}
void GLWidget::showEvent(QShowEvent *event) {
this->timerId = this->startTimer(500);
}
void GLWidget::timerEvent(QTimerEvent *event) {
if (event->timerId() == this->timerId) {
    } else {
QGLWidget::timerEvent(event);
    }
}
void GLWidget::mousePressEvent(QMouseEvent *event) {
if (Qt::LeftButton == event->button()) {
lastPos = event->pos();
    } else if (Qt::RightButton == event->button()) {
lastPos = event->pos();
    }
}
void GLWidget::mouseMoveEvent(QMouseEvent *event) {
if (Qt::LeftButton & event->buttons()) {
GLfloat dx = event->pos().x() - lastPos.x();
GLfloat dy = event->pos().y() - lastPos.y();
rotateX += dy;
rotateY += dx;
updateGL();
//qDebug() << QString("RotateX:%1, RotateY:%2").arg(rotateX).arg(rotateY);
    } else if (Qt::RightButton & event->buttons()) {
GLfloat dz = event->pos().y() - lastPos.y();
        dz *= 0.01f;
zoom += dz;
updateGL();
    }
lastPos = event->pos();
}
void GLWidget::mouseReleaseEvent(QMouseEvent *event) {
}
void GLWidget::wheelEvent(QWheelEvent *event) {
GLfloat degrees = event->delta();
zoom -= degrees * 0.0002f;
// 注意, 如果zoom为负值, eye就会被放置到z轴的负方向, 而从物体的背面看了.
if (zoom < 1.0f) {
zoom = 1.0f;
    }
updateGL();
}
void GLWidget::initializeGL() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CCW);
//glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glShadeModel(GL_SMOOTH);
// Point size
// glPointSize(GLfloat size);
GLfloat sizes[2];
GLfloat step;
glGetFloatv(GL_LINE_WIDTH_RANGE, sizes);
glGetFloatv(GL_LINE_WIDTH_GRANULARITY, &step);
}
void GLWidget::resizeGL(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(75, (GLdouble)w / h, 0.1, 100);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void GLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
//glTranslatef(0.0f, 0.0f, zoom);
gluLookAt(0.0f, 0.0f, zoom, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glRotatef(rotateX, 1, 0, 0);
glRotatef(rotateY, 0, 1, 0);
glRotatef(rotateZ, 0, 0, 1);
// Real draw code.
//glColor3f(1.0f, 0.0f, 0.0f);
//drawCube(1, 1, 1, 1);
glPolygonMode(GL_BACK, GL_LINE);
    drawCone(1.0f, 1.50, 48);
}
void GLWidget::drawCube(GLfloat factorX, GLfloat factorY,
GLfloat factorZ, GLfloat w) {
GLfloat x = factorX * 0.5f;
GLfloat y = factorY * 0.5f;
GLfloat z = factorZ * 0.5f;
// x / w, y / w, z / w
// 前左下, 前右下, 前右上, 前左上: p0, p1, p2, p3
// 后左下, 后右下, 后右上, 后左上: p4, p5, p6, p7
GLfloat p0[4] = {-x, -y, z, w};
GLfloat p1[4] = {x, -y, z, w};
GLfloat p2[4] = {x, y, z, w};
GLfloat p3[4] = {-x, y, z, w};
GLfloat p4[4] = {-x, -y, -z, w};
GLfloat p5[4] = {x, -y, -z, w};
GLfloat p6[4] = {x, y, -z, w};
GLfloat p7[4] = {-x, y, -z, w};
// 开始绘制Cube的六个面: 逆时针
glBegin(GL_QUADS);
// 前面: p0, p1, p2, p3
glVertex4fv(p0);
glVertex4fv(p1);
glVertex4fv(p2);
glVertex4fv(p3);
// 右面: p1, p5, p6, p2
glVertex4fv(p1);
glVertex4fv(p5);
glVertex4fv(p6);
glVertex4fv(p2);
// 后面: p5, p4, p7, p6
glVertex4fv(p5);
glVertex4fv(p4);
glVertex4fv(p7);
glVertex4fv(p6);
// 左右: p4, p0, p3, p7
glVertex4fv(p4);
glVertex4fv(p0);
glVertex4fv(p3);
glVertex4fv(p7);
// 上面: p2, p6, p7, p3
glVertex4fv(p2);
glVertex4fv(p6);
glVertex4fv(p7);
glVertex4fv(p3);
// 下面: p0, p4, p5, p1
glVertex4fv(p0);
glVertex4fv(p4);
glVertex4fv(p5);
glVertex4fv(p1);
glEnd();
}
void GLWidget::drawCone(GLfloat radius, GLfloat height,
GLuint steps) {
const GLfloat GL_PI = 3.1415f;
GLfloat angles = 2 * GL_PI / steps;
GLfloat vertices[steps][3];
for (int i = 0; i < steps; ++i) {
        vertices[i][0] = radius * cos(i * angles);
        vertices[i][1] = radius * sin(i * angles);
        vertices[i][2] = 0;
    }
// top surface
glBegin(GL_TRIANGLE_FAN);
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.0f, 0.0f, height);
for (int i = 0; i < steps; ++i) {
glVertex3fv(vertices[i]);
if ((i & 1) == 0) {
glColor3f(1.0f, 0.0f, 0.0f);
            } else {
glColor3f(0.0f, 0.0f, 1.0f);
            }
        }
glVertex3fv(vertices[0]);
glEnd();
// bottom surface
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0f, 0.0f, 0);
for (int i = steps - 1; i >= 0; --i) {
glVertex3fv(vertices[i]);
if ((i & 1) == 0) {
glColor3f(0.0f, 1.0f, 0.0f);
            } else {
glColor3f(1.0f, 0.0f, 1.0f);
            }
        }
glVertex3fv(vertices[steps - 1]);
glEnd();
}


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