【Overload游戏引擎细节分析】视图投影矩阵计算与摄像机

本文只罗列公式,不做具体的推导。

OpenGL本身没有摄像机(Camera)的概念,但我们为了产品上的需求与编程上的方便,一般会抽象一个摄像机组件。摄像机类似于人眼,可以建立一个本地坐标系。相机的位置是坐标原点,摄像机的朝向Forward是摄像机看的方向,再给定向上的Up轴即可建立本地坐标系。然后,可以通过矩阵将世界坐标系的物体变换到摄像机坐标系中,这个矩阵称为视图矩阵。通过改变摄像机的本地坐标系,可以产生场景漫游的效果。
图片来自网络

1. 视图矩阵公式

视图矩阵是将物体坐标从世界空间坐标变换到相机本地坐标系中。计算视图矩阵需给定摄像机的位置 e y e \mathbf{eye} eye,焦点位置 t o \mathbf{to} to, Forward与Up所在平面的内的矢量 Y Y Y ,注意Y可以不与Forward垂直,我们可以通过叉乘获得摄像机的本地坐标系:
f w d = n o r m a l i z e ( e y e − t o ) r i g h t = n o r m a l i z e ( Y × f w d ) u p = n o r m a l i z e ( f w d × r i g h t ) \begin{aligned} & \mathbf{fwd} = normalize(\mathbf{eye}-\mathbf{to}) \\& \mathbf{right}=normalize(Y\times \mathbf{fwd}) \\& \mathbf{up} = normalize(\mathbf{fwd}\times\mathbf{right})\end{aligned} fwd=normalize(eyeto)right=normalize(Y×fwd)up=normalize(fwd×right)
在这里插入图片描述
LookAt矩阵等于:

L o o k A t = [ s i d e x s i d e y s i d e z − s i d e ⋅ e y e u p x u p y u p z − u p ⋅ e y e f w d x f w d x f w d x − f w d ⋅ e y e 0 0 0 1 ] LookAt= \begin{bmatrix} \mathbf{side}_x & \mathbf{side}_y & \mathbf{side}_z & -\mathbf{side}\cdot \mathbf{eye}\\ \mathbf{up}_x & \mathbf{up}_y & \mathbf{up}_z & -\mathbf{up}\cdot \mathbf{eye}\\ \mathbf{fwd}_x & \mathbf{fwd}_x & \mathbf{fwd}_x & -\mathbf{fwd}\cdot \mathbf{eye}\\ 0& 0 & 0 & 1 \end{bmatrix} LookAt= sidexupxfwdx0sideyupyfwdx0sidezupzfwdx0sideeyeupeyefwdeye1

Overload中计算视图矩阵代码:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateView(const float p_eyeX, const float p_eyeY, const float p_eyeZ, const float p_lookX, const float p_lookY, const float p_lookZ, const float p_upX, const float p_upY, const float p_upZ)
{const OvMaths::FVector3 eye(p_eyeX, p_eyeY, p_eyeZ); // 摄像机位置const OvMaths::FVector3 look(p_lookX, p_lookY, p_lookZ); // 摄像机焦点const OvMaths::FVector3 up(p_upX, p_upY, p_upZ); // 摄像机upconst OvMaths::FVector3 forward(eye - look); // 摄像机的Z轴FVector3::Normalize(forward);// cross得到right轴const OvMaths::FVector3 upXForward(OvMaths::FVector3::Cross(up, forward));FVector3::Normalize(upXForward);// cross得到Up轴,等价于Y轴const OvMaths::FVector3 v(OvMaths::FVector3::Cross(forward, upXForward));OvMaths::FMatrix4 View;View.data[0] = upXForward.x;View.data[1] = upXForward.y;View.data[2] = upXForward.z;View.data[3] = -OvMaths::FVector3::Dot(eye, upXForward);View.data[4] = v.x;View.data[5] = v.y;View.data[6] = v.z;View.data[7] = -OvMaths::FVector3::Dot(eye, v);View.data[8] = forward.x;View.data[9] = forward.y;View.data[10] = forward.z;View.data[11] = -OvMaths::FVector3::Dot(eye, forward);return View;
}

