相机的核心构造一个是glm::lookAt函数,一个是glm::perspective函数,本文相机的一切运动都在于如何构建相应的参数传入上述两个函数里。

glm::mat4 glm::lookAt(glm::vec3 const &eye,//相机所在位置glm::vec3 const &center,//要凝视的点glm::vec3 const &up //相机上向量
);
glm::mat4 perspective(
float fovy, 
float aspect, 
float near, 
float far);

首先我们通常默认相机的Front向量为(0,0,-1),位置eye为(0,0,0),则center=eye+Front=(0,0,-1)。

默认up向量为(0,1,0),通过Front向量和up向量可以叉积出right向量。

1.视角抬起与左右环视

通过修改Front向量即可。简单点可直接用欧拉角,相机引入yaw跟pitch,麻烦点就直接用向量做。可知相机自身的Front向量,right向量以及叉积出来的Up向量(注意不是up向量),这三组向量构成一组坐标基。

    //上下抬动thetaFront=Front*cos(theta)+Up*sin(theta)center=eye+Front;//up 不变,eye不变//上下旋转动betaFront=Front*cos(beta)+right*sin(beta)center=eye+Front;//up 不变,eye不变

2.视角平移

前后平移即通过Front向量平移,左右平移即通过right向量平移。将eye跟center加减Front向量和right向量即可实现平移。

    //前后方向平移eye+=Front*k;//k为平移系数center+=Front*k;//up 不变//左右方向平移eye+=right*k;//k为平移系数center+=right*k;//up 不变

3.zoomIn/zoomOut

1)普通的视野变换

直接通过修改fov即可,fov越大则视野越宽看到的东西更多,但是屏幕上呈现的物体会变小;反之则视野越窄看到的东西更少,但是屏幕上呈现的物体会变大

2)在鼠标位置进行区域的视野放大缩小

这时候直接修改fov就不管用了,需要通过平移相机的方式来实现。

获取鼠标所在点映射的世界空间点P,然后让相机沿着有eye与P两点构成的向量前后移动即可达到zoomIn/zoomOut的效果。其本质还是利用了相似的性质,这种实现方法可以巧妙地保证鼠标所在位置对应的三维空间点永远会在鼠标所对应的屏幕像素点上。

    glm::vec3 dir=P-eye;//k为视野缩放系数,正数时zoomIn视野变大,负数则相反eye+=dir*k;center+=dir*k;//up 不变

4.聚焦到某个物体

首先获取到这个物体的包围盒中心点P,然后用相机当前的Front向量与之加减获得到新的相机的eye。然后将相机的center设置为P即可。

    //k为系数,可以根据包围盒的大小设置,包围盒越大可以让相机离远点    eye=k*(P-Front);center=P;//up 不变

5.绕某个物体旋转

可以先聚焦到这个物体。接下来获取到这个物体的包围盒中心点P,这个P可固定为相机center,然后P与eye的距离为r。然后如果向上旋转theta,相机的eye会绕着以P为球心,r为半径的面沿着相机当前Up向量方向旋转theta。如果向右旋转,相机的eye会绕着以P为球心,r为半径的面沿着相机当前right向量方向旋转beta。当然,如果相机引入yaw跟pitch的话会相对更简单一些。

// 计算单位球面上点P绕切线n旋转theta角后的新坐标
// O: 球心
// P: 球面上的点
// n: 切线方向向量(需单位化且与OP垂直)
// theta: 旋转角度(弧度)
glm::vec3 rotatePointOnSphere(const glm::vec3& O, const glm::vec3& P, const glm::vec3& n, float theta
) 
{// 验证输入条件glm::vec3 OP = P - O;float opLength = glm::length(OP);// 检查是否为单位球面(允许微小误差)if (std::abs(opLength - 1.0f) > 1e-6f) {std::cerr << "警告:输入点不在单位球面上,将进行归一化处理" << std::endl;}// 检查切线是否与半径垂直float dotProduct = glm::dot(OP, n);if (std::abs(dotProduct) > 1e-6f) {std::cerr << "警告:输入的切线方向不与半径垂直,将重新计算垂直分量" << std::endl;}// 确保OP是单位向量glm::vec3 unitOP = glm::normalize(OP);// 确保n是单位向量且与OP垂直glm::vec3 tangent = glm::normalize(n - dotProduct * unitOP);// 创建旋转四元数:绕切线方向旋转theta角glm::quat rotation = glm::angleAxis(theta, tangent);// 执行旋转:首先将点平移到原点,旋转后再平移回球心glm::vec3 P_origin = P - O;  // 点P相对于球心的坐标glm::vec3 P_rotated_origin = rotation * P_origin;  // 旋转glm::vec3 P_rotated = P_rotated_origin + O;  // 平移回球心// 由于浮点误差,可能需要重新归一化以确保在单位球面上return O + glm::normalize(P_rotated - O);
}//绕P点上下转动theta
center=P;
eye=rotatePointOnSphere(P,eye,Up,theta);
//up向量不变//绕P点左右转动beta
center=P;
eye=rotatePointOnSphere(P,eye,right,beta);
//up向量不变

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

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

