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

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

Coordinate system

我有一个称为dirglm::vec3,它表示三维空间中两个点AB之间的(归一化)方向2

Two points in space

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

Direction after rotation

我的最初想法是计算dir的“右”向量,并将其用作旋转轴。我尝试了以下操作:
glm::vec3 rotateVectorUpwards(const glm::vec3& input, const float aRadians)
{
    const glm::vec3 up{0.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::vec3{0.0, 0.0, tan(aRadians)}) 吗?它应该会产生相同的效果。 - Nelfeal
rotationMat 是一个打字错误吗? - G.M.
@G.M.:好的,已经修复了。抱歉! - Vittorio Romeo
在构建旋转矩阵之前,规范化右向量? - noobius
@noobius,input已经被标准化了 - right也应该是标准化的吧? - Vittorio Romeo
@VittorioRomeo,仅当您的输入和上向量正交且为单位向量时,才不需要标准化。如果它们不正交,则需要标准化结果。我不知道您的输入方向向量可能是什么,所以在进行叉积运算后标准化结果可能是安全的。 - noobius
1个回答

0

你不需要对up向量进行归一化,因为你已经定义它为单位向量,但是你需要对right向量进行归一化。

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

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

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