当前位置: 首页 > news >正文

视图矩阵的推导(2)

先来学习下uvn坐标系,如下图所示:

这里写图片描述

如图所示,我们定义摄像机的位置为:(-2,1,2)
目标点位置为(-1,2,3)。

然后我们明确一下,uvn坐标系统的uvn到底是什么?
u——右向量,相当于+x
v——上向量,相当于+y
n——朝向向量,相当于+z

u向量:这里是通过y叉乘n得到,y向量为(0,1,0),n向量为目标点-减去摄像机的位置点,即(-1,2,3)-(-2,1,2)=(1,1,1),经过叉乘我们可以得到u向量为(1,0,-1)。这个你可以通过这行代码验证:

glm::vec3 u = glm::cross(glm::vec3(0, 1, 0), glm::vec3(1, 1, 1));
cout << u.x << " " << u.y << " " << u.z << endl;

v向量:有了u向量,以及n向量,那么通过n叉乘u得到v向量,即上向量。这里n(1,1,1),u(1,0,-1),两者叉乘得到v(-1,2,-1)。
你可以通过代码验证:

glm::vec3 u = glm::cross(glm::vec3(1, 1, 1), glm::vec3(1, 0, -1));
cout << u.x << " " << u.y << " " << u.z << endl;

最终我们得到了下面的新的坐标系:
这里写图片描述

下面,我们就要介绍一下,世界坐标系中的点,比如P(1,2,3),在新的坐标系的坐标是什么了?我们首先列出下面的等式:
这里写图片描述
我们要求得(x’,y’,z’)即可。
这里写图片描述
ok,此时我们得到了世界中的一个点(1,2,3),在新的坐标系下的坐标为(-1,0,2)。

我们再看看上面的得到的uvn坐标系是不是有问题呢?有问题,因为没有把摄像机的位置算上去,我们的到的uvn坐标系是相对于原点的。那么下一步就要将这个uvn坐标系平移到摄像机的位置,如何做到呢?

这里写图片描述

u向量的平移:将(1,0,-1)+(-2,1,2)=(-1,1,1)
v向量的平移:将(-1,2,-1)+(-2,1,2)=(-3,3,1)
n向量的平移:将(1,1,1)+(-2,1,2)=(-1,2,3)
写成矩阵的形式为:
这里写图片描述
到这里我们才了解,网址中https://learnopengl.com/#!Getting-started/Camera的视图矩阵的推导。
我们还要说明下,上图中的R^-1,以及T^-1,怎么求,由于我们上面的得到R矩阵没有正交化,而在图形学中,一般是求正交矩阵,然后在单位化,这样R的逆矩阵,就等于它的转置矩阵了。而平移矩阵的逆,正好是其相反的操作,只要将平移的量取反即可。到此,我们就讨论完uvn系统,以及mvp矩阵中v矩阵的推导了。而这一步的迈出,必将为m矩阵,以及坐标系统的变换提供坚实的基础,这样可以更好的理解同一个向量在不同坐标系统下的变换过程。
同时,我们在线性代数中学习的,坐标系统、正交基、正交化、标准化,等概念,也再次在坐标变换中得到了实际的应用。当是学习并不太知道这将会用到什么地方,现在就明白了。
在图形学中,描述物体的空间位置,除了最大的世界坐标系,还有局部坐标系、视图(相机/眼睛)坐标系、那么不同的坐标系,都离不开三个基向量,它们是互相垂直的(也即是正交的)。
这样同一个向量,在不同的坐标系下,就有了不同的坐标。

相关文章:

  • opengl从画三角形到画一个立方体(一)
  • SphereCast和SphereCastAll
  • Java中String和byte[]间的转换浅析
  • opengl从画三角形到画一个立方体(二)
  • C语言列出真分数序列代码及解析
  • opengl从画三角形到画一个立方体(三)
  • es
  • opengl从画三角形到画一个立方体(四)
  • opengl从画三角形到画一个立方体(五)
  • ZYNQ. GPIO
  • bzoj 3027 [Ceoi2004]Sweet——生成函数
  • 将光源信息应用到立方体(一)
  • unity包内的内容读取
  • 栈和局部变量操作 将常量压入栈的指令
  • 将光源信息应用到立方体(二)
  • 【知识碎片】第三方登录弹窗效果
  • Fastjson的基本使用方法大全
  • git 常用命令
  • iOS筛选菜单、分段选择器、导航栏、悬浮窗、转场动画、启动视频等源码
  • Java|序列化异常StreamCorruptedException的解决方法
  • Javascript弹出层-初探
  • js学习笔记
  • SegmentFault 社区上线小程序开发频道,助力小程序开发者生态
  • 力扣(LeetCode)56
  • No resource identifier found for attribute,RxJava之zip操作符
  • LevelDB 入门 —— 全面了解 LevelDB 的功能特性
  • ​ 轻量应用服务器:亚马逊云科技打造全球领先的云计算解决方案
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • ​ArcGIS Pro 如何批量删除字段
  • #1014 : Trie树
  • #DBA杂记1
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (非本人原创)我们工作到底是为了什么?​——HP大中华区总裁孙振耀退休感言(r4笔记第60天)...
  • (附源码)计算机毕业设计ssm高校《大学语文》课程作业在线管理系统
  • (十六)一篇文章学会Java的常用API
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .Net 高效开发之不可错过的实用工具
  • .NET/C# 判断某个类是否是泛型类型或泛型接口的子类型
  • .NET/C# 如何获取当前进程的 CPU 和内存占用?如何获取全局 CPU 和内存占用?
  • .Net多线程总结
  • .project文件
  • @Async注解的坑,小心
  • @在php中起什么作用?
  • [ Linux ] git工具的基本使用(仓库的构建,提交)
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [Django开源学习 1]django-vue-admin
  • [HDOJ4911]Inversion
  • [Invalid postback or callback argument]昨晚调试程序时出现的问题,MARK一下
  • [JS设计模式]Prototype Pattern
  • [LeetCode]Balanced Binary Tree
  • [LeetCode刷题笔记]1 - 两数之和(哈希表)
  • [MFC] MFC消息机制的补充
  • [python] dict类型变量写在文件中
  • [Python] 什么是KMeans聚类算法以及scikit-learn中的KMeans使用案例