2

私は基本的な OpenGL ゲームをコーディングしており、カメラの移動に関してマウスを処理するコードをいくつか持っています。

私は次の方法を使用しています:

int windowWidth = 640;
int windowHeight = 480;

int oldMouseX = -1;
int oldMouseY = -1;

void mousePassiveHandler(int x, int y)
{
    int snapThreshold = 50;

    if (oldMouseX != -1 && oldMouseY != -1)
    {
        cam.yaw((x - oldMouseX)/10.0);
        cam.pitch((y - oldMouseY)/10.0);


        oldMouseX = x;
        oldMouseY = y;

        if ((fabs(x - (windowWidth / 2)) > snapThreshold) || (fabs(y - (windowHeight / 2)) > snapThreshold))
        {
            oldMouseX = windowWidth / 2;
            oldMouseY = windowHeight / 2;
            glutWarpPointer(windowWidth / 2, windowHeight / 2);
        }
    }
    else
    {
        oldMouseX = windowWidth / 2;
        oldMouseY = windowHeight / 2;
        glutWarpPointer(windowWidth / 2, windowHeight / 2);
    }


    glutPostRedisplay();

}

ただし、ぐるりと見回すと、カメラが「回転」(回転) し始めることがわかります。ピッチとヨーのみを呼び出しているため、これがどのように可能かわかりません。

Camera クラスに使用しているコードは次のとおりです: http://pastebin.com/m20d2b01e

私の知る限り、カメラの「ローリング」は発生しないはずです。上下にピッチングするか、左右にヨーイングするだけです。ロールしないでください。

何が原因でしょうか?

4

6 に答える 6

11

おめでとうございます -- リー群理論を発見しました!

はい、可能です。一連の変換の結果は、実行される順序によって異なります。ピッチに続いてヨーを行うことは、ヨーに続いてピッチを行うことと同じではありません。実際、極小のヨーとピッチの限界では、その差は純粋なロールになります。一般的なケースはもう少し複雑です。

(物理学者はこれを「回転群の交換関係」と呼んでいます。)

回転行列に精通している場合は、非常に簡単に解決できます。

于 2009-04-24T04:09:05.423 に答える
7

まだ行っていない場合は、おそらく回転を構成するためにクォータニオンを使用する必要があります。これにより、3 軸を中心に回転させてカメラを向ける際に発生するジンバル ロックの問題を回避できます。

ここでは、それらの間で変換する方法を示します。

于 2009-04-24T04:10:27.980 に答える
5

そうですね、地平線に対して水平に前方を見始め、90 度上に向け、次に 90 度左にヨーイングし、次に 90 度下に向けると、最初と同じ方向を見ていることになりますが、地平線は垂直になります (左に 90 度回転したかのように)。

編集:問題は、カメラが飛行機のように扱われている場合、ヨー/ピッチ/ロールが適切になることだと思います。おそらくやりたいことは、カメラを球のどこに向けているかを追跡して、球の点のように扱うことです。ヨー/ピッチの代わりに、シータ (緯度) とファイ (経度) を追跡する球座標を使用します。似ているように聞こえるかもしれませんが、カメラが真上を向いている極端なケースを考えてみてください。ヨー/ピッチを使用すると、その真上からのヨーとピッチを自由に調整できます。theta/phi では、theta を下方にしか調整できず、phi をどれだけ調整しても、theta を小さくしてもカメラは水平線に平行になります。これが FPS カメラのしくみです (後ろを見ているほど下を見ることはできません)。

編集 2rotLati(float angle) : リンク先のカメラ コードを見て、関数と関数を使用したいと考えていrotLongi(float angle)ます。

于 2009-04-24T03:57:57.853 に答える
4

数学的には、3D 空間での回転は交換されないためです。これが意味することは、pitch() の後に yaw() が続くのは yaw() の後に pitch() が続くのと同じではないということですが、その事実の結果として、3 種類の回転は密接に関連しており、実行することはできません。 3番目のいくつかを取得せずにそれらのうちの2つ。つまり、pitch()es と yaw()s のシーケンスは、シーケンスの後半が前半とまったく逆でない限り、時間の経過とともに顕著な roll() 効果を生み出します。(これにはかなり複雑な計算がたくさん含まれていますが、詳細は特に関係ありません)

于 2009-04-24T04:14:24.897 に答える
3

この状況はジンバルロックと呼ばれていると思います- ウィキペディアのページにイラスト付きの例があります.

于 2009-04-24T04:08:15.410 に答える
3

ピッチ/ヨー/ロールはすべて車両の向きに関連しています。ピッチアップ/ダウンすると、ヨーの軸が変わります。同様に、ヨーイングすると、ピッチ軸が変化します。したがって、コンビネーションとピッチ & ヨー操作だけで、ロール操作に似た方法で向きを変えることができます。

于 2009-04-24T04:02:18.950 に答える