Qt配置OpenGL相機踩的坑

項目根據LearnOpenGL配置Qt的相機,更新view矩陣和project矩陣的位移向量變得很大,我設置的明明相機位置是(0,0,3),理想的位移向量剛好是相反數(0,0,-3),對應的view矩陣位置向量可以變成(0,0,1200)…離模型非常遠矩陣模型也看不見:

#include "UI/RobotView.h"
#include <QtCore/QtGlobal>
#include <QtCore/QFile>
#include <QtCore/QDebug>
#include <QtGui/QMouseEvent>
#include <QtGui/QWheelEvent>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLBuffer>
#include <QtGui/QOpenGLVertexArrayObject>
#include <QtGui/QMatrix4x4>
#include <QtGui/QVector3D>
#include <QtWidgets/QOpenGLWidget>
#include <QElapsedTimer>
#include <QtMath>#include <urdf_model/model.h>
#include <urdf_parser/urdf_parser.h>RobotView::RobotView(QWidget *parent) : QOpenGLWidget(parent),VBO(QOpenGLBuffer::VertexBuffer),model_(nullptr),firstMouse(true),cameraZoom(45.0f),cameraYaw(-90.0f),cameraPitch(0.0f),cameraPosition(0.0f, 0.0f, 3.0f),worldUp(0.0f, 1.0f, 0.0f),cameraFront(0.0f, 0.0f, -1.0f), //*cameraUp(0.0f, 1.0f, 0.0f),mouseSensitivity(0.1f)
{setFocusPolicy(Qt::StrongFocus);frameCount = 0;fps = 0.0f;fpsTimer = new QTimer(this);connect(fpsTimer, &QTimer::timeout, this, [this](){fps = frameCount;frameCount = 0;emit sendFPS(fps); // 發送幀率信號});fpsTimer->start(1000);updateTimer = new QTimer(this);connect(updateTimer, &QTimer::timeout, this, [this](){ update(); });updateTimer->start(16); // 60 FPSmodel_ = new RobotModel();viewMatrix.lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp);projectionMatrix.perspective(cameraZoom, float(width()) / float(height()), 0.01f, 200.0f);if (!model_->loadFromURDF(":/assets/instrument_sim/urdf/instrument_sim.urdf")){qCritical() << "Failed to load URDF file";delete model_;}
}RobotView::~RobotView()
{delete fpsTimer;delete updateTimer;delete model_;fpsTimer = nullptr;updateTimer = nullptr;model_ = nullptr;cleanupGL();
}void RobotView::initializeGL()
{initializeOpenGLFunctions();VAO.create();VBO.create();VAO.bind();VBO.bind();if (!initShaders()){qCritical() << "Failed to initialize shaders";return;}VAO.release();VBO.release();glEnable(GL_DEPTH_TEST);
}void RobotView::resizeGL(int w, int h)
{glViewport(0, 0, w, h);
}void RobotView::paintGL()
{glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);glClearColor(0.2f, 0.3f, 0.3f, 1.0f);shaderProgram.bind();projectionMatrix.perspective(cameraZoom, float(width()) / float(height()), 0.01f, 200.0f);viewMatrix.lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp);// 將矩陣傳遞給著色器shaderProgram.setUniformValue("lightPos", lightPos);shaderProgram.setUniformValue("viewPos", cameraPosition);shaderProgram.setUniformValue("objectColor", objectColor);shaderProgram.setUniformValue("lightColor", lightColor);shaderProgram.setUniformValue("projectionMatrix", projectionMatrix);shaderProgram.setUniformValue("viewMatrix", viewMatrix);VAO.bind();// // Draw robot modelauto &link = model_->getLinks()[1];if (link.visual){VBO.bind();VBO.allocate(link.visual->getVertices(), link.visual->getVerticesSize() * sizeof(float));modelMatrix.setToIdentity();shaderProgram.setUniformValue("modelMatrix", modelMatrix);// Draw trianglesint positionAttribute = shaderProgram.attributeLocation("aPos");shaderProgram.enableAttributeArray(positionAttribute);shaderProgram.setAttributeBuffer(positionAttribute, GL_FLOAT, 0, 3, 6 * sizeof(GLfloat));// 設置頂點屬性int normalAttribute = shaderProgram.attributeLocation("aNormal");shaderProgram.enableAttributeArray(normalAttribute);shaderProgram.setAttributeBuffer(normalAttribute, GL_FLOAT, 3 * sizeof(GLfloat), 3, 6 * sizeof(GLfloat));glDrawArrays(GL_TRIANGLES, 0, link.visual->getVerticesSize() / 6);VBO.release();}VAO.release();shaderProgram.release();frameCount++;
}bool RobotView::initShaders()
{// Load vertex shaderQFile vertShaderFile(":/assets/shaders/phongShader.vert");if (!vertShaderFile.open(QIODevice::ReadOnly | QIODevice::Text)){qCritical() << "Failed to open vertex shader file:" << vertShaderFile.fileName();doneCurrent();return false;}QString vertShaderSource = vertShaderFile.readAll();vertShaderFile.close();// Load fragment shaderQFile fragShaderFile(":/assets/shaders/phongShader.frag");if (!fragShaderFile.open(QIODevice::ReadOnly | QIODevice::Text)){qCritical() << "Failed to open fragment shader file:" << fragShaderFile.fileName();return false;}QString fragShaderSource = fragShaderFile.readAll();fragShaderFile.close();// Compile shadersif (!shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex, vertShaderSource)){qCritical() << "Failed to compile vertex shader:" << shaderProgram.log();return false;}if (!shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment, fragShaderSource)){qCritical() << "Failed to compile fragment shader:" << shaderProgram.log();return false;}// Link shader programif (!shaderProgram.link()){qCritical() << "Failed to link shader program:" << shaderProgram.log();return false;}return true;
}void RobotView::mouseMoveEvent(QMouseEvent *event)
{// update Front, Right and Up Vectors using the updated Euler anglesif (event->buttons() & Qt::LeftButton){float xPos = event->x();float yPos = event->y();if (firstMouse){lastMousePosX = xPos;lastMousePosY = yPos;firstMouse = false;}float xoffset = xPos - lastMousePosX;float yoffset = lastMousePosY - yPos;lastMousePosX = xPos;lastMousePosY = yPos;xoffset *= mouseSensitivity;yoffset *= mouseSensitivity;cameraYaw += xoffset;cameraPitch += yoffset;// make sure that when pitch is out of bounds, screen doesn't get flippedif (cameraPitch > 89.0f)cameraPitch = 89.0f;if (cameraPitch < -89.0f)cameraPitch = -89.0f;QVector3D front;front.setX(cos(qDegreesToRadians(cameraYaw)) * cos(qDegreesToRadians(cameraPitch)));front.setY(sin(qDegreesToRadians(cameraPitch)));front.setZ(sin(qDegreesToRadians(cameraYaw)) * cos(qDegreesToRadians(cameraPitch)));cameraFront = front.normalized();}}void RobotView::cleanupGL()
{makeCurrent();VAO.destroy();VBO.destroy();shaderProgram.removeAllShaders();doneCurrent();
}

解決辦法:

  1. 在每一次使用lookat和perspective函數前都將矩陣置為identity,根據手冊,這兩個函數api和glm不一樣,會一直連乘之前的矩陣,所以調用這個函數api,先得吧矩陣view和project變為單位陣,防止一直連乘跑飛
    在這里插入圖片描述

在這里插入圖片描述

projectionMatrix.setToIdentity();
projectionMatrix.perspective(cameraZoom, float(width()) / float(height()), 0.01f, 200.0f);
viewMatrix.setToIdentity();
viewMatrix.lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp);

