相机为三维场景提供了灵活便捷的视角变换和交互能力,通过相机操作可以实现全方位、各角度的场景浏览。

怎样在三维场景中引入相机,怎样处理和实现视角的放缩、移动、旋转?在视角旋转时以指定目标为中心又该怎样处理?

原文:相机:Camera原理讲解(使用OpenGL+QT开发三维CAD)

7.相机:Camera原理讲解

提示:

  • 在本文中作者采用了glm库相关的接口讲解,在课程代码中采用QTMatrix中类似的接口,但参数略有不同,详细可参照《课程代码》;

  • 作者在《视频课程》中对相机原理和实现有详细的讲解,包括原理和代码逻辑,欢迎观看。

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

学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦

7.1.概述和原理

在显示交互中,往往需要进行移动、缩放、旋转等操作,便于多方位查看图形元素,可以通过把场景中的所有物体往相反方向变换的方式来模拟出摄像机,产生一种视角在变换的感觉,而不是场景在变换。

补充:

  • 我们根据相机实时的位置姿态等参数计算出观察矩阵(viewMatrix),传递给渲染管线中的顶点着色器;而后经过渲染管线的处理,场景物体依次经过多种坐标变换和处理后,通过视口变换(Viewport Transform)投射到屏幕上;

  • 场景中实际是没有相机的,我们通过虚拟出相机及参数,实时构造出viewMatrix及投影矩阵(ProjectionMatrix)传递给渲染管线,从而不断的变换和处理场景物体坐标,产生一种(通过操纵相机)在场景中进行运动的效果。

观察空间示意
图:观察空间示意

定义一个摄像机,我们需要构造观察空间,包括观察位置、方向、右方向向量以及上方向向量。

观察空间的范围有限,将观察坐标变换为裁剪坐标的投影矩阵可以为两种不同的形式:正射投影矩阵(Orthographic Projection Matrix)或一个透视投影矩阵(Perspective Projection Matrix),每种形式都定义了不同的平截头体。

透视投影示意
图:透视投影示意

7.2.缩放

通过控制fov大小来实现缩放,fov会在透视投影时控制投影矩阵的缩放元素。

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

具体可以监控鼠标滚轮来控制fov的变化。

7.3.移动

通过控制相机cameraPos来实现在场景中移动的效果,cameraPos会在观察空间转换矩阵中影响偏移元素。

view = glm::lookAt(cameraPos, cameraPos + cameraFront, cameraUp);

具体可以通过监控鼠标右键移动或按键WASD触发来控制cameraPos的变化。

7.4.旋转

下图为欧拉角示意,一共有3种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),对于我们的摄像机系统来说,我们只关心俯仰角和偏航角。

欧拉角
图:欧拉角

给定一个俯仰角和偏航角,我们可以把它们转换为一个代表新的方向向量的3D向量。

// calculate the new Front vector
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
// also re-calculate the Right and Up vector
// normalize the vectors, because their length gets closer to 0 the more you look up or down which results
// in slower movement.
Right = glm::normalize(glm::cross(Front, WorldUp));  
Up = glm::normalize(glm::cross(Right, Front));

通过控制pitch 和yaw,进而控制cameraPoscameraFront来实现相机旋转,模拟在场景中的旋转。根据旋转中心的不同可以分为绕原点旋转和绕指定点进行旋转。

7.4.1.绕原点旋转

绕原点旋转过程中,cameraPos与原点距离保持一致,而cameraFrontcameraRight在不断的更新,可以想象为一个飞机在球心和半径固定的球面擦边飞行。

当仅实现相机绕原点旋转时,容易求得cameraPos的值;当既支持绕原点旋转,也支持绕指定点旋转的情况下,绕原点旋转时的cameraPos计算方法同上。

7.4.2.绕指定点旋转

在实际操作中,往往需要绕指定点进行旋转,如绕当前选中的元素或绕鼠标悬浮点进行旋转。

