绕任意不穿过原点轴的四维旋转矩阵
最近工作需要根据给定的任意轴(起点(x1,y1,z1),终点(x2,y2,z2))旋转某个模型θ角度,查了很多资料都指向矩阵变换
# 矩阵和线性变换
# 在二维中的旋转
在二维平面中的旋转之前已经讨论过了,二维绕原点旋转矩阵
直接说一下结论,二维旋转矩阵:
# 围绕主轴的三维旋转
在三维中,旋转发生在一个轴而不是一个点上,术语轴呈现出它更场景的含义:它是一条线,有些东西绕着它转动。
旋转轴不一定必须是基本的x,y,z轴之一,但我们先从这些特殊情况开始。遵循左手规则,在左手坐标系中,正向旋转从轴的正端看时是顺时针,而在右手坐标系中,正向旋转是逆时针。
- 围绕x轴旋转的三维矩阵
- 围绕y轴旋转的三维矩阵
- 围绕z轴旋转的三维矩阵
注意
矩阵在左手或右手坐标系中均可正常工作,就像照镜子一样。
# 围绕任意轴的三维旋转
毫无疑问,也可以在三维中围绕任意轴旋转,当然,前提是该轴要穿过原点,因为此刻不考虑平移。
将θ定义为绕轴的旋转量,轴将由单位矢量n定义。让我们推导出一个围绕n旋转角度θ的矩阵。换句话说,我们希望推导出矩阵R(n,θ),使得当将矢量v乘以R(n,θ)时,得到的矢量v'将是v围绕n旋转角度θ的以下结果:
v' = vR(n,θ)
为了得到矩阵R(n,θ),首先看一看是否可以用v,n,和θ来表达v'。
其基本思路是解决垂直于n的平面中的问题,这是一个更简单的二维问题。
为此,将v分为两个矢量v∥和v⊥,它们分别平行和垂直于n,使得
v = v∥ + v⊥
通过单独旋转每个分量,可以将矢量作为一个整体旋转。换句话说:
v' = v'∥ + v'⊥
由于v∥与n平行,因此它不会受到围绕n旋转的影响。换句话说:
v'∥ = v∥
所以需要做的就是计算v'⊥,然后得到
v' = v∥ + v'⊥
为了计算v'⊥可以构造v∥、v⊥和中间矢量w,具体如下所述:
矢量v∥是v的与n平行的部分。另一种说法是v∥是投影到n上的v的值。因此 v∥=(v·n)n。
矢量v⊥是v与n垂直的部分。由于v = v∥ + v⊥, v⊥可以通过v-v∥计算。v⊥是将v投影到垂直于n的平面上的结果。
矢量w与v∥和v⊥相互垂直,并且长度与v⊥相同。它可以通过围绕n旋转v⊥90°来构造,因此看到它的值很容易通过w = n × v⊥ 来计算。
这些矢量如何帮助我们计算v'⊥呢?
请注意,w和v⊥形成了一个二维坐标空间,其中,v⊥作为“x轴”,而w作为“y轴”(注意v⊥和w这两个矢量并不一定需要具有单位长度)。
v'⊥是在这个平面上按照角度θ旋转v⊥的结果。
请注意,旋转角度θ的单位线条的端点是cosθ和sinθ。这里唯一的区别是,线条不是单位线条,并且使用了 v⊥ 和 w 作为基矢量。因此,v'⊥可以计算为:
v'⊥ = cosθv⊥ + sinθw
现在来总结一下计算出的以下矢量:
v∥ = (v·n)n
v⊥ = v - v∥ = v - (v·n)n
w = n × v⊥ = n × (v - v∥) = n × v - n × v∥ = n × v - 0 = n × v
v'⊥ = cosθv⊥ + sinθw = cosθ(v - (v·n)n) + sinθ(n × v)
带入v',可得:
v' = v'⊥ + v∥ = cosθ(v - (v·n)n) + sinθ(n × v) + (v·n)n
上式允许围绕任意轴旋转任意矢量。可以使用这个公式执行任意旋转变换,所以从某种意义上说已经完成了,剩下的算术基本上是将式子表示为矩阵乘积的符号变化。
p = [1, 0, 0]
p' = cosθ(p - (p·n)n) + sinθ(n × p) + (p·n)n
= cosθ([1, 0, 0] - ([1, 0, 0]·[nx, ny, nz])[nx, ny, nz]) + sinθ([nx, ny, nz]×[1, 0, 0]) + ([1, 0, 0]·[nx, ny, nz])[nx, ny, nz]
= cosθ([1, 0, 0] - nx[nx, ny, nz]) + sinθ[0, nz, -ny] + nx[nx, ny, nz]
= cosθ([1-nx2, -nxny, -nxnz]) + sinθ[0, nz, -ny] + [nx2, nxny, nxnz]
= [cosθ-nx2cosθ, -nxnycosθ, -nxnzcosθ] + [0, nzsinθ, -nysinθ] + [nx2, nxny, nxnz]
= [cosθ-nx2cosθ+nx2, -nxnycosθ+nzsinθ+nxny, -nxnzcosθ-nysinθ+nxnz]
= [nx2(1-cosθ)+cosθ, nxny(1-cosθ)+nzsinθ, nxnz(1-cosθ)-nysinθ]
q = [0 1 0], r = [0 0 1],计算可得围绕任意轴旋转的三维矩阵:
# 4 × 4齐次矩阵
# 关于四维齐次空间
四维矢量有4个分量,前3个分量是标准的x、y和z分量。四维矢量中的第四个分量是w,有时称为齐次坐标。
为了理解标准物理三维空间是如何扩展到四维的,让我们先来看一下二维中的齐次坐标,其形式为(x,y,w)。
想象一下,在三维中w = 1处的标准二维平面,实际的二维点(x,y)用齐次坐标表示为(x,y,1),对于那些不在w=1平面上的点,则可以通过除以w,将它们投影到w=1平面上,从而计算相应的二维的点。
这样,齐次坐标(x,y,w)就可以映射到实际的二维点(x/w, y/w)
对于任何给定的物理二维点(x,y),在齐次空间中存在无限数量的对应点,所有点的形式都是(kx, ky, k),条件是k≠0。这些点形成一条穿过(齐次)原点的直线。
当w=0时,该除法是未定义的,并且在二维空间中没有对应的物理点。但是我们可以将形式为(x,y,0)的二维齐次点解释为“无限远的点”,它定义的是方向而不是位置。
当我们对“点”和“矢量”进行概念上区分时,那么当w≠0时,它的“位置”就是“点”;而当w=0时,它的“方向”就是“矢量”。
将物理三维空间扩展到四维齐次空间时,同样的基本思想也使用。
物理三维点可以被认为是存在于四维的w = 1的超平面中。四维点的形式是(x,y,z,w),并且可以将四维点投射到该超平面上以产生相应的物理三维点(x/w,y/w,z/w)。当w=0时,四维点代表“无限远的点”,它将定义方向而不是位置。
为什么要使用四维空间呢?
- 可以表示三维空间的平移
- 如果将适当的值放入w中,则齐次除法将导致透视投影
# 关于4 × 4平移矩阵
3×3变换表示线性变换,不包含平移。由于矩阵乘法的特性,零矢量总是被变换为零矢量,因此,任何可以由矩阵乘法表示的变换都不能包含平移。
这是很糟糕额,因为矩阵乘法和求逆都是非常方便的工具,它们不但可以通过简单的方法组合出复杂的变换,而且还可以操纵嵌套的坐标空间关系。因此,如果能够找到一种方法以某种方式扩展标准的3×3变换矩阵以便能够处理包括平移的变换,那将是一件大好事!
4×4矩阵就提供了这样一个数学上的“方便之门”,允许我们这样做。
假设w始终为1,。因此,标准三维矢量[x,y,z]在四维中表示为[x,y,z,1]。任何3×3变换矩阵都可以通过以下转换公式实现在四维中的表示:
当将[x,y,z,1]形式的四维矢量乘以这种形式的4×4矩阵时,得到与标准3×3情况相同的结果,唯一的区别是附加坐标w=1,具体如下:
现在来到了非常有趣的部分。在四维中,可以用矩阵乘法来表示平移,而在三维中,这是几乎不可能的事情,具体如下:
提示
这种矩阵乘法仍然是线性变换。矩阵乘法不能表示四维中的“平移”,四维零矢量将始终变换回四维零矢量。这个技巧能够有效在三维中变换点的原因是我们实际上实在错切四维空间。
让我们来看一看,当执行一次没有平移的变换,然后再执行一次仅有平移的变换之后会发生什么。
设R是一个旋转矩阵(实际上,R还可以包含其他三维线性变换,但是现在,假设R只包含旋转),设T是平移矩阵,这两个矩阵分别如下:
然后可以先旋转再平移点v来计算新点v',其公式如下:
v' = vRT
请记住,这里的变换顺序很重要,因为选择使用的是行矢量,所以变换的顺序与矩阵从左到右相乘的顺序一致。我们先旋转再平移。
就像3×3矩阵一样,可以将两个矩阵连接成单个的变换矩阵,然后将它指定给矩阵M,具体如下:
M = RT
v' = vRT = v(RT) = vM
现在来看一看M的内容:
可以看到,M的上面的3×3部分包含旋转的部分,底下的行包含的是平移部分,最右边的列是[0,0,0,1]T
反过来应用该信息,可以采用任何4×4矩阵并将其分成线性变换部分和平移部分。通过将平移矢量[△x,△y,△z]指定给矢量t,可以用块矩阵表示法很简洁地将该公式转换为以下形式:
注意
目前,假设4×4变换矩阵的最右列总是[0,0,0,1]T
现在来看看所谓的“无限远的点”(w=0时的那些矢量)会发生什么。将它们乘以扩展为四维的“标准”3×3线性变换矩阵(不包含平移的变换),可得:
换句话说,当将形式为[x,y,z,0]的无穷远的点的矢量乘以包含旋转、缩放等的变换矩阵时,会发生预期的变换,结果是另一个形式为[x',y',z',0]的无穷远的点的矢量。
当将形式为[x,y,z,0]的无穷远的点的矢量乘以包含平移的变换矩阵时,会得到以下结果:
可以看到,其结果是一样的,也就是说,不会发生平移。
提示
换句话说,四维矢量的w分量可用于选择性地“开关”4×4矩阵的平移部分。
这个发现是很有用的,因为一些矢量代表“位置”,所以它应该被平移,而其他矢量则代表“方向”(比如表面法线),所以它不应该被平移。
在几何意义上,可以将第一类数据(w=1)视为“点”,将第二类数据,即“无限远的点”(w=0)视为“矢量”。
因此,4×4矩阵非常有用的原因之一,就是4×4变换矩阵可以包含平移。当仅为此目的而使用4×4矩阵时,矩阵的最右列始终为[0,0,0,1]T。
为什么不放弃列而使用4×3矩阵呢?
根据线性代数规则,4×3矩阵是不可取的,原因如下:
- 不能将4×3矩阵乘以另一个4×3矩阵。
- 不能获得4×3矩阵的逆,因为该矩阵不是正方形。
- 当将四维矢量乘以4×3矩阵时,结果是三维矢量。
# 一般仿射变换
使用4×4变换矩阵,现在可以创建包含平移的更一般性地仿射变换,例如:
- 围绕不穿过原点的轴旋转
- 围绕不穿过原点的平面进行缩放
- 围绕不穿过原点的平面反射
- 在不穿过原点的平面上进行正交投影
这里的基本思想是将变换的“中心”平移到原点,然后使用之前推导出的穿过原点的变换矩阵执行线性变换,最后将中心平移回原始位置。
我们从将点p平移到原点的平移矩阵T开始,然后执行线性变换矩阵R,最终仿射变换矩阵A将等于矩阵乘积TR(T-1),其中T-1是具有与T相反的平移量的平移矩阵。
观察这种矩阵的一般形式是很有趣的。现在先试用之前介绍过的形式分别写出以下T、R和T-1:
评估该矩阵乘法,可得:
因此,仿射变换中的额外平移仅改变4×4矩阵的最后一行,上面的3×3部分则不受影响。