是否可以将矩阵的快速逆应用于纯旋转和平移矩阵的串联,例如M = T2*R1*T1*R1
?
如果我将旋转和平移存储在 4x4 齐次列序矩阵中,我可以说:
M1 = [ R1 t1 ] given by [ 1 t1 ] * [ R1 0 ]
[ 0 1 ] [ 0 1 ] [ 0 1 ]
和
inv(M1) = [inv(R1) inv(R1)*-t1 ] given by [ 1 -t1 ] * [ inv(R1) 0 ]
[ 0 1 ] [ 1 1 ] * [ 0 1 ]
由于 R1 是旋转,只有我们知道 inv(R1( = 转置(R1(,所以我们可以简单地说:
inv(M1) = [transp(R1) transp(R1)*-t1 ]
[ 0 1 ]
现在给定一些其他类似的旋转和平移矩阵 M2,如果我们说两者的串联形式为 MFinal = M2 * M1 = T2*R1*T1*R1
我们可以说吗
inv(MFinal) = [transp(MFinalRot) transp(MFinalRot)*-tfinal ]
[ 0 1 ]
其中 MFinalRot 是 4x4 矩阵的旋转部分?
此外,如果顺序更随意,例如MFinal2 = R3*T3 * T2*R2*T1*R1
,但仍然只是单独的旋转和平移怎么办?
是的,如果您的 4x4 矩阵是纯旋转和平移矩阵的串联,您应该能够计算快速逆函数:
fast_inverse( [R1 t1] ) = [transpose(R1) transpose(R1)*(-t1)]
[0 1] [ 0 1 ]
这是因为 3x3 旋转矩阵(R1
在您的代码中(将只是输入旋转矩阵的乘积,因此它本身应该是一个旋转矩阵,并且它的转置应该是它的逆矩阵。
任何级联矩阵是缩放矩阵,或者如果底行未[0 0 0 1]
,则不再如此。
另请注意:在实践中,如果将足够多的矩阵相乘,浮点误差可能会导致它们"漂移"一些,因此它们可能不像新生成的矩阵那样接近适当的旋转矩阵。 根据你如何使用它,这可能不是问题 - 但如果是,你可以"重新正统化"它,如下所示:
orth(Vec3 a, Vec3 b): // return value orthogonal to b
return (a - (dot(a,b)/dot(b,b)) * b)
re_orthonormalize(Mat3x3 Rin):
Vec3 x = Rin.x;
Vec3 y = orth(Rin.y, x);
Vec3 z = orth(orth(Rin.z, x), y);
return Mat3x3(normalize(x),normalize(y),normalize(z))
只要您的输入不是太远,这应该会为您提供适当的旋转矩阵。
要查看re_orthonormalize
代码的工作原理,首先获取orth
输出的点积及其b
输入。 因为点积是线性的,所以我们有:
dot(a - (dot(a,b)/dot(b,b)*b, b)
== dot(a,b) - (dot(a,b)/dot(b,b)) * dot(b,b)
== dot(a,b) - dot(a,b)
== 0
因此,如果a
和b
已经大部分是正交的,ortho(a,b)
添加少量b
以确保点积确实是0
的。
这意味着在re_orthonormalize
中,y
正交于x
。 棘手的一点是确保z
与x
和y
正交。 这唯一有效,因为我们已经确保x
与y
完全正交,因此添加一点y
并不能阻止orth(Rin.z, x)
正交x
。
两个平方矩阵的乘积 (P=AB( 的逆函数一般为 Inv(B(*Inv(A(。轮换和翻译将通勤。通常,您必须以与应用顺序相反的方式展开操作。
但在这种情况下,R1*T1*R2*T2=R1*R2*T1*T2,然后您可以将串联的逆计算为各个旋转和平移组合的逆
。所以是的,这对于纯粹的旋转和平移来说是合理的。