4 座標系を指定したプログラムの例

4.1 先週のプログラムの問題点

先週のプログラムでは,最初は図2が描かれた.ウィンドウを変 形すると,それに応じて図3のように描いた図形が変形した.こ れは,ワールド座標系とウィンドウ座標系の対応が悪いためである.

図 2: 元の図
\includegraphics[keepaspectratio, scale=0.5]{figure/change_tri1}
図 3: ウィンドウを縮める.図形の形が変化する.
\includegraphics[keepaspectratio, scale=0.5]{figure/change_tri2}

4.2 サイズを変更しても図形が変化しない

ワールド座標系とウィンドウ座標系をきちんと指定し,ウィンドウのサイズを変化させて も,形が変わらないプログラムを書く.

4.2.1 プログラム例

リスト2のようにすると,ウィンドウのサイズを変えても図形の形は変 化しない.ウィンドウのサイズが変化するというイベントが発生すると,コールバック関 数resize()を呼び出すようにしている.イベントとコールバック関数の関係は,19 行目のglutReshapeFunc(resize);で決めている.このコールバック関数で,ワールド座 標系とウィンドウ座標系を次のように決めている.
54行目        void resize(int w, int h)

コールバック関数が呼び出された時に,仮引数whは,ウィ ンドウの幅と高さがピクセル単位で格納される.
60行目        glLoadIdentity()

変換行列の話.ちょっと難しいので,説 明しない.最初のうちは,とりあえず,このように書く.
61行目        gluOrtho2D(-w/200.0, w/200.0, -h/200.0, h/200.0)

ワー ルド座標を決めている.次のウィンドウ座標系の指定とあわせて,ウィンド ウ座標系の1ピクセルが,ワールド座標系の0.01に対応している.
62行目        glViewport(0, 0, w, h)

作成したウィンドウの全領域を 使って作図するように指示している.

このプログラムでは,イベントが発生したときにコールバック関数が呼び出されたことが 分かるようにしている.イベントに応じて,draw()関数とresize()関数が呼び 出される.これらの関数が呼び出されると,ターミナルにメッセージが書かれる.このメッ セージを見ると,コールバック関数が呼び出されるタイミングが分かる.


   1 #include <stdio.h>
   2 #include <GL/glut.h>
   3 
   4 void draw(void);                            // プロトタイプ宣言
   5 void resize(int w, int h);
   6 void set_color(void);
   7 
   8 //====================================================================
   9 // main関数
  10 //====================================================================
  11 int main(int argc, char *argv[])
  12 {
  13   glutInitWindowPosition(100,200);          // 初期位置(x,y)指定
  14   glutInitWindowSize(300,500);              // 初期サイズ(幅,高さ)指定
  15   glutInit(&argc, argv);                    // GLUT 初期化
  16   glutInitDisplayMode(GLUT_RGBA);           // 表示モードの指定
  17   glutCreateWindow("Yamamoto's window");    // windowをタイトルを付けてを開く
  18   glutDisplayFunc(draw);                    // イベントにより呼び出し
  19   glutReshapeFunc(resize);                  // サイズ変更のときに呼び出す関数指定
  20   set_color();                              // 塗りつぶす色指定
  21   glutMainLoop();                           // GLUTの無限ループ
  22 
  23   return 0;
  24 }
  25 
  26 //====================================================================
  27 // 図形を描く
  28 //====================================================================
  29 void draw(void)
  30 {
  31 
  32   printf("draw has been called.\n");   // イベント確認用(通常は不要)
  33 
  34   glClear(GL_COLOR_BUFFER_BIT);
  35 
  36   // ---- 三角形 ---------
  37   glColor3d(0.0, 0.7, 0.0);            // 線の色指定(RGB) 赤
  38   glBegin(GL_TRIANGLES);               // 開始 三角形
  39   glVertex2d(-0.7, -0.7);              // 頂点の指定
  40   glVertex2d( 0.0,  0.6);
  41   glVertex2d( 0.7, -0.7);
  42   glEnd();                             // 終了
  43 
  44   glFlush();                           // 描画
  45 }
  46 
  47 //====================================================================
  48 // リサイズ
  49 //     この関数は window のサイズが変化したら呼び出される
  50 //     引数
  51 //            w:ウィンドウの幅
  52 //            h:ウィンドウの高さ
  53 //====================================================================
  54 void resize(int w, int h)
  55 {
  56 
  57   // イベント確認用(通常は不要)
  58   printf("resize has been called. w=%d\th=%d\n", w, h);
  59 
  60   glLoadIdentity();             // 変換行列を単位行列に
  61   gluOrtho2D(-w/200.0, w/200.0, -h/200.0, h/200.0); // world座標系の範囲
  62   glViewport(0, 0, w, h);       // ウィンドウ座標系を指定
  63 }
  64 
  65 //====================================================================
  66 // 色の指定
  67 //====================================================================
  68 void set_color(void)
  69 {
  70   glClearColor(0.9, 1.0, 1.0, 1.0);  //赤緑青と透明度
  71 }


\fbox{\textgt{実行結果}}
端末には以下のように表示され,
resize has been called. w=739   h=317
draw has been called.
resize has been called. w=729   h=317
draw has been called.
draw has been called.
draw has been called.

図 4: ウィンドウの枠を変化させても,中の図形は変わらない.
\includegraphics[keepaspectratio, scale=0.5]{figure/const_tri.eps}



ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成19年11月21日


no counter