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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM