日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

opengl 如何加阴影_OpenGL + Qt: 3 - 旋转动画和键盘操纵

發布時間:2024/7/19 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opengl 如何加阴影_OpenGL + Qt: 3 - 旋转动画和键盘操纵 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前三篇鏈接:

OpenGL + Qt: 0 - 三角形繪制

OpenGL + Qt: 1 - 用下拉框選顏色

OpenGL + Qt: 2 - 走向3D,畫正四面體

這一周筆者經歷了漫長的洲際飛行和昏天黑地的倒時差,所以本篇內容相對少一些,側重 Qt 而不是 OpenGL。在上一篇中,我們繪制了一個正四面體,然而正四面體的一個特點是無論你從哪個角度看,同時至多只能看到三個面。為了能更好地觀察繪制效果,我們嘗試變換觀察的鏡頭位置來看被隱藏的面。這一篇中我們將實現動畫效果,通過不斷旋轉被觀察的四面體來看到它的四個面。同時我們再通過鍵盤操控相機位置,從而更好地展示不同相機位置導致的繪制效果變化。

QElapsedTimer 計時

如果要做動畫效果,首先我們需要知道程序運行到了什么時間,然后根據時間計算出此時的圖像信息,從而進行渲染。不同的操作系統和平臺有各種各樣的計時 API,但是 Qt 提供了一個簡單方便的工具 QElapsedTimer 來完成這件事。其功能非常簡單,就是給出從它的 start() 方法執行之后到現在經過了多久的時間。

首先我們先在 PaintingWidget 的聲明中添加這個東西,然后在構造函數中初始化它,并啟動它。已有的代碼我這里直接忽略,請參考前面幾篇文章。

class PaintingWidget : public QOpenGLWidget {...... private:......QElapsedTimer *m_timer; };PaintingWidget::PaintingWidget(QWidget* parent){......m_timer = new QElapsedTimer;m_timer->start(); }

接下來在 paintGL() 中,我們只需要調用 m_timer->elapsed() 就可以得到從 start() 到繪圖程序執行時刻,經過了多少時間,單位為毫秒。

旋轉矩陣

對于一個剛體而言,我們知道其旋轉變換是一個線性變換,通過一個旋轉矩陣確定。在二維中,圖形的旋轉是圍繞著一個點進行的。眾所周知,二維圖形圍繞原點旋轉

角的旋轉矩陣是

但是在三維世界里,旋轉變得復雜很多,旋轉中心不再是一個點,而是一個軸??紤]到圖形學中常用的是齊次坐標系,還需要處理第四維的情況。不過 Qt 的 QMatrix4x4 提供了簡單的接口幫我們完成這些復雜的數學計算:

void QMatrix4x4::rotate(float angle, const QVector3D &vector);

rotate()函數的第一個參數是旋轉的角度,以度數,為單位,而第二個參數是旋轉軸,必須以 QVector3D 類型傳入。我們在上一篇提到過,MVP矩陣是 P * V * M,物體本身的旋轉、放縮等變換就是編碼在 M 矩陣中,因此我們在繪圖函數中計算 MVP 矩陣的地方,添加旋轉代碼:

void PaintingWidget::paintGL() {QOpenGLFunctions *f = this->context()->functions();f->glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);f->glClearColor(0.0f, 0.2f, 0.0f, 1.0f);m_vao->bind();m_shader->bind();QMatrix4x4 mvp;mvp.perspective(45.0f, this->aspectRatio, 0.1f, 100.0f);mvp.lookAt(QVector3D(0.0f, 3.0f, 0.0f), QVector3D(0.0f, 0.0f, 0.0f), QVector3D(1.0f, 0.0f, 0.0f));float time_in_second = (float)m_timer->elapsed() / 1000;mvp.rotate(30.0f * time_in_second, QVector3D(0.7f, 0.5f, 0.2f));m_shader->setUniformValue(m_shader->uniformLocation("MVP"), mvp);f->glDrawArrays(GL_TRIANGLES, 0, 4 * 3);m_shader->release();m_vao->release();this->update(); }

