OpenGLで立方体を作るための完全ガイド

ページ名:OpenGLで立方体を作るための完全ガイド

OpenGLは、単純なプリミティブから複雑な3次元シーンを描画するために使用される強力な3Dプログラミングツールです。この記事では、回転させて3次元で見ることができる単純な立方体を描く方法を教えます!

このプロジェクトには、コードエディターとCプログラミングの知識が必要です。

知っておくべきこと

  • 立方体を作り始めるには、OpenGLと互換性のあるCコンパイラの両方をインストールする必要がある。
  • 線を描き始めるにはglBegin()コマンドを使い、線を終わらせるにはglEnd()コマンドを使う。
  • 立方体を3次元で視覚化できるように、必ず「深度テストを有効にする」ようにしてください。
パート1

セットアップ

  1. OpenGLをインストールする。すでにOpenGLと互換性のあるCコンパイラがインストールされている場合は、このステップを飛ばして次に進んでください。
  2. ドキュメントを作成する。お好きなコード・エディタで新規ファイルを作成し、mycube.cとして保存します。
  3. インクルードを追加します。これらは、プログラムに必要な基本的なインクルードです。オペレーティング・システムによって必要なインクルードが異なることを認識しておくことが重要です。プログラムが汎用的で、どのユーザでも実行できるようにするために、必ずこれらすべてをインクルードしてください。
      // インクルード #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef __APPLE__ #include #else #include #endif
  4. 関数のプロトタイプとグローバル変数を追加する。次のステップは関数のプロトタイプを宣言することです。
      // 関数プロトタイプ void display(); void specialKeys(); // グローバル変数 double rotate_y=0; double rotate_x=0;
  5. main()関数をセットアップします。
      int main(int argc, char* argv[]){ // GLUTを初期化し,ユーザパラメータを処理する glutInit(&argc,argv); // Zバッファー付きダブルバッファーのトゥルーカラーウィンドウを要求する glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    • このステートメントはあなたの環境をセットアップします。OpenGLプログラムを書くときに覚えておくべき大きなことは、すべてを求めなければならないということです。そのためには、あなたのプログラムがどのように動作し、あなたが望む機能を得るために何を含める必要があるのかをより深く理解する必要があります。この行では、ダブルバッファリング、RGBカラー、Zバッファを使ってディスプレイをセットアップします。
    • ダブルバッファリングは、画像が画面に描画される方法によって生じる問題を解消するために、グラフィックプログラムで使用されるテクニックです。シーンを再描画するたびに、まずディスプレイを消去してから新しい情報を描画しなければならない。二重バッファリングがないと、画面の消去と再描画が繰り返されるため、ちらつきが生じます。
    • この問題は、描画先に2つ目のバッファを追加することで解決される。この方法では、画像が最初のバッファに描画され、そのバッファが表示されます。次のフレームは2番目のバッファに描画され、それが終わると2つのバッファが入れ替わる。あなたはすぐに2つ目のバッファを見ることができますが、私たちからは見えないように、1つ目のバッファは消去され、終了後に入れ替わる3つ目のフレームで再描画されます。
    • また、ウィンドウでRGBカラーシステムを有効にしたい。
    • Zバッファリングは、あなたが望む3D効果を得る方法です。OpenGLは、x、y、z軸を持つ3次元座標系を使用します。オブジェクトがあなたの近くにあるように見せるにはz軸上の位置を大きくし、遠くにあるように見せるにはz軸上の位置を小さくします。
  6. ウィンドウの作成次のステップは、立方体を描くウィンドウを作成することです。このチュートリアルでは、このウィンドウを "Awesome Cube" と呼びます。
      // ウィンドウを作成する glutCreateWindow("Awesome Cube");
  7. 深度テストを有効にする。OpenGLは、特別な機能が有効になっていることを前提としないという点で、厳格な言語です。先に見たZバッファを使って3次元表示を行うには、深度テストを有効にする必要があります。OpenGLの探求を続けるうちに、ライティング、テクスチャ、カル・フェーシングなど、有効にする必要のある多くの機能を発見するでしょう。
      // Zバッファの深度テストを有効にする glEnable(GL_DEPTH_TEST);
  8. コールバック関数を追加します。先ほどプロトタイプを書いたコールバック関数です。メインループを通るたびに、これらの関数が呼び出されます。display関数は、前回の呼び出し以降に行われた変数の変更に基づいてシーンを再描画します。specialKeys関数は、プログラムとの対話を可能にします。
      // コールバック関数 glutDisplayFunc(display); glutSpecialFunc(specialKeys);
  9. MainLoopを開始する.これは,アニメーションやユーザとのインタラクションを可能にするために,プログラムを閉じるまでメイン関数を呼び出す.
      // イベントのためにGLUTに制御を渡す glutMainLoop(); // OSに戻る return 0; }.
その2

display()関数の書き方

  1. この関数の目的を理解してください。立方体を描画するすべての作業は、この関数内で行われます。立方体の一般的なアイデアは、6つの面をすべて個別に描画し、適切な位置に配置することです。
    • 概念的には、各辺は4つの角を定義し、OpenGLに線を接続させ、定義した色で塗りつぶすことで描画します。以下はその手順です。
  2. glClear()を追加する。この関数で必要な最初のステップは、色とZバッファをクリアすることです。このステップがないと、古い図面が新しい図面の下にまだ見えていたり、描画されたオブジェクトが画面上の正しい位置になかったりする可能性がある。
      void display(){ // スクリーンとZバッファをクリアする glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  3. glBegin()とglEnd()を追加する。OpenGLはオブジェクトを異なるポリゴンの組み合わせとして定義します。glBegin()コマンドを使うと、図形を描く鉛筆を効果的に置くことができます。鉛筆を持ち上げて新しい図形を描き始めるには、glEnd()コマンドを使わなければなりません。このチュートリアルでは、GL_POLYGON を使って立方体の各辺を描きますが、GL_LINE、GL_QUAD、GL_TRIANGLE などの他のパラメータ・オプションを使用して他の図形を作成することも可能です。
    • ここでは立方体の正面から始めます。後で、6つの側面すべてに色を追加します。
    • // 多色の側面 - 正面 glBegin(GL_POLYGON); // 頂点は次のステップで追加する glEnd();
  4. glVertex3f()を追加する。多角形の開始を指定したら、オブジェクトの頂点を定義する必要があります。glVertexには、オブジェクトで何をしたいかによって複数の形式があります。
    • まず、何次元で作業するかです。上のglVertex3fの3は3次元で描画することを意味します。2次元や4次元で作業することも可能です。glVertex3fの上のfは浮動小数点数を使っていることを示している。short、integer、doubleを使うこともできる。
    • これらの点は反時計回りに定義されていることに注意。今のところ、これはあまり重要ではありませんが、ライティング、テクスチャ、カルフ ェーシングを扱うようになると、これは非常に重要になります。
    • glBegin()とglEnd()の間に頂点を追加します。
    • // 多色面 - 正面 glBegin(GL_POLYGON); glVertex3f( -0.5, -0.5, -0.5); // P1 glVertex3f( -0.5, 0.5, -0.5); // P2 glVertex3f( 0.5, 0.5, -0.5); // P3 glVertex3f( 0.5, -0.5, -0.5); // P4 glEnd();
  5. glColor3f()を追加する。glColorはglVertexと同様に動作する。ポイントはshort、integer、double、floatで定義できる。各色は0から1までの値を持つ。0を全て指定すると点は黒くなり、1を指定すると点は白くなる。glColor3f()の3は、アルファチャンネルを持たないRGBカラーシステムを指します。色のアルファ値はその色の透明度を定義します。アルファレベルを変更するには、glColor4f()を使用し、最後のパラメータに0から1の値を指定します。
    • glColor3f()を呼び出すと、その時点から描画されるすべての頂点がその色になります。したがって、4つの頂点をすべて赤にしたい場合は、glVertex3f()コマンドの前に一度だけ色を設定すれば、すべての頂点が赤になります。
    • 下のFront側の定義では、各頂点に新しい色を定義する方法を示している。このようにすると、OpenGLの色の興味深い特性を見ることができます。ポリゴンの各頂点はそれぞれの色を持っているので、OpenGLは自動的に色をブレンドします!次のステップでは、4つの頂点に同じ色を割り当てる方法を示します。
    • // 多色の側面 - 正面 glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); // P1は赤 glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.5, 0.5, -0.5 ); // P2 は緑 glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.5, 0.5, -0.5 ); // P3 は青 glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.5, -0.5, -0.5 ); // P4 は紫 glEnd();
  6. 他の面を処理する。立方体の他の5つの側面について、各頂点の位置がどうなるかを調べますが、簡単にするために、これらはあなたのために計算され、以下の最終的なdisplay()関数に含まれています。
      // 白い面 - BACK glBegin(GL_POLYGON); glColor3f( 1.0, 1.0, 1.0 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glEnd(); // 紫側 - RIGHT glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glEnd(); // 緑側 - 左 glBegin(GL_POLYGON); glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEnd(); // 青側 - TOP glBegin(GL_POLYGON); glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glEnd(); // 赤側 - 下 glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEnd(); glFlush(); glutSwapBuffers(); }.
    • また、この関数の最後のコードを2行追加したい。これらはglFlush();とglutSwapBuffers();であり、先に学んだダブル・バッファリング効果を与えてくれる。
パート3

インタラクティブ性の構築

  1. specialKeys()を追加する。もう少しで完成ですが、現時点では立方体を描くことはできても回転させることはできません。そのため、矢印キーを押して立方体を回転させるためのspecialKeys()関数を作成します!
    • この関数が、グローバル変数rotate_xとrotate_yを宣言した理由です。右矢印キーと左矢印キーを押すと、rotate_yが5度ずつ増減します。同様に、上下の矢印キーを押すと、rotate_xはそれに応じて変化する。
    • void specialKeys( int key, int x, int y ) { // 右矢印 - 回転を5度増やす if (key == GLUT_KEY_RIGHT) rotate_y += 5; // 左矢印 - 回転を5度減らす else if (key == GLUT_KEY_LEFT) rotate_y -= 5; else if (key == GLUT_KEY_UP) rotate_x += 5; else if (key == GLUT_KEY_DOWN) rotate_x -= 5; // 表示の更新を要求する glutPostRedisplay(); }.
  2. glRotate()を追加する。最後のステートメントは、オブジェクトを回転させるステートメントを追加することです。display()関数に戻り、FRONT側の前に以下の行を追加する:
      // 変換をリセットする glLoadIdentity(); // ユーザーがrotate_xとrotate_yを変更したときに回転させる glRotatef( rotate_x, 1.0, 0.0, 0.0 ); glRotatef( rotate_y, 0.0, 1.0, 0.0 ); // 多色面 - FRONT ....
    • まず、glRotatef()の構文はglColor3f()やglVertex3f()と似ているが、常に4つのパラメータを必要とすることに注意。最初のパラメータは、適用する回転の度合いです。次の3つのパラメータは、どの軸について回転させるかを定義するもので、1つ目がx軸、2つ目がy軸、3つ目がz軸です。今必要なのは、x軸とy軸の回転だけです。
    • プログラムで書くすべての変換には、これと同じような行が必要です。概念的には、rotate_xで定義された量だけx軸を中心にオブジェクトを回転させ、rotate_yでy軸を中心に回転させると考えることができます。しかし、OpenGLはこれらすべてのステートメントを1つのマトリックス変換にまとめます。display関数を呼び出すたびに、変換行列を構築し、glLoadIdentity()は、各パスで新しい行列から始まることを保証します。
    • 他に適用できる変換関数は glTranslatef() と glScalef() です。これらの関数はglRotatef()と似ていますが、オブジェクトを平行移動または拡大縮小するためのx、y、zの3つのパラメータしか取りません。
    • 1つのオブジェクトに3つの変換をすべて適用したときに正しい効果を得るには、正しい順序で適用する必要があります。常にglTranslate、glRotate、glScaleの順に記述してください。OpenGLは基本的に、ボトムアップ方式でトランスフォームを適用します。これを理解するために、単純な1x1x1の立方体が、OpenGLが上から下へ、OpenGLが下から上へトランスフォームを適用した場合、どのように見えるかを想像してみてください。
  3. 次のコマンドを追加して、立方体を x 軸に沿って 2、y 軸に沿って 2 だけ拡大縮小し、立方体を y 軸を中心に 180 度回転させ、立方体を x 軸に沿って 0.1 だけ平行移動させます。これらのコマンドと前のglRotate()コマンドを、上記のように正しい順序で並べるようにしてください。(わからない場合は、チュートリアルの最後にある最終的なコードで行います)。
      // その他の変換 glTranslatef( 0.1, 0.0, 0.0 ); glRotatef( 180, 0.0, 1.0, 0.0 ); glScalef( 2.0, 2.0, 0.0 );
  4. コードをコンパイルして実行します。コンパイラとしてgccを使用していると仮定して、以下のコマンドをターミナルから実行してプログラムをコンパイルし、テストしてください。
      Linux の場合: gcc cube.c -o cube -lglut -lGL ./ mycube Mac の場合: gcc -o foo foo.c -framework GLUT -framework OpenGL ./ mycube Windows の場合: gcc -Wall -ofoo foo.c -lglut32cu -lglu32 -lopengl32 ./ mycube
  5. 完成したコードを確認してください。このようになっているはずです:
      // ファイル: mycube.c // 作成者: 作成者: Matt Daisley // Created: 2012/4/25 // プロジェクト: Make a Cube in OpenGL のソースコード // Description:OpenGLウィンドウを作成し、3D立方体を描画します // ユーザーは矢印キーを使って回転させることができます // // コントロール: 左矢印 - 左回転 // 右矢印 - 右回転 // 上矢印 - 上回転 // 下矢印 - 下回転 // ---------------------------------------------------------- // Includes // ---------------------------------------------------------- #include #include #include #define GL_GLEXT_PROTOTYPES #ifdef __APPLE__ #include #else #include #endif // ---------------------------------------------------------- // 関数のプロトタイプ // ---------------------------------------------------------- void display(); void specialKeys(); // ---------------------------------------------------------- // グローバル変数 // ---------------------------------------------------------- double rotate_y=0; double rotate_x=0; // ---------------------------------------------------------- // display() コールバック関数 // ---------------------------------------------------------- void display(){ // スクリーンとZバッファをクリアする glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // トランスフォームをリセットする glLoadIdentity(); // その他のトランスフォーム // glTranslatef( 0.1, 0.0, 0.0 ); // 含まれない // glRotatef( 180, 0.0, 1.0, 0.0 ); // 含まれない // ユーザーが rotate_x と rotate_y を変更したときに回転する glRotatef( rotate_x, 1.0, 0.0, 0.0 ); glRotatef( rotate_y, 0.0, 1.0, 0.0 ); // その他の変形 // glScalef( 2.0, 2.0, 0.0 ); // 含まれない //多色面 - FRONT glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); // P1 は赤 glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( 0.5, 0.5, -0.5 ); // P2 は緑 glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( -0.5, 0.5, -0.5 ); // P3 は青 glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( -0.5, -0.5, -0.5 ); // P4 は紫 glEnd(); // 白側 - BACK glBegin(GL_POLYGON); glColor3f( 1.0, 1.0, 1.0 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glEnd(); // 紫側 - RIGHT glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 1.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glEnd(); // 緑側 - 左 glBegin(GL_POLYGON); glColor3f( 0.0, 1.0, 0.0 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEnd(); // 青側 - TOP glBegin(GL_POLYGON); glColor3f( 0.0, 0.0, 1.0 ); glVertex3f( 0.5, 0.5, 0.5 ); glVertex3f( 0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, -0.5 ); glVertex3f( -0.5, 0.5, 0.5 ); glEnd(); // 赤側 - 下 glBegin(GL_POLYGON); glColor3f( 1.0, 0.0, 0.0 ); glVertex3f( 0.5, -0.5, -0.5 ); glVertex3f( 0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, 0.5 ); glVertex3f( -0.5, -0.5, -0.5 ); glEnd(); glFlush(); glutSwapBuffers(); } // ---------------------------------------------------------- // specialKeys() コールバック関数 // ---------------------------------------------------------- void specialKeys( int key, int x, int y ) { // 右矢印 - 回転を5度増加 if (key == GLUT_KEY_RIGHT) rotate_y += 5; // 左矢印 - 回転を5度下げる else if (key == GLUT_KEY_LEFT) rotate_y -= 5; else if (key == GLUT_KEY_UP) rotate_x += 5; else if (key == GLUT_KEY_DOWN) rotate_x -= 5; // 表示の更新を要求する glutPostRedisplay(); } // -------------------------------------------------------------------------- // main()関数 // -------------------------------------------------------------------------- int main(int argc, char* argv[]){ // GLUTを初期化し,ユーザパラメータを処理する glutInit(&argc,argv); // Zバッファを持つダブルバッファのトゥルーカラーウィンドウを要求する glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); // ウィンドウの作成 glutCreateWindow("Awesome Cube"); // Zバッファの深度テストを有効にする glEnable(GL_DEPTH_TEST); // コールバック関数 glutDisplayFunc(display); glutSpecialFunc(specialKeys); // イベントのためにGLUTに制御を渡す glutMainLoop(); // OSに戻る return 0; }.
この記事は、CC BY-NC-SAで公開されている " A Complete Guide to Making a Cube in OpenGL " を改変して作成した。特に断りのない限り、CC BY-NC-SAで利用可能です。

シェアボタン: このページをSNSに投稿するのに便利です。

コメント

返信元返信をやめる

※ 悪質なユーザーの書き込みは制限します。

最新を表示する

NG表示方式

NGID一覧