使用 `glm::rotate` 和四元数向上旋转 3D 方向向量

Posted

技术标签:

【中文标题】使用 `glm::rotate` 和四元数向上旋转 3D 方向向量【英文标题】:Rotating a 3D direction vector upwards with `glm::rotate` and quaternions 【发布时间】:2020-05-21 10:45:10 【问题描述】:

给定以下坐标系1,其中正z 朝向天花板:

我有一个名为dirglm::vec3 表示3D 空间中AB 两点之间的(标准化)方向2

AB 这两个点恰好在同一平面上,因此dirz 坐标为零。现在,给定一个角度α,我想将dir 向天花板旋转指定的量。例如,如果 α 是 45 度,我希望 dir 指向相同的 x/y 方向,但朝向天花板 45 度3

我最初的想法是计算dir 的“右”向量,并将其用作旋转轴。我尝试了以下方法:

glm::vec3 rotateVectorUpwards(const glm::vec3& input, const float aRadians)

    const glm::vec3 up0.0, 0.0, 1.0;
    const glm::vec3 right = glm::cross(input, glm::normalize(up));

    glm::mat4 rotationMatrix(1); // Identity matrix
    rotationMatrix = glm::rotate(rotationMatrix, aRadians, right);
    return glm::vec3(rotationMatrix * glm::vec4(input, 1.0));

我希望调用 rotateVectorUpwards(dir, glm::radians(45)) 会返回一个表示我想要的新方向的向量,但它总是返回一个带有零 z 分量的向量。

我也尝试用四元数表示相同的旋转:

glm::quat q;
q = glm::rotate(q, aRadians, right);
return q * input;

但是,结果向量似乎总是有一个零 z 分量。

我做错了什么?

我是否误解了“旋转轴”的含义? 我的right 计算不正确吗?

我怎样才能达到我想要的结果?

【问题讨论】:

你能试试glm::normalize(input + glm::vec30.0, 0.0, tan(aRadians))吗?它应该做同样的事情。 rotationMat 是错字吗? @G.M.:是的,已修复。对不起! 在构建旋转矩阵之前对正确的向量进行归一化? @noobius, input 已经标准化 - right 不会也被标准化吗? 【参考方案1】:

您不需要标准化 up 向量,因为您将其定义为单位向量,但您确实需要标准化您的 right 向量。

但是,虽然我不熟悉 glm,但我怀疑问题是您正在围绕轴旋转矩阵(或四元数),而不是创建表示围绕轴旋转的矩阵/四元数。快速浏览一下文档,看起来您可能想要使用:

glm::mat4 rotationMatrix = glm::rotate(radians, right);

【讨论】:

以上是关于使用 `glm::rotate` 和四元数向上旋转 3D 方向向量的主要内容,如果未能解决你的问题,请参考以下文章

Unity复杂的旋转-欧拉角和四元数

Unity3D 控制物体旋转详解 —— 自身绕轴旋转缓慢旋转鼠标控制旋转欧拉数和四元数的关系

matlab练习程序(求向量间的旋转矩阵与四元数)

unityvector3和四元数的区别

Unity基础:欧拉角、四元数

四元数运动学笔记旋转的雅克比矩阵