2. 投影矩阵

投影是将物体的光线投射到相机的近平面上,将3D物体变成2D图像,是将相机坐标空间转换到屏幕空间,类似于真实相机的曝光过程。投影有两种透视投影与正交投影。
透视投影:通过透视概念模仿我们看到的真实世界的方式,尝试让2D图像看起来像是3D的。物体近大远小,这样3D空间中有的平行线看起来就不再平行。
正投影:与透视投影相反,在视锥体中的物体不因其距离相机远近做任何调整,直接进行投影。正投影在CAD软件中使用广泛。

在这里插入图片描述

透视投影矩阵:
[ 2 Z n e a r R − L 0 R + L R − L 0 0 2 Z n e a r T − B T + B T − B 0 0 0 − Z f a r + Z n e a r Z f a r − Z n e a r − 2 Z n e a r Z f a r Z f a r − Z n e a r 0 0 − 1 0 ] \begin{bmatrix} \frac{2Z_{near}}{R-L} & 0 & \frac{R+L}{R-L} & 0\\ 0 & \frac{2Z_{near}}{T-B} & \frac{T+B}{T-B} & 0\\ 0 & 0 & -\frac{Z_{far}+Z_{near}}{Z_{far}-Z_{near}} & -\frac{2Z_{near}Z_{far}}{Z_{far}-Z_{near}} \\ 0 & 0 & -1 & 0 \end{bmatrix} RL2Znear0000TB2Znear00RLR+LTBT+BZfarZnearZfar+Znear100ZfarZnear2ZnearZfar0
其中:
     Z n e a r 、 Z f a r 是相机位置到近平面、远平面的距离 Z_{near}、Z_{far}是相机位置到近平面、远平面的距离 ZnearZfar是相机位置到近平面、远平面的距离
     R、L–投影平面左右边界的X坐标
     T、B–投影平面上下边界的Y坐标

Overload中计算透视投影矩阵的代码:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateFrustum(const float p_left, const float p_right, const float p_bottom, const float p_top, const float p_zNear, const float p_zFar)
{const float maxView = 2.0f * p_zNear;const float width = p_right - p_left;const float height = p_top - p_bottom;const float zRange = p_zFar - p_zNear;FMatrix4 Frustum;Frustum.data[0] = maxView / width;Frustum.data[5] = maxView / height;Frustum.data[2] = (p_right + p_left) / width;Frustum.data[6] = (p_top + p_bottom) / height;Frustum.data[10] = (-p_zFar - p_zNear) / zRange;Frustum.data[14] = -1.0f;Frustum.data[11] = (-maxView * p_zFar) / zRange;Frustum.data[15] = 0.0f;return Frustum;
}

正投影矩阵:
[ 2 R − L 0 0 − R + L R − L 0 2 T − B 0 − T + B T − B 0 0 1 Z f a r − Z n e a r − Z n e a r Z f a r − Z n e a r 0 0 0 1 ] \begin{bmatrix} \frac{2}{R-L} & 0 & 0 & -\frac{R+L}{R-L} \\ 0 & \frac{2}{T-B} & 0 & -\frac{T+B}{T-B} \\ 0 & 0 & \frac{1}{Z_{far}-Z_{near}} & -\frac{Z_{near}}{Z_{far}-Z_{near}} \\ 0 & 0 & 0 & 1 \end{bmatrix} RL20000TB20000ZfarZnear10RLR+LTBT+BZfarZnearZnear1

Overload中计算正投影矩阵的代码:

OvMaths::FMatrix4 OvMaths::FMatrix4::CreateOrthographic(const float p_size, const float p_aspectRatio, const float p_zNear, const float p_zFar)
{auto ortho = OvMaths::FMatrix4::Identity;const auto right = p_size * p_aspectRatio;const auto left = -right;const auto top = p_size;const auto bottom = -top;ortho(0, 0) = 2.0f / (right - left);ortho(1, 1) = 2.0f / (top - bottom);ortho(2, 2) = -2.0f / (p_zFar - p_zNear);ortho(0, 3) = -(right + left) / (right - left);ortho(1, 3) = -(top + bottom) / (top - bottom);ortho(2, 3) = -(p_zFar + p_zNear) / (p_zFar - p_zNear);ortho(3, 3) = 1.0f;return ortho;
}

