GLUT による [手抜き] OpenGL 入門

システム準備

System Version: Mac OS X 10.6.4

Kernel Version: Darwin 10.4.0

Compiler: gcc-4.2.1

Compile: gcc -Wall -O2 -o PROGRAM PROGRAM.c -framework OpenGL -framework GLUT

空のウィンドウを開く

1-window.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#include <GLUT/glut.h>

void display(void){
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./1-window 初めてのウィンドウ

_images/1-window.png

ウィンドウを塗りつぶす

2-window.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT); // ウィンドウを塗りつぶす
  glFlush(); // まだ実行されていない OpenGL の命令を全部実行する
}

void init(void){
  // glClear(GL_COLOR_BUFFER_BIT) で
  // ウィンドウを塗りつぶす際の色を指定する
  // 最後の引数は α  と呼ばれる (0: 透明, 1: 不透明)
  glClearColor(1.0, 0.0, 0.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  
  // ディスプレーの表示モードを設定する
  // RGB (赤緑青, 光の三原色)
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./2-window

_images/2-window.png

線を引く

line.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  
  glBegin(GL_LINE_LOOP); // 図形のタイプを指定する

  // 図形の各頂点の座標値を設定する
  glVertex2d(-0.5, -0.5); // 第 3 象限
  glVertex2d(0.5, -0.5); // 第 4 象限
  glVertex2d(0.5, 0.5); // 第 1 象限
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void init(void){
  glClearColor(0.0, 0.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./line

_images/rectangle.png

OpenGL における座標系:

_images/coordinate.png

図形のタイプ:

_images/image-type.png

線に色を付ける

line-color.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);

  glColor3d(1.0, 0.5, 0.0); // これから描画するものの色を指定する
  
  glBegin(GL_LINE_LOOP); // 図形のタイプを指定する

  // 図形の各頂点の座標値を設定する
  glVertex2d(-0.5, -0.5); // 第 3 象限
  glVertex2d(0.5, -0.5); // 第 4 象限
  glVertex2d(0.5, 0.5); // 第 1 象限
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void init(void){
  glClearColor(0.0, 0.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./line-color

_images/line-color.png

図形を塗りつぶす

polygon-color.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);

  glColor3d(1.0, 0.5, 0.0); // これから描画するものの色を指定する
  
  glBegin(GL_POLYGON); // 図形のタイプを指定する

  // 図形の各頂点の座標値を設定する
  glVertex2d(-0.5, -0.5); // 第 3 象限
  glVertex2d(0.5, -0.5); // 第 4 象限
  glVertex2d(0.5, 0.5); // 第 1 象限
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./polygon-color

_images/polygon-color.png

polygon-color1.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  
  glBegin(GL_POLYGON); // 図形のタイプを指定する

  glColor3d(1.0, 0.0, 0.0); // 赤
  glVertex2d(-0.5, -0.5); // 第 3 象限

  glColor3d(0.0, 1.0, 0.0); // 緑
  glVertex2d(0.5, -0.5); // 第 4 象限
    
  glColor3d(0.0, 0.0, 1.0); // 青
  glVertex2d(0.5, 0.5); // 第 1 象限

  glColor3d(1.0, 1.0, 0.0); // 黄
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./polygon-color1

_images/polygon-color1.png

関数の命令法

_images/func.png

座標軸とビューポーと

viewport.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  
  glBegin(GL_POLYGON); // 図形のタイプを指定する

  glColor3d(1.0, 0.0, 0.0); // 赤
  glVertex2d(-0.5, -0.5); // 第 3 象限

  glColor3d(0.0, 1.0, 0.0); // 緑
  glVertex2d(0.5, -0.5); // 第 4 象限
    
  glColor3d(0.0, 0.0, 1.0); // 青
  glVertex2d(0.5, 0.5); // 第 1 象限

  glColor3d(1.0, 1.0, 0.0); // 黄
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  // スクリーン上の表示域をビューポートの大きさに比例させる
  glOrtho(-w / 400.0, w / 400.0, -h / 400.0, h /400.0, -1.0, 1.0);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./viewport

_images/viewport.png

位置やサイズを指定してウィンドウを開く

size-window.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  
  glBegin(GL_POLYGON); // 図形のタイプを指定する

  glColor3d(1.0, 0.0, 0.0); // 赤
  glVertex2d(-0.5, -0.5); // 第 3 象限

  glColor3d(0.0, 1.0, 0.0); // 緑
  glVertex2d(0.5, -0.5); // 第 4 象限
    
  glColor3d(0.0, 0.0, 1.0); // 青
  glVertex2d(0.5, 0.5); // 第 1 象限

  glColor3d(1.0, 1.0, 0.0); // 黄
  glVertex2d(-0.5, 0.5); // 第 2 象限
  
  glEnd();
  glFlush();
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  // スクリーン上の表示域をビューポートの大きさに比例させる
  glOrtho(-w / 400.0, w / 400.0, -h / 400.0, h /400.0, -1.0, 1.0);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(320, 240); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[1]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./size-window

_images/size-window.png

マウスボタンをクリックする

mouse.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <GLUT/glut.h>
#include <stdio.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    printf("Left");
    break;
  case GLUT_MIDDLE_BUTTON:
    printf("Middle");
    break;
  case GLUT_RIGHT_BUTTON:
    printf("Right");
    break;
  default:
    break;
  }
  
  printf(" button is ");

  switch(state){
  case GLUT_UP:
    printf("up");
    break;
  case GLUT_DOWN:
    printf("down");
    break;
  default:
    break;
  }
  printf(" at (%d, %d)\n", x, y);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(400, 400); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./mouse

_images/mouse.png

mouse1.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <GLUT/glut.h>
#include <stdio.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);
  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  //スクリーン上の座標系をマウスの座標系に一致させる
  glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

  static int x0, y0;
  
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_UP){
      // ボタンを押した位置から離した位置まで線を引く
      glColor3d(1.0, 0.0, 0.0);
      glBegin(GL_LINES);
      glVertex2i(x0, y0);
      glVertex2i(x, y);
      glEnd();
      glFlush();
    }
    else{
      // ボタンを押した位置を覚える
      x0 = x;
      y0 = y;
    }
    break;
  case GLUT_MIDDLE_BUTTON:
    break;
  case GLUT_RIGHT_BUTTON:
    break;
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(400, 400); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./mouse1

_images/mouse1.png

mouse2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#include <GLUT/glut.h>
#include <stdio.h>

#define MAXPOINTS 100 // 記憶する点の数
GLint point[MAXPOINTS][2]; // 座標を記憶する配列
int pointnum = 0; // 記憶した座標の数

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 記憶したデータで線を描く
  if (pointnum > 1){
    glColor3d(1.0, 0.0, 0.0);
    glBegin(GL_LINES);
    for(i = 0; i < pointnum; i++){
      glVertex2iv(point[i]);
    }
    glEnd();
  }
  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  //スクリーン上の座標系をマウスの座標系に一致させる
  glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

  switch(button){
  case GLUT_LEFT_BUTTON:
    // ボタンを操作した位置を記憶する
    point[pointnum][0] = x;
    point[pointnum][1] = y;
    if(state == GLUT_UP){
      // ボタンを押した位置から離した位置まで線を引く
      glColor3d(1.0, 0.0, 0.0);
      glBegin(GL_LINES);
      glVertex2iv(point[pointnum - 1]); // 一つ前は押した位置
      glVertex2iv(point[pointnum]); // 今の位置は離した位置
      glEnd();
      glFlush();
    }
    else{
    }
    if (pointnum < MAXPOINTS -1 ) pointnum++;
    break;
  case GLUT_MIDDLE_BUTTON:
    break;
  case GLUT_RIGHT_BUTTON:
    break;
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(400, 400); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./mouse2

_images/mouse2.png

マウスをドラッグする

mouse-drag.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
#include <GLUT/glut.h>
#include <stdio.h>

#define MAXPOINTS 100 // 記憶する点の数
GLint point[MAXPOINTS][2]; // 座標を記憶する配列
int pointnum = 0; // 記憶した座標の数
int rubberband = 0; // ラバーバンドの消去

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 記憶したデータで線を描く
  if (pointnum > 1){
    glColor3d(1.0, 0.0, 0.0);
    glBegin(GL_LINES);
    for(i = 0; i < pointnum; i++){
      glVertex2iv(point[i]);
    }
    glEnd();
  }
  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  //スクリーン上の座標系をマウスの座標系に一致させる
  glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

  switch(button){
  case GLUT_LEFT_BUTTON:
    // ボタンを操作した位置を記憶する
    point[pointnum][0] = x;
    point[pointnum][1] = y;
    if(state == GLUT_UP){
      // ボタンを押した位置から離した位置まで線を引く
      glColor3d(1.0, 0.0, 0.0);
      glBegin(GL_LINES);
      glVertex2iv(point[pointnum - 1]); // 一つ前は押した位置
      glVertex2iv(point[pointnum]); // 今の位置は離した位置
      glEnd();
      glFlush();
      // 始点ではラバーバンドを描いていないので
      // 消さない
      rubberband = 0;
    }
    else{
    }
    if (pointnum < MAXPOINTS -1 ) pointnum++;
    break;
  case GLUT_MIDDLE_BUTTON:
    break;
  case GLUT_RIGHT_BUTTON:
    break;
  default:
    break;
  }
}

void motion(int x, int y){
  static GLint savepoint[2]; // 以前のラバーバンドの端点
  // 論理演算機能 ON
  glEnable(GL_COLOR_LOGIC_OP); // 引数 cap に指定した機能を使用可能にする
  glLogicOp(GL_INVERT);

  glBegin(GL_LINES);
  if(rubberband){
    // 以前のラバーバンドを消す
    glVertex2iv(point[pointnum - 1]);
    glVertex2iv(savepoint);
  }
  // 新しいラバーバンドを描く
  glVertex2iv(point[pointnum - 1]);
  glVertex2i(x, y);
  glEnd();

  glFlush();

  // 論理演算機能 OFF
  glLogicOp(GL_COPY);
  glDisable(GL_COLOR_LOGIC_OP);
  // 今描いたラバーバンドの端点を保存
  savepoint[0] = x;
  savepoint[1] = y;

  // 今描いたラバーバンドは次のタイミングで消す
  rubberband = -1;
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(400, 400); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./mouse-drag

_images/mouse-drag.png

キーボードから読み込み

keyboard.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <GLUT/glut.h>
#include <stdio.h>
#include <stdlib.h>

#define MAXPOINTS 100 // 記憶する点の数
GLint point[MAXPOINTS][2]; // 座標を記憶する配列
int pointnum = 0; // 記憶した座標の数
int rubberband = 0; // ラバーバンドの消去

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 記憶したデータで線を描く
  if (pointnum > 1){
    glColor3d(1.0, 0.0, 0.0);
    glBegin(GL_LINES);
    for(i = 0; i < pointnum; i++){
      glVertex2iv(point[i]);
    }
    glEnd();
  }
  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h); // ウィンドウ全体をビューポートにする
  glLoadIdentity(); // 変換行列の初期化
  //スクリーン上の座標系をマウスの座標系に一致させる
  glOrtho(-0.5, (GLdouble)w - 0.5, (GLdouble)h - 0.5, -0.5, -1.0, 1.0);
}

void mouse(int button, int state, int x, int y){

  switch(button){
  case GLUT_LEFT_BUTTON:
    // ボタンを操作した位置を記憶する
    point[pointnum][0] = x;
    point[pointnum][1] = y;
    if(state == GLUT_UP){
      // ボタンを押した位置から離した位置まで線を引く
      glColor3d(1.0, 0.0, 0.0);
      glBegin(GL_LINES);
      glVertex2iv(point[pointnum - 1]); // 一つ前は押した位置
      glVertex2iv(point[pointnum]); // 今の位置は離した位置
      glEnd();
      glFlush();
      // 始点ではラバーバンドを描いていないので
      // 消さない
      rubberband = 0;
    }
    else{
    }
    if (pointnum < MAXPOINTS -1 ) pointnum++;
    break;
  case GLUT_MIDDLE_BUTTON:
    break;
  case GLUT_RIGHT_BUTTON:
    break;
  default:
    break;
  }
}

void motion(int x, int y){
  static GLint savepoint[2]; // 以前のラバーバンドの端点
  // 論理演算機能 ON
  glEnable(GL_COLOR_LOGIC_OP); // 引数 cap に指定した機能を使用可能にする
  glLogicOp(GL_INVERT);

  glBegin(GL_LINES);
  if(rubberband){
    // 以前のラバーバンドを消す
    glVertex2iv(point[pointnum - 1]);
    glVertex2iv(savepoint);
  }
  // 新しいラバーバンドを描く
  glVertex2iv(point[pointnum - 1]);
  glVertex2i(x, y);
  glEnd();

  glFlush();

  // 論理演算機能 OFF
  glLogicOp(GL_COPY);
  glDisable(GL_COLOR_LOGIC_OP);
  // 今描いたラバーバンドの端点を保存
  savepoint[0] = x;
  savepoint[1] = y;

  // 今描いたラバーバンドは次のタイミングで消す
  rubberband = -1;
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII コード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc, char *argv[]){
  glutInitWindowPosition(250, 250); // 新たに開くウィンドウの位置を指定する
  glutInitWindowSize(400, 400); // 新たに開くウィンドウの幅と高さを指定する
  glutInit(&argc, argv); // GLUT 及び OpenGL 環境を初期化する
  glutCreateWindow(argv[0]); // ウィンドウを開く
  glutDisplayFunc(display); // display ウィンドウに描画する関数へのポインタ
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop(); // 無限ループで, プログラムはイベントの待ち受け状態になる
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./keyboard

_images/keyboard.png

2 次元と 3 次元

2-3.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <GLUT/glut.h>

void display(void){
  glClear(GL_COLOR_BUFFER_BIT);

  glRotated(23.0, 0.0, 1.0, 0.0);

  glBegin(GL_POLYGON);

  glColor3d(1.0, 0.0, 0.0); // 赤
  glVertex2d(-0.9, -0.9);

  glColor3d(0.0, 1.0, 0.0); // 緑
  glVertex2d(0.9, -0.9);

  glColor3d(0.0, 0.0, 1.0); // 青
  glVertex2d(0.9, 0.9);

  glColor3d(1.0, 1.0, 0.0); // 黄
  glVertex2d(-0.9, 0.9);

  glEnd();

  glFlush();
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./2-3

_images/2-3.png

線画を表示する

_images/cube-model.png

cube.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <GLUT/glut.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int edge[][2] = {
  {0, 1}, // A -> B ア
  {1, 2}, // B -> C イ
  {2, 3}, // C -> D ウ
  {3, 0}, // D -> A エ
  {4, 5}, // E -> F オ
  {5, 6}, // F -> G カ
  {6, 7}, // G -> H キ
  {7, 4}, // H -> E ク
  {0, 4}, // A -> E ケ
  {1, 5}, // B -> F コ
  {2, 6}, // C -> G サ
  {3, 7}  // D -> H シ
};

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 図形の描画
  glColor3d(0.0, 0.0, 0.0);
  glBegin(GL_LINES);
  for(i = 0; i< 12; i++){
    glVertex3dv(vertex[edge[i][0]]);
    glVertex3dv(vertex[edge[i][1]]);
  }

  glEnd();

  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  glLoadIdentity();
  glOrtho(-2.0, 2.0, -2.0, 2.0, -2.0, 2.0);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./cube

_images/cube.png

透視投影する

cube1.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <GLUT/glut.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int edge[][2] = {
  {0, 1}, // A -> B ア
  {1, 2}, // B -> C イ
  {2, 3}, // C -> D ウ
  {3, 0}, // D -> A エ
  {4, 5}, // E -> F オ
  {5, 6}, // F -> G カ
  {6, 7}, // G -> H キ
  {7, 4}, // H -> E ク
  {0, 4}, // A -> E ケ
  {1, 5}, // B -> F コ
  {2, 6}, // C -> G サ
  {3, 7}  // D -> H シ
};

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 図形の描画
  glColor3d(0.0, 0.0, 0.0);
  glBegin(GL_LINES);
  for(i = 0; i< 12; i++){
    glVertex3dv(vertex[edge[i][0]]);
    glVertex3dv(vertex[edge[i][1]]);
  }

  glEnd();

  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
  glTranslated(0.0, 0.0, -5.0);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./cube1

_images/cube1.png

視点の位置を変更する

cube2.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#include <GLUT/glut.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int edge[][2] = {
  {0, 1}, // A -> B ア
  {1, 2}, // B -> C イ
  {2, 3}, // C -> D ウ
  {3, 0}, // D -> A エ
  {4, 5}, // E -> F オ
  {5, 6}, // F -> G カ
  {6, 7}, // G -> H キ
  {7, 4}, // H -> E ク
  {0, 4}, // A -> E ケ
  {1, 5}, // B -> F コ
  {2, 6}, // C -> G サ
  {3, 7}  // D -> H シ
};

void display(void){
  int i;
  glClear(GL_COLOR_BUFFER_BIT);

  // 図形の描画
  glColor3d(0.0, 0.0, 0.0);
  glBegin(GL_LINES);
  for(i = 0; i< 12; i++){
    glVertex3dv(vertex[edge[i][0]]);
    glVertex3dv(vertex[edge[i][1]]);
  }

  glEnd();

  glFlush();
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./cube2

_images/cube2.png

図を動かす

anime.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int edge[][2] = {
  {0, 1}, // A -> B ア
  {1, 2}, // B -> C イ
  {2, 3}, // C -> D ウ
  {3, 0}, // D -> A エ
  {4, 5}, // E -> F オ
  {5, 6}, // F -> G カ
  {6, 7}, // G -> H キ
  {7, 4}, // H -> E ク
  {0, 4}, // A -> E ケ
  {1, 5}, // B -> F コ
  {2, 6}, // C -> G サ
  {3, 7}  // D -> H シ
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる.
}

void display(void){
  int i;
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glColor3d(0.0, 0.0, 0.0);
  glBegin(GL_LINES);
  for(i = 0; i< 12; i++){
    glVertex3dv(vertex[edge[i][0]]);
    glVertex3dv(vertex[edge[i][1]]);
  }

  glEnd();

  glFlush();

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./anime

_images/anime.png

ダブルバッファリング

double-buffering.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int edge[][2] = {
  {0, 1}, // A -> B ア
  {1, 2}, // B -> C イ
  {2, 3}, // C -> D ウ
  {3, 0}, // D -> A エ
  {4, 5}, // E -> F オ
  {5, 6}, // F -> G カ
  {6, 7}, // G -> H キ
  {7, 4}, // H -> E ク
  {0, 4}, // A -> E ケ
  {1, 5}, // B -> F コ
  {2, 6}, // C -> G サ
  {3, 7}  // D -> H シ
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glColor3d(0.0, 0.0, 0.0);
  glBegin(GL_LINES);
  for(i = 0; i< 12; i++){
    glVertex3dv(vertex[edge[i][0]]);
    glVertex3dv(vertex[edge[i][1]]);
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./double-buffering

_images/double-buffering.png

多面体を塗りつぶす

real-cube.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble color[][3] = {
  {1.0, 0.0, 0.0}, // 赤
  {0.0, 1.0, 0.0}, // 緑
  {0.0, 0.0, 1.0}, // 青
  {1.0, 1.0, 0.0}, // 黄
  {1.0, 0.0, 1.0}, // マゼンタ
  {0.0, 1.0, 1.0}  // シアン
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glColor3dv(color[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./real-cube

_images/real-cube.png

デプスバッファを使用する

real-cube1.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble color[][3] = {
  {1.0, 0.0, 0.0}, // 赤
  {0.0, 1.0, 0.0}, // 緑
  {0.0, 0.0, 1.0}, // 青
  {1.0, 1.0, 0.0}, // 黄
  {1.0, 0.0, 1.0}, // マゼンタ
  {0.0, 1.0, 1.0}  // シアン
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glColor3dv(color[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./real-cube1

_images/real-cube1.png

カリング

culling.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble color[][3] = {
  {1.0, 0.0, 0.0}, // 赤
  {0.0, 1.0, 0.0}, // 緑
  {0.0, 0.0, 1.0}, // 青
  {1.0, 1.0, 0.0}, // 黄
  {1.0, 0.0, 1.0}, // マゼンタ
  {0.0, 1.0, 1.0}  // シアン
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glColor3dv(color[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_BACK);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./culling

_images/culling.png

光を当ててみる

light.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./light

_images/light.png

光源を設定する

light1.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./light1

_images/light1.png

材質を設定する

material.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑
GLfloat red[] = {0.8, 0.2, 0.2, 1.0};

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){
  int i;
  int j;
  
  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0);

  // 図形の色 (赤)
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);

  // 図形の描画
  glBegin(GL_QUADS);
  for(j = 0; j< 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }

  glEnd();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./material

_images/material.png

階層構造

hierarchy.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑
GLfloat red[] = {0.8, 0.2, 0.2, 1.0};

void cube(void){
  int i;
  int j;

  glBegin(GL_QUADS);
  for(j = 0; j < 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }
  glEnd();
}

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){

  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // モデルビュー変換行列の保存
  glPushMatrix();

  // 図形の回転
  glRotated((double)r, 1.0, 0.0, 0.0); // X 軸に沿って回る

  // 図形の色 (赤)
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);

  // 図形の描画
  cube();

  // モデルビュー変換行列の復帰
  glPopMatrix();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./hierarchy

_images/hierarchy.png

hierarchy1.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑
GLfloat red[] = {0.8, 0.2, 0.2, 1.0};

void cube(void){
  int i;
  int j;

  glBegin(GL_QUADS);
  for(j = 0; j < 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }
  glEnd();
}

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){

  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // モデルビュー変換行列の保存
  glPushMatrix();

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0); // Y 軸に沿って回る

  // 図形の色 (赤)
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);

  // 図形の描画
  cube();

  // 二つ目の図形の描画
  glPushMatrix();
  glTranslated(1.0, 1.0, 1.0);
  cube();
  glPopMatrix();

  // モデルビュー変換行列の復帰
  glPopMatrix();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./hierarchy1

_images/hierarchy1.png

hierarchy2.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑
GLfloat red[] = {0.8, 0.2, 0.2, 1.0};

void cube(void){
  int i;
  int j;

  glBegin(GL_QUADS);
  for(j = 0; j < 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }
  glEnd();
}

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){

  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // モデルビュー変換行列の保存
  glPushMatrix();

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0); // Y 軸に沿って回る

  // 図形の色 (赤)
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);

  // 図形の描画
  cube();

  // 二つ目の図形の描画
  glPushMatrix();
  glTranslated(1.0, 1.0, 1.0);
  glRotated((double)(2 * r), 0.0, 1.0, 0.0);
  cube();
  glPopMatrix();

  // モデルビュー変換行列の復帰
  glPopMatrix();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./hierarchy2

_images/hierarchy2.png

hierarchy3.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#include <GLUT/glut.h>
#include <stdlib.h>

GLdouble vertex[][3] = {
  {0.0, 0.0, 0.0}, // A
  {1.0, 0.0, 0.0}, // B
  {1.0, 1.0, 0.0}, // C
  {0.0, 1.0, 0.0}, // D
  {0.0, 0.0, 1.0}, // E
  {1.0, 0.0, 1.0}, // F
  {1.0, 1.0, 1.0}, // G
  {0.0, 1.0, 1.0}  // H
};

int face[][4] = {
  {0, 1, 2, 3}, // A-B-C-D を結ぶ面
  {1, 5, 6, 2}, // B-F-G-C を結ぶ面
  {5, 4, 7, 6}, // F-E-H-G を結ぶ面
  {4, 0, 3, 7}, // E-A-D-H を結ぶ面
  {4, 5, 1, 0}, // E-F-B-A を結ぶ面
  {3, 2, 6, 7}  // D-C-G-H を結ぶ面
};

GLdouble normal[][3] = {
  { 0.0,  0.0, -1.0 },
  { 1.0,  0.0,  0.0 },
  { 0.0,  0.0,  1.0 },
  {-1.0,  0.0,  0.0 },
  { 0.0, -1.0,  0.0 },
  { 0.0,  1.0,  0.0 }
};

GLfloat light0pos[] = {0.0, 3.0, 5.0, 1.0}; // ライト 1
GLfloat light1pos[] = {5.0, 3.0, 0.0, 1.0}; // ライト 2

GLfloat green[] = {0.0, 1.0, 0.0, 1.0}; // 光源の色: 緑
GLfloat red[] = {0.8, 0.2, 0.2, 1.0};
GLfloat blue[] = {0.2, 0.2, 0.8, 1.0};

void cube(void){
  int i;
  int j;

  glBegin(GL_QUADS);
  for(j = 0; j < 6; j++){
    glNormal3dv(normal[j]);
    for(i = 0; i < 4; i++){
      glVertex3dv(vertex[face[j][i]]);
    }
  }
  glEnd();
}

void idle(void){
  glutPostRedisplay(); // 再描画イベントを発生させる
}

void display(void){

  static int r = 0; // 回転角
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();

  // 視点位置と視線方向
  gluLookAt(3.0, 4.0, 5.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0);

  // 光源の位置設定
  glLightfv(GL_LIGHT0, GL_POSITION, light0pos);
  glLightfv(GL_LIGHT1, GL_POSITION, light1pos);

  // モデルビュー変換行列の保存
  glPushMatrix();

  // 図形の回転
  glRotated((double)r, 0.0, 1.0, 0.0); // Y 軸に沿って回る

  // 図形の色 (赤)
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, red);

  // 図形の描画
  cube();

  // 二つ目の図形の描画
  glPushMatrix();
  glTranslated(1.0, 1.0, 1.0);
  glRotated((double)(2 * r), 0.0, 1.0, 0.0);
  glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, blue);
  cube();
  glPopMatrix();

  // モデルビュー変換行列の復帰
  glPopMatrix();

  glutSwapBuffers(); // ダブルバッファリングの二つのバッファを交換する

  // 一周回ったら回転角を 0 に戻す
  if (r++ >= 360) r = 0;
  
}

void resize(int w, int h){
  glViewport(0, 0, w, h);

  // 透視変換行列の設定
  glMatrixMode(GL_PROJECTION);

  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  // モデルビュー変換行列の設定
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

void mouse(int button, int state, int x, int y){
  switch(button){
  case GLUT_LEFT_BUTTON:
    if(state == GLUT_DOWN){
      // アニメーション開始
      glutIdleFunc(idle);
    }
    else{
      // アニメーション停止
      glutIdleFunc(0); // 0 でも NULL でも OK
    }
    break;
  case GLUT_RIGHT_BUTTON:
    if(state == GLUT_DOWN){
      // コマ送り (1 ステップだけ進める)
      glutPostRedisplay();
    }
    break;
  default:
    break;
  }
}

void keyboard(unsigned char key, int x, int y){
  switch(key){
  case 'q':
  case 'Q':
  case '\033': // '\033' は ESC の ASCII のコード
    exit(0);
  default:
    break;
  }
}

void init(void){
  glClearColor(1.0, 1.0, 1.0, 1.0);
  glEnable(GL_DEPTH_TEST);

  glEnable(GL_CULL_FACE);
  glCullFace(GL_FRONT);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0); // 数値 0 である, 0 番目の光源
  glEnable(GL_LIGHT1); // 数値 1 である, 1 番目の光源
  glLightfv(GL_LIGHT1, GL_DIFFUSE, green);
  glLightfv(GL_LIGHT1, GL_SPECULAR, green);
}

int main(int argc ,char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutMouseFunc(mouse);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./hierarchy3

_images/hierarchy3.png

ウォークスルーの実験

walkthrough.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include <stdlib.h>
#include <GLUT/glut.h>

void scene(void){
  /* 物体の色 */
  static GLfloat red[] = {0.8, 0.2, 0.2, 1.0};
  static GLfloat green[] = {0.2, 0.8, 0.2, 1.0};
  static GLfloat blue[] = {0.2, 0.2, 0.8, 1.0};
  static GLfloat yellow[] = {0.8, 0.8, 0.2, 1.0};
  static GLfloat ground[][4] ={
    {0.6, 0.6, 0.6, 1.0},
    {0.3, 0.3, 0.3, 1.0}
  };

  int i, j;

  /* 赤い箱 */
  glPushMatrix();
  glTranslated(0.0, 0.0, -3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, red);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 緑の箱 */
  glPushMatrix();
  glTranslated(0.0, 0.0, 3.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, green);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 青い箱 */
  glPushMatrix();
  glTranslated(-3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 黄色い箱 */
  glPushMatrix();
  glTranslated(3.0, 0.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
  glutSolidCube(1.0);
  glPopMatrix();

  /* 地面 */
  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -5; j < 5; j++) {
    for (i = -5; i < 5; i++) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)j);
      glVertex3d((GLdouble)i, -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), -0.5, (GLdouble)j);
    }
  }
  glEnd();
}

void display(void){
  static GLfloat lightpos[] = {3.0, 4.0, 5.0, 1.0}; /* 光源の位置 */

  static double ex = 0.0, ez = 0.0; /* 視点の位置 */
  static double r = 0.0;            /* 視点の向き */

  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* モデルビュー変換行列の初期化 */
  glLoadIdentity();

  /* 視点の移動 */
  glRotated(r, 0.0, 1.0, 0.0);
  glTranslated(ex, 0.0, ez);

  /* 光源の位置を設定 */
  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  /* シーンの描画 */
  scene();

  glFlush();
}

void resize(int w, int h){
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, h);

  /* 透視変換行列の指定 */
  glMatrixMode(GL_PROJECTION);

  /* 透視変換行列の初期化 */
  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  /* モデルビュー変換行列の指定 */
  glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

void init(void){
  /* 初期設定 */
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./walkthrough

_images/walkthrough.png

ロボットアームの実験

robotarm.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>

/*
 * 直方体を描く
 */
void myBox(double x, double y, double z){
  GLdouble vertex[][3] = {
    { -x, -y, -z },
    {  x, -y, -z },
    {  x,  y, -z },
    { -x,  y, -z },
    { -x, -y,  z },
    {  x, -y,  z },
    {  x,  y,  z },
    { -x,  y,  z }
  };

  static int face[][4] = {
    { 0, 1, 2, 3 },
    { 1, 5, 6, 2 },
    { 5, 4, 7, 6 },
    { 4, 0, 3, 7 },
    { 4, 5, 1, 0 },
    { 3, 2, 6, 7 }
  };

  static GLdouble normal[][3] = {
    { 0.0, 0.0,-1.0 },
    { 1.0, 0.0, 0.0 },
    { 0.0, 0.0, 1.0 },
    {-1.0, 0.0, 0.0 },
    { 0.0,-1.0, 0.0 },
    { 0.0, 1.0, 0.0 }
  };

  static GLfloat red[] = { 0.8, 0.2, 0.2, 1.0 };

  int i, j;

  /* 材質を設定する */
  glMaterialfv(GL_FRONT, GL_DIFFUSE, red);

  glBegin(GL_QUADS);
  for (j = 0; j < 6; ++j) {
    glNormal3dv(normal[j]);
    for (i = 4; --i >= 0;) {
      glVertex3dv(vertex[face[j][i]]);
    }
  }
  glEnd();
}

/*
 * 円柱を描く
 */
void myCylinder(double radius, double height, int sides){
  static GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 };
  double step = 6.28318530717958647692 / (double)sides;
  int i = 0;

  /* 材質を設定する */
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);

  /* 上面 */
  glNormal3d(0.0, 1.0, 0.0);
  glBegin(GL_TRIANGLE_FAN);
  while (i < sides) {
    double t = step * (double)i++;
    glVertex3d(radius * sin(t), height, radius * cos(t));
  }
  glEnd();

  /* 底面 */
  glNormal3d(0.0, -1.0, 0.0);
  glBegin(GL_TRIANGLE_FAN);
  while (--i >= 0) {
    double t = step * (double)i;
    glVertex3d(radius * sin(t), -height, radius * cos(t));
  }
  glEnd();

  /* 側面 */
  glBegin(GL_QUAD_STRIP);
  while (i <= sides) {
    double t = step * (double)i++;
    double x = sin(t);
    double z = cos(t);

    glNormal3d(x, 0.0, z);
    glVertex3f(radius * x, height, radius * z);
    glVertex3f(radius * x, -height, radius * z);
  }
  glEnd();
}

/*
 * 地面を描く
 */
void myGround(double height){
  static GLfloat ground[][4] = {
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };

  int i, j;

  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -5; j < 5; ++j) {
    for (i = -5; i < 5; ++i) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, height, (GLdouble)j);
      glVertex3d((GLdouble)i, height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)j);
    }
  }
  glEnd();
}

