OpenGL系列(六)摄像机
在 OpenGL系列(六)变换 中,一个目标物体经过模型矩阵、观察矩阵和投影矩阵的变换才能正常显示出来,其中模型矩阵主要针对目标物体,它会影响物体的位姿。观察矩阵和投影矩阵主要针对观察者而已,这两个变换决定了观察者以怎样的视角观察世界,可以把观察者比作一台摄像机,摄像机拍摄景象的角度由观察矩阵和投影矩阵决定。
在本例中要实现摄像机类Camera,该类主要向外提供观察矩阵和投影矩阵,类定义如下。
class Camera {
public:Camera();virtual ~Camera();glm::mat4 getViewMatrix();virtual glm::mat4 getProjectionMatrix();
private:glm::vec3 mPosition = glm::vec3(0.0f,0.0f,1.0f);glm::vec3 mUp = glm::vec3(0.0f,1.0f,0.0f);glm::vec3 mRight = glm::vec3(1.0f,0.0f,0.0f);};
在Camera类主要成员如下。
- mPosition表示摄像机的位置。
- mUp表示摄像机上方的方向。
- mRight表示摄像机右边的方向。
- getViewMatrix返回观察矩阵。
- getProjectionMatrix返回投影矩阵。
投影矩阵有两种,一种是正交投影矩阵,一种是透视投影,因此可以从Camera派生出两个子类,一个是OrthographicCamera表示正交投影摄像机,一个是PerspectiveCamera表示透视投影摄像机。
正交投影摄像机类为OrthographicCamera,定义如下。
class OrthographicCamera: public Camera{
public:OrthographicCamera(float left,float right,float top,float bottom,float near,float far);~OrthographicCamera();glm::mat4 getProjectionMatrix() override;private:float mLeft{0.0f};float mRight{0.0f};float mTop{0.0f};float mBottom{0.0f};float mNear{0.0f};float mFar{0.0f};
};
OrthographicCamera主要成员解析如下。
mLeft、mRight、mTop、mBottom、mNear、mFar分别表示裁剪空间的左、右、上、下、近、远。
getProjectionMatrix重新了父类的方法,返回正交投影摄像机的投影矩阵。
透视投影摄像机类为PerspectiveCamera,定义如下。
class PerspectiveCamera: public Camera{
public:PerspectiveCamera(float fovy, float aspect, float near, float far);~PerspectiveCamera();glm::mat4 getProjectionMatrix() override;
private:float mFovy{0.0f};float mAspect{0.0f};float mNear{0.0f};float mFar{0.0f};
};
PerspectiveCamera主要成员解析如下。
- mFovy表示视张角
- mAspect表示宽高比
- mNear表示近裁剪面
- mFar表示远裁剪面。
类定义完后,接下来实现返回观察矩阵和投影矩阵。
观察矩阵的计算方法如下。
glm::mat4 Camera::getViewMatrix(){glm::vec3 front = glm::cross(mUp,mRight);glm::vec3 center = mPosition + front;return glm::lookAt(mPosition,center,mUp);
}
观察矩阵的计算步骤如下。
- 对mUp和mRight进行叉乘得到向前的向量
- 当前位置加上向前向量得到观察的中心点,只要沿着该向量向前任何一个点都可以作为观察中心点。
- 通过lookAt返回观察矩阵,第1个参数是摄像机的位置,第2个参数是观察中心点,第3个参数是摄像机向上的向量
正交投影摄像机和透视投影摄像机的观察矩阵是一样的,所以放到父类Camera实现,但是投影矩阵就有差异,所以放到各自子类实现。
正交投影摄像机的投影矩阵实现如下。
glm::mat4 OrthographicCamera::getProjectionMatrix() {return glm::ortho(mLeft,mRight,mBottom,mTop,mNear,mFar);
}
调用glm的ortho即可返回正交投影矩阵。
透视投影摄像机的投影矩阵实现如下。
glm::mat4 PerspectiveCamera::getProjectionMatrix() {return glm::perspective(glm::radians(mFovy),mAspect,mNear,mFar);
}
调用glm的perspective可返回投影投影矩阵。
该示例的工程已经上传到,地址如下
示例工程代码
在开发过程中,首先要确定射线机的类型,以确定是创建OrthographicCamera对象还是PerspectiveCamera对象,摄像机对象创建好以后,一般不会修改投影矩阵,但是经过修改摄像机的观察角度,通过对Camera的mPosition、mRight和mUp可以改变观察的角度。有以下情况。
修改mPosition可以摄像机的前后左右上下移动。
修改mUp可以实现类似点头的效果。
修改mRight可以实现摇头的效果
同时修改mUp和mRight可以实现观察角度的左右倾斜。
同时修改mPosition和mRight可以实现围绕某个点左右转动,假设围绕转动的点是某个物体的中心点,转动一圈可以观察到物体前后左右4个面
同时修改mPosition和mUp可以实现围绕某个点上下转动,转动一圈可以观察某个物体的上、下、前、后4个面。
相关文章:
OpenGL系列(六)摄像机
在 OpenGL系列(六)变换 中,一个目标物体经过模型矩阵、观察矩阵和投影矩阵的变换才能正常显示出来,其中模型矩阵主要针对目标物体,它会影响物体的位姿。观察矩阵和投影矩阵主要针对观察者而已,这两个变换决…...
一个端口配置两个vue和后端服务,nginx以及前后端服务怎么配?
nginx配置重点看server中的内容: worker_processes 8; pid /usr/local/nginx/logs/nginx.pid;events {# 此为 Linux 系统特为处理大批量文件描述符而作改进的 poll 事件模型use epoll;worker_connections 512; # 工作进程的最大连接数量# 允许同时接受多个网络连…...
295. 数据流的中位数
class MedianFinder {Queue<Integer> A,B;public MedianFinder() {A new PriorityQueue<>();//小根堆存储后半部分B new PriorityQueue<>((x,y)->(y-x));//大根堆存储前半部分}public void addNum(int num) {if(A.size()0 && B.size()0){B.add(…...
OCR训练和C#部署英文字符训练
PaddleOCR是一个基于飞桨开发的OCR(Optical Character Recognition,光学字符识别)系统。其技术体系包括文字检测、文字识别、文本方向检测和图像处理等模块。以下是其优点: 高精度:PaddleOCR采用深度学习算法进行训练…...
webpack【实用教程】
基础配置 配置的拆分和合并 通常 webpack 的配置文件会有3个 webpack.common.js 公共配置(会被另外两个配置文件导入并合并)webpack.dev.js 开发环境的配置webpack.prod.js 生产环境的配置 开发环境的本地服务 在 webpack.dev.js 中配置 devServer:…...
如何使用C++进行文件读写操作
在C中,我们可以使用标准库中的 <fstream>(文件流)来进行文件的读写操作。以下是一些基本的文件读写操作的示例。 读取文件 cpp复制代码 #include <fstream> #include <iostream> #include <string> int main() { s…...
Tensorflow Lite移动平台编译
Android平台编译 如果不做定制化操作,我们不需要自己编译TensorFlow Lite Android库。我们可以直接使用位于MavenCentral的TensorFlow Lite AAR。但是在某些情况下,我们需要本地编译TensorFlow Lite。例如,您可能正在构建一个包含operations selected from TensorFlow的自定…...
2024年6月24日-6月30日(ue5肉鸽视频p16-p25)
试过重点放在独立游戏上,有个indienova独立游戏团队是全职的,由于他们干了几个月,节奏暂时跟不上,紧张焦虑了。五一时也有点自暴自弃了,实在没必要,按照自己的节奏走即可。精力和时间也有限,放在…...
LeetCode.面试题17.24.最大子矩阵详解
问题描述 给定一个正整数、负整数和 0 组成的 N M 矩阵,编写代码找出元素总和最大的子矩阵。 返回一个数组 [r1, c1, r2, c2],其中 r1, c1 分别代表子矩阵左上角的行号和列号,r2, c2 分别代表右下角的行号和列号。若有多个满足条件的子矩阵…...
云动态摘要 2024-06-28
给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 [新客专享]WeData 限时特惠 腾讯云 2024-06-21 数据分类分级管理,构建数据安全屏障 ,仅需9.9元! 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器…...
六、资产安全—信息分级资产管理与隐私保护(CISSP)
目录 1.信息分级 2.信息分级方法 3.责任的层级 4.资产管理 5.隐私数据管理角色 6.数据安全控制 7.数据保护方案 8.使用安全基线 六、资产安全—数据管理(CISSP): 五、身份与访问管理—身份管理和访问控制管理(CISSP): 1.信息分级 信息分级举列: 2.信息分级方…...
香港服务器托管对外贸行业必要性和优势
在当今全球化的经济环境下,外贸企业面临着前所未有的机遇与挑战。其中,服务器托管的选择对于外贸企业的运营效率和市场拓展具有举足轻重的作用。香港服务器,凭借其独特的地理位置、优质的网络环境和卓越的服务性能,一直是外贸企业…...
Vue Router 导航守卫,多次执行的解决方案
Vue Router 是 Vue.js 官方提供的路由器,它用于处理单页应用(SPA)中的路由导航。在 Vue Router 中,导航守卫是非常重要的功能,它可以在路由跳转之前或之后执行一些特定的操作。但是,如果你不小心,导航守卫可能会多次执行,这可能会导致一些问题。本文将介绍如何避免导航…...
SpringBoot集成道历(实现道历日期查询)
官网地址:官网地址https://6tail.cn/calendar/api.html 1、导入依赖 <dependency><groupId>cn.6tail</groupId><artifactId>lunar</artifactId><version>1.3.9</version></dependency><dependency><group…...
面对.rmallox勒索病毒:如何有效防范及应对
引言: 在当今数字化社会,网络安全问题日益严重,勒索病毒成为企业和个人不可忽视的威胁之一。最近出现的.rmallox勒索病毒更是给全球各地的用户带来了严重的数据安全问题。本文将探讨.rmallox勒索病毒的特点、感染方式及应对策略,…...
嘉立创学习
1.两个设置,一般用左边那个 2.焊盘分类 基本焊盘 热风盘:也叫花焊盘(负片) 隔离焊盘:外面那圈黑色,用作隔离(负片) 钢网层:(锡膏) 阻焊层&…...
ECharts 响应式设计
ECharts 响应式设计 ECharts 是一个由百度开源的,基于 JavaScript 的可视化库,它提供了一系列丰富的图表类型和灵活的配置选项,使得数据可视化变得简单而高效。在当今数据驱动的世界中,ECharts 已经成为许多开发者和设计师的首选工具,用于创建交互式和视觉吸引力强的图表…...
基于java语言+springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码
基于java语言springboot技术架构开发的 互联网智能3D导诊系统源码支持微信小程序、APP 医院AI智能导诊系统源码 一、智慧导诊系统开发原理 导诊系统从原理上大致可分为基于规则模板和基于数据模型两类。 1、基于规则推理的方法通过人工建立症状、疾病和科室之间的对应规则实现…...
MySQL事务——Java全栈知识(31)
1、事务的特性 原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。 一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。 隔离…...
2毛钱不到的2A同步降压DCDC电压6V频率1.5MHz电感2.2uH封装SOT23-5芯片MT3520B
前言 2A,2.3V-6V输入,1.5MHz 同步降压转换器,批量价格约0.18元 MT3520B 封装SOT23-5 丝印AS20B5 特征 高效率:高达 96% 1.5MHz恒定频率操作 2A 输出电流 无需肖特基二极管 2.3V至6V输入电压范围 输出电压低至 0.6V PFM 模式可在…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
蓝桥杯3498 01串的熵
问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798, 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...
sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...
嵌入式学习之系统编程(九)OSI模型、TCP/IP模型、UDP协议网络相关编程(6.3)
目录 一、网络编程--OSI模型 二、网络编程--TCP/IP模型 三、网络接口 四、UDP网络相关编程及主要函数 编辑编辑 UDP的特征 socke函数 bind函数 recvfrom函数(接收函数) sendto函数(发送函数) 五、网络编程之 UDP 用…...
Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...
npm安装electron下载太慢,导致报错
npm安装electron下载太慢,导致报错 背景 想学习electron框架做个桌面应用,卡在了安装依赖(无语了)。。。一开始以为node版本或者npm版本太低问题,调整版本后还是报错。偶尔执行install命令后,可以开始下载…...