和绕原点旋转类似,绕指定点center旋转的过程中,cameraPoscenter距离保持一致,而由cameraPos指向center的向量curFront和对应的右向量curRight在不断的更新。

容易求得centercameraPos的向量,再叠加center即可得到更新后的cameraPos

绕指定点旋转
图:绕指定点旋转

glm::vec3 rPt(Position.x - center.x, Position.y - center.y, Position.z - center.z);//  计算position在right、front、up坐标系下的局部坐标
float lX = glm::dot(rPt, Right);
float lY = glm::dot(rPt, Front);
float lZ = glm::dot(rPt, Up);// update Front, Right and Up Vectors using the updated Euler angles
updateCameraVectors();Position = lX * Right + lY * Front + lZ * Up;
Position.x += center.x;
Position.y += center.y;
Position.z += center.z;

7.5.光标绘制

提示:

最新内容请参考11 添加旋转中心标识16 Add snap label章节。

当实现绕鼠标悬浮点进行旋转时,当前光标位置尤为重要,可以直观的看到到旋转中心位置。

鼠标光标绘制方法较多,如在OpenGL渲染管线中进行绘制,或用SVG等其他库进行绘制。

在OpenGL中绘制时,可以定义单独的VBOEBOVAO,在每个渲染循环中根据当前鼠标位置更新光标偏移。

