5

私はOpenGL(具体的にはLWJGLバインディング)を使用してJavaでゲームを書いています。カメラを含む各エンティティには、回転を表すクォータニオンがあります。クォータニオンを現在のOpenGLマトリックスに適用する方法を理解しましたが、すべてが正常に回転します。私が抱えている問題は、カメラをマウスで回転させることです。

現在、フレームごとに、ゲームはマウスが1つの軸上で移動した量を取得し、その量をカメラの回転のためにクォータニオンに適用します。クォータニオンを回転させるコードは次のとおりです。問題が発生する場所だと思うので、投稿します(ただし、この種のことについては常に間違っています)。

    public void rotateX(float amount){
        Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));
        Quaternion.mul(rot, rotation, rotation);
        rotation.normalise();
    }

このメソッドは、X軸を中心にクォータニオンを回転させることになっています。「回転」は、エンティティの回転を表すクォータニオンです。「amount」は、クォータニオンを回転させたい量(マウスを動かした量)です。'rot'は、ラジアンに変換された量のaw値を持つX軸に沿った正規化されたベクトルです(ここでの目標は、角度(たとえば、10度)を与え、指定された軸に沿ってクォータニオンを回転させることです。角度)。Quaternion.mulを使用すると、新しいクォータニオンを取得し、それを回転クォータニオンで乗算してから、結果を回転クォータニオンとして格納します。'rot'は正常であり、'rotation'はすでに正規化されているはずなので、正規化が必要かどうかはわかりません。

rotateYメソッドとrotateZメソッドは、「rot」のベクトルを変更することを除いて、同じことを行います(yの場合は0.0、1.0、0.0、zの場合は0.0、0.0、1.0)。

ゲームが開始され、カメラが負のZ軸を見下ろしている場合、コードは正常に機能しているように見えます。Y軸を中心に、またはX軸を中心に回転できます。しかし、Z軸を見下ろさずにカメラを回転させようとすると、すべてが本当に厄介になります(私はそれを説明することさえできません、それは非常に奇妙に回転します)。

ここでの私の最終目標は、アップベクトルのない空間で船を制御するために使用するものを用意することです。したがって、Y軸上でマウスを動かすと、船の角度に関係なく、船のピッチが変化します(X軸に沿った回転)。同様に、X軸上でマウスを動かすと、ヨー(Y軸に沿った回転)が変わります。私はこれを間違った方法で行っている可能性があり、おそらく正しい方向に押す(または突き出す)必要があります。

何か(私のレンダリングがどのように行われるか、私がやろうとしている他の数学)についてさらに詳細が必要な場合は、質問してください。私はオイラー角を使用していたときにすべてを理解しました(これは明らかに3Dアプリケーション開発にとっては大したことではありません...誰かが私がそれらを動作させるために多くの時間を沈める前に私に言ってくれたらいいのにと思います)クォータニオンに切り替えて、私は頭をとても速く乗り越えました。私は過去数か月間、このコードで遊んで、それを機能させるためにクォータニオンについて読んでいましたが、実際にはどこにも到達していません:'(

非常に、非常にイライラします...3Dで何かを作ろうとしたことを後悔し始めました>_ <

4

1 に答える 1

10
Quaternion rot = new Quaternion(1.0f, 0.0f, 0.0f, (float)Math.toRadians(amount));

OK、これは完全に間違っています。

4つのfloatを受け取るコンストラクターは、それらが実際のクォータニオンを表すことを前提としています。そのコンストラクターに与えるものはクォータニオンではありません。これは、vec3軸であり、回転すると予想される角度です。

それらをクォータニオンクラスに押し込み、正当なクォータニオンをそこから取得することを期待することはできません。

クォータニオンクラスに、角度と回転軸からクォータニオンを作成するコンストラクターまたはその他の手段が必要です。しかし、あなたがリンクしたドキュメントによると、そうではありません。だからあなたは自分でそれをしなければなりません。

クォータニオンは、角度である4番目の値を持つvec3軸ではありません。方向の変化を表す単位クォータニオンは、回転軸*回転角の半分の正弦であるvec3と、回転角の半分の余弦であるスカラー成分です。これは、回転角が[-pi / 2、pi/2]の範囲に固定されていることを前提としています。

したがって、必要なのはこれです。

float radHalfAngle = ... / 2.0; //See below
float sinVal = Math.Sin(radHalfAngle);
float cosVal = Math.Cos(radHalfAngle);
float xVal = 1.0f * sinVal;
float yVal = 0.0f * sinVal;  //Here for completeness.
float zVal = 0.0f * sinVal;  //Here for completeness.
Quaternion rot = new Quaternion(xVal, yVal, zVal, cosVal);

また、ラジアンに直接変換amountすることは意味がありません。特にamount、マウスが移動したピクセル座標のデルタだけの場合は意味がありません。マウスが移動する距離と回転する量の間に、ある種の変換スケールが必要です。そして、あなたが望む種類のスケールでtoRadiansはありません。

もう一つ。rotここで行うように、左に乗算すると、カメラ空間のX軸を中心に回転します。ワールドスペースのX軸を中心に回転する場合は、右に乗算する必要があります。

于 2011-10-20T23:09:31.603 に答える