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 *event) { 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(); } |