/*
 * 画面表示
 */
void display(void){
  static GLfloat blue[] = { 0.2, 0.2, 0.8, 1.0 };     /* 球の色 */
  static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 }; /* 光源の位置 */

  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* モデルビュー変換行列の初期化 */
  glLoadIdentity();

  /* 光源の位置を設定 */
  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  /* 視点の移動(シーンの方を奥に移す)*/
  glTranslated(0.0, 0.0, -10.0);

  /* シーンの描画 */
  myGround(-2.0);                           /* 地面    */

  glTranslated(0.0, -1.8, 0.0);
  myCylinder(1.0, 0.2, 16);                 /* 土台    */

  glTranslated(0.0, 1.0, 0.0);
  myBox(0.3, 1.0, 0.3);                     /* 1番目の腕 */

  glTranslated(0.0, 1.0, 0.0);
  glRotated(90.0, 1.0, 0.0, 0.0);
  myCylinder(0.4, 0.4, 16);                 /* 関節    */

  glTranslated(0.0, 0.0, -1.0);
  myBox(0.3, 0.3, 1.0);                     /* 2番目の腕 */

  glTranslated(0.0, 0.0, -1.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, blue);
  glutSolidCube(0.9);                       /* ハンド   */

  glFlush();
}

void resize(int w, int h){
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, h);

  /* 透視変換行列の指定 */
  glMatrixMode(GL_PROJECTION);

  /* 透視変換行列の初期化 */
  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  /* モデルビュー変換行列の指定 */
  glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y)
{
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

void init(void){
  /* 初期設定 */
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./robotarm

_images/robotarm.png

ピッチングマシーンの実験

pitcingmachine

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
#include <stdlib.h>
#include <GLUT/glut.h>

#define W 10             /* 地面の幅        */
#define D 10             /* 地面の長さ       */
#define QX 0.0           /* 球の初期位置のx座標値 */
#define QY 1.5           /* 球の初期位置のy座標値 */
#define QZ (-5.0)        /* 球の初期位置のz座標値 */
#define G (-9.8)         /* 重力加速度       */
#define V 25.0           /* 初速度         */
#define TSTEP 0.01       /* フレームごとの時間   */
#define R 0.1            /* ボールの半径      */

/*
 * 地面を描く
 */
void myGround(double height){
  static GLfloat ground[][4] = {
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };

  int i, j;

  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -D / 2; j < D / 2; ++j) {
    for (i = -W / 2; i < W / 2; ++i) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, height, (GLdouble)j);
      glVertex3d((GLdouble)i, height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)j);
    }
  }
  glEnd();
}