加了以后好一點了,但是鼠標拖拽有時候移動到其他位置再拖動,模型會突然跳一下,分析了一下原因是因為鼠標的位置沒有及時更新:

  1. 在構造函數加上鼠標的跟蹤,修改把獲取位置更新上一時刻位置放在if判斷外面:

void RobotView::mouseMoveEvent(QMouseEvent *event)
{// update Front, Right and Up Vectors using the updated Euler anglesfloat xPos = event->x();float yPos = event->y();if (event->buttons() & Qt::LeftButton){if (firstMouse){lastMousePosX = xPos;lastMousePosY = yPos;firstMouse = false;}float xoffset = xPos - lastMousePosX;float yoffset = lastMousePosY - yPos;xoffset *= mouseSensitivity;yoffset *= mouseSensitivity;cameraYaw += xoffset;cameraPitch += yoffset;// make sure that when pitch is out of bounds, screen doesn't get flippedif (cameraPitch > 89.0f)cameraPitch = 89.0f;if (cameraPitch < -89.0f)cameraPitch = -89.0f;QVector3D front;front.setX(cos(qDegreesToRadians(cameraYaw)) * cos(qDegreesToRadians(cameraPitch)));front.setY(sin(qDegreesToRadians(cameraPitch)));front.setZ(sin(qDegreesToRadians(cameraYaw)) * cos(qDegreesToRadians(cameraPitch)));cameraFront = front.normalized();// viewMatrix.setToIdentity();// viewMatrix.lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp);}lastMousePosX = xPos;lastMousePosY = yPos;
}