相关文章

java设计模式 -【策略模式】

策略模式定义 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为设计模式&#xff0c;允许在运行时选择算法的行为。它将算法封装成独立的类&#xff0c;使得它们可以相互替换&#xff0c;而不影响客户端代码。 核心组成 Context&#xff08;上下文&#xff09;&…

项目重新发布更新缓存问题,Nginx清除缓存更新网页

server {listen 80;server_name your.domain.com; # 替换为你的域名root /usr/share/nginx/html; # 替换为你的项目根目录# 规则1&#xff1a;HTML 文件 - 永不缓存# 这是最关键的一步&#xff0c;确保浏览器总是获取最新的入口文件。location /index.html {add_header Cache-…

系统架构师:系统安全与分析-思维导图

系统安全与分析的定义​​系统安全与分析是系统架构师在系统全生命周期中贯穿的核心职责&#xff0c;其本质是通过​​识别、评估、防控安全风险&#xff0c;并基于数据与威胁情报进行动态分析​​&#xff0c;构建从技术到管理的多层次防护体系&#xff0c;确保系统的保密性&a…

利用 Google Guava 的令牌桶限流实现数据处理限流控制

目录 一、令牌桶限流机制原理 二、场景设计与目标 三、核心实现代码&#xff08;Java&#xff09; 1. 完整代码实现 四、运行效果分析 五、应用建议 在高吞吐数据处理场景中&#xff0c;如何限制数据处理速率、保护系统资源、防止下游服务过载是系统设计中重要的环节。本文…

小黑课堂计算机二级 WPS Office题库安装包2.52_Win中文_计算机二级考试_安装教程

软件下载 【名称】&#xff1a;小黑课堂计算机二级 WPS Office题库安装包2.52 【大小】&#xff1a;584M 【语言】&#xff1a;简体中文 【安装环境】&#xff1a;Win10/Win11&#xff08;其他系统不清楚&#xff09; 【迅雷网盘下载链接】&#xff08;务必手机注册&#…

CSS3知识补充

1.伪类和伪元素&#xff1a; 简单的伪类实例 :first-chlid :last-child :only-child :invalid 用户行为伪类 :hover——上面提到过&#xff0c;只会在用户将指针挪到元素上的时候才会激活&#xff0c;一般就是链接元素。:focus——只会在用户使用键盘控制&#xff0c;选…

Spring Retry 异常重试机制:从入门到生产实践

Spring Retry 异常重试机制&#xff1a;从入门到生产实践 适用版本&#xff1a;Spring Boot 3.x spring-retry 2.x 本文覆盖 注解声明式、RetryTemplate 编程式、监听器、最佳实践 与 避坑清单&#xff0c;可直接落地生产。 一、核心坐标 <!-- Spring Boot Starter 已经帮…

VTK交互——CallData

0. 概要 这段代码https://examples.vtk.org/site/Cxx/Interaction/CallData/是一个使用VTK(Visualization Toolkit)库的示例程序,主要演示了自定义事件、回调函数和定时器的使用。程序创建一个旋转球体场景,并通过定时器触发自定义事件来更新计数器。以下是详细解释: 1.…

OCR工具集下载与保姆级安装教程!!

软件下载 软件名称&#xff1a;OCR工具集1.1 软件语言&#xff1a;简体中文 软件大小&#xff1a;78.8M 系统要求&#xff1a;Windows7或更高&#xff0c; 32/64位操作系统 硬件要求&#xff1a;CPU2GHz &#xff0c;RAM4G或更高 盘丨下载&#xff1a;https://tool.nineya…

平时遇到的错误码及场景?404?400?502?都是什么场景下什么含义,该怎么做 ?

✅ 一、常见 HTTP 错误码及含义状态码含义简述类型400Bad Request&#xff1a;请求格式有误客户端错误401Unauthorized&#xff1a;未授权客户端错误403Forbidden&#xff1a;禁止访问客户端错误404Not Found&#xff1a;资源不存在客户端错误405Method Not Allowed&#xff1a…

基于Tornado的WebSocket实时聊天系统:从零到一构建与解析

引言 在当今互联网应用中&#xff0c;实时通信已成为不可或缺的一部分。无论是社交媒体、在线游戏还是协同办公&#xff0c;用户都期待即时、流畅的交互体验。传统的HTTP协议是无状态的、单向的请求-响应模式&#xff0c;客户端发起请求&#xff0c;服务器返回响应&#xff0c…

【语义分割】记录2:yolo系列

图像分割笔记1、源码下载2、数据获取3、环境配置4、模型训练5、模型推理6、模型部署6.1 yolov5_flask学习7、版本上传1、源码下载 git clone https://github.com/ultralytics/ultralytics.gitgit回到对应版本&#xff1a; 方式一&#xff1a;使用 git checkout&#xff08;临…

ubuntu22.04系统 算力4090服务器 病毒防护 查杀等 运维入门(三)clamAV工具离线查杀

以下有免费的4090云主机提供ubuntu22.04系统的其他入门实践操作 地址&#xff1a;星宇科技 | GPU服务器 高性能云主机 云服务器-登录 相关兑换码星宇社区---4090算力卡免费体验、共享开发社区-CSDN博客 兑换码要是过期了&#xff0c;可以私信我获取最新兑换码&#xff01;&a…

微信小程序文件下载与预览功能实现详解

在微信小程序开发中&#xff0c;文件处理是常见需求&#xff0c;尤其是涉及合同、文档等场景。本文将通过一个实际案例&#xff0c;详细讲解如何实现文件的下载、解压、列表展示及预览功能。 功能概述 该页面主要实现了以下核心功能&#xff1a; 列表展示可下载的文件信息支持 …

postgresql执行创建和删除时遇到的问题

删除数据库的时候出现的问题 有连接在占用 postgres=# DROP DATABASE "subgraph-dev"; ERROR: database "subgraph-dev" is being accessed by other users DETAIL: There is 1 other session using the database.强制断开在用的连接 -- 替换 subgraph…

linux 应用层直接操作GPIO的方法

了解&#xff01;你使用的是 Rockchip RK3588S 平台&#xff0c;需要操作 GPIO3_D5_d 这个引脚&#xff08;即 MCU_JTAG_TMS_M1/.../GPIO3_D5_d&#xff09;。以下是基于你提供的系统信息的具体操作步骤&#xff1a;&#x1f50d; 第一步&#xff1a;确认 GPIO 系统编号 在 RK3…

JavaScript核心概念全解析

目录 1. 作用域 (1) 局部作用域 (2) 全局作用域 2. 垃圾回收 (1) 引用计数法 (2) 标记清除法 3. 闭包 (1) 作用 (2) 风险 4. 变量提升 (1) var (2) let 和 const (3) const 5. 函数提升 (1) 函数声明 (2) 函数表达式 6. 函数参数 (1) 动态参数 (2) 剩余参数…

力扣刷题(第一百天)

灵感来源 - 保持更新&#xff0c;努力学习- python脚本学习提莫攻击解题思路初始化总中毒时间 total。遍历每次攻击的时间点&#xff08;从第二个开始&#xff09;&#xff1a;计算当前攻击与前一次攻击的时间间隔 gap。若 gap < duration&#xff0c;则本次中毒时间为 gap&…

JMeter 性能测试实战笔记

JMeter 性能测试实战笔记 本文档是一份详细的 JMeter 指南&#xff0c;涵盖了从创建测试计划、执行测试到解读性能结果的全过程。 一、创建测试计划 一个完整的测试计划是执行性能测试的基础。下面将分步介绍如何创建一个针对文件上传接口的测试场景。 第一步&#xff1a;添加线…

图像处理:第二篇 —— 选择镜头的基础知识及对图像处理的影响

一、图像传感器的典型应用图像处理过程大致可分为如下四步&#xff1a;1.拍 摄 按下快门&#xff0c;拍摄图像2.传 送 将图像数据由照相机传送到控制器。3.处 理 前处理 : 对于图像数据进行加工&#xff0c;使其特征更加明显。测算处理 : 根据图像数据对于损…