如何正确旋转GLM四元数?

7

我想在我玩的游戏中将我的汽车向左旋转90度。

当我使用以下代码:

            glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
            glm::quat done(glm::rotate(rot,glm::eulerAngles(rot)+glm::vec3(90.0f,0.0,0.0)));
            info.Rotation.x = done.x;
            info.Rotation.y = done.y;
            info.Rotation.z = done.z;
            info.Rotation.w = done.w;

汽车发生了奇怪的旋转。

然而,以下代码根本不会改变汽车的旋转(正如我所预期的那样,只是为了确保GLM与游戏中的四元数兼容):

            glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
            glm::quat done(rot);
            info.Rotation.x = done.x;
            info.Rotation.y = done.y;
            info.Rotation.z = done.z;
            info.Rotation.w = done.w;

每当我尝试这样做以检查是否通过它更改了旋转:

            glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
            glm::quat done(glm::rotate(rot,vec3(0.0,0.0,0.0)));
            info.Rotation.x = done.x;
            info.Rotation.y = done.y;
            info.Rotation.z = done.z;
            info.Rotation.w = done.w;

汽车在游戏中的旋转只设置为0,0,0,0。我原本以为使用这段代码后,汽车的旋转角度不会改变,因为我预期以下代码能将汽车向左旋转90度:

            glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
            glm::quat done(glm::rotate(rot,vec3(90.0,0.0,0.0)));
            info.Rotation.x = done.x;
            info.Rotation.y = done.y;
            info.Rotation.z = done.z;
            info.Rotation.w = done.w;

但是它并不能按照我想要的方式工作。它只是设置旋转,而不是将其添加到“rot”中。
我做错了什么?

我从那里复制了代码,但是我的车没有真正旋转,我需要在“角度”参数中输入什么,才能让它正确工作?是Z角度还是其他什么? - user1182183
@Gizmo:去看看这个问题和答案。 - Nicol Bolas
3个回答

1
[虽然这不是GLM,但四元数在乘法中的排序仍然非常清晰,这通常是问题所在]
我曾经使用过类似这样的代码来避免万向锁(因为任何引入万向锁的解决方案都太具有讽刺意味,无法考虑)。
这是C代码,QuaternionFromAngles()和QuaternionMultiply()会覆盖第一个参数的目标。world->axis6_input_rotation只是一个Quaternionf_t。输入来自6轴控制器,它比您的车辆模拟更加自由形式,除非您实际上正在在代码中传递向量。
typedef struct { float w, x, y, z; } Quaternionf_t; 

void GuiMotion6axis(World_t *world, Port_t *port,
                    int x,  int y,  int z,
                    int xr, int yr, int zr)
{
    // convert spaceball input to World->rotation (a quaternion)
    //    Source http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm
    const float scale = 0.0004; // should factor in the time delta it covers as well.
    float xrf = (float)xr * scale;
    float yrf = (float)yr * scale;
    float zrf = (float)zr * scale;

    QuaternionFromAngles(& world->axis6_input_rotation, xrf, yrf, zrf);
    QuaternionMultiply(& world->rotation,  // worldrot = inputrot * worldrot
                       & world->axis6_input_rotation,  // a read-only use
                       & world->rotation               // a read-only use
                       );

    world->position.x += (float)x * scale;  // really should factor in the
    world->position.y += (float)y * scale;  //   elasped time.
    world->position.z += (float)z * scale;
    return;
}

0
如果你不关心万向锁问题,那么这样做应该可以。
glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
glm::quat rot_euler_angles = glm::gtx::quaternion::eulerAngles(rot);
rot_euler_angles.x += 90;

glm::quat done(glm::rotate(rot,rot_euler_angles));
info.Rotation.x = done.x;
info.Rotation.y = done.y;
info.Rotation.z = done.z;
info.Rotation.w = done.w;

我认为这也是有效的

glm::vec3 rot(90.0*(float)M_PI/180.0, 0, 0);
info.Rotation = glm::normalize(info.Rotation * glm::quat(rot));

四元数非常棒,因为它们可以组合在一起进行非常复杂的旋转。

0
这是我编写的一个简单函数,可以围绕参考轴旋转(度数)。 您可以通过分别创建w和(x,y,z)组件来创建四元数。GLM有一个初始化器可以接受这个四元数,然后您可以将其转换为4x4或3x3矩阵进行变换。
    void QuaternionRotate(const glm::vec3& axis, float angle)
    {
        float angleRad = glm::radians(angle);
        auto& axisNorm = glm::normalize(axis);

        float w = glm::cos(angleRad / 2);
        float v = glm::sin(angleRad / 2);
        glm::vec3 qv = axisNorm * v;

        glm::quat quaternion(w, qv);
        glm::mat4 quatTransform = glm::mat4_cast(quaternion);
        
       // Now with the quaternion transform you rotate any vector or compound it with another transformation matrix
    }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接