3

我有一个四元数,基于 Y 轴向上、X 轴向右、Z 轴朝向我的坐标系。

现在我想基于这个四元数在另一个应用程序(C++)中移动一个字符。如果坐标系相同,但此应用程序使用不同的坐标系,这将没有问题。Z 向上,X 向右,Y 穿过显示器(向内)。

我试图简单地旋转四元数来调整坐标系,但我尝试的每一次旋转,看起来都不太正确。

我的想法是我需要某种基本转换,但我不知道如何用四元数做到这一点,有人知道如何对四元数执行基本转换吗?

编辑

我将 Eigen C++ 库用于四元数。这是我使用的四元数:

Quaternion<float> QX90( Eigen::AngleAxisf( M_PI /2.0, Eigen::Vector3f::UnitX() ) );
Quaternion<float> nQX90( Eigen::AngleAxisf( -M_PI /2.0, Eigen::Vector3f::UnitX() ) );

Quaternion<float> Qrshoulder = .... //the Quaternion in the Y up coordinate system

我尝试旋转 X 轴:

Qrshoulder=Qrshoulder*QX90; 
Qrshoulder=QX90*Qrshoulder;
Qrshoulder=Qrshoulder*nQX90;
Qrshoulder=nQX90*Qrshoulder;

这没有用。我还尝试了其他几种乘法,我几乎尝试了每一个看起来合乎逻辑的旋转。我很困惑..似乎这不能用四元数乘法来完成

编辑 2

我有绝对和分层四元数。分层四元数提供 3D 空间中从父骨骼到子骨骼的旋转量。绝对四元数是相乘的分层骨骼方向。

另一方面,我想要制作动画的角色背后有一个引擎,它已经使骨骼倍增,所以我肯定需要使用分层旋转。但问题是,当我使用分层旋转时,Y 轴总是位于骨骼的方向上。

我从 Nolnoch 的回答中尝试了什么:

Quaternion<float> QNX( Eigen::AngleAxisf( 0, Eigen::Vector3f(1,0,0) ) );

rot=(QNX*QX90*Qrshoulder).toRotationMatrix();
targetNode->setRotation( Eigen::Transform3f( rot ) );

这既不适用于层次结构,也不适用于绝对方向。这是描述我得到什么四元数的文章:http: //msdn.microsoft.com/en-us/library/hh973073.aspx

我想我想念的是,当使用分层方向时,我得到了我需要的正确旋转量,但是坐标系完全搞砸了,因为 Y 轴沿着骨骼,而在我的 collada 中,坐标系总是Z起来。我不知道如何改变这一点,我什至不确定这是否是我的问题。

4

2 回答 2

2

你能展示你尝试过的旋转吗?听起来您的次要基础是围绕负 X 轴旋转 90 度后的原始基础。

您可以使用基于角轴矢量 [(PI / 2) 的四元数 [w, x, y, z] = [cos(PI / 4), sin(PI / 4), 0, 0] 1, 0, 0]。您还可以将原始四元数转换为矩阵形式并连接仿射旋转矩阵。我现在忘记了 sin/cos 项的顺序。

还要注意乘以向量和矩阵的顺序。(v' = Rv) != (v' = vR)。

[编辑 1]
问题是,四元数没有固有的惯用手或对特定基础的依恋。它们只是关于参考原点定义的方向分量的运动量。此外,它们不存储有关先前旋转的明确信息。

因此,在一个上下文中表示围绕 Z 轴旋转 35 度的最终四元数在另一个上下文中仍将围绕 Z 轴旋转 35 度。由于您的第二个基础是从原始基础绕 X 旋转,所以这应该有效。

其他需要考虑的事项:

你提到了一个肩膀——这是一个层次结构吗?如果是这样,这个特定的四元数是该肢体的真正最终/全局四元数,还是参考另一个本地上下文(并被连接)?

你在什么情况下在你的其他应用程序中实现这个四元数?如果它是相同的层次结构,请在开始递归渲染之前尝试通过此校正四元数转换您的 ModelView,然后在完成后转换回来(或使用矩阵堆栈)。

[编辑 2]
什么是 QNX?您定义一个没有关联运动的轴。如果您尝试使用零或“空”四元数,则为 [w, x, y, z] = [1, 0, 0, 0]。

四元数乘法,除非在库的实现中进行了修改,否则是从右(基本旋转)到左(新旋转)。我检查了 Eigen,它没有提到在文档中切换东西。

此外,每次旋转都会随对象一起变换全局轴,所以正如我上面提到的,这个校正四元数 (QX90) 应该在渲染分层模型之前添加到全局绝对旋转中。见下文。

Identity Matrix (clean slate)             Rotations in effect: [ ]
  Rotation 1                                                   [1]
    Draw some object                                           [1]

Identity Matrix                                                [ ]
  Rotation Q (QX90)                                            [Q]
    Rotation A (hip)                                           [A*Q]
      Draw hip                                                 [A*Q]
      Rotation B (spine)                                       [B*A*Q]
        Draw spine                                             [B*A*Q]
        Rotation C (shoulder)                                  [C*B*A*Q]
          Draw shoulder                                        [C*B*A*Q]

与您发布的 MSDN 指南的迭代结构相反,我仅以递归方式呈现分层模型。尽管如此,这仍然是全局变换矩阵相对于其旋转分量的状态背后的想法。

于 2013-04-22T15:10:27.223 回答
0

没有 Q 的旋转会给出你想要的,因为新空间 Q' 中的正交基具有不同的旋向性。

获得所需内容的一种方法是提取输入四元数 Q 的 X、Y、Z 向量,如下所示:

X = <1-2*qY*qY-2*qZ*qZ, 2*qX*qY+2*qZ*qW, 2*qX*qZ-2*qY*qW>
Y = <2*qX*qY-2*qZ*qW, 1-2*qX*qX-2*qZ*qZ, 2*qZ*qY+2*qX*qW>
Z = <2*qX*qZ+2*qY*qW, 2*qZ*qY-2*qX*qW, 1-2*qX*qX-2*qY*qY>

其中 qX,qY,qZ,qW 是 Q 的元素,X,Y,Z 是基向量。这是从四元数到矩阵 (Quaternion::getMatrix) 的函数中提取的

现在根据需要交换轴。

X' = X
Y' = -Z
Z' = Y

最后,使用新的基向量 X',Y',Z' 构造一个新的四元数。我最近在此问题的答案中讨论了如何从正交基础构建四元数: 来自正交基础的四元数

于 2021-10-31T08:58:42.317 回答