//  draw mouse
glm::mat4 modelMouse = glm::mat4(1.0f);
modelMouse = glm::translate(modelMouse, { ourModel->mousePos.X, ourModel->mousePos.Y, ourModel->mousePos.Z }); // translate it down so it's at the center of the scene
//modelMouse = glm::scale(modelMouse, glm::vec3(1.0f, 1.0f, 1.0f)); // it's a bit too big for our scene, so scale it down
ourShader.setMat4("model", modelMouse);
ourModel->DrawMouse(ourShader);
voidDrawMouse(Shader& shader)
{shader.setVec3("objectColor", 1.0f, 0.5f, 0.f);glLineWidth(2.0f);glBindVertexArray(VAOMouse);glDrawElements(GL_LINES, static_cast<unsignedint>(indices.size()), GL_UNSIGNED_INT, 0);glBindVertexArray(0);// always good practice to set everything back to defaults once configured.glActiveTexture(GL_TEXTURE0);}

补充:

相机议题中常见的问题有相机裁剪等问题,本文不对此进行深入的探讨,感兴趣的读者可自行搜索和研究。

7.5.效果

https://www.bilibili.com/video/BV1kUKuzAE2A/

也可在《课程视频》中进行观看~

学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦


专注于图形学(渲染和几何算法)、数据处理、并行计算相关研究和研发,欢迎交流~

学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦

系列课程已上线,详细的视频讲解,打下扎实的图形学基础,欢迎大家观看和支持~

往期文章:

  • GLViewer:添加ViewCube

  • 学习!《从零开发一款三维CAD软件(OpenGL/QT/C++)》课程上线啦

  • OpenGL模板缓冲:实现亮显外轮廓效果

  • 2025 想从事工业软件开发要掌握哪些知识?

  • 30.抗锯齿(anti aliasing):使用OpenGL+QT开发三维CAD

  • MSAA抗锯齿技术的不足和优化(PPAA)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/87704.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/87704.shtml
英文地址,请注明出处:http://en.pswp.cn/web/87704.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源的虚拟电厂预测数据:资源、应用与挑战

引言 虚拟电厂(Virtual Power Plant, VPP)是一种通过聚合分布式能源资源(如太阳能、风能、储能系统、电动汽车和可控负荷)来优化电力系统运行的数字化能源管理平台。准确的预测数据是虚拟电厂高效运行的关键,而开源数据为研究者和企业提供了低成本、高透明度的解决方案。…

IDE全家桶专用快捷键----------个人独家分享!!

给大家分享一下我个人整理的快捷键&#xff0c;其中包含对电脑的操作&#xff0c;以及在编写代码时的操作&#x1f680;Window系列1 WindowsR 开启运行对话框--->输入cmd启动黑窗口​2 WindowsE 快速打开我的电脑 ​3 WindowsL 电脑锁屏 ​4 WindowsD 显示/恢复桌面 ​5 Win…

人工智能概念:RNN中的基础Encoder-Decoder框架

文章目录一、序列&#xff08;Seq2Seq&#xff09;转换的核心架构二、Encoder-Decoder框架基础原理2.1 整体工作流程2.2 编码器&#xff08;Encoder&#xff09;详解2.3 解码器&#xff08;Decoder&#xff09;工作机制与缺陷三、基础框架的核心缺陷分析&#xff08;以"欢…

R 列表:深入解析与高效应用

R 列表&#xff1a;深入解析与高效应用 引言 在R语言中&#xff0c;列表&#xff08;List&#xff09;是一种非常重要的数据结构&#xff0c;它允许我们将不同类型的数据组合在一起。列表在数据分析和统计建模中扮演着至关重要的角色。本文将深入探讨R列表的概念、创建方法、…

uniapp 国密sm2加密

1. uniapp 国密sm2加密 在uniapp中使用国密SM2算法进行加密解密&#xff0c;你可以通过安装第三方库miniprogram-sm-crypto来实现。这个库提供了SM2、SM3和SM4算法的实现&#xff0c;可以在小程序和uniapp项目中使用。 1.1. 安装miniprogram-sm-crypto 首先&#xff0c;你需要…

07_持续集成与部署:DevOps的核心引擎

07_持续集成与部署:DevOps的核心引擎 引言 在快速迭代的软件开发时代,持续集成(CI)与持续部署(CD)已成为企业提升竞争力的关键。通过自动化构建、测试和部署流程,CI/CD能够显著缩短交付周期,提高软件质量,降低发布风险。本文将深入探讨CI/CD的核心理念、实施路径与最…

电脑休眠设置

Dont Sleep的意思就是“不要睡觉”&#xff0c;用在电脑里就是“阻止休眠”的意思。但这款软件其实有“阻止休眠”和“允许休眠”两个功能。 阻止休眠时可以选择事件&#xff0c;是计时器、电池、CPU、网络这几个事件进行触发阻止休假的功能。 允许休眠也可以根据自己的需求进行…

蓝牙墨水屏上位机学习(3)

main.js中sendimg()函数学习&#xff0c;对应发送图片按钮函数代码如下&#xff1a;async function sendimg() {const canvasSize document.getElementById(canvasSize).value;const ditherMode document.getElementById(ditherMode).value;const epdDriverSelect document.…

Linux应用基础

1. 基础概念 1.1 系统调用 系统调用实际上是Linux内核为上层应用程序提供的API接口&#xff0c;方便应用程序进行调用&#xff0c;类似于SVC。 1.2 库函数 库函数是应用层里边的东西&#xff0c;在系统调用的上层&#xff0c;通常以动态库文件&#xff08;.so&#xff09;形式…

【时间序列数据处理的噩梦与救赎:一次复杂数据可视化问题的深度复盘】

时间序列数据处理的噩梦与救赎&#xff1a;一次复杂数据可视化问题的深度复盘 创建时间: 2025/7/3 技术栈: Vue 3 TypeScript UniApp ECharts 问题级别: &#x1f534; 系统性架构问题 &#x1f3af; 引言&#xff1a;当简单需求变成技术噩梦 “老哥&#xff0c;这个图表时…

Redis--黑马点评--基于stream消息队列的秒杀优化业务详解

基于redis的stream结构作为消息队列&#xff0c;实现异步秒杀下单 需求&#xff1a; 创建一个Stream类型的消息队列&#xff0c;名为stream.oreders 修改之前的秒杀下单Lua脚本&#xff0c;在认定有抢够资格后&#xff0c;直接向stream.orders中添加消息&#xff0c;内容包括…

Zephyr RTOS 防止中断影响数据写入

目录 概述 1 中断保护核心策略 1.1 中断锁定/解锁 (IRQ Locking) 1.2 自旋锁 (Spin Locks) 2 高级保护技术 2.1 双重缓冲技术 2.2 RCU (Read-Copy-Update) 模式 3 中断安全数据写入模式 3.1 FIFO队列保护 3.2 原子操作保护 4 性能优化策略 4.1 分区数据保护 4.2 中断…

Hinge×亚矩云手机:以“深度连接”为名,重构云端社交的“真实感”

当传统婚恋社交应用困于“浅层匹配”“硬件性能瓶颈”与“信任成本高企”&#xff0c;当Z世代对“灵魂共鸣、沉浸体验、隐私安全”的需求愈发迫切&#xff0c;以“设计让你删除的应用”为理念的Hinge&#xff0c;正携手亚矩云手机开启一场“云端深度社交革命”——用云端算力破…

OpenSSL 内存泄漏修复全景:119 个历史 Commit 的类型分析与防御启示

1 前言 openssl 开源库作为 C/C 项目中常用的组件库&#xff0c;截至 2025年7月4日 &#xff0c;openssl 的提交记录包含 119 个 Fix memory leak 。 本文基于源码 Commit 分析&#xff0c;揭示了 OpenSSL 内存泄漏修复从被动应对到主动防御的演进趋势&#xff0c;给各位 C/C…

十一、Python 3.13 的新特性和更新内容

1. 性能提升 1.1 解释器性能优化 更快的启动速度&#xff1a;Python 3.13 启动时间比 3.12 快约 10-15%。内存使用优化&#xff1a;减少了内存占用&#xff0c;特别是在处理大型数据结构时。 1.2 字节码优化 新的字节码指令&#xff1a;引入了更高效的字节码指令&#xff0…

后端 Maven打包 JAR 文件、前端打包dist文件、通过后端服务访问前端页面、Nginx安装与部署

打包 JAR 文件通常使用 Maven 或 Gradle 构建工具&#xff08;Spring Boot 项目默认推荐 Maven&#xff09;。以下是详细步骤和常见问题解答&#xff1a; 一、后端 Maven打包 JAR 文件 1. 确保项目是 Spring Boot 项目 项目结构应包含 pom.xml&#xff08;Maven 配置文件&am…

大数据系列 | 日志数据采集工具Filebeat的架构分析及应用

大数据系列 | 日志数据采集工具Filebeat的架构分析及应用 1. Filebeat的由来2. Filebeat原理架构分析3. Filebeat的应用3.1. 安装Filebeat3.2. 实战采集应用程序日志1. Filebeat的由来 在介绍Filebeat之前,先介绍一下Beats。Beats是一个家族的统称,Beats家族有8个成员,早期的…

基于 Vue + RuoYi 架构设计的商城Web/小程序实训课程

以下是基于 Vue RuoYi 架构设计的商城Web/小程序实训课程方案&#xff0c;结合企业级开发需求与教学实践&#xff0c;涵盖全栈技术栈与实战模块&#xff1a; &#x1f4da; 一、课程概述 目标&#xff1a;通过Vue前端 RuoYi后端&#xff08;Spring Boot&#xff09;开发企业…

Puppeteer 相关漏洞-- Google 2025 Sourceless

题目的代码非常简单,核心只有这一句 page.goto(url, { timeout: 2000 });方案1 Puppeteer 是一个常用的自动化浏览器工具&#xff0c;默认支持 Chrome&#xff0c;但也可以配置支持 Firefox。然而&#xff0c;当 Puppeteer 运行在 Firefox 上时&#xff0c;会自动关闭一些安全特…

LucidShape 2024.09 最新

LucidShape的最新版本2024.09带来了一系列新功能与增强功能&#xff0c;旨在解决光学开发者面临的最常见和最复杂的挑战。从微透镜阵列&#xff08;MLA&#xff09;的自动掩模计算&#xff0c;到高级分析功能的改进&#xff0c;LucidShape 2024.09致力于简化工作流程并增强设计…