两组向量之间的四元数旋转

时间:2015-05-13 03:08:30

标签: c++ vector rotation quaternions

我想在3D中找到两组两个矢量之间的旋转作为四元数。在每对中,向量彼此成直角并具有单位长度(基本上是两个向量)。

我当前的代码看起来像这样:

Vector3 look1, up1, right1, look2, up2, right2;
// look1, up1, right1 form orthonormal basis,
// ditto with look2, up2, and right2
Vector3 lookRotateAxis = look1 % look2;
// operator% defined as cross product for convenience
float lookRotateAngle = acos(look1 * look2);
// operator* defined as dot product for convenience
Quaternion lookRotate;
lookRotate.makeRotation(lookRotateAngle, lookRotateAxis);
up1Transformed = lookRotate.rotateVector(up1);
Vector3 upRotateAxis = up1Transformed % up2;
float upRotateAngle = up1Transformed * up2;
Quaternion upRotate;
upRotate.makeRotation(upRotateAngle, upRotateAxis);
Quaternion finalRotation = upRotate * lookRotate;
// quaternion finalRotation rotates basis 1 to basis 2

我现在使用的方法是在每对的第一个中找到两个向量之间的四元数旋转,然后乘以每对第二个向量之间的四元数旋转。这导致单个四元数我可以旋转两个向量以获得另外两个向量。是否有更简单的方法来计算四元数,而不是通过乘以两个旋转,而是计算单个旋转?

谢谢!

1 个答案:

答案 0 :(得分:2)

我认为可以非常快速有效地做你想做的事。首先,您应该将每个正交对向量完成为标准正交基础。显而易见的方法是采用前两个向量的叉积。顺序重要:如果你想要u0映射到v0而u1映射到v1,那么形成标准正交基础{u0,u1,u2},其中u2 = u0 x u1(交叉乘积),也形成标准正交基础{v0,v1 ,v2}其中v2 = v0 x v1,并将u2映射到v2。如果你不小心并设置v2 = v1 x v0,你最终会遇到一种不可能的情况(尝试将右手坐标系映射到带旋转的左手坐标系)。所以要小心交叉产品中的术语顺序。

现在您有两个正交基,或,很容易构造表示从{x,y,z}帧到给定帧的旋转的正交矩阵。 (同样,你必须考虑{x,y,z}框架的方向或旋向性......例如,你可能不得不使用{x,z,y}。)矩阵乘法乘以表示从帧{x,y,z}到{u0,u1,u2}的旋转的正交矩阵是

[u00 u01 u02]
[u10 u11 u12]
[u20 u21 u22]

其中,根据计算机图形学的通常惯例,我们通过矩阵预乘矢量。因此,例如,我们的矩阵对(1,0,0)的影响是

        [u00 u01 u02]
[1 0 0] [u10 u11 u12] = [u00 u01 u02]
        [u20 u21 u22]

这正是我们想要的; {x,y,z}中的其他两个基矢量相同。

要将一个帧映射到另一个帧,我们将通过框架{x,y,z}作为中介。所以我们必须找到第一个正交矩阵的逆。幸运的是,反转正交矩阵非常简单:只需要​​进行转置即可。因此,要将帧{u0,u1,u2}映射到帧{v0,v1,v2},请使用矩阵乘积

[u00 u10 u20] [v00 v01 v02]
[u01 u11 u21] [v10 v11 v12]
[u02 u12 u22] [v20 v21 v22]

让我们看看当我们将向量u1 = [u10,u11,u12]输入到这个矩阵乘积中时会发生什么:

              [u00 u10 u20] [v00 v01 v02]           [v00 v01 v02]
[u10 u11 u12] [u01 u11 u21] [v10 v11 v12] = [0 1 0] [v10 v11 v12] = [v10 v11 v12]
              [u02 u12 u22] [v20 v21 v22]           [v20 v21 v22]

按要求。这里我们使用了公式u1。 u0 = 0,u1。 u1 = 1,u1。 u2 = 0,其后跟{u0,u1,u2}为正交框架。

因此,表示所需旋转的正交矩阵正好是

[u00 u10 u20] [v00 v01 v02]
[u01 u11 u21] [v10 v11 v12]
[u02 u12 u22] [v20 v21 v22]

执行矩阵乘法以获得单个矩阵,然后如果需要四元数表示,请通过http://en.wikipedia.org/wiki/Rotation_matrix#Quaternion中描述的方法将旋转矩阵转换为四元数。