• 45.Qt openGL实现三维绘图


    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];
    }
  • 相关阅读:
    phpcms新建模板页教程
    Linux方向职业规划
    Codeforces Round #417 (Div. 2)-A. Sagheer and Crossroad
    Codeforces Round #396(Div. 2) A. Mahmoud and Longest Uncommon Subsequence
    ACM hdu 3336 Count the string
    ACM KMP 格式输入导致TLE
    swing JTable 更新数据
    swing JTable
    HashMap 和 HashTable 区别
    Java中next()和nextLine()
  • 原文地址:https://www.cnblogs.com/xiaochi/p/9032963.html
Copyright © 2020-2023  润新知