OpenGL ES 的很多教程里都会有这样一个例子来讲解纹理:将一张图片作为纹理显示在屏幕上。

因为纹理坐标和实际屏幕显示的坐标不一样,把图片渲染在屏幕上后,图片是上下颠倒的。

一个解决方法是对当前的顶点坐标,乘以绕 z 轴旋转180度的矩阵,这样图片就能正确显示了。

那么如何理解这个旋转矩阵呢?

影响我们理解这个矩阵的第一个问题是:

为什么这个矩阵是 4x4 的? 而且我们发现旋转,缩放、平移等变换矩阵都是 4x4 的。

在直观上的认知里,表达一个三维空间的坐标用 x,y,z 就足够了,那在三维空间里进行矩阵变换,用 3x3 的矩阵就够了,为什么需要 4x4 呢?

为了回答这个问题,下面我们先在几何意义上理解**向量和矩阵之间的关系,然后通过推导旋转矩阵**和平移矩阵,一步步来解开这个疑惑。

向量和矩阵

在几何平面上,我们可以把平面上任意一,当作与原点组成的一个 向量 来理解。

如图 ,A 点可以表示成向量    ;在 x 轴和 y 轴上各有 i 点(1, 0)和  j 点(0,1),同样的,让它们与原点组成向量,为了简化,我们用    和 表示这两个向量。

向量和矩阵

因为 A 点的坐标为 (3, 2),如果我们要用    和  表示 ,那是这样的:

这里的几何意义是 延展到  , 延展到 ,然后把这两个向量相加即可得到

i  坐标是 (1, 0),j 坐标是 (0,1),我们把上面这个等式转换成竖列的形式:

这里其实是向量的简单运算,运算过程如下:

看到运算过程是否有种似曾相识的感觉?这不就是矩阵与向量的乘法计算吗?这个运算其实就是将向量左乘一个矩阵 的计算:

这里  其实就是单元矩阵,左乘一个单元矩阵并不会改变原来的值。而这个单元矩阵以两个竖列来看,正是 i 和 j 点的坐标,也是向量    和   ,在数学上将    和    称为此坐标系的 基向量

推导旋转矩阵

我们现在把整个坐标轴绕原点逆时针旋转   :

推导旋转矩阵

旋转后  i 点和 j 点对应    和   位置。

通过简单的三角函数计算得到: 坐标为 , 坐标为

旋转后,A 点的坐标是多少呢?回顾上面的做法, 延展到  , 延展到 ,然后把这两个向量相加即可得到 。结合上面一节矩阵和向量的推演,可以变成下面的形式:

我们发现,左边的矩阵不正是开头所看到的 旋转矩阵 吗?只不过这是二维平面上的旋转矩阵:

结合图形和计算,我们可以这样理解这个二维矩阵:二维矩阵代表一个坐标系里的两个基向量,而在这个坐标系里的点与原点组成的向量,都可以用这两个基向量的变换来表示。那么旋转一个点,可以转换成旋转这个点所在的坐标系,从而通过变化的基向量求出旋转后的点的位置。

其实这种变换在数学上称作 线性变换 ,线性变换是通过 矩阵乘法 来实现

线性变换:是在两个向量空间(包括由函数构成的抽象的向量空间)之间的一种保持向量加法和标量乘法的特殊映射

线性变换在几何直观上有如下特点:

  • 变换前后,直线仍然保持是直线的状态

  • 变换前后,原点保持固定,不会变化

我们从二维平面,推导到三维坐标也是同理,只不过是多了个 z 轴

竖着来看这个矩阵,是 x,y,z轴上的三个基向量,同时它又是一个单元矩阵。

同理上面二维平面的推导,三维坐标绕 z 轴的旋转矩阵为:

推导平移矩阵

那么平移操作,能不能也用这种矩阵与向量相乘的形式呢?我们再次回到二维平面,看看将 A 点平移到 B 点的情况是怎样的。

