4×4齐次矩阵
作者:追风剑情 发布于:2018-12-15 21:46 分类:Algorithms
4D齐次空间
4D向量有4个分量,前3个是标准的x,y和z分量,第四个是w,有时称作齐次坐标。
为了理解标准3D坐标是怎样扩展到4D坐标的,让我们先看一下2D中的齐次坐标,它的形式为(x,y,w)。想象在3D中w=1处的标准2D平面,实际的2D点(x,y)用齐次坐标表示为(x,y,1),对于那些不在w=1平面上的点,则将它们投影到w=1平面上。所以齐次坐标(x,y,w)映射的实际2D点为(x/w,y/w)。
因此,给定一个2D点(x,y),齐次空间中有无数多个点与之对应。所有点的形式都为(kx,ky,k),k≠0。这些点构成一条穿过齐次原点的直线。
当w=0时,除法未定义,因此不存在实际的2D点。然而,可以将2D齐次点(x,y,0)解释为“位于无穷远的点”,它描述了一个方向而不是一个位置。
4D坐标的基本思想相同。实际的3D点能被认为是在4D中w=1“平面”上。4D点的形式为(x,y,z,w),将4D点投影到这个"平面"上得到相应的实际3D点(x/w,y/w,z/w)。w=0时4D点表示"无限远点",它描述了一个方向而不是一个位置。
齐次坐标和通过除以w来投影是很有趣的,那我们为什么要使用4D坐标呢?有两个基本原因使得我们要使用4D向量和4×4矩阵。第一个原因实际上就是因为它是一种方便的记法。
4×4平移矩阵
3×3变换矩阵表示的是线性变换,不包含平移。因为矩阵乘法的性质,零向量总是变换成零向量,因此,任何能用矩阵乘法表达的变换都不包含平移。这很不幸,因为矩阵乘法和它的逆是种非常方便的工具,不仅可以用来将复杂的变换组合成简单的单一变换,还可以操纵嵌入式坐标系间的关系。如果能找到一种方法将3×3变换矩阵进行扩展,使它能处理平移,这将是一件多么美妙的事情啊,4×4矩阵恰好提供了一种数学上的“技巧”,使我们能够做到这一点。
暂时假设w总是等于1。那么,标准3D向量[x, y, z]对应的4D向量为[x, y, z, 1]。任意3×3变换矩阵在4D中表示为:
任意一个形如[x, y, z, 1]的向量乘以上面形式的矩阵,其结果和标准的3×3情况相同,只是结果是用w=1的4D向量表示的:
现在,到了最有趣的部分。在4D中,仍然可以用矩阵乘法来表示平移,如下面公式所示,而在3D中是不可能的:
记住,即使是在4D中,矩阵乘法仍然是线性变换。矩阵乘法不能表达4D中的“平移”,4D零向量也将总是被变换成零向量。这个技巧之所以能在3D中平移点是因为我们实际上是在切变4D空间。与实际3D空间相对应的4D中的“平面”并没有穿过4D中的原点。因此,我们能通过切变4D空间来实现3D中的平移。
设想没有平移的变换后接一个有平移的变换会发生什么情况呢?设R为旋转矩阵(实际上,R还能包含其他的3D线性变换,但现在假设R只包含旋转),T为下面形式的变换矩阵:
将向量v先旋转再平移,新的向量v`计算如下:
注意,变换的顺序是非常重要的。因为我们使用的是行向量,变换的顺序必须和矩阵乘法的顺序相吻合(从左往右),先旋转再平移。和3×3矩阵一样,能将两个矩阵连成单个矩阵,记作矩阵M,如下:
观察M的内容:
注意到,M的上边3×3部分是旋转部分,最下一行是平移部分。最右一列为[0, 0, 0, 1]T。逆向利用这些信息,能将任意4×4矩阵分解为线性变换部分和平移部分。将平移向量[△x, △y, △z]记作t,则M可简写为:
注意:现在,我们暂时假设最右的一列总是[0, 0, 0, 1]T。后面我们很快就会遇到与此不同的情况。
接下来看w=0所表示的“无穷远点”。它乘以一个由“标准”3×3变换矩阵扩展成的4×4矩阵(不包含平移),得到:
换句话说,当一个形如[x, y, z, 0]的无穷远点乘以一个包含旋转、缩放等的变换矩阵,将会发生预期的变换。结果仍然是一个无穷远点,形式为[x`, y`, z`, 0]。
一个无穷远点经过包含平移的变换可得到:
注意到结果是一样的(和没有平移的情况相比)。换句话说,4D向量中的w分量能够“开关”4×4矩阵的平移部分。这个现象是非常有用的,因为有些向量代表“位置”,应当平移,而有些向量代表“方向”,如表面的法向量,不应该平移。从几何意义上说,能将第一类数据当作“点”,第二类数据当作“向量”。
使用4×4矩阵的一个原因就是4×4变换矩阵能包含平移。当我们仅为这个目的使用4×4矩阵时,矩阵的最右一列总是[0, 0, 0, 1]T。既然是这样,为什么不去掉最右一列而改用4×3矩阵呢?根据线性代数法则,由于多种原因,4×3矩阵不符合我们的需求,如下:
- 不能用一个4×3矩阵乘以另一个4×3矩阵。
- 4×3矩阵没有逆矩阵,因为它不是一个方阵。
- 一个4D向量乘以4×3矩阵时,结果是一个3D向量。
为了严格遵守线性代数法则,我们加上了第4列。当然,在代码中,可以不受线性代数法则的约束。
一般仿射变换
用3×3矩阵表达了很多基本变换。3×3矩阵仅能表达3D中的线性变换。经过4×4矩阵的武装后,现在我们可以构造包含平移在内的一般仿射变换矩阵了。例如:
- 绕不通过原点的轴旋转
- 沿不穿过原点的平面缩放
- 沿不穿过原点的平面镜象
- 向不穿过原点的平面正交投影
它们的基本思想是将变换的“中心点”平移到原点,然后进行线性变换,然后再将“中心点”平移回原来的位置。开始使用平移矩阵T将点P移到原点,接着用线性变换矩阵R进‘行线性变换,最终的仿射变换矩阵M等于矩阵的积,即:TRT-1。T-1是平移矩阵,执行和T相反的变换。
观察这种矩阵的一般形式,它非常有趣。让我们先用“分块”形式写出前面用到的T,R,T-1:
现在进行矩阵乘法有:
可以看出,仿射变换中增加的平移部分仅仅改变了4×4矩阵的最后一行,并没有影响到上面所包含的线性变换的3×3部分。
透视投影
上面对“齐次”坐标的使用不过是一种数学上的技巧,目的是使我们能在变换中包含平移。我们在“齐次”两边使用了引号,因为w总是为1(或0,当点在无穷远处时)。本节将讨论使用其他w值的有意义的4D坐标。
将4D齐次向量变换到3D中时,要先把4D向量除以w。这给出了一种前面没有加以利用的数学方法,因为在之前中,w要么等于1,要么等于0。这个除法使我们可以非常简洁地包含一些重要的几何运算。更加明确一些,我们能进行透视投影。
学习透视投影最好的方法就是将它和我们已经学习过的一种投影——平行投影相比较。将3D空间投影到2D平面上,该平面称作投影平面,使用的是正交投影。正交投影也被称作平行投影,因为投影都是平行的(投影线是指从原空间中的点到投影点的连线)。3D中的透视投影仍然是投影到2D平面上,但是,投影线不再平行。实际上,它们相交于一点,该点称作投影中心。
因为投影中心在投影平面前面,投影线到达平面之前已经相交,所以投影平面上的图像是翻转的。当物体远离投影中心时,正交投影仍保持不变,但透视投影变小了(这是一种非常重要的视觉现象(近大远小),称作:透视缩略)。
参见 投影平面
使用4×4矩阵进行透视投影
从4D到3D的变换就意味着除法运算,因此我们可以利用4×4阶矩阵来编写代码,以实现透视投影。基本思想是提出一个关于P`的公式,其中的x,y,z有公分母,然后构造一个4×4矩阵,使w与这个公分母相等。这里我们假设初始点处有w=1。
先对3D形式表达的P`公式变形,可以得到:
将4D齐次向量变换到3D中时,要用4D向量除以w,反推可知P`的4D形式为:
因此我们需要一个4×4矩阵,它可接收一个奇异的齐次向量。该向量的形式为[x, y, z, 1],然后将其变换为上述形式。这样的矩阵如下所示:
用4×4矩阵向z=d平面投影:
这样,就得到了一个4×4投影矩阵。有几个需要注意的地方:
- 乘以这个矩阵并没有进行实际的透视投影变换,它只是计算出合适的分母。投影实际发生在从4D向3D变换时。
- 存在多种变化。例如,将投影平面放在z=0处而投影中心在[0,0,-d]。这将导致一个不同的公式。
- 这里看起来比较复杂,似乎只需要简单地除以z,不必劳烦矩阵。那么为什么要使用齐次矩阵呢?第一,4×4矩阵提供了一种方法将投影表达为变换,这样就能和其他变换相连接;第二,使得投影到不平行于坐标轴的平面变得可行。实际上,我们不需要齐次坐标做任何运算,但4×4矩阵提供了一种简洁的方法表达和操纵投影变换。
- 实际的图形几何管道中的投影矩阵不是像这里导出的那样。还有许多重要的细节需要考虑。如,用以上矩阵对向量进行变换后,z值实际上被舍弃了,而很多图形系统的z缓冲用到了该值。
标签: Algorithms
日历
最新文章
随机文章
热门文章
分类
存档
- 2024年11月(3)
- 2024年10月(5)
- 2024年9月(3)
- 2024年8月(3)
- 2024年7月(11)
- 2024年6月(3)
- 2024年5月(9)
- 2024年4月(10)
- 2024年3月(11)
- 2024年2月(24)
- 2024年1月(12)
- 2023年12月(3)
- 2023年11月(9)
- 2023年10月(7)
- 2023年9月(2)
- 2023年8月(7)
- 2023年7月(9)
- 2023年6月(6)
- 2023年5月(7)
- 2023年4月(11)
- 2023年3月(6)
- 2023年2月(11)
- 2023年1月(8)
- 2022年12月(2)
- 2022年11月(4)
- 2022年10月(10)
- 2022年9月(2)
- 2022年8月(13)
- 2022年7月(7)
- 2022年6月(11)
- 2022年5月(18)
- 2022年4月(29)
- 2022年3月(5)
- 2022年2月(6)
- 2022年1月(8)
- 2021年12月(5)
- 2021年11月(3)
- 2021年10月(4)
- 2021年9月(9)
- 2021年8月(14)
- 2021年7月(8)
- 2021年6月(5)
- 2021年5月(2)
- 2021年4月(3)
- 2021年3月(7)
- 2021年2月(2)
- 2021年1月(8)
- 2020年12月(7)
- 2020年11月(2)
- 2020年10月(6)
- 2020年9月(9)
- 2020年8月(10)
- 2020年7月(9)
- 2020年6月(18)
- 2020年5月(4)
- 2020年4月(25)
- 2020年3月(38)
- 2020年1月(21)
- 2019年12月(13)
- 2019年11月(29)
- 2019年10月(44)
- 2019年9月(17)
- 2019年8月(18)
- 2019年7月(25)
- 2019年6月(25)
- 2019年5月(17)
- 2019年4月(10)
- 2019年3月(36)
- 2019年2月(35)
- 2019年1月(28)
- 2018年12月(30)
- 2018年11月(22)
- 2018年10月(4)
- 2018年9月(7)
- 2018年8月(13)
- 2018年7月(13)
- 2018年6月(6)
- 2018年5月(5)
- 2018年4月(13)
- 2018年3月(5)
- 2018年2月(3)
- 2018年1月(8)
- 2017年12月(35)
- 2017年11月(17)
- 2017年10月(16)
- 2017年9月(17)
- 2017年8月(20)
- 2017年7月(34)
- 2017年6月(17)
- 2017年5月(15)
- 2017年4月(32)
- 2017年3月(8)
- 2017年2月(2)
- 2017年1月(5)
- 2016年12月(14)
- 2016年11月(26)
- 2016年10月(12)
- 2016年9月(25)
- 2016年8月(32)
- 2016年7月(14)
- 2016年6月(21)
- 2016年5月(17)
- 2016年4月(13)
- 2016年3月(8)
- 2016年2月(8)
- 2016年1月(18)
- 2015年12月(13)
- 2015年11月(15)
- 2015年10月(12)
- 2015年9月(18)
- 2015年8月(21)
- 2015年7月(35)
- 2015年6月(13)
- 2015年5月(9)
- 2015年4月(4)
- 2015年3月(5)
- 2015年2月(4)
- 2015年1月(13)
- 2014年12月(7)
- 2014年11月(5)
- 2014年10月(4)
- 2014年9月(8)
- 2014年8月(16)
- 2014年7月(26)
- 2014年6月(22)
- 2014年5月(28)
- 2014年4月(15)
友情链接
- Unity官网
- Unity圣典
- Unity在线手册
- Unity中文手册(圣典)
- Unity官方中文论坛
- Unity游戏蛮牛用户文档
- Unity下载存档
- Unity引擎源码下载
- Unity服务
- Unity Ads
- wiki.unity3d
- Visual Studio Code官网
- SenseAR开发文档
- MSDN
- C# 参考
- C# 编程指南
- .NET Framework类库
- .NET 文档
- .NET 开发
- WPF官方文档
- uLua
- xLua
- SharpZipLib
- Protobuf-net
- Protobuf.js
- OpenSSL
- OPEN CASCADE
- JSON
- MessagePack
- C在线工具
- 游戏蛮牛
- GreenVPN
- 聚合数据
- 热云
- 融云
- 腾讯云
- 腾讯开放平台
- 腾讯游戏服务
- 腾讯游戏开发者平台
- 腾讯课堂
- 微信开放平台
- 腾讯实时音视频
- 腾讯即时通信IM
- 微信公众平台技术文档
- 白鹭引擎官网
- 白鹭引擎开放平台
- 白鹭引擎开发文档
- FairyGUI编辑器
- PureMVC-TypeScript
- 讯飞开放平台
- 亲加通讯云
- Cygwin
- Mono开发者联盟
- Scut游戏服务器引擎
- KBEngine游戏服务器引擎
- Photon游戏服务器引擎
- 码云
- SharpSvn
- 腾讯bugly
- 4399原创平台
- 开源中国
- Firebase
- Firebase-Admob-Unity
- google-services-unity
- Firebase SDK for Unity
- Google-Firebase-SDK
- AppsFlyer SDK
- android-repository
- CQASO
- Facebook开发者平台
- gradle下载
- GradleBuildTool下载
- Android Developers
- Google中国开发者
- AndroidDevTools
- Android社区
- Android开发工具
- Google Play Games Services
- Google商店
- Google APIs for Android
- 金钱豹VPN
- TouchSense SDK
- MakeHuman
- Online RSA Key Converter
- Windows UWP应用
- Visual Studio For Unity
- Open CASCADE Technology
- 慕课网
- 阿里云服务器ECS
- 在线免费文字转语音系统
- AI Studio
- 网云穿
- 百度网盘开放平台
- 迅捷画图
- 菜鸟工具
- [CSDN] 程序员研修院
- 华为人脸识别
- 百度AR导航导览SDK
- 海康威视官网
- 海康开放平台
- 海康SDK下载
- git download
交流QQ群
-
Flash游戏设计: 86184192
Unity游戏设计: 171855449
游戏设计订阅号