四元数旋转不起作用

时间:2011-06-15 22:49:33

标签: c++ 3d camera rotation quaternions

我刚刚开始使用Quaternions,但是我在使用Quaternions使一个简单的FPS相机正常工作时遇到了一些令人讨厌的困难。

基本上,每当我尝试移动鼠标时,我在屏幕上绘制的三角形变得疯狂,并且在屏幕上移动的速度比我看到的要快。移动键(wsad)按预期工作,UNTIL我移动鼠标,然后它全部搞砸了。我认为问题在于轮换,但过去几天我一直在倾倒这个问题但无济于事。

以下是有关正在发生的事情的视频:Quaternion Test Video

  • 要查看鼠标输入,请从头开始观看。
  • 要查看键盘输入(前进,后退等),请跳至0:51秒。

仅供参考,以下是我正在使用的3个主要类:
Quaternion.h
CameraSceneNode.h
CameraSceneNode.cpp

最相关的部分是tick()(我更新旋转四元数)和render()(我渲染'相机',其中包括旋转和翻译场景)。

以下是tick()方法:

void CameraSceneNode::tick(float32 time) {
    // movement direction
    if (movement_[MOVE_DIR_FORWARD] == 1)
        pos_ += rotation_ * vmath::Vector3f(0, 0, -moveSpeed_ * time);

    if (movement_[MOVE_DIR_BACKWARD] == 1)
        pos_ += rotation_ * vmath::Vector3f(0, 0, moveSpeed_ * time);

    if (movement_[MOVE_DIR_LEFT] == 1)
        pos_ += rotation_ * vmath::Vector3f(-moveSpeed_ * time, 0, 0);

    if (movement_[MOVE_DIR_RIGHT] == 1)
        pos_ += rotation_ * vmath::Vector3f(moveSpeed_ * time, 0, 0);

    // rotation
    if (xRot_ != 0) {
        Quaternion quatRotation = Quaternion();
        quatRotation.buildFromAxisAngle(1, 0, 0, (xRot_ * time * rotSpeed_) *         math::DEGTORAD);
        //quatRotation.normalize();
        rotation_ = rotation_ * quatRotation;
        xRot_ = 0;
        rotation_.normalize();
    }
    if (yRot_ != 0) {
        Quaternion quatRotation = Quaternion();
        quatRotation.buildFromAxisAngle(0, 1, 0, (yRot_ * time * rotSpeed_) *         math::DEGTORAD);
        //quatRotation.normalize();
        rotation_ = quatRotation * rotation_;
        yRot_ = 0;
        rotation_.normalize();
    }
}

这是render()方法:

void CameraSceneNode::render() {
    if (isActive()) {
        float32 matrix[16];
        rotation_.fillMatrix(matrix);

        glMultMatrixf(&matrix[0]);

        //glRotatef(rotYTest, 0, 1, 0);
        //glRotatef(rotXTest, 1, 0, 0);

        glTranslatef(-pos_.x, -pos_.y, -pos_.z);
    }
}

此外,在我在相机上调用render()之前,我运行了这段代码:

glMatrixMode(GL_MODELVIEW);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

我的主游戏循环中的每一帧都会调用tick(..)render()CameraSceneNode类中有一些功能可以接受移动方向和相机旋转的变化(即更改movement_缓冲区或xRot_yRot_)。

如果这还不够,我很抱歉。一些函数(如fillMatrix(..))在我上面引用的3 .h / .cpp文件中定义。我已经多次检查了Quaternion类,它看起来对我来说是正确的。但话说回来,我使用的所有代码对我来说都是正确的,所以谁知道:S

我完全凭借这一点完成了我的智慧。如果有人能说清楚为什么这不起作用,我会非常感激!!

干杯

Jarrett的

1 个答案:

答案 0 :(得分:6)

从它的外观来看,你逐渐累积每个刻度的旋转(rotation_ = quatRotation * rotation_;),这首先是有意义的,因为你所做的只是略微调整旋转,所以它应该是安全的对已经存在的东西进行另一个或两个轮换,对吗?

然而,每次你旋转(通过你正在做的事情),你实际上每次都会略微改变旋转轴,这就是你看到这种不稳定行为的原因。

我建议跟踪整个X / Y旋转,在鼠标移动时递增或递减,然后每次直接计算旋转而不是累积旋转。因此,如果您在X中旋转了1度15次,那么您当前的代码基本上是“在X中旋转1度,在X中添加旋转1度等”。我建议的是跟踪单个旋转因子X,并且当它改变时直接设置旋转“旋转13度,旋转14度,旋转15度等”。

从你的视频来看,旋转看起来也太大了,所以你可能希望将最终轮换比例调整为10或50(或其他)。

我可能会离开,但我在3D编码冒险中遇到过类似的事情,这是我最好的建议。如果这不是问题,因为您正在处理相机旋转,您可能需要使用矩阵反转。更糟糕的是,看看模型视图矩阵是否有某些旋转,看它是否符合你的期望(痛苦,但也是一个有价值的调试练习)。