原文连接前端
做者:天瑜web
在二维平面内,咱们用(x, y)
来表示点的位置,经过向坐标原始值累加偏移值便可将点移动。但在三维空间内除了位置偏移外,还存在着旋转变化,所以空间内的每一个物体都具备至少两个基础特性:位置和方向。位置咱们能够用坐标来表达,那么方向由什么概念来表达呢?api
三维空间中物体的旋转变化,能够映射为坐标系的方向变化。换言之,咱们去旋转一个空间内的物体,能够将其转化为旋转坐标系。所谓一图胜千言,直接看下图:函数
咱们尽可能用简明意赅的语言来描述图片所传达出来的信息。图中有两个三维坐标系,一个蓝色(xyz)
,另外一个是红色(XYZ)
。首先,咱们先将蓝色坐标系沿z
轴旋转α
角度,再将蓝色坐标系沿新的x
轴旋转β
角度,最后将蓝色坐标系沿新Z
轴旋转γ
角度,就获得新的红色坐标系(XYZ)。若是将三次变换所围绕轴和角度记录下来,那么本次旋转的欧拉角为(z-x-z)-(α, β, γ)
。对三种旋转轴顺序进行排列组合后,咱们总结共有12种旋转顺序组合,也就是十二种欧拉角。post
对于某些简单的旋转方式,好比先绕x
轴旋转90
度,再绕y
轴旋转90
度,最后绕x
轴旋转-90
度,获得的结果与直接围绕z
轴旋转-90
度结果相同。也就是说实现一个三维旋转不必定非要围绕xyz
三个轴每一个轴都旋转一次。所以能够对十二种欧拉角作以下分类:学习
旋转轴顺序形如ABA
的经典欧拉角适用于相对简单的旋转场景,而须要三个旋转轴的泰布莱恩角更多应用于复杂的旋转场景,好比航空航天领域。google
线性代数中的矩阵不一样于咱们熟悉的形如y = ax + b
的数学关系式,很容易被"古怪"的概念和各类"方框"搞的晕头转向。正由于矩阵不一样于传统具体的数学关系式,在学习和理解矩阵须要转换思考方式。好比,咱们能够用具体公式来描述曲线,像贝塞尔曲线、三角函数曲线,但他们都是基于二维平面的,如何用数学来描述线性三维空间内的变换呢?矩阵所以应运而生。.net
回到本文主题,旋转顺序和角度咱们能够用欧拉角来表示,那么如何将其实际应用呢?答案是用旋转矩阵来表示旋转角。之前文坐标系转换为例,抽象出矩阵关系式:3d
依据矩阵除法求得M的值,便可获得旋转矩阵。在实际推导三维旋转矩阵以前,咱们首先推导二维旋转矩阵,有助于咱们更好的理解三维旋转矩阵:code
原始向量op
围绕o
点旋转φ
角度,原坐标(x, y)
变为(x', y')
,由图中标注可得:
由三角函数关系式可得:
依据矩阵乘法法则,以上关系式用矩阵表示为:
三维变换就是比二维变换多了一个z
轴罢了,当空间内的物体围绕x
轴旋转时,咱们能够理解为在yz
平面进行二维变换。实际推导过程与上式相似,只是x
坐标保持不变:
得出围绕x
轴的旋转矩阵为:
同理,当空间内的物体围绕y
轴和z
轴旋转时,记围绕x
、y
、z
三轴的旋转角分别为θ
、β
、γ
(即欧拉角),矩阵分别为P
、M
、Q
,有:
使用欧拉角来描述三维方向变化并非完美的,很经典的例子就是炮台问题:
假设地面上有一个炮台,它能够与地面平行的360度环绕,围绕轴记为x
轴,与地面垂直,也能够俯仰(仰视90度或俯视-90度),俯仰旋转时所围绕的轴记为y
轴,与地面平行。正北地平线方向记作x=0, y=0
。此时一个飞行器从正东x=90 y=10
方向向炮台飞来,炮口跟踪瞄准了该飞行器。当飞行器飞到炮台头顶时,飞行器的坐标(同时也是炮口的指向)也从x=90 y=10
逐渐递增到了x=90 y=90
。忽然飞行器向南飞行,但此时炮口垂直地面,不管如何旋转x
轴炮口始终指向天顶。从数据的角度说,从正东的x=90
到x=180
发生了不连续突变,然而飞行器的位置倒是连续的。
究其根本缘由,欧拉角的理论基础是分别计算围绕x
、y
、z
三轴旋转角度后合并而成的,多种旋转方式的结果会对应同一个三维空间角度,致使在插值场景中使用欧拉角会出现不连续的死锁问题(如上文的大炮跟踪)。死锁问题与解决在3D空间轨迹跟踪等领域有普遍的应用,更多例子有兴趣的读者能够自行google。
如何解决死锁问题呢?答案是四元数。核心理念就是摆脱对围绕x
、y
、z
旋转计算的依赖,空间内的旋转基于围绕任意轴计算,好比围绕(0, 4, 7)
轴。不过四元数就是另外一个复杂的话题了。
在前端应用层,并不是只有旋转这一种场景,除了旋转,还有平移、缩放等等。在上文中咱们使用三阶矩阵来表达变换,但在更复杂的变换场景中一般使用四阶矩阵来作计算,例如设平移距离分别为Tx
、Ty
、Tz
,那么获得平移四阶矩阵:
三阶矩阵的运算已经很繁琐,四阶更让人头皮发麻。万幸的是矩阵计算早已工程化了,没必要手工操做底层矩阵运算。以表明性的 three.js 为例,它有不少封装成熟的 api 可供使用,大大下降了开发前端3D应用的成本。还有函数库glmatrix,开发者只关心输入输出便可。
了解欧拉角和矩阵变换随便只是开发3D应用的第一步,更宽广的世界依然须要咱们不懈探索。