要将 A 点(3,2)平移到 B 点(4,5),实际上就是先将 A 点往右移动 1 ,再往上移动 3,即 x 坐标值增加 1,y坐标值增加 3

从上面的运算来看,平移这种操作实际上是 向量的加法,即:

我们可以通过向量加法的 平行四边形法则 加深理解,如下图:

对于平移这种操作,我们无法仅仅通过矩阵乘法来实现

而实际上,平移这种操作属于 仿射变换

仿射变换,又称仿射映射,是指在几何中,对一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。

仿射变换在几何直观上,相比线性变换,它不需要保证变换前后坐标原点不变。

如下图,从 A 点平移到 B 点,我们换一个角度思考,这次不移动点,而是移动整个坐标轴,同样可以达到平移 A 点到 B 点的需求,但是坐标原点移动到了 O' 点(1,3)。

我们希望构造的是像下面这种矩阵乘法的等式,这样才能用一个通用的计算模式来处理坐标点的变换。

矩阵

到这里,我们终于要请出 齐次坐标 了。

齐次坐标就是将一个原本是 n 维的向量用一个 n+1 维向量来表示,是指一个用于投影几何里的坐标系统,如同用于欧氏几何里的笛卡儿坐标一般。

用一个通俗的讲法是,我们需要 升维 来处理这个问题。

通过增加一个维度,我们可以在高维度上,通过线性变换来处理低维度的仿射变换。

这句话咋一听感觉很有哲理,但是通过下面的数学等式就能知道其中的奥妙:

观察上面的运算过程,结果 不正是我们上面所得的 吗?只不过多了一个 z 轴的坐标值。

我们通过升级一个维度,将在二维平面上的平移问题转换成了在三维坐标的矩阵和向量乘法。那么在二维平面上,这个平移矩阵就为:

tx 和 ty 就对应在 x 轴 和 y 轴上的移动距离。

同理推广到三维坐标系,要实现三维坐标的平移操作,同样需要通过升维,引入齐次坐标来计算。那么三维坐标下的平移矩阵就为:

总结

至此,我们可以回答最开始的问题了,为什么 OpenGL 里的矩阵变换是 4x4 的矩阵呢?

我们来想象这样一个场景:如果我要让顶点坐标旋转一定角度后,再平移一段距离,那么这里面的操作就涉及 3x3 矩阵的计算和 4x4 矩阵的计算,如果不统一起来,这种连续变换的计算操作将很复杂。

所以如果要用矩阵乘法来统一所有的平移、旋转等等变换计算,为了照顾到平移这类仿射变换,统一用 4x4 矩阵来计算既能满足场景又方便计算。

