相機:以鼠標點為中心縮放(使用OpenGL+QT開發三維CAD)

很多軟件中(Auto CAD、ODA等)支持以鼠標點為中心進行放縮操作,有什么黑科技嗎?

本章節為相機原理和實現的補充內容,支持鼠標放縮時以鼠標點為中心進行放縮。

對應視頻課程已上線,歡迎觀看和支持~

https://www.bilibili.com/cheese/play/ss168681371

學習!《從零開發一款三維CAD軟件(OpenGL/QT/C++)》課程上線啦

圖片

31.相機:縮放時以鼠標點為中心

在三維軟件中,?以鼠標點為中心縮放可以做到保持聚焦點位置不變,達到視覺上的“中心點聚焦”。這種技術常用于電影鏡頭語言和游戲場景設計中,通過動態調整視角和物體大小,使用戶始終關注特定區域。

31.1.思考和討論

通常我們會通過鼠標滾輪事件實現場景縮放,而在場景中進行縮放時,會以相機當前的Position(也就是視點)為觀察位置進行縮放,通過滾輪滑動的方向和幅度來更新相機的Zoom

回顧

你應該還記得在頂點著色器中將坐標點轉換為裁剪坐標過程中需要經過modelMatrixviewMatrixprojectionMatrix的處理,而projectionMatrix的構造與Zoom有關系,當然還與近平面遠平面寬高比有關。

在不考慮鼠標位置進行縮放時,會以固定的Position進行觀察,而僅僅改變Zoom的大小,這樣會出現無論鼠標在場景中任何位置進行滾動,縮放行為都不會考慮鼠標位置,也就是不會考慮我們當前關注的位置。為了實現以鼠標點為中心的縮放,我們還需要更新相機的Position來實現聚焦點的“固定”,這也意味著我們需要同時更新viewMatrixprojectionMatrix

想象和思考

在原理和實現講解之前,我們先一起想象一下。

  • 鼠標在(curPx,curPy)像素位置進行滾輪放大,當前視角下場景會放大,我們現在看到的范圍更小了(也更清晰了),這也意味著(curPx,curPy)像素原本對應的場景位置(curScenePos)可能移出我們屏幕范圍了!

怎么樣讓它固定在(curPx,curPy)像素位置而不是移動呢?

在上述情景想象中,

  • 觀察矩陣viewMatrix沒有任何變化(也就是觀察空間中的效果沒有變化);

  • 而由于Zoom的變化,透視平截頭體的范圍變小了,可見的場景空間變小了(近平面遠平面尺寸變小了);

  • (curPx,curPy)

    像素原本對應的場景位置(curScenePos)可能已經不在透視平截頭體的范圍內了,當然該像素現在對應到另一個場景位置(nextScenePos)了;

我們需要把(curPx,curPy)像素位置固定在對應的場景位置上,那么移動相機的Position就好了,讓它靠近原本聚焦點(對應的場景位置)。是的,其實邏輯挺簡單的,至于要移動多少?那就移動curScenePos?-?nextScenePos

nextScenePos怎么計算?以相同的(curPx,curPy)depth來計算場景空間坐標系對應位置就好了。

31.2.原理

我們先不考慮透視投影或者正交投影的概念(這和當前的邏輯原理沒有什么關系)。在Zoom更新后,平截頭體的范圍變化了,(curPx,curPy)屏幕像素對應了新的場景位置(nextScenePos),我們只需要(通過平移Position)把這個位置“平移”到原本對應的場景位置(curScenePos),這樣聚焦的目標就“固定”住了。

偏移Position,實現鼠標點的聚焦
圖:偏移Position,實現鼠標點的聚焦

?

上圖展示了縮放前后、Position平移前后的邏輯示意:

  1. 縮放前鼠標像素位置對應一個場景空間位置curScenePos(為我們聚焦的位置);

  2. 放大后,curScenePos不可見了,而鼠標像素位置對應了另一個場景空間位置nextScenePos了;

  3. 我們把Camera.Position移動(curScenePos?-?nextScenePos)向量,鼠標像素位置重新對應到了原本的curScenePos

  4. 這樣就實現?了保持聚焦點位置不變的以鼠標點為中心縮放。

31.3.關鍵代碼