3. 摄像机封装

Overload中摄像机类比较简单,主要是对上面两个矩阵计算的封装。每次就是的时候需传入摄像机的位置及转动四元数,计算完视图投影矩阵后保存到自己的字段中。代码比较简单,不再分析了。

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

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

相关文章

AMEYA360-罗姆ROHM马来西亚工厂新厂房竣工

全球知名半导体制造商罗姆为了加强模拟IC的产能,在其马来西亚制造子公司ROHM-Wako Electronics (Malaysia) Sdn. Bhd.(以下简称“RWEM”)投建了新厂房,近日新厂房已经竣工,并举行了竣工仪式。 RWEM此前主要生产二极管和LED等小信号产品&#…

自己写spring boot starter问题总结

1. Unable to find main class 创建spring boot项目写自己的starterxi写完之后使用install出现Unable to find main class&#xff0c;这是因为spring boot打包需要一个启动类&#xff0c;按照以下写法就没事 <plugins><plugin><groupId>org.springframewo…

二、K8S之Pods

Pod 一、概念 K8S作为一个容器编排管理工具&#xff0c;它可以自动化容器部署、容器扩展、容器负载均衡等任务&#xff0c;并提供容器的自愈能力等功能。在Kubernetes中&#xff0c;Pod是最基本的调度单元&#xff0c;它是一组共享存储和网络资源的容器集合&#xff0c;通常是…

数字孪生与智慧城市:重塑未来城市生活的奇迹

今天&#xff0c;我们将探讨数字孪生和智慧城市两个颠覆性技术&#xff0c;它们正引领着未来城市生活的巨大变革。随着科技的飞速发展&#xff0c;数字孪生和智慧城市成为实现可持续发展和提升居民生活质量的关键策略。 数字孪生&#xff1a;实现现实与虚拟的完美融合 数字孪生…

使用RCurl和R来爬虫视频

以下是一个使用RCurl和R来爬虫视频的示例代码&#xff0c;代码中使用了https://www.duoip.cn/get_proxy来获取代理IP&#xff1a; # 引入必要的库 library(RCurl) library(rjson)# 获取代理IP proxy_url <- "https://www.duoip.cn/get_proxy" proxy <- getURL…

Java 反射

目录 反射机制&#x1f6a9;一个需求引出反射&快速入门反射机制反射的扩展-反射相关类反射的优点和缺点反射调用时会造成性能的一些降低->反射调用性能优化&#xff08;虽然优化程度不高&#xff0c;但是也是可以起到适当的优化的作用&#xff09; Class类&#x1f6a9;…

基于Springboot实现在线答疑平台系统项目【项目源码+论文说明】

基于Springboot实现在线答疑平台系统演示 摘要 社会的发展和科学技术的进步&#xff0c;互联网技术越来越受欢迎。网络计算机的生活方式逐渐受到广大师生的喜爱&#xff0c;也逐渐进入了每个学生的使用。互联网具有便利性&#xff0c;速度快&#xff0c;效率高&#xff0c;成本…

第五届芜湖机器人展,正运动助力智能装备“更快更准”更智能!

■展会名称&#xff1a; 第十一届中国(芜湖)科普产品博览交易会-第五届机器人展 ■展会日期 2023年10月21日-23日 ■展馆地点 中国ㆍ芜湖宜居国际博览中心B馆 ■展位号 B029 正运动技术&#xff0c;作为国内领先的运动控制企业&#xff0c;将于2023年10月21日参加芜湖机…

《优化接口设计的思路》系列:第五篇—接口发生异常如何统一处理

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址&#xff1a;summo-springboot-interface-demo 前言 大家好&#xff01;…

如何从一门编程语言过渡到另一门编程语言?

