两组向量之间的四元数旋转
Quaternion Rotation Between Two Sets of Vectors
我需要一些帮助来找到 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
我现在使用的方法是先求每对两个向量之间的四元数旋转,然后乘以每对第二个向量之间的四元数旋转。这会产生一个四元数,我可以通过旋转两个向量来获得其他两个向量。有没有更简单的方法来计算四元数,不是通过将两个旋转相乘,而是计算一个旋转?
谢谢!
我认为可以非常快速有效地完成您想做的事情。首先,您应该将每对正交向量完成一个正交基。这样做的明显方法是取前两个向量的叉积。顺序很重要:如果你想 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.
中描述的方法从旋转矩阵转换为四元数
我需要一些帮助来找到 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
我现在使用的方法是先求每对两个向量之间的四元数旋转,然后乘以每对第二个向量之间的四元数旋转。这会产生一个四元数,我可以通过旋转两个向量来获得其他两个向量。有没有更简单的方法来计算四元数,不是通过将两个旋转相乘,而是计算一个旋转?
谢谢!
我认为可以非常快速有效地完成您想做的事情。首先,您应该将每对正交向量完成一个正交基。这样做的明显方法是取前两个向量的叉积。顺序很重要:如果你想 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.
中描述的方法从旋转矩阵转换为四元数