0

私はOpenGLのこのチュートリアルシリーズに従っています:GLUT

http://www.lighthouse3d.com/opengl/glut/

キーボードを使用してカメラ コントロールを実装する段階に達しました。

http://www.lighthouse3d.com/opengl/glut/index.php?8

高度なチュートリアルを実行すると、機能しなくなります。私はほとんどそれをコピーして貼り付けただけです。そのバージョンのコードを実行すると、動作します。私のはうまくいかないようです。左右に移動するとカメラ ビューが回転し、上下キーを使用すると前後に移動します。

私のコードはここに分解されています:

コードのこの部分は、値などを初期化する init() を使用してシーン内のコンポーネントをレンダリングします。

void display(void)
{
 if (deltaMove)
  moveMeFlat(deltaMove);
 if (deltaAngle) {
  angle += deltaAngle;
  orientMe(angle);
 }

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glBindTexture(GL_TEXTURE_2D, texture[0]);
 RenderSkyDome();
 glBindTexture(GL_TEXTURE_2D, NULL);

 glutSwapBuffers();

}

void init(void)
{
 glClearColor(0.0, 0.0, 0.0, 0.0);
 glClearDepth(1.0f);
 glColor3f(0.0, 0.0, 1.0);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glEnable(GL_TEXTURE_2D);
 glEnable(GL_DEPTH_TEST);
 glDepthFunc(GL_LEQUAL);
 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

 LoadTextures("clouds2.bmp", 0);
 GenerateDome(600.0f, 5.0f, 5.0f, 1.0f, 1.0f);

 snowman_display_list = createDL();
}

これは私の主なループ関数です:

int main ()
{
 glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
 glutInitWindowSize(800, 600);
 glutInitWindowPosition(0, 0);
 glutCreateWindow("Captain Ed's Adventures: Great Wall of China");
 init();

 //Glut Input Commands
 glutIgnoreKeyRepeat(1);
 glutSpecialFunc(pressKey);
 glutSpecialUpFunc(releaseKey);
 glutKeyboardFunc(processNormalKeys);

 glutDisplayFunc(display);
 glutIdleFunc(display);
 glutReshapeFunc(reshape);  // This redraws everything on screen when window size is changed.               
 glutMainLoop();
 return 0;
}

呼び出される入力関数は次のとおりです。

void pressKey(int key, int x, int y) {

 switch (key) {
  case GLUT_KEY_LEFT : deltaAngle = -0.10f;break;
  case GLUT_KEY_RIGHT : deltaAngle = 0.10f;break;
  case GLUT_KEY_UP : deltaMove = 50;break;
  case GLUT_KEY_DOWN : deltaMove = -50;break;
 }
}

void releaseKey(int key, int x, int y) {

 switch (key) {
  case GLUT_KEY_LEFT : if (deltaAngle < 0.0f) 
         deltaAngle = 0.0f;
        break;
  case GLUT_KEY_RIGHT : if (deltaAngle > 0.0f) 
         deltaAngle = 0.0f;
        break;
  case GLUT_KEY_UP :  if (deltaMove > 0) 
         deltaMove = 0;
        break;
  case GLUT_KEY_DOWN : if (deltaMove < 0) 
         deltaMove = 0;
        break;
 }
}

void processNormalKeys(unsigned char key, int x, int y) {

 if (key == 27) 
  exit(0);
}

カメラで使用される変数とそれを変更する関数:

static float angle=0.0,deltaAngle = 0.0,ratio;
static float x=0.0f,y=1.75f,z=5.0f;
static float lx=0.0f,ly=0.0f,lz=-1.0f;
static int deltaMove=0;

void orientMe(float ang) {

 lx = sin(ang);
 lz = -cos(ang);
 glLoadIdentity();
 gluLookAt(x, y, z, 
        x + lx,y + ly,z + lz,
     0.0f,1.0f,0.0f);
} 

void moveMeFlat(int i) {
 x = x + i*(lx)*0.1;
 z = z + i*(lz)*0.1;
 glLoadIdentity();
 gluLookAt(x, y, z, 
        x + lx,y + ly,z + lz,
     0.0f,1.0f,0.0f);
}

私はそれが私が取り組んでいるほとんどすべてだと信じているので、基本的に何が起こるべきかというと、上キーを押すと deltaMove は = 50 になり、これが起こると void display(void) の if ステートメントは moveMeFlat(deltaMove); を実行する必要があります。これが間違っているのか、それともより良い結果があるのか​​ わかりません....

関連するスイッチケース内で「moveMeFlat(deltaMove)」を移動できますが、これでは必要な動きができません。上記のチュートリアルのソースコードを正しい機能で使用しているように見えますが、私の場合はそうではないので、表示されているifステートメントに関係していると思います。

私が探している最終結果は、カメラを左右に回転させて前方と後方を操作できるようにすることです。前方キーと左キーを押して、レーシング ゲームのようにカメラが左に曲がるのを確認できるようにしたいと思います...

4

2 に答える 2

2

すべてのグローバル変数宣言の前にある static を取り除いてみてください。

static の最後の使用は、コードのファイル内のグローバル変数としてです。この場合、static の使用は、プロジェクトの一部である他のファイルのソース コードが変数にアクセスできないことを示します。単一ファイル内のコードのみが変数を参照できます。(スコープ、つまり可視性はファイルに限定されます。) この手法は、変数の可視性を制限し、名前の競合を回避するのに役立つため、オブジェクト指向コードをシミュレートするために使用できます。この static の使用は、C からの継承です。

- http://www.cprogramming.com/tutorial/statickeyword.html

また、これの代わりに:

if (deltaMove)
  moveMeFlat(deltaMove);
 if (deltaAngle) {
  angle += deltaAngle;
  orientMe(angle);
 }

これを試して:

if (deltaMove != 0)
  moveMeFlat(deltaMove);
 if (deltaAngle != 0.0) {
  angle += deltaAngle;
  orientMe(angle);
 }
于 2010-01-01T14:54:03.697 に答える
0

キーが押されているときに GLUT はアイドル状態ですか? アイドルではないと思います。display() 関数は、ウィンドウが作成されたときと GLUT がアイドル状態のときにのみ呼び出されるため、位置を変更することはできません。

追加することをお勧めします:

glutTimerFunc(40, display, 1);

表示機能の最後まで。これにより、display が 40 ミリ秒ごとに呼び出されます。

また、表示をアイドル関数として登録しないでください。そうしないと、一連のタイマー関数の多くを開始するアイドル関数が作成されます。

PS 私は glFlush(); と呼びます。表示関数でバッファを交換する直前。

于 2009-11-16T22:54:50.183 に答える