鼠標輸入

一、隱藏并捕捉光標

偏航角和俯仰角是通過鼠標移動獲得的,水平的移動影響偏航角,豎直的移動影響俯仰角。

原理是,存儲上一幀鼠標的位置,在當前幀中計算鼠標位置與上一幀的位置相差多少。如果水平/豎直差別越大,那么俯仰角或偏航角就改變越大,也就是攝像機需要移動更多的距離。

首先我們應該告訴GLFW,它應該隱藏光標,并捕捉它。

結果:無論我們怎樣移動鼠標,光標都不會顯示,但它也不會離開窗口。

glfwSetInputMode(window,GLFW_CURSOR,GLFW_CURSOR_DISABLED);

二:監聽鼠標移動事件

為了計算俯仰角和偏航角,我們需要讓GLFW監聽鼠標移動事件(和鍵盤輸入相似)。用一個回調函數來完成,函數原型如下:

void mouse_callback(GLFWwindow *window,double xpos,double ypos);

xpos,ypos代表當前鼠標的位置。當我們用GLFW注冊了回調函數之后,鼠標一移動mouse_callback函數就會被調用:

1 glfwSetCursorCallback(window,mouse_callback);

三、在處理FPS風格攝像機的鼠標輸入的時候,我們必須在最終獲取方向向量之前做下面這幾步

1、計算鼠標距上一幀的偏移量

2、把偏移量添加到攝像機的俯仰角和偏航角中

3、對俯仰角和偏航角進行最大和最小值的限制

4、計算方向向量

第一步:計算鼠標距上一幀的偏移量,所以必須在程序中存儲上一幀的鼠標位置,我們把它的初始值設置為屏幕的中心

1 float lastX = screenWidth/2.0f;
2 float lastY = screenHeight/2.0f;

第二步:在鼠標的回調函數中計算當前幀和上一幀鼠標位置的偏移量:

1 float xoffest = xpos-lastX;
2 float yoffset = lastY - ypos;//注意這里是相反的,因為y坐標是從底部往頂部依次增大的
3 lastX = xpos;
4 lastY = ypos;
5 
6 float sensitivity = 0.05f;
7 xoffest *= sensitivity;
8 yoffest *= sensitivity;

注意我們把偏移量乘以了sensitivity(靈敏度)值。如果我們忽略這個值,鼠標移動就會太大了

俯仰角(Pitch)、偏航角(Yaw)

接下來我們把偏移量加到全局變量pitch和yaw上

1 yaw +=xoffset;
2 pitch +=yoffset;

第三步:給攝像機添加一些限制,這樣攝像機就不會發生奇怪的移動了。對于俯仰角,要讓用戶不能看高于89度的地方(在90度是視角會發生逆轉,所以我們把89度看成極限),同樣也不允許-89度。

1 if(pitch>89.0f)
2     pitch = 89.0f;
3 if(pitch <-89.0f)
4     pitch = -89.0f;

注意到我們沒有給偏航角設置限制,這是因為我們不希望限制用戶的水平旋轉。

第四步:通過俯仰角和偏航角來計算得到真正的方向向量:

1 glm::vec3 front;
2 front.x = cos(glm::radians(pith))*cos(glm::radians(yaw));
3 front.y = sin(glm::radians(pitch));
4 front.z = cos(glm::radians(pith))*cos(glm::radians(yaw));
5 cameraFront = glm::normolize(front);

計算出來的方向向量就會包含根據鼠標移動計算出來所有的旋轉了。

我們可以簡單的使用一個bool變量檢驗我們是否是第一次獲取鼠標輸入,如果是,那么我們先把鼠標的初始位置更新為xposypos值,這樣就能解決這個問題;接下來的鼠標移動就會使用剛進入的鼠標位置坐標來計算偏移量了:

1 if(firstMouse)//這個bool變量初始時是設定為true的
2 {
3     lastX = xpos;
4     lastY = ypos;
5     firstMouse = false;   
6 }

最后的代碼應該是這樣的:

 1 void mouse_callback(GLFWwindow* window, double xpos, double ypos)
 2 {
 3     if(firstMouse)
 4     {
 5         lastX = xpos;
 6         lastY = ypos;
 7         firstMouse = false;
 8     }
 9 
10     float xoffset = xpos - lastX;
11     float yoffset = lastY - ypos; 
12     lastX = xpos;
13     lastY = ypos;
14 
15     float sensitivity = 0.05;
16     xoffset *= sensitivity;
17     yoffset *= sensitivity;
18 
19     yaw   += xoffset;
20     pitch += yoffset;
21 
22     if(pitch > 89.0f)
23         pitch = 89.0f;
24     if(pitch < -89.0f)
25         pitch = -89.0f;
26 
27     glm::vec3 front;
28     front.x = cos(glm::radians(yaw)) * cos(glm::radians(pitch));
29     front.y = sin(glm::radians(pitch));
30     front.z = sin(glm::radians(yaw)) * cos(glm::radians(pitch));
31     cameraFront = glm::normalize(front);
32 }

