Qt上的OpenGL 编程(11)Qt实例hellogl代码解析
Qt下的OpenGL 编程(11)Qt实例hellogl代码解析
如上图,项目*有三个类.
glwidget:opengl的渲染窗口,主要负责图形的绘制,同时响应键盘鼠标事件;
window:主窗口类,负责界面的布局,一些信号和槽的实现;
qtlogo:图形类,负责logo的绘制。
三、glwidget类的分析
首先来看glwidget的头文件:
首先是类的构造函数和析构函数,构造函数中可以对成员进行初始化,析够函数
可以在不再需要这个对象的时候将不再需要的数据删除掉。
接下来的
QSize minimumSizeHint() const;
QSize sizeHint() const;
用来设置窗口的最小尺寸。
接下来的三个signal和三个slot分别对应三个方向的旋转:X,Y,Z。
protected成员中有三个最主要的函数:initializeGL()负责初始化,paintGL()
负责渲染窗口,resizeGL(int width, int height)在窗口大小变化时调用。后面两个
则是定义鼠标点击和移动的事件。
剩下的一些私有变量则是用来记录旋转角度,或是用来初始化logo的变量。
接下来看一下它的实现:
构造函数中首先对几个私有变量进行了初始化,析够函数中什么都没有做(自动回收?),
接下来的qNormalizeAngle函数,是用于纠正角度的,因为在旋转了很多圈之后,角度会变得很大,需要对其进行纠正。
接下来是对三个槽函数的定义,在调用之前都要对角度进行纠正,然后改变相应的角度的值,接着发出角度改变的信号。
这个信号最后是和window类中的控制滑动条的槽链接起来了,当logo发生旋转的时候,就会把旋转的角度告诉给window,然后
window的槽执行相应的语句,滑动条位置发生改变。
相反,当window的滑动条数值发生改变的时候,也会发出相应的信号给glwiget的三个槽函数,然后logo执行旋转。
initializeGL中对logo进行了初始化,还定义了灯光等的参数,比较好理解。
paintGL中我们主要来看一下坐标的变换:首先是把绘制点移到了(0,0,-10)的
位置,然后绕三个轴进行旋转,做后将logo绘制出来(logo的绘制还是有点麻烦,有兴趣的同学可以慢慢研究一下qtlogo类)。
mouseMoveEvent则是对鼠标拖动的响应,左键拖动和右键拖动分别绕不同的方向旋转。
调用的是之前定义的set槽函数。
所以这个类的槽函数有两个作用:1.当作一般的函数;2.响应某个信号。
三、参考
QT帮助。
一、提要
还记得我们在第一篇教程中运行的例子吗?那是那个可以到处转的大Q,今天我们就来分析一下这个Qt自带的OpenGL例子。
如上图,项目*有三个类.
glwidget:opengl的渲染窗口,主要负责图形的绘制,同时响应键盘鼠标事件;
window:主窗口类,负责界面的布局,一些信号和槽的实现;
qtlogo:图形类,负责logo的绘制。
三、glwidget类的分析
首先来看glwidget的头文件:
#ifndef GLWIDGET_H #define GLWIDGET_H #include <QGLWidget> class QtLogo; //! [0] class GLWidget : public QGLWidget { Q_OBJECT public: GLWidget(QWidget *parent = 0); ~GLWidget(); QSize minimumSizeHint() const; QSize sizeHint() const; //! [0] //! [1] public slots: void setXRotation(int angle); void setYRotation(int angle); void setZRotation(int angle); signals: void xRotationChanged(int angle); void yRotationChanged(int angle); void zRotationChanged(int angle); //! [1] //! [2] protected: void initializeGL(); void paintGL(); void resizeGL(int width, int height); void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); //! [2] //! [3] private: QtLogo *logo; int xRot; int yRot; int zRot; QPoint lastPos; QColor qtGreen; QColor qtPurple; }; //! [3] #endif
首先是类的构造函数和析构函数,构造函数中可以对成员进行初始化,析够函数
可以在不再需要这个对象的时候将不再需要的数据删除掉。
接下来的
QSize minimumSizeHint() const;
QSize sizeHint() const;
用来设置窗口的最小尺寸。
接下来的三个signal和三个slot分别对应三个方向的旋转:X,Y,Z。
protected成员中有三个最主要的函数:initializeGL()负责初始化,paintGL()
负责渲染窗口,resizeGL(int width, int height)在窗口大小变化时调用。后面两个
则是定义鼠标点击和移动的事件。
剩下的一些私有变量则是用来记录旋转角度,或是用来初始化logo的变量。
接下来看一下它的实现:
#include <QtGui> #include <QtOpenGL> #include <math.h> #include "glwidget.h" #include "qtlogo.h" #ifndef GL_MULTISAMPLE #define GL_MULTISAMPLE 0x809D #endif //! [0] GLWidget::GLWidget(QWidget *parent) : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) { logo = 0; xRot = 0; yRot = 0; zRot = 0; qtGreen = QColor::fromCmykF(0.40, 0.0, 1.0, 0.0); qtPurple = QColor::fromCmykF(0.39, 0.39, 0.0, 0.0); } //! [0] //! [1] GLWidget::~GLWidget() { } //! [1] //! [2] QSize GLWidget::minimumSizeHint() const { return QSize(50, 50); } //! [2] //! [3] QSize GLWidget::sizeHint() const //! [3] //! [4] { return QSize(400, 400); } //! [4] static void qNormalizeAngle(int &angle) { while (angle < 0) angle += 360 * 16; while (angle > 360 * 16) angle -= 360 * 16; } //! [5] void GLWidget::setXRotation(int angle) { qNormalizeAngle(angle); if (angle != xRot) { xRot = angle; emit xRotationChanged(angle); updateGL(); } } //! [5] void GLWidget::setYRotation(int angle) { qNormalizeAngle(angle); if (angle != yRot) { yRot = angle; emit yRotationChanged(angle); updateGL(); } } void GLWidget::setZRotation(int angle) { qNormalizeAngle(angle); if (angle != zRot) { zRot = angle; emit zRotationChanged(angle); updateGL(); } } //! [6] void GLWidget::initializeGL() { qglClearColor(qtPurple.dark()); logo = new QtLogo(this, 64); logo->setColor(qtGreen.dark()); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); glShadeModel(GL_SMOOTH); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glEnable(GL_MULTISAMPLE); static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 }; glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); } //! [6] //! [7] void GLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glLoadIdentity(); glTranslatef(0.0, 0.0, -10.0); glRotatef(xRot / 16.0, 1.0, 0.0, 0.0); glRotatef(yRot / 16.0, 0.0, 1.0, 0.0); glRotatef(zRot / 16.0, 0.0, 0.0, 1.0); logo->draw(); } //! [7] //! [8] void GLWidget::resizeGL(int width, int height) { int side = qMin(width, height); glViewport((width - side) / 2, (height - side) / 2, side, side); glMatrixMode(GL_PROJECTION); glLoadIdentity(); #ifdef QT_OPENGL_ES_1 glOrthof(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0); #else glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0); #endif glMatrixMode(GL_MODELVIEW); } //! [8] //! [9] void GLWidget::mousePressEvent(QMouseEvent *event) { lastPos = event->pos(); } //! [9] //! [10] void GLWidget::mouseMoveEvent(QMouseEvent *event) { int dx = event->x() - lastPos.x(); int dy = event->y() - lastPos.y(); if (event->buttons() & Qt::LeftButton) { setXRotation(xRot + 8 * dy); setYRotation(yRot + 8 * dx); } else if (event->buttons() & Qt::RightButton) { setXRotation(xRot + 8 * dy); setZRotation(zRot + 8 * dx); } lastPos = event->pos(); }
构造函数中首先对几个私有变量进行了初始化,析够函数中什么都没有做(自动回收?),
接下来的qNormalizeAngle函数,是用于纠正角度的,因为在旋转了很多圈之后,角度会变得很大,需要对其进行纠正。
接下来是对三个槽函数的定义,在调用之前都要对角度进行纠正,然后改变相应的角度的值,接着发出角度改变的信号。
这个信号最后是和window类中的控制滑动条的槽链接起来了,当logo发生旋转的时候,就会把旋转的角度告诉给window,然后
window的槽执行相应的语句,滑动条位置发生改变。
相反,当window的滑动条数值发生改变的时候,也会发出相应的信号给glwiget的三个槽函数,然后logo执行旋转。
initializeGL中对logo进行了初始化,还定义了灯光等的参数,比较好理解。
paintGL中我们主要来看一下坐标的变换:首先是把绘制点移到了(0,0,-10)的
位置,然后绕三个轴进行旋转,做后将logo绘制出来(logo的绘制还是有点麻烦,有兴趣的同学可以慢慢研究一下qtlogo类)。
mouseMoveEvent则是对鼠标拖动的响应,左键拖动和右键拖动分别绕不同的方向旋转。
调用的是之前定义的set槽函数。
所以这个类的槽函数有两个作用:1.当作一般的函数;2.响应某个信号。
三、参考
QT帮助。