zoukankan      html  css  js  c++  java
  • 46.Qt 使用OpenGL绘制立方体

    main.cpp

    #include <QApplication>
    #include <iostream>
    
    #include "vowelcube.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;
        }
    
        VowelCube cube;
        cube.setWindowTitle(QObject::tr("Vowel Cube"));
        cube.setMinimumSize(200, 200);
        cube.resize(450, 450);
        cube.show();
    
        return app.exec();
    }

    vowelcube.h

    #ifndef VOWELCUBE_H
    #define VOWELCUBE_H
    
    #include <QGLWidget>
    #include <QRadialGradient>
    
    //使用OpenGL绘制立方体,使用QPainter绘制背景
    //的渐变,接着使用renderText()绘制立方体角上的8个
    //元音字母,最后使用QPainter和QTextDocument绘制图例。
    //用户可以单击并拖动鼠标来旋转立方体,并且可以使用鼠标滚轮进行放大或缩小
    class VowelCube : public QGLWidget
    {
        Q_OBJECT
    
    public:
        VowelCube(QWidget *parent = 0);
        ~VowelCube();
    
    protected:
        void paintEvent(QPaintEvent *event);
        void mousePressEvent(QMouseEvent *event);
        void mouseMoveEvent(QMouseEvent *event);
        void wheelEvent(QWheelEvent *event);
    
    private:
        void createGradient();
        void createGLObject();
        void drawBackground(QPainter *painter);
        void drawCube();
        void drawLegend(QPainter *painter);
    
        GLuint glObject;
        QRadialGradient gradient;
        GLfloat rotationX;
        GLfloat rotationY;
        GLfloat rotationZ;
        GLfloat scaling;
        QPoint lastPos;
    };
    
    #endif

    vowelcube.cpp

      1 #include <QtGui>
      2 #include <QtOpenGL>
      3 #include <cmath>
      4 
      5 #ifndef GL_MULTISAMPLE
      6 #define GL_MULTISAMPLE 0x809D
      7 #endif
      8 
      9 #include "vowelcube.h"
     10 
     11 VowelCube::VowelCube(QWidget *parent)
     12     : QGLWidget(parent)
     13 {
     14     //调用setFormat()使OpenGL的显示描述表支持饭走样。
     15     setFormat(QGLFormat(QGL::SampleBuffers));
     16 
     17     //初始化私有变量
     18     rotationX = -38.0;
     19     rotationY = -58.0;
     20     rotationZ = 0.0;
     21     scaling = 1.0;
     22 
     23     //设置填充背景的QRadialGradient
     24     createGradient();
     25     //创建OpenGL立方体对象
     26     createGLObject();
     27 
     28     setAutoBufferSwap( false );
     29     setAutoFillBackground( false );
     30 }
     31 
     32 VowelCube::~VowelCube()
     33 {
     34     makeCurrent();
     35     //删除构造函数创建的OpenGL立方体对象
     36     glDeleteLists(glObject, 1);
     37 }
     38 
     39 //绘制,在paintEvent()中创建一个QPainter,在进行纯OpenGL操作时
     40 //保存和恢复其状态。
     41 //QPainter的构造函数(或者QPainter::begin())自动调用glClear
     42 //除非预先调用窗口部件的setAutoFillBackground(false)
     43 //QPainter的析构函数(或者QPainter::end())自动调用QGLWidget::swapBuffers()
     44 //切换可见缓存和离屏缓存,除非预先调用setAutoBufferSwap(false).
     45 //当QPainter被激活,我们可以交叉使用纯OpenGL命令,只要在执行纯OpenGL命令之前保存OpenGL状态,之后恢复OpenGL状态
     46 void VowelCube::paintEvent(QPaintEvent * /* event */)
     47 {
     48     QPainter painter( this );
     49     //绘制背景
     50     drawBackground( &painter );
     51     //背景绘制结束
     52     painter.end( );
     53     //绘制立方体
     54     drawCube();
     55     //绘制开始
     56     painter.begin(this);
     57     //使用HTML文字设置QTextDocument对象
     58     drawLegend(&painter);
     59     painter.end( );
     60     swapBuffers( );
     61 }
     62 
     63 //鼠标按下事件
     64 void VowelCube::mousePressEvent(QMouseEvent *event)
     65 {
     66     lastPos = event->pos();
     67 }
     68 
     69 //鼠标移动事件
     70 void VowelCube::mouseMoveEvent(QMouseEvent *event)
     71 {
     72     GLfloat dx = GLfloat(event->x() - lastPos.x()) / width();
     73     GLfloat dy = GLfloat(event->y() - lastPos.y()) / height();
     74 
     75     if (event->buttons() & Qt::LeftButton) {
     76         rotationX += 180 * dy;
     77         rotationY += 180 * dx;
     78         update();
     79     } else if (event->buttons() & Qt::RightButton) {
     80         rotationX += 180 * dy;
     81         rotationZ += 180 * dx;
     82         update();
     83     }
     84     lastPos = event->pos();
     85 }
     86 
     87 //鼠标滚动的事件,调用update
     88 void VowelCube::wheelEvent(QWheelEvent *event)
     89 {
     90     double numDegrees = -event->delta() / 8.0;
     91     double numSteps = numDegrees / 15.0;
     92     scaling *= std::pow(1.125, numSteps);
     93     update();
     94 }
     95 
     96 //使用蓝色渐变色设置QRadialGradient
     97 void VowelCube::createGradient()
     98 {
     99     //确保指定的中心和焦点坐标根据窗口部件大小进行调整
    100     gradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    101     //位置用0和1之间的浮点数表示,0对应焦点坐标,1对应圆的边缘
    102     gradient.setCenter(0.45, 0.50);
    103     gradient.setFocalPoint(0.40, 0.45);
    104     gradient.setColorAt(0.0, QColor(105, 146, 182));
    105     gradient.setColorAt(0.4, QColor(81, 113, 150));
    106     gradient.setColorAt(0.8, QColor(16, 56, 121));
    107 }
    108 
    109 //创建OpenGL列表,该列表保存绘制的立方体的边。
    110 void VowelCube::createGLObject()
    111 {
    112     makeCurrent();
    113 
    114     glShadeModel(GL_FLAT);
    115 
    116     glObject = glGenLists(1);
    117     glNewList(glObject, GL_COMPILE);
    118     qglColor(QColor(255, 239, 191));
    119     glLineWidth(1.0);
    120 
    121     glBegin(GL_LINES);
    122     glVertex3f(+1.0, +1.0, -1.0);
    123     glVertex3f(-1.0, +1.0, -1.0);
    124     glVertex3f(+1.0, -1.0, -1.0);
    125     glVertex3f(-1.0, -1.0, -1.0);
    126     glVertex3f(+1.0, -1.0, +1.0);
    127     glVertex3f(-1.0, -1.0, +1.0);
    128     glEnd();
    129 
    130     glBegin(GL_LINE_LOOP);
    131     glVertex3f(+1.0, +1.0, +1.0);
    132     glVertex3f(+1.0, +1.0, -1.0);
    133     glVertex3f(+1.0, -1.0, -1.0);
    134     glVertex3f(+1.0, -1.0, +1.0);
    135     glVertex3f(+1.0, +1.0, +1.0);
    136     glVertex3f(-1.0, +1.0, +1.0);
    137     glVertex3f(-1.0, +1.0, -1.0);
    138     glVertex3f(-1.0, -1.0, -1.0);
    139     glVertex3f(-1.0, -1.0, +1.0);
    140     glVertex3f(-1.0, +1.0, +1.0);
    141     glEnd();
    142 
    143     glEndList();
    144 }
    145 
    146 void VowelCube::drawBackground(QPainter *painter)
    147 {
    148     painter->setPen(Qt::NoPen);
    149     painter->setBrush(gradient);
    150     painter->drawRect(rect());
    151 }
    152 
    153 //绘制立方体
    154 void VowelCube::drawCube()
    155 {
    156     glPushAttrib(GL_ALL_ATTRIB_BITS);
    157 
    158     glMatrixMode(GL_PROJECTION);
    159     glPushMatrix();
    160     glLoadIdentity();
    161     GLfloat x = 3.0 * GLfloat(width()) / height();
    162     glOrtho(-x, +x, -3.0, +3.0, 4.0, 15.0);
    163 
    164     glMatrixMode(GL_MODELVIEW);
    165     glPushMatrix();
    166     glLoadIdentity();
    167     glTranslatef(0.0, 0.0, -10.0);
    168     glScalef(scaling, scaling, scaling);
    169 
    170     glRotatef(rotationX, 1.0, 0.0, 0.0);
    171     glRotatef(rotationY, 0.0, 1.0, 0.0);
    172     glRotatef(rotationZ, 0.0, 0.0, 1.0);
    173 
    174     //设置反走样
    175     glEnable(GL_MULTISAMPLE);
    176 
    177     //绘制立方体
    178     glCallList(glObject);
    179 
    180     //设置文字颜色和字体
    181     setFont(QFont("Times", 24));
    182     qglColor(QColor(255, 223, 127));
    183 
    184     //绘制字符,renderText使文字不变形
    185     renderText(+1.1, +1.1, +1.1, QChar('a'));
    186     renderText(-1.1, +1.1, +1.1, QChar('e'));
    187     renderText(+1.1, +1.1, -1.1, QChar('o'));
    188     renderText(-1.1, +1.1, -1.1, QChar(0x00F6));
    189     renderText(+1.1, -1.1, +1.1, QChar(0x0131));
    190     renderText(-1.1, -1.1, +1.1, QChar('i'));
    191     renderText(+1.1, -1.1, -1.1, QChar('u'));
    192     renderText(-1.1, -1.1, -1.1, QChar(0x00FC));
    193 
    194     glMatrixMode(GL_MODELVIEW);
    195     glPopMatrix();
    196 
    197     glMatrixMode(GL_PROJECTION);
    198     glPopMatrix();
    199 
    200     glPopAttrib();
    201 }
    202 
    203 
    204 //使用HTML文字设置QTextDocument对象,在半透明的蓝色矩形上绘制它们
    205 void VowelCube::drawLegend(QPainter *painter)
    206 {
    207     const int Margin = 11;
    208     const int Padding = 6;
    209 
    210     QTextDocument textDocument;
    211     textDocument.setDefaultStyleSheet("* { color: #FFEFEF }");
    212     textDocument.setHtml("<h4 align="center">Vowel Categories</h4>"
    213                          "<p align="center"><table width="100%">"
    214                          "<tr><td>Open:<td>a<td>e<td>o<td>&ouml;"
    215                          "<tr><td>Close:<td>&#305;<td>i<td>u<td>&uuml;"
    216                          "<tr><td>Front:<td>e<td>i<td>&ouml;<td>&uuml;"
    217                          "<tr><td>Back:<td>a<td>&#305;<td>o<td>u"
    218                          "<tr><td>Round:<td>o<td>&ouml;<td>u<td>&uuml;"
    219                          "<tr><td>Unround:<td>a<td>e<td>&#305;<td>i"
    220                          "</table>");
    221     textDocument.setTextWidth(textDocument.size().width());
    222 
    223     QRect rect(QPoint(0, 0), textDocument.size().toSize()
    224                              + QSize(2 * Padding, 2 * Padding));
    225     painter->translate(width() - rect.width() - Margin,
    226                        height() - rect.height() - Margin);
    227     painter->setPen(QColor(255, 239, 239));
    228     painter->setBrush(QColor(255, 0, 0, 31));
    229     painter->drawRect(rect);
    230 
    231     painter->translate(Padding, Padding);
    232     textDocument.drawContents(painter);
    233 }
  • 相关阅读:
    WPF数据爬取小工具-某宝推广位批量生成,及订单爬取 记:接单最痛一次的感悟
    .net core2.1
    Ng Alain使用
    MediatR
    RN错误随笔
    【转载】DDD分层架构的三种模式
    1.RN环境搭建,创建项目,使用夜神模拟调试
    ExtJs4 笔记(2) ExtJs对js基本语法扩展支持
    ExtJs4 笔记(1) ExtJs大比拼JQuery:Dom文档操作
    vue的父子通信
  • 原文地址:https://www.cnblogs.com/xiaochi/p/9033712.html
Copyright © 2011-2022 走看看