但是發現還是有問題,貌似mouseMove事件需要按鍵按下才觸發,鼠標的位置沒有得到及時更新,經過查資料,推測可能是沒有開啟鼠標的跟蹤,在構造函數加入下面的語句就可以了

setMouseTracking(true);

調bug還是看看用戶手冊的好

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/72120.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/72120.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/72120.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++設計模式】第十六篇:迭代器模式(Iterator)

注意&#xff1a;復現代碼時&#xff0c;確保 VS2022 使用 C17/20 標準以支持現代特性。 遍歷聚合對象的統一方式 1. 模式定義與用途 核心思想 ?迭代器模式&#xff1a;提供一種方法順序訪問聚合對象的元素&#xff0c;而無需暴露其內部表示。關鍵用途&#xff1a; 1.?統一…

關于WPS的Excel點擊單元格打開別的文檔的兩種方法的探究【為單元格添加超鏈接】

問題需求 目錄和文件結構如下&#xff1a; E:\Dir_Level1 │ Level1.txt │ └─Dir_Level2│ Level2.txt│ master.xlsx│└─Dir_Level3Level3.txt現在要在master.xlsx點擊單元格進而訪問Level1.txt、Level2.txt、Level3.txt這些文件。 方法一&#xff1a;“單元格右鍵…

聚類中的相似矩陣和拉普拉斯矩陣

前言&#xff08;可以略過&#xff09; 最近在看的是關于聚類的論文&#xff0c;之前對聚類的步驟和相關內容不太了解&#xff0c;為了讀懂論文就去學習了一下&#xff0c;這里將自己的理解記錄下來。學習的不全面&#xff0c;主要是為了看懂論文&#xff0c;后續如果有涉及到聚…

前端筆記 --- vue框架

目錄 基礎知識 指令的修飾符 計算屬性 watch偵聽器的寫法 Vue的生命周期 工程化開發&腳手架 VUE CLI 組件注冊的方式 scoped樣式沖突與原理 data 組件之間的關系和組件通信 v-model詳解 sync修飾符 Dom介紹 操作HTML標簽 總結 ref 和 $refs $nextTick 自…

智能雙劍合璧:基于語音識別與大模型的技術沙龍筆記整理實戰

智能雙劍合璧&#xff1a;基于語音識別與大模型的技術沙龍筆記整理實戰 ——記一次網絡安全技術沙龍的高效知識沉淀 引言&#xff1a;當網絡安全遇上AI生產力工具 在綠盟科技舉辦的"AI驅動的未來網絡安全"內部技術沙龍中&#xff0c;筆者親歷了一場關于網絡安全攻…

數據結構(藍橋杯常考點)

數據結構 前言&#xff1a;這個是針對于藍橋杯競賽常考的數據結構內容&#xff0c;基礎算法比如高精度這些會在下期給大家總結 數據結構 競賽中&#xff0c;時間復雜度不能超過10的7次方&#xff08;1秒&#xff09;到10的8次方&#xff08;2秒&#xff09; 空間限制&#x…

使用 UNIX 命令在設計中搜索標識符:vcsfind 的入門指南

在現代軟件開發和硬件設計中&#xff0c;快速準確地定位和搜索特定標識符是提高開發效率的關鍵。本文將介紹如何使用 UNIX 命令 vcsfind 在設計中搜索標識符&#xff0c;幫助您更高效地管理您的項目。 什么是 vcsfind&#xff1f; vcsfind 是一個強大的 UNIX 命令行工具&#x…

第56天:Web攻防-SQL注入增刪改查盲注延時布爾報錯有無回顯錯誤處理審計復盤

#知識點 1、Web攻防-SQL注入-操作方法&增刪改查 2、Web攻防-SQL注入-布爾&延時&報錯&盲注 一、增刪改查 1、功能&#xff1a;數據查詢 查詢&#xff1a;SELECT * FROM news where id$id 2、功能&#xff1a;新增用戶&#xff0c;添加新聞等 增加&#xff1a;IN…

跳表實現學習

1.介紹 2.源碼 跳表節點&#xff1a; /* ZSETs use a specialized version of Skiplists */ /*** brief 定義跳躍表節點的數據結構。* * 該結構體用于表示跳躍表中的一個節點&#xff0c;包含元素、分數、后向指針和多層鏈表信息。*/ typedef struct zskiplistNode {sds ele;…

Python:正則表達式

