【Qt OpenGL教程】04:旋轉
第04課:旋轉 (參照NeHe)
這次教程中,我們將在第03課的基礎上,教大家如何旋轉三角形和四邊形。我們將讓三角形沿y軸旋轉,四邊形沿x軸旋轉,最終我們能得到一個三角形和四邊形自動旋轉的場景。
程式執行時效果如下:
下面進入教程:
首先開啟myglwidget.h檔案,我們需要增加兩個變數來控制這兩個物件的旋轉。這兩個變數加在類的私有宣告處,將類宣告更改如下:
我們增加了兩個浮點型別的變數,使得我們能夠非常精確地旋轉物件,你漸漸會發現浮點數是OpenGL程式設計的基礎。新變數中叫做m_rtri的用來旋轉三角形,m_rquad旋轉四邊形。#ifndef MYGLWIDGET_H #define MYGLWIDGET_H #include <QWidget> #include <QGLWidget> class MyGLWidget : public QGLWidget { Q_OBJECT public: explicit MyGLWidget(QWidget *parent = 0); ~MyGLWidget(); protected: //對3個純虛擬函式的重定義 void initializeGL(); void resizeGL(int w, int h); void paintGL(); void keyPressEvent(QKeyEvent *event); //處理鍵盤按下事件 private: bool fullscreen; //是否全屏顯示 GLfloat m_rtri; //控制三角形的角度 GLfloat m_rquad; //控制四邊形的角度 }; #endif // MYGLWIDGET_H
接下來,我們需要開啟myglwidget.cpp,在建構函式中對兩個新變數進行初始化,這部分很簡單,不作過多解釋,程式碼如下:
MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{
fullscreen = false;
m_rtri = 0.0f;
m_rquad = 0.0f;
}
然後進入重點的paintGL()函數了,我們只需在第03課程式碼的基礎上,做一定的修改,就能實現三角形和四邊形的旋轉了。
下面我將重寫整個paintGL()函式,具體程式碼如下:
上面的程式碼繪製三角形時多了一新函式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軸旋轉,參照此原理,我們也能實現四邊形的旋轉。void MyGLWidget::paintGL() //從這裡開始進行所以的繪製 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除螢幕和深度快取 glLoadIdentity(); //重置當前的模型觀察矩陣 glTranslatef(-1.5f, 0.0f, -6.0f); //左移1.5單位,並移入螢幕6.0單位 glRotatef(m_rtri, 0.0f, 1.0f, 0.0f); //繞y軸旋轉三角形 glBegin(GL_TRIANGLES); //開始繪製三角形 glColor3f(1.0f, 0.0f, 0.0f); //設定當前色為紅色 glVertex3f(0.0f, 1.0f, 0.0f); //上頂點 glColor3f(0.0f, 1.0f, 0.0f); //設定當前色為綠色 glVertex3f(-1.0f, -1.0f, 0.0f); //左下 glColor3f(0.0f, 0.0f, 1.0f); //設定當前色為藍色 glVertex3f(1.0f, -1.0f, 0.0f); //右下 glEnd(); //三角形繪製結束 glLoadIdentity(); //重置模型觀察矩陣 glTranslatef(1.5f, 0.0f, -6.0f); //右移1.5單位,並移入螢幕6.0單位 glRotatef(m_rquad, 1.0f, 0.0f, 0.0f); //繞x軸旋轉四邊形 glColor3f(0.5f, 0.5f, 1.0f); //一次性將當前色設定為藍色 glBegin(GL_QUADS); //開始繪製四邊形 glVertex3f(-1.0f, 1.0f, 0.0f); //左上 glVertex3f(1.0f, 1.0f, 0.0f); //右上 glVertex3f(1.0f, -1.0f, 0.0f); //左下 glVertex3f(-1.0f, -1.0f, 0.0f); //右下 glEnd(); //四邊形繪製結束 m_rtri += 0.5f; //增加三角形的旋轉變數 m_rquad -= 0.5f; //減少四邊形的旋轉變數 }
我們會發現畫完三角形後,相比原來的程式碼多了一行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()的呼叫情況請參見)
MyGLWidget::MyGLWidget(QWidget *parent) :
QGLWidget(parent)
{
fullscreen = false;
m_rtri = 0.0f;
m_rquad = 0.0f;
QTimer *timer = new QTimer(this); //建立一個定時器
//將定時器的計時訊號與updateGL()繫結
connect(timer, SIGNAL(timeout()), this, SLOT(updateGL()));
timer->start(10); //以10ms為一個計時週期
}
這裡將定時器的timeout()訊號與updateGL()槽繫結,每過10ms就會呼叫一次updateGL(),而updateGL()呼叫後會呼叫paintGL()對場景進行重繪,這樣就通過對場景不停地重繪實現物件的旋轉。(對Qt定時器不瞭解的朋友請先百度瞭解下其機制)現在就可以執行程式看效果了!
相關推薦
【Qt OpenGL教程】04:旋轉
第04課:旋轉 (參照NeHe) 這次教程中,我們將在第03課的基礎上,教大家如何旋轉三角形和四邊形。我們將讓三角形沿y軸旋轉,四邊形沿x軸旋轉,最終我們能得到一個三角形和四邊形自動旋轉的場景。 程式執行時效果如下: 下面進入教程: 首先開啟myglwidget.h
【Qt OpenGL教程】25:變形和從檔案中載入3D物體
第25課:變形和從檔案中載入3D物體 (參照NeHe) 這次教程中,我們將學會如何從檔案中載入3D模型,並且平滑的從一個模型變形為另一個模型。在這一課裡,我們將介紹如何實現模型的變形過程,這將會是效果很棒的一課! 程式執行時效果如下: 下面進入教程: 我們這次將在第
【Qt OpenGL教程】08:混合
第08課:混合 (參照NeHe) 這次教程中,我們將在紋理對映的基礎上加上混合,使它看起來具有透明的效果,當然解釋它不是那麼容易但程式碼並不難,希望你喜歡它。 OpenGL中的絕大多數特效都與某些型別的(色彩)混合有關。混色的定義為,將某個畫素的顏色和已繪製在螢幕上與其對應
【Qt OpenGL教程】06:紋理對映
void MyGLWidget::paintGL() //從這裡開始進行所以的繪製 { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //清除螢幕和深度快取 glLoadIden
【Qt OpenGL教程】01:建立一個OpenGL視窗
void MyGLWidget::resizeGL(int w, int h) //重置OpenGL視窗的大小 { glViewport(0, 0, (GLint)w, (GLint)h); //重置當前的視口 glMatrixMod
【Qt OpenGL教程】29:Blitter函式
第29課:Blitter函式 (參照NeHe) 這次教程中,我們將介紹類似於DirectDraw的blit(其實blit函式在許多繪相簿都有),我們將用程式碼自己來實現它。它的作用非常簡單,就是把一塊紋理的貼到另一塊紋理上。想想,有了這個函式,我們就可以自由拼接紋理了,是不
【Qt OpenGL教程】28:貝塞爾曲面
第28課:貝塞爾曲面 (參照NeHe) 這次教程中,我們將介紹貝塞爾曲面,因此這是關於數學運算的一課(這導致很不好講),來吧,相信你能搞定它的!這一課中,我們並不是要做一個完整的貝塞爾曲面庫(庫的話OpenGL已經完成了),而是一個展示概念的程式,來讓你熟悉曲面是怎麼計算實
Django2.0:【Django2.0教程】04.使用模版顯示內容 視訊學習筆記
檢視文章頁面:唯一標示id article/migrations/0001_initial.py的內容如下: # Generated by Django 2.0.5 on 2018-05-11 06:54 from django.db import m
【Qt OpenGL】Qt Creator中的3D繪圖及動畫教程
Qt Creator中的3D繪圖及動畫教程(參照NeHe) 剛剛學習了Qt Creator,發現Qt提供了QtOpenGL模組,對OpenGL做了不錯的封裝,這使得我們可以很輕鬆地在Qt程式中使用OpenGL進行繪圖渲染。雖然裡面還是由不少專業的解釋照搬原文的,但還是加入了
【Unity3D基礎教程】給初學者看的Unity教程(零):如何學習Unity3D
cos 詳解 component lock index unity3d遊戲 design 技術棧 log 【Unity3D基礎教程】給初學者看的Unity教程(零):如何學習Unity3D http://www.cnblogs.com/neverdie/p/How_To_
【BBC micro:bit基礎教程】04-micro:bit讀取光敏電阻
www. inf 訪問 主板 bit 讀取 藍色 電路 問題 【所需材料】 BBC micro:bit 主板 x 1 Micro USB 線 x 1 能容納2節7號(AAA)電池的電池盒 x 1 7號(AAA)電池 x 2 光敏電阻 x 1 10kΩ 電阻 x 1 鱷
【Qt學習筆記】在Qt編譯好之後執行程式時提示:程式異常結束。The process was ended forcefully. ....exe crashed.
最近在Qt結合imagingsource相機使用時編譯能夠通過,但是一直無法執行出現如下提示 此時進入Debug模式也無法進入一直提示出錯,在網上搜尋了很多資料一般的結論是少了一些配置,後來順著這個思路,折騰了兩三天發現是沒有加入DLL。因為其他的工業相機一般安裝sdk的
【Unity3D基礎教程】給初學者看的Unity教程(六):理解Unity的新GUI系統(UGUI)
理解UGUI的基礎架構 UGUI是Unity在4.6中引入的新的GUI系統,與傳統的中介軟體NGUI相比,這套新GUI系統有幾個核心亮點: 放棄了Atlas的概念,使用Packing Tag的方式來進行圖集的規劃 放棄了depth來確定UI顯示層級的概念,使用Hierarchy的SiblingIndex
【Unity3D基礎教程】給初學者看的Unity教程(二):所有指令碼元件的基類 -- MonoBehaviour的前世今生
引子 上一次我們講了GameObject,Compoent,Time,Input,Physics,其中Time,Input,Physics都是Unity中的全域性變數。GameObject是遊戲中的基本物件。GameObject是由Component組合而成的,GameObject本身必須有
【Unity3D基礎教程】給初學者看的Unity教程(五):詳解Unity3D中的協程(Coroutine)
為什麼需要協程 在遊戲中有許多過程(Process)需要花費多個邏輯幀去計算。 你會遇到“密集”的流程,比如說尋路,尋路計算量非常大,所以我們通常會把它分割到不同的邏輯幀去進行計算,以免影響遊戲的幀率。 你會遇到“稀疏”的流程,比如說遊戲中的觸發器,這種觸發器大多數時候什麼也不做,但
【Unity3D基礎教程】給初學者看的Unity教程(三):通過製作Flappy Bird瞭解Native 2D中的Sprite,Animation
引子 上一次我們講了MonoBehaviour的前世今生,瞭解了遊戲中的每一個GameObjec都是由指令碼控制的,這一次我們開始將Unity中Native 2D中的Sprite,並且使用Animation來讓Sprite動起來。 在接下來的幾篇部落格裡,我會通過做一個Flappy Bird來講解
【Unity3D基礎教程】給初學者看的Unity教程(四):通過製作Flappy Bird瞭解Native 2D中的RigidBody2D和Collider2D
引子 認識RigidBody 當RigidBody2D的質量屬性被設定為0時,剛體的質量變為無限大,此時剛體相當於靜態剛體,永遠一動不動。但是在Unity中你是無法把一個RigidBody2D的質量設定為0的,所以,當你想建立一個靜態剛體時,只需要建立碰撞器,而不需要建立RigidBo
【Unity3D基礎教程】給初學者看的Unity教程(七):在Unity中構建健壯的單例模式(Singleton)
該部落格中的程式碼均出自我的開源專案 : 迷你微信 為什麼需要單例模式 遊戲中需要單例有以下幾個原因: 我們需要在遊戲開始前和結束前做一些操作,比如網路的連結和斷開,資源的載入和解除安裝,我們一般會把這部分邏輯放在單例裡。 單例可以控制初始化和銷燬順序,而靜態變數和場景中的GameObject都無法控制
【Unity3D基礎教程】給初學者看的Unity教程(一):GameObject,Compoent,Time,Input,Physics
Unity3D重要模組的類圖 最近剛剛完成了一個我個人比較滿意的小專案:【深入Cocos2d-x】使用MVC架構搭建遊戲Four,在這個遊戲中,我使用了自己搭建的MVC架構來製作一個遊戲,做到了比較好的SoC(關注點分離)。但是苦於Cocos2d-x沒有一個比較完善的編輯器,所以我開始學習另一個非常流行
Django2.0:【Django2.0教程】02.入門儀式:Hello World 視訊學習筆記
進入到需要放置專案的路徑,使用如下命令建立專案: $ django-admin startproject mysite 這裡,mysite為專案名稱,也可以是其他的名字。進入到mysite目錄之後,可以看到目錄結構如下: . ├── mana