gpt4 book ai didi

c++ - 如何沿所有轴正确旋转四元数?

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:21:50 27 4
gpt4 key购买 nike

我想编写第一人称相机的代码,并将其旋转存储在四元数中。不幸的是,旋转有问题。

下面的函数负责旋转相机。参数MouseSpeed 传递鼠标移动和旋转速度。然后函数获取旋转四元数,旋转它并存储结果。顺便说一下,我正在使用 Bullet Physics这就是类型和函数的来源。

void Rotate(vec2 Mouse, float Speed)
{
btTransform transform = camera->getWorldTransform();
btQuaternion rotation = transform.getRotation();

Mouse = Mouse * Speed; // apply mouse sensitivity
btQuaternion change(Mouse.y, Mouse.x, 0); // create quaternion from angles
rotation = change * rotation; // rotate camera by that

transform.setRotation(rotation);
camera->setWorldTransform(transform);
}

为了说明鼠标移动时产生的相机旋转,我向您展示了一张手绘图。左侧显示了相机实际执行的错误旋转。在右侧显示了所需的正确情况。箭头表示向上(橙色)和向下(蓝色)移动鼠标时相机如何旋转。

wrong rotation on the left and desired rotation on the right

如您所见,只要偏航为零,旋转就是正确的。但是它的偏航越大,相机旋转的圆圈就越小。相反,圆圈应该像经度一样始终沿着整个球体延伸。

我对四元数不是很熟悉,所以在这里我问一下如何正确旋转它们。

最佳答案

我自己找到了正确旋转四元数的方法。关键是找到我想要旋转的轴的 vector 。这些用于从轴和角度创建四元数,当角度是围绕实际轴旋转的量时。

以下代码显示了我最终得到的结果。它还允许转动相机,这在某些时候可能会有用。

void Rotate(btVector3 Amount, float Sensitivity)
{
// fetch current rotation
btTransform transform = camera->getWorldTransform();
btQuaternion rotation = transform.getRotation();

// apply mouse sensitivity
Amount *= Sensitivity;

// create orientation vectors
btVector3 up(0, 1, 0);
btVector3 lookat = quatRotate(rotation, btVector3(0, 0, 1));
btVector3 forward = btVector3(lookat.getX(), 0, lookat.getZ()).normalize();
btVector3 side = btCross(up, forward);

// rotate camera with quaternions created from axis and angle
rotation = btQuaternion(up, Amount.getY()) * rotation;
rotation = btQuaternion(side, Amount.getX()) * rotation;
rotation = btQuaternion(forward, Amount.getZ()) * rotation;

// set new rotation
transform.setRotation(rotation);
camera->setWorldTransform(transform);
}

由于我很少找到关于四元数旋转的信息,所以我将花一些时间进一步解释上面的代码。

获取和设置旋转是物理引擎特有的,与这个问题无关,所以我不会详细说明。下一部分,将数量乘以鼠标灵敏度应该非常清楚。让我们继续方向 vector 。

  • up vector 取决于您自己的实现。最方便的是,正 Y 轴指向上,因此我们以 0, 1, 0 结束。
  • lookat vector 表示相机注视的方向。我们简单地通过相机旋转四元数旋转一个指向前方的单位 vector 。同样,前向 vector 取决于您的约定。如果 Y 轴向上,则 Z 轴正向可能指向前方,即 0, 0, 1
  • 不要将其与下一个 vector 混淆。它被命名为 forward,它引用了相机旋转。因此我们只需要将 lookat vector 转换到地面上。在这种情况下,我们只需采用 lookat vector 并忽略向上指向的分量。为了整洁起见,我们将该 vector 归一化。
  • side vector 从相机方向指向左侧。因此它垂直于 upforward vector ,我们可以使用 cross product计算它。

根据这些 vector ,我们可以围绕它们正确地旋转相机四元数。您以 Z、Y 还是 Z 开头取决于 Euler angle sequence这又是一个因应用程序而异的约定。由于我想按 Y X Z 顺序应用旋转,因此我执行以下操作。

  • 首先,将相机绕向上 轴旋转 Y 轴的量。这是偏航。
  • 然后围绕指向左侧的 side 轴旋转 X 量。这是音调。
  • 最后,围绕 forward vector 旋转 Z 量以应用滚动。

要应用这些旋转,我们需要将由轴和角度创建的四元数与当前相机旋转相乘。最后我们将得到的四元数应用于物理模拟中的 body 。

关于c++ - 如何沿所有轴正确旋转四元数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16384571/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com