/*
 * 画面表示
 */
void display(void){
  static GLfloat white[] = { 0.8, 0.8, 0.8, 1.0 };    /* 球の色 */
  static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 }; /* 光源の位置 */
  static double px = QX, py = QY, pz = QZ;            /* 球の位置 */

  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* モデルビュー変換行列の初期化 */
  glLoadIdentity();

  /* 光源の位置を設定 */
  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  /* 視点の移動(物体の方を奥に移す)*/
  glTranslated(0.0, -QY, -D);

  /* シーンの描画 */
  myGround(0.0);
  glTranslated(px, py, pz);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, white);
  glutSolidSphere(R, 16, 8);

  glFlush();
}

void resize(int w, int h){
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, h);

  /* 透視変換行列の指定 */
  glMatrixMode(GL_PROJECTION);

  /* 透視変換行列の初期化 */
  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  /* モデルビュー変換行列の指定 */
  glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y){
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

void init(void){
  /* 初期設定 */
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./pitchingmachine

_images/pitchingmachine.png

ラジコンティーポットの実験

raidoconteapot.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
#include <stdlib.h>
#include <GLUT/glut.h>

#define W 6                        /* 地面の幅の2分の1  */
#define D 9                        /* 地面の長さの2分の1 */

/*
 * 地面を描く
 */
void myGround(double height){
  static GLfloat ground[][4] = {
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };

  int i, j;

  glBegin(GL_QUADS);
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -D; j < D; ++j) {
    for (i = -W; i < W; ++i) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, height, (GLdouble)j);
      glVertex3d((GLdouble)i, height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)j);
    }
  }
  glEnd();
}

