5

クォータニオンを使い始めたばかりですが、クォータニオンを使用して単純な FPS カメラを適切に動作させるのに苦労しています。

基本的に、マウスを動かそうとすると、画面上に描いた三角形が狂ってしまい、目に見えない速さで画面上を移動します。マウスを動かすまで、移動キー (wsad) は期待どおりに機能していますが、その後、すべてが台無しになります。問題はローテーションにあると思いますが、ここ数日間、この問題に頭を悩ませていましたが、役に立ちませんでした。

何が起こっているかのビデオは次のとおりです。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

私はこれで完全に機知に富んでいます。なぜこれがうまくいかないのか、誰かが光を当てることができれば、とても感謝しています!!

乾杯

ジャレット

4

1 に答える 1

6

見た目から、ティックごとに徐々に回転を蓄積しています (rotation_ = quatRotation * rotation_;)。これは最初は理にかなっています。これは、回転をわずかに調整するだけであり、別のものをタックしても安全なはずだからです。すでにあるものに対して 1 ~ 2 度回転しますよね?

ただし、回転するたびに (何をしているかによって)、実際には毎回回転軸をわずかに変更しているため、この不規則な動作が見られます。

私が提案するのは、全体的な X/Y 回転を追跡し、マウスの移動に応じて増分または減分し、回転を累積する代わりに毎回直接回転を計算することです。したがって、X で 1 度 15 回回転した場合、現在のコードは基本的に「X で 1 度回転し、X で 1 度回転するなど」と言っています。私が提案しているのは、単一の回転係数 X を追跡することです。それが変化すると、回転を直接「13 度回転、14 度回転、15 度回転など」に設定します。

ビデオからは、回転が大きすぎるようにも見えるため、使用される最終的な回転を 10 倍または 50 倍 (またはその他) でスケーリングすることをお勧めします。

私はかなり外れているかもしれませんが、3D コーディングの冒険で似たようなことに出くわしたので、これが私の最善の提案です。それが問題でない場合は、カメラの回転を扱っているため、逆行列を使用する必要がある場合があります。さらに悪いことに、特定のローテーションのモデル ビュー マトリックスを見て、それが期待どおりかどうかを確認します (面倒ですが、貴重なデバッグ作業でもあります)。

于 2011-06-15T23:36:09.093 に答える