求一个向量变换为另一个向量的矩阵_OpenGL里旋转等变换矩阵为什么是4x4的矩阵...相关推荐

  1. 合同变换为什么是一个行变换再跟一个相应的列变换?

    01 为什么合同变换总是一对一对的? 定义 两个 n n n阶方阵 A A A和 B B B满足关系: B = C T A C B=C^TAC B=CTAC,其中 C C C是可逆矩阵,则称 A A ...

  2. C4D制作一个物体变换成另一个物体动画

    整体流程 1.用ps或者Ai绘制两条这样的轮廓线,可以通过旋转制作2个物体 2.将这两个物体放置在原点,并将物体轴心也放置在原点. 3.制作一个旋转,分别查看物体是否正确 4.去掉旋转生成器,添加矩阵 ...

  3. 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文,但“good”不是回文。试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈)

    栈与队列习题:回文是指正读反读均相同的字符序列,如"abba"和"abdba"均是回文,但"good"不是回文.试写一个算法判定给定的字符向 ...

  4. MATLAB的size()函数的返回值是一个1*2的向量哦,即使参数是向量也是1*2的向量哦!

    MATLAB的size()函数的返回值是一个1*2的向量哦,即使参数是向量也是1*2的向量哦! 返回的向量第一个元素表示有多少行,第二个元素表示有多少列,如果size()的输入参数是一个向量,那么返回 ...

  5. 可由线性表示且表达式唯一_一个向量能由另一个向量组线性表示,且表示式唯一的等价条件是什么?...

    展开全部 表示唯一即需要A中的向量不能相互表示,也就是A中的向量线性无关时,由A中向量表示成b时表示方法唯32313133353236313431303231363533e58685e5aeb9313 ...

  6. 回文是指正读反读均相同的字符序列,如“abba“和“abdba“均是回文,但“good“不是回文。试写一个算法判定给定的字符向量是否为回文。(提示:将一半字符入栈)

    题目要求:回文是指正读反读均相同的字符序列,如"abba"和"abdba"均是回文,但"good"不是回文.试写一个算法判定给定的字符向量是 ...

  7. 一个向量图像创建为一个矢量插图程序直线和曲线是连接点

    所有的计算机图像分为两种基本类型:光栅图像(也称为一个位图)和矢量图像.在某些情况下,推荐使用矢量图形,在其他人,这取决于项目的性质,我们建议使用一个位图图像.有时,这两种格式可以一起使用.理解的优点 ...

  8. Games101计算机图形学入门基础之一:向量变换、矩阵变换、视图变换、欧拉角与四元数

    Games101计算机图形学入门基础之一:向量变换.矩阵变换.齐次坐标.欧拉角与四元数 目录 Games101计算机图形学入门基础之一:向量变换.矩阵变换.齐次坐标.欧拉角与四元数 前言 向量 向量加 ...

  9. c#中计算三角形面积公式_高中数学|向量公式之用平面向量求三角形面积

    高中数学|数列求和的几种策略 点击上方蓝字关注"公众号" 向量公式之 用平面向量求三角形面积 在学习向量时,我们能体会到向量的表达形式的多样化和直观性,而这些特点使解题更加简洁,可 ...

最新文章

  1. SharePoint技术峰会2009视频(6)
  2. oracle如果为空替换为0,oracle 如何把0转为null
  3. c++简单实现http协议服务器和客户端
  4. 电商等大型网站高可用,高负载架构借鉴方案(转载)
  5. css禁用选中文本_使用CSS禁用文本选择突出显示
  6. 嵌入式设备中支持国密算法的方法
  7. 问题 A: 【一本通提高组合数学】Bullcow 牡牛和牝牛
  8. java.lang.IllegalArgumentException: No enum constant org.apache.ws.commons.schema.XmlSchemaForm.
  9. SpringMVC返回JSON格式数据
  10. SIP呼叫中关于PRACK的使用
  11. 基于C++和AStar算法求解八数码问题的方案
  12. BIM项目分享---港珠澳大桥的BIM应用与管理
  13. jsp linux 一键安装包,JspStudy免费版|JspStudy(jsp环境一键安装包) v2016.01.01免费版_星星软件园...
  14. 洛谷-明明的随机数(C语言实现)
  15. iOS 16 Beta 系统上线,Testin云测试云真机服务全新升级
  16. c语言对文本霍夫曼编码,C语言之霍夫曼编码学习
  17. 初装vs2010旗舰版 遇到的错误
  18. 使用fir im进行内测托管
  19. 老生常谈之防止刷新重复提交表单。
  20. left join和left semi join的联系和区别

热门文章

  1. 11.04.30 半夜清晨
  2. cocos 制作动态生成内容的列表_零代码工具,让你在线轻松制作交互内容!
  3. 电子科技大学2019年计算机复试分数线,2019考研电子科技大学复试分数线已公布...
  4. mysql函数使用场景_mysql的函数和存储过程的比较,以及在实际场景中的使用案例...
  5. 魅族15系统是android,魅族15系列评测:性能够用王者荣耀优化
  6. splat net_Ruby中的Splat参数
  7. hbase 伪分布安装 java_HBase基础和伪分布式安装配置
  8. Haproxy实现负载均衡
  9. 计算机考研985院校不歧视,考研最不歧视的985大学有哪些
  10. java nextlong_Java Random nextLong()方法与示例