三、縮放

實現一個縮放(Zoom)接口。在之前的教程中我們說視野(Field of View)或fov定義了我們可以看到場景中多大的范圍。當視野變小時,場景投影出來的空間就會減小,產生放大(Zoom In)了的感覺。我們會使用鼠標的滾輪來放大。與鼠標移動、鍵盤輸入一樣,我們需要一個鼠標滾輪的回調函數:

1 void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
2 {
3   if(fov >= 1.0f && fov <= 45.0f)
4     fov -= yoffset;
5   if(fov <= 1.0f)
6     fov = 1.0f;
7   if(fov >= 45.0f)
8     fov = 45.0f;
9 }

當滾動鼠標滾輪的時候,yoffset值代表我們豎直滾動的大小。當scroll_callback函數被調用后,我們改變全局變量fov變量的內容。因為45.0f是默認的視野值,我們將會把縮放級別(Zoom Level)限制在1.0f45.0f

我們現在在每一幀都必須把透視投影矩陣上傳到GPU,但現在使用fov變量作為它的視野:

projection = glm::perspective(glm::radians(fov), 800.0f / 600.0f, 0.1f, 100.0f);

最后不要忘記注冊鼠標滾輪的回調函數:

glfwSetScrollCallback(window, scroll_callback);

?

轉載于:https://www.cnblogs.com/keguniang/p/9949855.html

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

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

相關文章

c#用canny算子做邊緣提取_機器視覺學習(三)邊緣檢測

一、邊緣檢測二、邊緣檢測流程三、Canny邊緣檢測前言邊緣檢測是圖像處理和計算機視覺中&#xff0c;尤其是特征提取中的一個研究領域。有許多方法用于邊緣檢測&#xff0c;它們的絕大部分可以劃分為兩類&#xff1a;基于一階導數首先計算邊緣強度&#xff0c; 通常用一階導數表…

一個有關Update類型的存儲過程的問題

CREATE PROCEDURE testupdateproc AS declare id int declare trandate datetime declare tranlimit int update test set trandatetrandate, tranlimittranlimit where test.idid GO 存儲過程語句如上&#xff0c;檢查語法是沒有問題的&#xff0c;但是在程序中執行時卻不行…

[20190805]在小程序中使用npm包

小程序是可以使用npm包的 1. 初始化npm&#xff1b;&#xff08;在項目目錄下輸入&#xff09; npm init 此時項目文件夾會創建一個配置信息的package.json文件 2. 手動新建node_modules文件夾&#xff1b;&#xff08;在項目目錄下新建&#xff09; 3. 安裝npm包&#xff1b; …

bindresult必須在哪個位置_手機視頻剪輯工具哪個好?清爽視頻編輯APP有人推薦嗎?...

作為一個非常喜歡旅游的人&#xff0c;每次出門在外都喜歡發各種照片&#xff0c;以前發照片覺得就能夠表達自己的狀態和心情&#xff0c;但是隨著時間的變化發現&#xff0c;身邊的人都開始喜歡發視頻了。此前在飛機上拍攝了一段覺得不錯的天空視頻&#xff0c;想要制作成短片…

[轉] 能ping通,但不能上網.

一、感染了病毒所致這種情況往往表現在打開IE時&#xff0c;在IE界面的左下框里提示&#xff1a;正在打開網頁&#xff0c;但老半天沒響應。在任務管理器里查看進程&#xff0c;&#xff08;進入方法&#xff0c;把鼠標放在任務欄上&#xff0c;按右鍵—任務管理器—進程&#…

Gradle打包命令記錄

Gradle打包命令記錄第一種方式&#xff1a;gradle build執行后在在build/lib下生成war包第二種方式&#xff1a;gradle cleangradle --refresh-dependencies assemble

淺談ASP中Web頁面間的數據傳遞

【簡 介】  基于Web的動態網頁設計必會涉及到頁面間的數據傳遞&#xff0c;文章探討了ASP設計中常用的Web頁面間的數據傳遞方式&#xff0c;分析各種數據傳遞方式的使用方法、使用場合及優缺點&#xff0c;其都是設計階段選擇數據傳遞方式考慮的關鍵 往往使用動態網頁技術制作…

變頻電源出現故障了怎么辦,該如何去診斷呢

在變頻電源使用時間過長之后就會出現一些小故障&#xff0c;在出現這些小故障的時候很多人都不知道問題出在哪&#xff0c;今天中港揚盛的技術員教你如何的快速診斷變頻電源的故障方法。只有及時的發現&#xff0c;這樣就能夠有效地去解決變頻電源所出現的故障。下面就是變頻電…

無法訪問你試圖使用的功能所在的網絡位置_[steam實用工具]解決無法訪問商店/社區/好友列表的問題...

