0

3Dワールドに飛行機があり、その方向は任意の方法(ピッチ、ヨー、ロールなど)で保存されます。飛行機を左に曲がらせたいのですが、glRotatefはグローバル座標に固執し、飛行機の回転を気にしないため、仕事をしません。ヨーを変更するだけでも、これも役に立たないため、役に立ちません。飛行機の実際の回転に対して、飛行機が地平線にまっすぐ飛ぶときだけ「左」を意味します。私が必要とするものは次のようになります:

    float pitch = 10 , yaw = 20, roll = 30;        //some initial values
    Turn(&pitch, &yaw, &roll ,  5, 0 , 0 )   //calculate new pitch, yaw and roll as if 
    //the plane had turned 5 degrees to the right (relative to its current orientation and roll!)
    //pitch, yaw and roll are updated to reflect the new orientation.

多くの人がクォータニオンの使用を提案していますが、Turn関数にそれらを実装する方法がわかりません(1つの実用的な例はBlitz3Dで、glRotatefのようなグローバル回転用の「RotateEntity」関数と方向に基づく回転用の「TurnEntity」があります)この関数は内部的に次のように機能すると思います。

  • ピッチ、ヨー、ロールをOpenGLのEulerToQuatのようなクォータニオンに変換 +ローカル軸を中心としたSDL回転
  • クォータニオン数学を使用してローカルローテーションを実行します(ソースが見つかりません)
  • クォータニオンをヨー、ロール、ピッチに戻す(ソースが見つかりません)
4

1 に答える 1

0

私は最終的に、すべての船のマトリックスを常に運ぶように切り替えることで問題を解決しました。ピッチ、ヨー、ロールは必要な場合にのみ計算されますが、これはめったにありません。最後に、glRotatefがその役割を果たし(すでに回転された行列に適用するだけで済みます)、結果を保存して、変更が削除されないようにします。

次のコードは、x、y、z、Matrix [16]、dx、dy、dzを運ぶ船の構造での私の実装です。(すべての船の配列はIdentityMatrixで初期化する必要があることに注意してください):

//*************************** Turn Ship **********************************
void TurnShip(long nr,float yaw, float pitch=0,float roll=0) {
  //Turns ship by pitch, yaw and roll degrees.
  glMatrixMode(GL_MODELVIEW);

  glLoadMatrixf(&ship[nr].Matrix[0]); 
  glRotatef(yaw,0,1,0);  
  glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);

  glLoadMatrixf(&ship[nr].Matrix[0]); 
  glRotatef(pitch,1,0,0); 
  glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);

  glLoadMatrixf(&ship[nr].Matrix[0]); 
  glRotatef(roll,0,0,1); 
  glGetFloatv(GL_MODELVIEW_MATRIX,&ship[nr].Matrix[0]);  
}

この関数は、単純なfloat配列に格納されている船の行列をロードし、それを操作してから、配列に保存し直します。ゲームのグラフィックセクションでは、この配列にglLoadMatrixfが読み込まれるため、面倒なことや数学を使わずに船に適用されます。

//*************************** Accelerate Ship relative to own orientation **
void AccelerateShip(long nr,float speedx,float speedy, float speedz)   
{   //use speedz to move object "forward".
ship[nr].dx+= speedx*ship[nr].Matrix[0];   //accelerate sidewards (x-vector)
ship[nr].dy+= speedx*ship[nr].Matrix[1];  //accelerate sidewards (x-vector)
ship[nr].dz+= speedx*ship[nr].Matrix[2]; //accelerate sidewards (x-vector)

ship[nr].dx+= speedy*ship[nr].Matrix[4];   //accelerate upwards (y-vector)
ship[nr].dy+= speedy*ship[nr].Matrix[5];  //accelerate upwards (y-vector)
ship[nr].dz+= speedy*ship[nr].Matrix[6]; //accelerate upwards (y-vector)

ship[nr].dx+= speedz*ship[nr].Matrix[8];   //accelerate forward (z-vector)
ship[nr].dy+= speedz*ship[nr].Matrix[9];  //accelerate forward (z-vector)
ship[nr].dz+= speedz*ship[nr].Matrix[10]; //accelerate forward (z-vector)
}  

これは私が今日学んだことの最良の部分です-チュートリアルはすべて数学に関するものであるため、チュートリアルではしばしば教えてくれません-私はマトリックスから右上、左、船の前を指すベクトルを引き出すことができます私の船が左、右、上、下、加速、ブレーキをかけることができるようにそれらに加速を適用します-そしてglRotatefはそれらを世話し、それらが常に更新され、私たちの側に数学がまったく関与しないようにします:-)

于 2013-02-03T20:31:41.940 に答える