在数字时代&#xff0c;软件开发领域不断进化&#xff0c;不同编程语言层出不穷。作为一位富有经验的开发者&#xff0c;你可能曾面临过一个重要的问题&#xff1a;如何顺利过渡到一门全新的编程语言&#xff1f; 这个问题不仅是对技术领域的学习&#xff0c;更是对职业生涯的…

多数元素-----题解报告

题目&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 这一题仔细阅读题目意思就会发现&#xff0c;主要就是找众数&#xff0c;并且题目中明确告知&#xff0c;给出的数组中必然有出现次数超过n/2的元素。 那就很简单了&#xff0c;有一…

[计算机提升] 系统及用户操作

1.4 系统及用户操作 1.4.1 系统操作 1.4.1.1 开机、关机、重启 在Windows系统中&#xff0c;开机&#xff08;Power On&#xff09;&#xff0c;关机&#xff08;Shutdown&#xff09;和重启&#xff08;Restart&#xff09;是指计算机的不同电源控制操作。 开机&#xff1a;…

UE4 顶点网格动画播放后渲染模糊问题

问题描述&#xff1a;ABC格式的顶点网格动画播放结束后&#xff0c;改模型看起来显得很模糊有抖动的样子 解决办法&#xff1a;关闭逐骨骼动态模糊

JSONObject和JSONArray区别及注意事项

1、JSONObject和JSONArray的数据表示形式 JSONObject的数据是用 { } 来表示的&#xff0c; 例如&#xff1a; {"name":"John","age":30,"city":"New York"}而JSONArray&#xff0c;顾名思义是由JSONObject构成的数组&…

Nodejs原型链污染学习

文章目录 前置知识JavaScript数据类型prototype原型同步和异步child_process模块 原型链污染利用条件 实例 前置知识 JavaScript数据类型 let和var关键字的区别 使用var或let关键字可以定义变量 let和var的区别如下&#xff1a; var是全局作用域&#xff0c;let 只在当前代码…

只会Python,怎么用PC控制无人机自动飞行?

PC-SDK是阿木实验室 (AMOVLAB) 为了简化开源飞控的控制协议MAVLink&#xff0c;优化和维护的一个基于PC电脑运行MAVSDK(支持Windows和Ubuntu)的Python SDK库。 相对于传统的无人机控制开发&#xff0c;开发者无需掌握C/C语言和ROS等相关知识&#xff0c;只要学会Python编程及懂…

你的助听器装置效果好吗?

作者&#xff1a;兰明 助听效果的好坏是一个多维的概念&#xff0c;简单的讲就是能使听障人士成功地应付生活的程度。影响助听装置效果的因素主要有三个方面&#xff1a;听障人士自身的因素、助听装置本身的因素以及专业服务的因素。其中病史超过半年的听障人士自身的因素&…

ubuntu 18.04 LTS交叉编译opencv 3.4.16并编译工程[全记录]

一、下载并解压opencv 3.4.16源码 https://opencv.org/releases/ 放到home路径下的Exe文件夹&#xff08;专门放用户安装的软件&#xff09;中&#xff0c;其中build是后期自建的 为了版本控制&#xff0c;保留了3.4.16&#xff0c;并增加了-gcc-arm 二、安装cmake和cmake-g…

查看双翌视觉软件版本号

查看双翌视觉软件版本号 MasterAlign视觉对位软件 MasterAlign视觉对位软件的版本号在软件界面的右下角&#xff0c;如下图所示&#xff1a; 进入界面查看右下角编号尾号为O的代表旧协议版本 而编号尾号为N的则为新协议版本。 WiseAlign视觉对位软件 打开WiseAlign视觉对位软…

新版pycharm(2023.2.2)修改字体大小

下载了2023新版pycharm&#xff0c;想修改字体&#xff0c;发现找不到之前的setting入口&#xff0c;网上搜索也都是file-setting-editor这些&#xff0c;自己找了找&#xff0c;记录下 2023版pycharm的修改字体大小在file-Manage IDE Settings-Setting Sync… 里面&#xff0…