[steam實用工具]解決無法訪問商店/社區/好友列表的問題在我們使用steam的過程中&#xff0c;由于某些原因&#xff0c;在訪問商店/社區/好友列表時會被受到限制。針對這種情況&#xff0c;國內的大神些開發出了以下工具來解決我們訪問的難題。本文章中的軟件由“羽翼誠"大…

tomcat6.0+mysql5.0+jdk5.0+myeclipse6.0打造JSP開發平臺

1.下載tomcat6.0(http://tomcat.apache.org/download-60.cgi), mysql5.0(http://download.mysql.cn/src/2006/0710/5543.html), jdk5.0(http://download.mysql.cn/src/2006/0710/5543.html)以及myeclipse6.0(http://www.myeclipseide.com/module-htmlpages-display-pid-4.html)…

程序設計中的感悟

1. 學習應該從基礎打起&#xff0c;不要一開始就嘗試最高深的技術。 2. 每看一本書&#xff0c;不要說這章我以前學習過了&#xff0c;也掌握的很好&#xff0c;因此我可以跳過這一章看更重要的了。 3. 對于作業&#xff0c;遇到不會的盡量不要立刻向別人請教。如果實在解決…

(轉)用Java獲得當前性能信息

(轉&#xff09;用Java獲得當前性能信息 http://www.blogjava.net/amigoxie/archive/2008/04/30/197564.html在Java中&#xff0c;可以獲得總的物理內存、剩余的物理內存、已使用的物理內存等信息&#xff0c;本例講解如何取得這些信息&#xff0c;并且獲得在Windows下的內存使…

docker wsl2啟動不了_Docker學習筆記

在筆記本上主要還是想以輕量、方便為主&#xff0c;所以采用的是在WSL2中使用docker的這么一個方案。WSL2我筆記本原來是預裝的是WIN10家庭版&#xff0c;需要先升級為專業版&#xff0c;并加入windows預覽體驗計劃。更新完之后&#xff0c;安裝WSL&#xff0c;我選擇的是Ubunt…

暑假集訓-8.06總結

學習內容&#xff1a; 搜索 今日完成題數&#xff08;不包含多校&#xff09;&#xff1a;4 今日看書情況&#xff1a;15頁 今日心得&#xff1a; 今天學的是搜索&#xff0c;雖然以前學過&#xff0c;但書上講的更具體些&#xff0c; 比如說如何去優化搜索的次數等 英語題目好…

網易馬進:DDB從分布式數據庫到結構化數據中心的架構變遷

導語&#xff1a; 本文根據馬進老師在2018年5月10日【第九屆中國數據庫技術大會(DTCC)】現場演講內容整理而成。馬進 網易 DDB項目負責人來自網易杭研大數據平臺組&#xff0c;入職以來先后參與了分布式數據庫DDB&#xff0c;緩存NKV&#xff0c;網易數據運河NDC等項目&#xf…

element label動態賦值_淺析 vuerouter 源碼和動態路由權限分配

背景上月立過一個 flag&#xff0c;看完 vue-router 的源碼&#xff0c;可到后面逐漸發現 vue-router 的源碼并不是像很多總結的文章那么容易理解&#xff0c;閱讀過你就會發現里面的很多地方都會有多層的函數調用關系&#xff0c;還有大量的 this 指向問題&#xff0c;而且會有…

MessagePack Java 0.6.X List, Map 對象的序列化和反序列化

為了序列化原生的容器對象例如 List 和 Map 對象&#xff0c;你必須使用 Template。 Template 對象是 serializer 和 deserializer 的配對。例如&#xff0c;為了序列化一個 List 對象&#xff0c;在 List 對象中 Integer 對象為元素&#xff0c;你可以使用下面的方法來創建一…

世界領先的界面設計公司:The Skins Factory

該公司的網站&#xff1a; http://www.theskinsfactory.com/skinsfactory/ 該公司誕生于2000年&#xff0c;由一群狂熱的界面愛好者&#xff0c;帶著對GUI的熱情和大膽的洞察力創立。很快&#xff0c;皮膚工廠便成長為世界領先的、真正的、革命性界面解決方案提供商。 更多的精…

HDU 1253 勝利大逃亡 題解

勝利大逃亡 Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 44540 Accepted Submission(s): 15483 Problem DescriptionIgnatius被魔王抓走了,有一天魔王出差去了,這可是Ignatius逃亡的好機會.魔王住在一個城堡…

lstm需要優化的參數_使用PyTorch手寫代碼從頭構建LSTM,更深入的理解其工作原理...

這是一個造輪子的過程&#xff0c;但是從頭構建LSTM能夠使我們對體系結構進行更加了解&#xff0c;并將我們的研究帶入下一個層次。LSTM單元是遞歸神經網絡深度學習研究領域中最有趣的結構之一&#xff1a;它不僅使模型能夠從長序列中學習&#xff0c;而且還為長、短期記憶創建…