1

我在 OpenGL 引擎中使用四元数进行旋转。目前,为了为 x、y 和 z 旋转创建旋转矩阵,我为每个轴旋转创建一个四元数。然后我将它们相乘以获得最终的四元数:

  void RotateTo3(const float xr ,const float yr ,const float zr){

    quat qRotX=angleAxis(xr, X_AXIS); 
    quat qRotY=angleAxis(yr, Y_AXIS);
    quat qRotZ=angleAxis(zr, Z_AXIS);

    quat resQuat=normalize(qRotX * qRotY * qRotZ);
    resQuat=normalize(resQuat);
    _rotMatrix= mat4_cast(resQuat);

 }

现在一切都很好,但我只想从所有 3 个轴角创建一个四元数并跳过最后的乘法。quat 构造函数之一具有欧拉角向量的参数,如下所示:

quat resQuat(vec3(yr,xr,zr))

因此,如果我尝试此操作,则最终旋转是错误的。(还尝试了 quat(vec3(xr,yr,zr)) )。GLM 中没有办法在一个实例中从所有 3 个轴填充最终四元数吗?

现在,还有一件事: 正如 Nicol Bolas 建议的那样,我可以使用 glm::eulerAngleYXZ() 立即填充旋转矩阵,因为他认为执行中间四元数步骤是没有意义的。但我发现该函数至少对我来说不能正常工作。例如:

这 :

          mat4 ex=  eulerAngleX(radians(xr));
      mat4 ey=  eulerAngleY(radians(yr));
      mat4 ez=  eulerAngleZ(radians(zr));

       rotMatrix= ex * ey * ez; 

不返回与此相同的内容:

   rotMatrix= eulerAngleYXZ(radians(yr),radians(xr),radians(zr));

从我对正确旋转状态的比较来看,第一种方式给出了正确的旋转,而第二种方式是错误的。

4

3 回答 3

3

与流行的看法相反,四元数并不是神奇的“解决万向节锁定”装置,因此四元数的任何使用都会使欧拉角在某种程度上不是欧拉角。

您的RotateTo3函数采用 3 个欧拉角并将它们转换为旋转矩阵。您如何执行此过程并不重要。无论您使用 3 个矩阵、3 个四元数还是glm::eulerAngleYXZ. 结果仍然是由 3 个轴向旋转组成的矩阵。它将具有欧拉角的所有特性和缺点。因为欧拉角。

在这里使用四元数作为中介是没有意义的。它一无所获;您也可以只使用由连续glm::rotate调用构建的矩阵。

如果您想在没有万向节锁定或其他欧拉角问题的情况下进行定向,那么您需要停止将您的方向表示为欧拉角

在回答您实际提出的问题时,您可以使用glm::eulerAngleYXZ来计算

于 2013-04-24T08:37:48.580 回答
2

你的意思是这样的:

quat formQuaternion(double x, double y, double z, double angle){
     quat out;
     //x, y, and z form a normalized vector which is now the axis of rotation.
     out.w  = cosf( fAngle/2)
     out.x = x * sinf( fAngle/2 )
     out.y = y * sinf( fAngle/2 )
     out.z = z * sinf( fAngle/2 )
     return out;
}

抱歉,我实际上并不知道您正在使用的 quat 类,但它仍然应该有一些方法来设置 4 个维度。来源:四元数教程

于 2013-04-27T16:48:41.470 回答
1

eulerAngleYXZ 给出了一组可能的欧拉角,如果按照 api 名称指示的顺序重新组合,将产生与给定四元数相同的方向。这不是一个错误的结果——它是几个正确的结果之一。

使用四元数在内部存储您的方向 - 旋转它,将您的方向 quat 乘以另一个表示旋转量的 quat,可以从角度/轴构建以实现您想要的。

于 2015-07-15T12:14:11.027 回答