main.cpp
#include <QApplication> #include <iostream> #include "tetraheadron.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); if (!QGLFormat::hasOpenGL()) { std::cerr << "This system has no OpenGL support" << std::endl; return 1; } Tetrahedron tetrahedron; tetrahedron.setWindowTitle(QObject::tr("Tetrahedron")); tetrahedron.resize(300, 300); tetrahedron.show(); return app.exec(); }
tetraheaderon.h
#ifndef TETRAHEDRON_H #define TETRAHEDRON_H #include <QGLWidget> class Tetrahedron : public QGLWidget { Q_OBJECT public: Tetrahedron(QWidget *parent = 0); protected: //在QGLWidget中实现 void initializeGL(); void resizeGL(int width, int height); void paintGL(); //鼠标事件处理在QWidget中实现 void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void mouseDoubleClickEvent(QMouseEvent *event); private: void draw(); int faceAtPosition(const QPoint &pos); GLfloat rotationX; GLfloat rotationY; GLfloat rotationZ; QColor faceColors[4]; QPoint lastPos; }; #endif
tetraheadron.cpp
#include <QtGui> #include <QtOpenGL> #include <GL/glu.h> #include "tetraheadron.h" Tetrahedron::Tetrahedron(QWidget *parent) : QGLWidget(parent) { //指定OpenGL的显示描述表 setFormat(QGLFormat(QGL::DoubleBuffer | QGL::DepthBuffer)); //初始化私有变量 rotationX = -21.0; rotationY = -57.0; rotationZ = 0.0; faceColors[0] = Qt::red; faceColors[1] = Qt::green; faceColors[2] = Qt::blue; faceColors[3] = Qt::yellow; } //在调用paintGL()之前被调用一次.这里设置 //OpenGL的绘图描述表,定义显示列表,以及执行其他的初始化 void Tetrahedron::initializeGL() { qglClearColor(Qt::black); glShadeModel(GL_FLAT); glEnable(GL_DEPTH_TEST); glEnable(GL_CULL_FACE); } //调用initializeGL之后调用resizeGL()函数,窗口部件改变大小时也调用resizeGL() //函数,设置OpenGL视口,投影,以及其他与窗口部件尺寸相关的设置 void Tetrahedron::resizeGL(int width, int height) { glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); GLfloat x = GLfloat(width) / height; glFrustum(-x, +x, -1.0, +1.0, 4.0, 15.0); glMatrixMode(GL_MODELVIEW); } //需要重绘的时候调用 void Tetrahedron::paintGL() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //实际的绘制由私有函数draw()实现 draw(); } //鼠标按下的事件 void Tetrahedron::mousePressEvent(QMouseEvent *event) { lastPos = event->pos(); } //鼠标移动的事件 void Tetrahedron::mouseMoveEvent(QMouseEvent *event) { GLfloat dx = GLfloat(event->x() - lastPos.x()) / width(); GLfloat dy = GLfloat(event->y() - lastPos.y()) / height(); //左键绕X,Y轴 if (event->buttons() & Qt::LeftButton) { rotationX += 180 * dy; rotationY += 180 * dx; updateGL(); } //右键绕X,Z轴 else if (event->buttons() & Qt::RightButton) { rotationX += 180 * dy; rotationZ += 180 * dx; updateGL(); } lastPos = event->pos(); } //双击事件 void Tetrahedron::mouseDoubleClickEvent(QMouseEvent *event) { int face = faceAtPosition(event->pos()); if (face != -1) { QColor color = QColorDialog::getColor(faceColors[face], this); if (color.isValid()) { faceColors[face] = color; updateGL(); } } } //绘制 void Tetrahedron::draw() { static const GLfloat P1[3] = { 0.0, -1.0, +2.0 }; static const GLfloat P2[3] = { +1.73205081, -1.0, -1.0 }; static const GLfloat P3[3] = { -1.73205081, -1.0, -1.0 }; static const GLfloat P4[3] = { 0.0, +2.0, 0.0 }; //四个面 static const GLfloat * const coords[4][3] = { { P1, P2, P3 }, { P1, P3, P4 }, { P1, P4, P2 }, { P2, P4, P3 } }; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glTranslatef(0.0, 0.0, -10.0); //设置旋转 glRotatef(rotationX, 1.0, 0.0, 0.0); glRotatef(rotationY, 0.0, 1.0, 0.0); glRotatef(rotationZ, 0.0, 0.0, 1.0); //设置颜色 for (int i = 0; i < 4; ++i) { glLoadName(i); glBegin(GL_TRIANGLES); qglColor(faceColors[i]); for (int j = 0; j < 3; ++j) { glVertex3f(coords[i][j][0], coords[i][j][1], coords[i][j][2]); } glEnd(); } } //返回窗口部件某位置所在的面的编号 int Tetrahedron::faceAtPosition(const QPoint &pos) { const int MaxSize = 512; GLuint buffer[MaxSize]; GLint viewport[4]; makeCurrent(); glGetIntegerv(GL_VIEWPORT, viewport); glSelectBuffer(MaxSize, buffer); glRenderMode(GL_SELECT); glInitNames(); glPushName(0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluPickMatrix(GLdouble(pos.x()),GLdouble(viewport[3] - pos.y()),5.0,5.0,viewport); GLfloat x = GLfloat(width()) / height(); glFrustum(-x, x, -1.0, 1.0, 4.0, 15.0); draw(); glMatrixMode(GL_PROJECTION); glPopMatrix(); if (!glRenderMode(GL_RENDER)) return -1; return buffer[3]; }