将快速逆应用于串联的 4x4 仿射变换



是否可以将矩阵的快速逆应用于纯旋转和平移矩阵的串联,例如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

因此,如果ab已经大部分是正交的,ortho(a,b)添加少量b以确保点积确实是0的。

这意味着在re_orthonormalize中,y正交于x。 棘手的一点是确保zxy交。 这唯一有效,因为我们已经确保xy完全正交,因此添加一点y并不能阻止orth(Rin.z, x)正交x

两个平方矩阵的乘积 (P=AB( 的逆函数一般为 Inv(B(*Inv(A(。轮换和翻译将通勤。通常,您必须以与应用顺序相反的方式展开操作。

但在这种情况下,R1*T1*

R2*T2=R1*R2*T1*T2,然后您可以将串联的逆计算为各个旋转和平移组合的逆

所以是的,这对于纯粹的旋转和平移来说是合理的。

最新更新