四元数旋转不起作用

Quaternion rotation not working

本文关键字:不起作用 旋转 四元数      更新时间:2023-10-16

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

基本上,每当我试图移动鼠标时,我在屏幕上画的三角形就会变得疯狂,在屏幕上移动的速度比我看到的还要快。移动键(wsad)按预期工作,直到我移动鼠标,然后一切都乱了。我认为问题出在轮换上,但过去几天我一直在讨论这个问题,但都无济于事。

这是一个正在发生的事情的视频:四元数测试视频

  • 要查看鼠标输入,请从头开始观察
  • 要查看键盘输入(向前、向后等),请跳到0:51秒

仅供参考,以下是我正在使用的3个主要类:
四元数.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文件中定义的。我已经检查了好几次四元数类,在我看来它是正确的。但话说回来,我使用的所有代码在我看来都是正确的,所以谁知道呢:S

我对此完全不知所措。如果有人能解释为什么这不起作用,我将不胜感激!!

干杯

Jarrett

从外观上看,你在每个刻度上都在逐渐累积你的旋转(rotation_=quatRegation*rotation_;),这一点一开始是有意义的,因为你所做的只是稍微调整旋转,所以在已经存在的旋转的基础上再旋转一两度应该是安全的,对吧?

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

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

从你的视频中看,旋转似乎也太大了,所以你可能希望将使用的最终旋转缩放10或50(或其他)。

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