2015-05-13 403 views
1

我希望能找到两组两个向量之间的旋转,作为四元数。在每一对中,矢量将彼此成直角并具有单位长度(基本上以正交基准为基础的两个矢量)。两组向量之间的四元数旋转

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

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 

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

谢谢!

+0

没有代码可以看,这纯粹是一个数学问题...所以“更快地做到”只能用非常抽象的数学方法来回答......不懂数学的人不能帮助与一般的性能编码调整。由于这是一个编程站点,您是否可以编辑您的问题(通过编辑按钮)以提供您现在以[MCVE](http://stackoverflow.com/help/mcve)的形式写入的内容? *(在早期的问题中,最好按照规则生活“包含一些代码”,并且只有在稍后考虑包含哪些非代码问题(包括主题考虑的问题)时才会生效......)* – HostileFork

+0

@HostileFork感谢您的建议,我会考虑编辑。我对这个网站并不陌生,我的旧帐户被意外地恶意破坏。 – Josh

+1

@Josh如果它是恶意做的,那不是偶然的。无论哪种方式。 =( – WhozCraig

回答

1

我认为可以非常快速和有效地做你想做的事情。首先,你应该完成每一个正交正常的矢量对成正交基。这样做的显而易见的方法是通过前两个向量的交叉乘积。顺序很重要:如果你想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中描述。

+0

在我决定使用Quaternion之前,我正在使用矩阵并基本做到这一点。将矩阵转换为四元数是完全有效的,我猜我不愿意使用它的最大原因是我似乎记得矩阵到四元数的转换是一个糟糕的糟糕的代码片段......并不是说它效率低下,一定。这并不坏,现在我再看一遍......谢谢你的回复! – Josh