/*
 * 画面表示
 */
void display(void){
  static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 }; /* 光源の位置 */
  static GLfloat yellow[] = { 0.8, 0.8, 0.2, 1.0 };   /* 車の色   */
  static GLdouble px = 0.0, pz = 0.0;                 /* 車の位置  */
  static GLdouble r = 0.0;                            /* 車の方向  */

  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* モデルビュー変換行列の初期化 */
  glLoadIdentity();

  /* 光源の位置を設定 */
  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  /* 視点の移動(物体の方を奥に移す)*/
  glTranslated(0.0, 0.0, -25.0);
  glRotated(30.0, 1.0, 0.0, 0.0);

  /* シーンの描画 */
  myGround(0.0);
  glPushMatrix();
  glTranslated(px, 1.0, pz);
  glRotated(r - 90.0, 0.0, 1.0, 0.0);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
  glutSolidTeapot(1.0);
  glPopMatrix();

  glFlush();
}

void resize(int w, int h){
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, h);

  /* 透視変換行列の指定 */
  glMatrixMode(GL_PROJECTION);

  /* 透視変換行列の初期化 */
  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  /* モデルビュー変換行列の指定 */
  glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y){
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

void init(void){
  /* 初期設定 */
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./radioconteapot

_images/radioconteapot.png

エアホッケーの実験

airhockey.c

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>

#define PX 0.0                     /* 初期位置      */
#define PZ 0.0                     /* 初期位置      */
#define W 4                        /* 台の幅の2分の1  */
#define D 6                        /* 台の長さの2分の1 */
#define H 0.5                      /* 壁の高さ      */
#define R 0.3                      /* パックの半径    */
#define TIMESCALE 0.01             /* フレームごとの時間 */
#define SPEED 30.0                 /* パックの初速度   */
#define MU 0.5                     /* 台との摩擦係数   */
#define WEIGHT 1.0                 /* パックの質量    */

int wh;                            /* ウィンドウの高さ  */
int frame = 0;                     /* 現在のフレーム数  */
double vx0, vz0;                   /* パックの初速度   */
double px0 = PX, pz0 = PZ;         /* パックの初期位置  */

/*
 * 台を描く
 */
void myGround(double height){
  static GLfloat ground[][4] = {   /* 台の色       */
    { 0.6, 0.6, 0.6, 1.0 },
    { 0.3, 0.3, 0.3, 1.0 }
  };
  static GLfloat wall[] = {        /* 壁の色       */
    0.8, 0.8, 0.8, 1.0
  };
  static GLdouble panel[][9] = {   /* 壁の形状データ   */
    {  0.0,  0.0,  1.0, -W, 0.0, -D, -W, H, -D },
    { -1.0,  0.0,  0.0,  W, 0.0, -D,  W, H, -D },
    {  0.0,  0.0, -1.0,  W, 0.0,  D,  W, H,  D },
    {  1.0,  0.0,  0.0, -W, 0.0,  D, -W, H,  D },
    {  0.0,  0.0,  1.0, -W, 0.0, -D, -W, H, -D },
  };
  int i, j;

  glBegin(GL_QUADS);

  /* 床を描く */
  glNormal3d(0.0, 1.0, 0.0);
  for (j = -D; j < D; ++j) {
    for (i = -W; i < W; ++i) {
      glMaterialfv(GL_FRONT, GL_DIFFUSE, ground[(i + j) & 1]);
      glVertex3d((GLdouble)i, height, (GLdouble)j);
      glVertex3d((GLdouble)i, height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)(j + 1));
      glVertex3d((GLdouble)(i + 1), height, (GLdouble)j);
    }
  }

  /* 壁を描く */
  glMaterialfv(GL_FRONT, GL_DIFFUSE, wall);
  for (i = 0; i < 4; ++i) {
    glNormal3dv(panel[  i  ]);
    glVertex3dv(panel[  i  ] + 3);
    glVertex3dv(panel[i + 1] + 3);
    glVertex3dv(panel[i + 1] + 6);
    glVertex3dv(panel[  i  ] + 6);
  }

  glEnd();
}

/*
 * 円柱を描く
 */
void myCylinder(double radius, double height, int sides){
  double step = 6.2831853072 / (double)sides;
  int i = 0;

  /* 上面 */
  glNormal3d(0.0, 1.0, 0.0);
  glBegin(GL_TRIANGLE_FAN);
  while (i < sides) {
    double t = step * (double)i++;
    glVertex3d(radius * sin(t), height, radius * cos(t));
  }
  glEnd();

  /* 底面 */
  glNormal3d(0.0, -1.0, 0.0);
  glBegin(GL_TRIANGLE_FAN);
  while (--i >= 0) {
    double t = step * (double)i;
    glVertex3d(radius * sin(t), -height, radius * cos(t));
  }
  glEnd();

  /* 側面 */
  glBegin(GL_QUAD_STRIP);
  while (i <= sides) {
    double t = step * (double)i++;
    double x = sin(t);
    double z = cos(t);

    glNormal3d(x, 0.0, z);
    glVertex3f(radius * x, height, radius * z);
    glVertex3f(radius * x, -height, radius * z);
  }
  glEnd();
}
/*
 * 画面表示
 */
void display(void){
  static GLfloat lightpos[] = { 3.0, 4.0, 5.0, 1.0 }; /* 光源の位置    */
  static GLfloat yellow[] = { 0.9, 0.9, 0.2, 1.0 };   /* パックの色    */

  double t = TIMESCALE * frame;         /* フレーム数から現在時刻を求める */

  double v = exp(-MU * t / WEIGHT);                   /* パックの速度比  */
  double p = WEIGHT * (1.0 - v) / MU;                 /* パックの相対位置 */

  double px = vx0 * p + px0;                          /* パックの現在位置 */
  double pz = vz0 * p + pz0;                          /* パックの現在位置 */

  /*
  ** パックが台の壁に当たったら初期位置と初速度を変更する
  ** 速度(比)が一定以下になったら現在位置を初期位置にして
  ** アニメーションを止める
  ** (ここは自分で考えてください)
  */

  /* フレーム数(画面表示を行った回数)をカウントする */
  ++frame;

  /* 画面クリア */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  /* モデルビュー変換行列の初期化 */
  glLoadIdentity();

  /* 光源の位置を設定 */
  glLightfv(GL_LIGHT0, GL_POSITION, lightpos);

  /* 視点の移動(物体の方を奥に移す)*/
  glTranslated(0.0, 0.0, -20.0);
  glRotated(45.0, 1.0, 0.0, 0.0);

  /* シーンの描画 */
  myGround(0.0);
  glPushMatrix();
  glTranslated(px, 0.0, pz);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, yellow);
  myCylinder(0.3, 0.1, 8);
  glPopMatrix();

  glFlush();
}

