Qt OpenGL 旋轉
這次教程中,我們將在第03課的基礎上,教大家如何旋轉三角形和四邊形。我們將讓三角形沿y軸旋轉,四邊形沿x軸旋轉,最終我們能得到一個三角形和四邊形自動旋轉的場景。
程式執行時效果如下:
下面進入教程:
首先開啟myglwidget.h檔案,我們需要增加兩個變數來控制這兩個物件的旋轉。這兩個變數加在類的私有宣告處,將類宣告更改如下:
1 #ifndef MYGLWIDGET_H
2 #define MYGLWIDGET_H
3
4 #include <QWidget>
5 #include <QGLWidget>
6
7 class MyGLWidget : public QGLWidget
8 {
9 Q_OBJECT
10 public:
11 explicit MyGLWidget(QWidget *parent = 0);
12 ~MyGLWidget();
13
14 protected:
15 //對3個純虛擬函式的重定義
16 void initializeGL();
17 void resizeGL(int w, int h);
18 void paintGL();
19
20 void keyPressEvent(QKeyEvent *event); //處理鍵盤按下事件
21
22 private:
23 bool fullscreen; //是否全屏顯示
24
25 GLfloat m_rtri; //控制三角形的角度
26 GLfloat m_rquad; //控制四邊形的角度
27 };
28
29 #endif // MYGLWIDGET_H
我們增加了兩個浮點型別的變數,使得我們能夠非常精確地旋轉物件,你漸漸會發現浮點數是OpenGL程式設計的基礎。新變數中叫做m_rtri的用來旋轉三角形,m_rquad旋轉四邊形。
接下來,我們需要開啟myglwidget.cpp,在建構函式中對兩個新變數進行初始化,這部分很簡單,不作過多解釋,程式碼如下:
1 MyGLWidget::MyGLWidget(QWidget *parent) :
2 QGLWidget(parent)
3 {
4 fullscreen = false;
5 m_rtri = 0.0f;
6 m_rquad = 0.0f;
7 }
然後進入重點的paintGL()函數了,我們只需在第03課程式碼的基礎上,做一定的修改,就能實現三角形和四邊形的旋轉了。
下面我將重寫整個paintGL()函式,具體程式碼如下:
1 void MyGLWidget::paintGL() //從這裡開始進行所以的繪製
2 {
3 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除螢幕和深度快取
4 glLoadIdentity(); //重置當前的模型觀察矩陣
5
6 glTranslatef(-1.5f, 0.0f, -6.0f); //左移1.5單位,並移入螢幕6.0單位
7 glRotatef(m_rtri, 0.0f, 1.0f, 0.0f); //繞y軸旋轉三角形
8 glBegin(GL_TRIANGLES); //開始繪製三角形
9 glColor3f(1.0f, 0.0f, 0.0f); //設定當前色為紅色
10 glVertex3f(0.0f, 1.0f, 0.0f); //上頂點
11 glColor3f(0.0f, 1.0f, 0.0f); //設定當前色為綠色
12 glVertex3f(-1.0f, -1.0f, 0.0f); //左下
13 glColor3f(0.0f, 0.0f, 1.0f); //設定當前色為藍色
14 glVertex3f(1.0f, -1.0f, 0.0f); //右下
15 glEnd(); //三角形繪製結束
16
17 glLoadIdentity(); //重置模型觀察矩陣
18 glTranslatef(1.5f, 0.0f, -6.0f); //右移1.5單位,並移入螢幕6.0單位
19 glRotatef(m_rquad, 1.0f, 0.0f, 0.0f); //繞x軸旋轉四邊形
20 glColor3f(0.5f, 0.5f, 1.0f); //一次性將當前色設定為藍色
21 glBegin(GL_QUADS); //開始繪製四邊形
22 glVertex3f(-1.0f, 1.0f, 0.0f); //左上
23 glVertex3f(1.0f, 1.0f, 0.0f); //右上
24 glVertex3f(1.0f, -1.0f, 0.0f); //左下
25 glVertex3f(-1.0f, -1.0f, 0.0f); //右下
26 glEnd(); //四邊形繪製結束
27
28 m_rtri += 0.5f; //增加三角形的旋轉變數
29 m_rquad -= 0.5f; //減少四邊形的旋轉變數
30 }
上面的程式碼繪製三角形時多了一新函式glRotatef(Angle, Xvector, Yvector, Zvector)。該函式負責讓物件繞某個軸旋轉,這個函式有諸多用處。Angle通常是個變數代表物件轉過的角度,後三個引數則共同決定旋轉軸的方向。故(1.0f, 0.0f, 0.0f)、(0.0f, 1.0f, 0.0f)、(0.0f, 0.0f, 1.0f)表示依次繞x、y、z軸旋轉,參照此原理,我們也能實現四邊形的旋轉。
我們會發現畫完三角形後,相比原來的程式碼多了一行glLoadIdentity(),目的是為了重置模型觀察矩陣。如果我們沒有重置,直接呼叫glTranslate的話,會發現可能沒有朝著我們所希望的方向旋轉,這是由於座標軸以前已經旋轉了。所以我們本來要左右移動物件的,可能就變成上下移動了。還不理解的朋友可以試著將glLoadIdentity()試註釋掉之後,看會出現什麼結果。
重置模型觀察矩陣之後,x、y、z軸都復位,我們呼叫glTranslate時只向右移動了1.5單位,而不是之前的3.0單位。因為我們重置場景的時候,焦點又回到了場景的中心,這樣只需右移單位即可。
最後我們通過增加m_rtri和減少m_rquad使得物體自己旋轉起來,我們可以嘗試改變程式碼中的+和-,來體會物件旋轉的方向是如何改變的。並嘗試著將0.5改成4.0,。這個數字越大,物體就轉得越快,這個數字越小,物體轉的就越慢。
至此,我們似乎已經完成了,但是執行程式時發現,三角形和四邊形並沒有自動旋轉起來。這是由於paintGL()被呼叫一次之後,沒有發生其他的事件使得它被自動呼叫。我們可以通過拉伸視窗的大小,發現三角形和四邊形就動起來了,這是由於我們改變了視窗大小,呼叫了reszieGL()之後緊接著呼叫了paintGL()對場景進行重繪。顯然,我們不能一直通過拉伸視窗來實現旋轉,這樣顯得很拙,我們可以在建構函式中利用Qt的定時器事件來控制paintGL()的呼叫。先在myglwidget.cpp中新增標頭檔案#include <QTimer>。建構函式程式碼如下:(具體initializeGL()、reszieGL()、paintGL()的呼叫情況請參見)
1 MyGLWidget::MyGLWidget(QWidget *parent) :
2 QGLWidget(parent)
3 {
4 fullscreen = false;
5 m_rtri = 0.0f;
6 m_rquad = 0.0f;
7
8 QTimer *timer = new QTimer(this); //建立一個定時器
9 //將定時器的計時訊號與updateGL()繫結
10 connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
11 timer->start(10); //以10ms為一個計時週期
12 }
這裡將定時器的timeout()訊號與updateGL()槽繫結,每過10ms就會呼叫一次updateGL(),而updateGL()呼叫後會呼叫paintGL()對場景進行重繪,這樣就通過對場景不停地重繪實現物件的旋轉。(對Qt定時器不瞭解的朋友請先百度瞭解下其機制)
現在就可以執行程式看效果了!