這里我們通過 m_timer 獲得程序開始運行到此刻的時間,然后以每秒 30° 的速度圍繞軸 (0.7, 0.5, 0.2) 進行旋轉。這個軸是我隨便選的,為的是能夠看到四面體的四個面。這段代碼的最后一行調用了 update() 方法。在前面我們提到過,這個方法是發出一個繪圖請求,但并不立即執行,而是等到下一個處理時間節點再執行。另一個要求重新繪圖的方法是 repaint(),這個方法會立即觸發繪圖,但是 repaint() 會調用 paintGL() 來完成繪圖,因此如果在 paintGL() 中調用 repaint() 會導致無窮遞歸而使程序崩潰。

至此,旋轉動畫效果就實現了,效果如下圖。

鍵盤控制相機位置

在大多數 OpenGL 教程中,都會介紹如何使用各種工具庫(如 GLUT)實現用鍵盤和鼠標操縱圖像。這對于 Qt 來說則更是小菜一碟,畢竟 Qt 的老本行就是做用戶界面,有非常完善的各種輸入設備的響應機制。

與一般控件的響應機制不同,Qt 中鍵盤事件的響應機制反倒是很簡單,直接通過重載 QWidget 上的各種事件處理器來實現,并不需要使用信號-槽機制。最基本的鍵盤事件有兩種:key press 和 key release,分別由 QWidget::keyPressEvent() 和 QWidget::keyReleaseEvent() 兩個事件處理方法進行處理。

這里我僅僅簡單實現用方向鍵控制相機的位置。默認情況下,我們的相機位置在四面體正上方(0, 3, 0)的位置,為了簡單起見,我們設置相機觀察的中心點為相機位置到 y=0 平面的投影點,用方向鍵控制前后左右的位置,即相機的 x 坐標和 z 坐標;用正負號鍵控制相機高度。首先我們需要在 PaintingWidget 的聲明部分添加 keyPressEvent() 和相機位置變量 camera_pos:

class PaintingWidget : public QOpenGLWidget {...... protected:......void keyPressEvent(QKeyEvent *keyEvent); private:......QVector3D camera_pos; }

在構造函數中,將相機坐標初始化為默認位置,并且還需要使用 setFocusPolicy() 設置這個 Widget 獲取焦點的方式,從而確保它能夠得到焦點

PaintingWidget::PaintingWidget(QWidget* parent):QOpenGLWidget (parent), camera_pos(0.0f, 3.0f, 0.0f), ......{......setFocusPolicy(Qt::StrongFocus); }

在繪圖的時候,我們需要計算出相機觀察的中心點,同樣取x正方向為上方向。

QVector3D center(camera_pos);center.setY(0);mvp.lookAt(camera_pos, center, QVector3D(1.0f, 0.0f, 0.0f));

這樣在重載 keyPressEvent() 的代碼中,我們就將右方向鍵設置為x坐標加一個量,因為 OpenGL 是一個右手系,右方向鍵就變為z坐標加一個量,最后別忘了請求繪圖,代碼如下:

void PaintingWidget::keyPressEvent(QKeyEvent *keyEvent){switch (keyEvent->key()){case Qt::Key_Right:camera_pos.setZ(camera_pos.z() + 0.1f);break;case Qt::Key_Left:camera_pos.setZ(camera_pos.z() - 0.1f);break;case Qt::Key_Up:camera_pos.setX(camera_pos.x() + 0.1f);break;case Qt::Key_Down:camera_pos.setX(camera_pos.x() - 0.1f);break;case Qt::Key_Plus:camera_pos.setY(camera_pos.y() + 0.1f);break;case Qt::Key_Minus:camera_pos.setY(camera_pos.y() - 0.1f);break;}update(); }

大功告成,現在這個 demo 開始變得豐富起來,我們可以通過鍵盤看到相機在不同位置觀察物體得到的效果,也更有 3D 的感覺了!

本期代碼鏈接:https://github.com/linmx0130/QGLDemo/tree/ch3

總結

以上是生活随笔為你收集整理的opengl 如何加阴影_OpenGL + Qt: 3 - 旋转动画和键盘操纵的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。