将四元数从当前旋转角度旋转一定角度的正确方法是什么?

What is the correct way to rotate a quaternion from its current rotation a certain angle?

我正在尝试使用 JOML 中的四元数来使用四元数旋转:https://github.com/JOML-CI/JOML/blob/main/src/org/joml/Quaternionf.java

我可以让物体旋转,但它们卡住了,无法完成完整的旋转。该对象每帧都在更新。

编辑: 删除了所有与欧拉相关的代码,我只是想让对象根据某个角度在单个轴上旋转。

编辑 2: 我正在尝试使用共轭并将四元数相乘,就像我在一些视频中看到的那样。我不太清楚,因为模型出于某种原因从屏幕上旋转出来。

编辑 3: 规范化四元数修复了消失的行为。问题似乎是没有简单的方法来旋转一定量而没有定时器来 lerp ,这在我的情况下不起作用,因为我试图将对象旋转任意量而没有设置开始和结束。

旋转功能

public void rotate(float angle, float x, float y, float z) {
    Quaternionf rot = new Quaternionf();
    rot.rotateAxis((float) Math.toRadians(angle), x, y, z);

    Quaternionf conjugate = rot.conjugate();

    rotation = rot.mul(rotation).mul(conjugate);
}

调用旋转函数

entity.transform.rotate( 1,0,1, 0);

不管你把你的欧拉角转换成矩阵还是四元数或任何表示形式都没有关系:只要你用欧拉角来表示一个方向,Gimbal Lock是不可避免的.

因此,为了避免 Gimbal Lock 发生,您必须放弃使用欧拉角,并使用一种方向表示法(例如 3x3 矩阵或四元数)和对它们应用 delta 更改,而不是尝试将完整方向表示为三个欧拉角。因此,每当您 - 让我们说 - 将对象围绕某个轴旋转几度时,您就会将该增量变化或方向应用到 matrix/quaternion.

我相信我已经弄明白了。

  1. 您需要创建一个四元数并将其旋转到您的增量值,不要直接操作四元数值(例如,改用 rotationX 函数)。

  2. 要将四元数相加,需要将它们相乘。

  3. 最后你需要使用等式:

    delta 四元数 * 要旋转的四元数 * delta 四元数的逆

代码:

    public void rotate(float x, float y, float z) {
        //Use modulus to fix values to below 360 then convert values to radians
        float newX = (float) Math.toRadians(x % 360);
        float newY = (float) Math.toRadians(y % 360);
        float newZ = (float) Math.toRadians(z % 360);

        //Create a quaternion with the delta rotation values
        Quaternionf rotationDelta = new Quaternionf();
        rotationDelta.rotationXYZ(newX, newY, newZ);

        //Calculate the inverse of the delta quaternion
        Quaternionf conjugate = rotationDelta.conjugate();

        //Multiply this transform by the rotation delta quaternion and its inverse
        rotation.mul(rotationDelta).mul(conjugate);
    }