如何正确旋转GLM四元数?

时间:2013-02-24 19:03:59

标签: c++ rotation transformation quaternions glm-math

我想在我的游戏中向左旋转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与游戏中的quats兼容):

            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'。

我做错了什么?

3 个答案:

答案 0 :(得分: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));

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

答案 1 :(得分:0)

[虽然这不是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;
}

答案 2 :(得分:0)

这是我编写的一个简单函数,它将使用参考轴旋转(度)。 您可以通过在单独的部分(w 和 (x,y,z) 分量)中创建四元数来创建四元数。 GLM 有一个初始值设定项,然后您可以将其转换为 4x4 或 用于转换的 3x3 矩阵。

# Generated by https://quicktype.io
#
# To change quicktype's target language, run command:
#
#   "Set quicktype target language"

from typing import List, Union


class Hometown:
    name: str
    id: int

    def __init__(self, name: str, id: int) -> None:
        self.name = name
        self.id = id


class Key:
    key: int

    def __init__(self, key: int) -> None:
        self.key = key


class Object:
    key: Key

    def __init__(self, key: Key) -> None:
        self.key = key


class FbData:
    name: str
    hometown: Hometown
    list: List[Union[Key, int, str]]
    object: Object

    def __init__(self, name: str, hometown: Hometown, list: List[Union[Key, int, str]], object: Object) -> None:
        self.name = name
        self.hometown = hometown
        self.list = list
        self.object = object