【问题标题】:Rotate quaternion on all 3 axis from axis angle in GLM从 GLM 中的轴角度在所有 3 个轴上旋转四元数
【发布时间】:2013-04-17 17:00:16
【问题描述】:

我在 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));

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

【问题讨论】:

    标签: math opengl quaternions


    【解决方案1】:

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

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

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

    如果你想在没有云台锁定或其他欧拉角问题的情况下进行定向,那么你需要stop representing your orientation as Euler angles

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

    【讨论】:

    • glm::eulerAngleYXZ 给出错误的结果。这就是我问这个问题的原因之一
    • @MichaelIV:“错误结果”是什么?你如何定义对与错?欧拉角都是基于约定的。
    • 我比较了 AfterEffects 中实体层的旋转。所以上面的例子给了我正确的旋转,而使用 eulerAngleYXZ smth 非常不同......另外,你可以扩展“然后你需要停止代表你的方向作为欧拉角。” ?你的意思是直接旋转四元数?
    【解决方案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 个维度。来源:Quaternion tutorial

    【讨论】:

    • 所以你说这是他们使用“纯”四元数的方式?就像上面提到的尼可波拉斯?
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-25
      • 1970-01-01
      • 1970-01-01
      • 2012-03-14
      • 2023-04-01
      • 1970-01-01
      相关资源
      最近更新 更多