正則表達式的基礎和應用 一、正則表達式核心語法&#xff08;四大基石&#xff09; 1. ?元字符&#xff08;特殊符號&#xff09;? ?定位符 ^&#xff1a;匹配字符串開始位置 $&#xff1a;匹配字符串結束位置 \b&#xff1a;匹配單詞邊界?&#xff08;如 \bword\b 匹配…

EB-Cable許可管理中的數據安全與隱私保護

在數字化時代&#xff0c;數據安全與隱私保護已成為企業關注的重中之重。作為專業的電纜管理軟件&#xff0c;EB-Cable許可管理不僅在功能豐富和操作便捷方面表現出色&#xff0c;更在數據安全與隱私保護方面為用戶提供了堅實的保障。本文將詳細介紹EB-Cable許可管理在數據安全…

串口通信函數匯總-ing

謝謝各位佬的閱讀&#xff0c;本文是我自己的理解&#xff0c;如果您發現錯誤&#xff0c;麻煩請您指出&#xff0c;謝謝 首先談談我自己對于串口的理解&#xff0c;隨便拿一個嵌入式的板子&#xff0c;它上面有兩個引腳&#xff0c;一個是rx&#xff0c;一個是tx&#xff0c;r…

如何用HTML5 Canvas實現電子簽名功能??

&#x1f916; 作者簡介&#xff1a;水煮白菜王&#xff0c;一位前端勸退師 &#x1f47b; &#x1f440; 文章專欄&#xff1a; 前端專欄 &#xff0c;記錄一下平時在博客寫作中&#xff0c;總結出的一些開發技巧和知識歸納總結?。 感謝支持&#x1f495;&#x1f495;&#…

大模型開源的工具包有哪些特殊符號可以使用;SEP 是什么

大模型開源的工具包有哪些特殊符號可以使用 目錄 大模型開源的工具包有哪些特殊符號可以使用自定義特殊token:special_tokens=True一、**對話輪次分隔符(必選)**二、**系統提示標記(提升指令理解)**三、**中文特色分隔符(貼合書寫習慣)**四、**開源模型專屬符號(按文檔…

控制系統分類

文章目錄 定義與特點1. 自治系統&#xff08;Autonomous System&#xff09;與非自治系統&#xff08;Non-Autonomous System&#xff09;自治系統非自治系統 2. 線性系統&#xff08;Linear System&#xff09;與非線性系統&#xff08;Nonlinear System&#xff09;線性系統非…

通過 ElasticSearch的Python API和`curl` 命令獲取Elasticsearch 所有索引名稱

導言 在大數據管理和實時搜索場景中&#xff0c;Elasticsearch 是一款不可或缺的工具。無論是開發調試、數據維護&#xff0c;還是系統監控&#xff0c;快速列出所有索引名稱都是一個高頻需求。本文將手把手教你如何通過 Python 客戶端連接 Elasticsearch&#xff0c;并用兩種方…

2024年廣州市智能網聯汽車創新實踐年度報告

政策法規方面&#xff0c;積極推進《廣州市智能網聯汽車創新發展條例》的制定和發布&#xff0c;不斷完善法規標準體系&#xff0c;為產業創新發展營造良好政策環境&#xff1b;技術創新方面&#xff0c;企業加大研發投入&#xff0c;在自動駕駛算法、車聯網安全等關鍵領域取得…

計算機操作系統(一) 什么是操作系統

計算機操作系統&#xff08;一&#xff09; 什么是操作系統 前言一、什么是操作系統二、操作系統的作用三、推動操作系統發展的主要動力總結&#xff08;核心概念速記&#xff09;&#xff1a; 前言 當你打開電腦、點擊應用、播放音樂時&#xff0c;是誰在背后默默協調這一切&…

韋伯望遠鏡的拉格朗日點計算推導過程,包含MATLAB和python運動軌跡仿真代碼

研究過程 起源與提出&#xff1a;1687 年牛頓提出 “三體問題”&#xff0c;旨在研究三個可視為質點的天體在相互之間萬有引力作用下的運動規律&#xff0c;但因運動方程過于復雜&#xff0c;難以得到完全解。歐拉的貢獻1&#xff1a;1767 年&#xff0c;瑞士數學家萊昂哈德?…

Gateway:網關路由與登錄鑒權

在微服務架構中&#xff0c;用戶登錄和身份校驗的處理方式確實與單體應用有所不同。在單體架構中&#xff0c;一旦用戶通過身份驗證&#xff0c;其會話信息可以在整個應用范圍內共享&#xff0c;所有模塊都能訪問到用戶信息。然而&#xff0c;在微服務架構下&#xff0c;每個服…