void ProcessMouseScroll(float?yoffset)
{
// ?scale by the mouse hover point if it's pixes is validQVector3D curPt;
float?depth;
bool?hoverValid = ViewerSetting::mouseScaleByCenter && GetScenePoint(ViewerSetting::currentMousePos[0], ViewerSetting::currentMousePos[1], curPt, depth);// ?modify zoom
float?downValue =?1.0f;
float?upValue =?89.f/*45.0f*/;Zoom -= (float)yoffset;
if?(Zoom < downValue)Zoom = downValue;
if?(Zoom > upValue)Zoom = upValue;if?(hoverValid){
// ?cal point of current pixesQVector3D nextPt;GetScenePoint(ViewerSetting::currentMousePos[0], ViewerSetting::currentMousePos[1], depth, nextPt);// ?move PositionPosition += (curPt - nextPt);}
}

思考

為什么在計算nextPt時的depth參數要用此前curPt對應的值呢?讀者可自行思考。

31.4.效果

效果視頻:https://www.bilibili.com/video/BV15zG3zzEgK/

也可在《課程視頻》中進行觀看,有詳細的講解~

學習!《從零開發一款三維CAD軟件(OpenGL/QT/C++)》課程上線啦


專注于圖形學(渲染和幾何算法)、數據處理、并行計算相關研究和研發,歡迎交流~

學習!《從零開發一款三維CAD軟件(OpenGL/QT/C++)》課程上線啦

系列課程已上線,詳細的視頻講解,打下扎實的圖形學基礎,歡迎大家觀看和支持~

往期文章:

  • GLViewer:添加ViewCube

  • 學習!《從零開發一款三維CAD軟件(OpenGL/QT/C++)》課程上線啦

  • OpenGL模板緩沖:實現亮顯外輪廓效果

  • 2025 想從事工業軟件開發要掌握哪些知識?

  • 30.抗鋸齒(anti aliasing):使用OpenGL+QT開發三維CAD

  • MSAA抗鋸齒技術的不足和優化(PPAA)

  • 相機:Camera原理講解(使用OpenGL+QT開發三維CAD)

  • 開發三維CAD:實現框選和反選功能

  • 圖形學:一分鐘看懂網格剖分原理(耳切法)

  • 視圖立方體:ViewCube的繪制(使用OpenGL+QT開發三維CAD)


圖片

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

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

相關文章

??XAMPP安全升級指南:修復CVE-2024-4577漏洞,從PHP 8.2.12升級至PHP 8.4.10??

??1. 背景與漏洞概述?? 近期,PHP官方披露了一個高危漏洞 ??CVE-2024-4577??,該漏洞影響PHP 8.2.x及更早版本,可能導致遠程代碼執行(RCE)或信息泄露。由于XAMPP默認捆綁的PHP版本(如8.2.12)可能受此漏洞影響,建議用戶盡快升級至最新的??PHP 8.4.10??(或官…

ES 壓縮包安裝

以下是 Elasticsearch (ES) 通過 .tar.gz 壓縮包安裝的詳細步驟&#xff08;適用于 Linux/macOS 系統&#xff09;&#xff1a; 1. 準備工作 1.1 檢查系統依賴 Java 環境&#xff1a;ES 需要 JDK&#xff0c;推薦 OpenJDK 11/17&#xff08;ES 7.x/8.x 兼容版本&#xff09;。…

RoboRefer:面向機器人視覺-語言模型推理的空間參考

25年6月來自北航、北大和北京智源的論文“RoboRefer: Towards Spatial Referring with Reasoning in Vision-Language Models for Robotics”。 空間參考是實體機器人與三維物理世界交互的基本能力。然而&#xff0c;即使有了強大的預訓練視覺-語言模型 (VLM)&#xff0c;近期方…

【Unity】MiniGame編輯器小游戲(十)連連看【Link】

更新日期:2025年7月9日。 項目源碼:獲取項目源碼 索引 連連看【Link】一、游戲最終效果二、玩法簡介三、正式開始1.定義游戲窗口類2.規劃游戲窗口、視口區域3.方塊 Block①.定義方塊類②.生成方塊所有類型③.生成連連看棋盤④.繪制方塊陣列4.連線 Line①.點擊方塊連線②.嘗試…

Enable ADB Debugging Before Connect

If you don’t enable Developer Options and turn on USB Debugging before plugging in the cable, adb devices won’t detect the phone because the Android system doesn’t trust the connection yet. Here’s what you need to do step-by-step to fix this:? 1. Enab…

從互聯網電腦遷移Dify到內網部署Dify方法記錄

一、在互聯網電腦上準備遷移文件1. 保存 Docker 鏡像# 獲取所有 Dify 相關鏡像&#xff08;根據實際容器名調整&#xff09; docker ps --filter "namedify" --format "{{.Image}}" | sort -u > dify-images.list# 保存鏡像為 .tar 文件 docker save $(…

【EGSR2025】材質+擴散模型+神經網絡相關論文整理隨筆(一)

MatSwap: Light-aware material transfers in images介紹任務&#xff1a;輸入一張拍攝圖像、示例材質紋理圖像&#xff08;這里跟BRDF無關&#xff0c;通常我們講到材質一般指的是SVBRDF&#xff0c;但是這里的材質指的只是紋理&#xff09;、用戶為拍攝圖像指定的遮罩區域&am…

餓了么el-upload上傳組件報錯:TypeError: ***.upload.addEventListener is not a function

在本地上傳沒有報這個錯誤&#xff0c;部署到服務器后會報這個錯誤&#xff0c;一開始以為是服務器配置等什么原因&#xff0c;但是一想這個報錯應該還是在前端&#xff0c;接口都還沒請求&#xff0c;不可能到后臺去&#xff0c;后面搜了好幾個AI也沒有找到想要的答案或解決方…

淘寶直播與開源鏈動2+1模式AI智能名片S2B2C商城小程序的融合發展研究

摘要&#xff1a;本文聚焦于淘寶直播這一以“網紅”內容為主的社交電商平臺&#xff0c;深入分析其特點與流量入口優勢。同時&#xff0c;引入開源鏈動21模式AI智能名片S2B2C商城小程序這一新興概念&#xff0c;探討二者融合的可能性與潛在價值。通過分析融合過程中的技術、市場…

【macos用鏡像站體驗】Claude Code入門使用教程和常用命令

一、下載安裝nodejs # macOS 用戶安裝nodejs brew update brew install node二、安裝官方Claude Code # 安裝 Claude Code npm install -g anthropic-ai/claude-code # 查看版本 claude --version三、正式使用&#xff08;國內鏡像站&#xff09; 今天發現的一個鏡像站&…

算法學習筆記:11.冒泡排序——從原理到實戰,涵蓋 LeetCode 與考研 408 例題

在排序算法的大家族中&#xff0c;冒泡排序是最基礎也最經典的算法之一。它的核心思想簡單易懂&#xff0c;通過重復地走訪待排序序列&#xff0c;一次比較兩個相鄰的元素&#xff0c;若它們的順序錯誤就把它們交換過來&#xff0c;直到沒有需要交換的元素為止。雖然冒泡排序的…

Linux小白學習基礎內容

記錄第一天重新學習2025/7/10 15&#xff1a;467/10 17&#xff1a;02這里面一個命令帶多個參數舉例&#xff08;多個參數之間用空格隔開&#xff09;ls&#xff08;命令&#xff09; ~ / /etc/&#xff08;參數&#xff09; :這里就是同時查看主機的家目錄&#xff0c;根目…

從零開始搭建深度學習大廈系列-2.卷積神經網絡基礎(5-9)

(1)本人挑戰手寫代碼驗證理論&#xff0c;獲得一些AI工具無法提供的收獲和思考&#xff0c;對于一些我無法回答的疑問請大家在評論區指教&#xff1b; (2)本系列文章有很多細節需要弄清楚&#xff0c;但是考慮到讀者的吸收情況和文章篇幅限制&#xff0c;選擇重點進行分享&…

【iOS設計模式】深入理解MVC架構 - 重構你的第一個App

目錄 一、MVC模式概述 二、創建Model層 1. 新建Person模型類 2. 實現Person類 三、重構ViewController 1. 修改ViewController.h 2. 重構ViewController.m 四、MVC組件詳解 1. Model&#xff08;Person類&#xff09; 2. View&#xff08;Storyboard中的UI元素&#x…

前端項目集成lint-staged

lint-staged (lint-staged) 這個插件可以只針對進入git暫存區中的代碼進行代碼格式檢查與修復&#xff0c;極大提升效率&#xff0c;避免掃描整個項目文件&#xff0c;代碼風格控制 eslint prettier stylelint 看這兩篇文章 前端項目vue3項目集成eslint9.x跟prettier 前端項…

李宏毅genai筆記:模型編輯

0 和post training的區別直接用post training的方法是有挑戰的&#xff0c;因為通常訓練資料只有一筆而且之后不管問什么問題&#xff0c;都有可能只是這個答案了1 模型編輯的評估方案 reliability——同樣的問題&#xff0c;需要是目標答案generalization——問題&#xff08;…

Oracle:union all和union區別

UNION ALL和UNION在Oracle中的主要區別體現在處理重復記錄、性能及結果排序上&#xff1a;處理重復記錄?UNION?&#xff1a;自動去除重復記錄&#xff0c;確保最終結果唯一。?UNION ALL?&#xff1a;保留所有記錄&#xff0c;包括完全重復的行。性能表現?UNION?&#xff…

[C#/.NET] 內網開發中如何使用 System.Text.Json 實現 JSON 解析(無需 NuGet)

在實際的企業開發環境中&#xff0c;尤其是內網隔離環境&#xff0c;開發人員經常面臨無法使用 NuGet 安裝外部包的問題。對于基于 .NET Framework 4.8 的應用&#xff0c;JSON 解析是一個常見的需求&#xff0c;但初始項目中往往未包含任何 JSON 處理相關的程序集。這時&#…

JVM(Java 虛擬機)的介紹

JVM原理JVM 核心架構與工作流程1. 類加載機制&#xff08;Class Loading&#xff09;2. 運行時數據區&#xff08;Runtime Data Areas&#xff09;堆&#xff08;Heap&#xff09;方法區&#xff08;Method Area&#xff09;:元空間&#xff08;Metaspace&#xff09;公共區域虛…

Qt 信號槽的擴展知識

Qt 信號槽的擴展知識一、信號與槽的重載Qt信號與槽的重載問題注意事項示例場景二、一個信號連接多個槽1、直接連接多個槽2、使用lambda表達式連接3、連接順序控制4、斷開特定連接5、自動連接方式三、 多個信號連接一個槽基本連接語法使用QSignalMapper區分信號源&#xff08;Qt…