5

OpenGL (java LWGJL) でいくつかの単純な 3D グラフィックスに取り組んでおり、ヨー、ピッチ、ロールを移動ベクトルの x、y、z コンポーネントに変換する方法を見つけようとしています。ピッチとヨーだけでこれを行う方法は知っていますが (ここで説明されているように)、この式にロールを統合する方法を説明するものは何も見つかりませんでした。

3D 空間でベクトルを定義するために必要なのはヨーとピッチだけであることは承知していますが、この例ではロールも必要です。A基本的な WASD 構成 (ローカル左、Wローカル前方、ローカル上) でカメラに対するさまざまな動きにバインドされたキーがあるSPACEため、ロールはカメラの動きに影響します (たとえばD、pi/2 のロールで押す (デフォルト)はカメラを右に移動します(ワールド座標で)がD、円周率で押すとカメラがワールド座標で上に移動します)。

これまでのコードは次のとおりです。

//b = back
//f = forward
//r = right
//l = left
//u = up
//d = down

    private void move()
    {
        double dX = 0, dY = 0, dZ = 0;


        if (f ^ b)
        {
            dZ += cos(yaw) * cos(pitch) * (b ? 1 : -1);
            dX += sin(yaw) * cos(pitch) * (b ? 1 : -1);
            dY += -sin(pitch) * (b ? 1 : -1);
        }

        if (l ^ r)
        {
            dZ += sin(yaw) * sin(roll) * (l ? 1 : -1);
            dX += cos(yaw) * - sin(roll) * (l ? 1 : -1);
            dY += cos(roll) * (l ? 1 : -1);
        }

        if (u ^ d) //this part is particularly screwed up
        {
            dZ += sin(pitch) * sin(roll) * (u ? 1 : -1);
            dX += cos(roll) * (u ? 1 : -1);
            dY += cos(pitch) * sin(roll) * (u ? 1 : -1);
        }



        motion.x = (float) dX;
        motion.y = (float) dY;
        motion.z = (float) dZ;

        if (motion.length() != 0)
        {
            motion.normalise();
            motion.scale(2);
        }

        x += motion.x;
        y += motion.y;
        z += motion.z;

これはいくつかの回転では機能しますが、多くの場合、正しくない結果になります。

質問は次のとおりです。

ヨー、ピッチ、およびロールを考慮して、目的の方向 (押されたキー) に基づいてモーション ベクトルの x、y、および z コンポーネントを正常に計算するようにコードを変更するにはどうすればよいですか?

生の三角関数 (私がやろうとしているように)、行列を含むソリューション、またはほとんど何でも使用しても問題ありません。

編集:

オイラー角に関するウィキペディアの記事にリンクするだけで回答しないでください。私はそれを読みましたが、それを自分の状況に適用する方法を理解するのに十分な数学のバックグラウンドがありません.

編集#2:

カメラの向きを変えるまでの間、向きを保存するためにオイラー角のみを使用しています。実際のカメラ操作には、回転行列を使用します。必要に応じて、オイラー角を削除して、行列のみを使用できます。重要なのは、向きをベクトルに変換できることだけです。

編集#3:

コメントで説明されているように、前方ベクトルに回転行列を掛けて解決策を見つけました。

//b = back
//f = forward
//r = right
//l = left
//u = up
//d = down

private Vector3f motion;

protected void calcMotion()
{
    //1 for positive motion along the axis, -1 for negative motion, 0 for no motion
    motion.x = r&&!l ? -1 : l ? 1 : 0; 
    motion.y = u&&!d ? 1 : d ? -1 : 0;
    motion.z = f&&!b ? 1 : b ? -1 : 0;

    if (motion.length() == 0)
    {
        return;         
    }

    motion.normalise();

    //transform.getRotation() returns a Matrix3f containing the current orientation
    Matrix3f.transform(transform.getRotation(), motion, motion);
}

ただし、これにはまだ問題があります。

4

2 に答える 2

3

純粋な三角関数の答えを見つけることはできないと思います。とにかく、エレガントなものではありません。

オイラー角 (ピッチ/ヨー/ロール) は、このジョブに適したツールではありません。ジンブルロックが問題になるだけでなく、操作の順序があいまいになります。

オブジェクトの現在の回転状態をマトリックスまたはクォータニオンに保存することをお勧めします。比較的小さなデルタに対してのみオイラー角を使用します。

于 2013-09-16T20:21:49.333 に答える
0

すべての回転後の最終位置を計算するために広く使用されている同次変換行列法を使用できます。

于 2016-12-28T10:04:33.433 に答える