void resize(int w, int h){
  /* ウィンドウ全体をビューポートにする */
  glViewport(0, 0, w, wh = h);

  /* 透視変換行列の指定 */
  glMatrixMode(GL_PROJECTION);

  /* 透視変換行列の初期化 */
  glLoadIdentity();
  gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0);

  /* モデルビュー変換行列の指定 */
  glMatrixMode(GL_MODELVIEW);
}

void keyboard(unsigned char key, int x, int y){
  /* ESC か q をタイプしたら終了 */
  if (key == '\033' || key == 'q') {
    exit(0);
  }
}

void mouse(int button, int state, int x, int y){
  switch (button) {
  case GLUT_LEFT_BUTTON:

    /*
    ** マウスをクリックしたウィンドウ上の座標から
    ** 表示されている台の表面の空間位置を求める
    */

    if (state == GLUT_DOWN) {
      GLdouble model[16], proj[16];
      GLint view[4];
      GLfloat z;
      GLdouble ox, oy, oz;

      /* クリックした時にフレーム数を 0(すなわち時間を 0)にする */
      frame = 0;

      /*
      ** モデルビュー変換行列・透視変換行列・ビューポート変換行列を取り出す
      */
      glGetDoublev(GL_MODELVIEW_MATRIX, model);
      glGetDoublev(GL_PROJECTION_MATRIX, proj);
      glGetIntegerv(GL_VIEWPORT, view);

      /*
      ** クリックした位置の奥行きを z に取り出す
      ** (台の外をクリックするとまずいけどもういいや)
      */
      glReadPixels(x, wh - y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &z);

      /* クリックしたところの台の上の位置を求める */
      gluUnProject(x, wh - y, z, model, proj, view, &ox, &oy, &oz);

      /*
      ** (px0, pz0) と (ox, oz) を使ってパックを打ち出す方向を決め,
      ** パックの初速度 (vx0, vz0) を決めて,アニメーションを開始する.
      ** (ここは自分で考えて下さい)
      */

      break;
    case GLUT_MIDDLE_BUTTON:
      break;
    case GLUT_RIGHT_BUTTON:
      break;
    default:
      break;
    }
  }
}

void init(void){
  /* 初期設定 */
  glClearColor(1.0, 1.0, 1.0, 0.0);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_CULL_FACE);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
}

int main(int argc, char *argv[]){
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH);
  glutCreateWindow(argv[0]);
  glutDisplayFunc(display);
  glutReshapeFunc(resize);
  glutKeyboardFunc(keyboard);
  glutMouseFunc(mouse);
  init();
  glutMainLoop();
  return 0;
}

[cactus:~/code_c/opengl/kumamoto]% ./airhockey

_images/airhockey.png