MinGW 3Dグラフィックス
3Dグラフィックス
MinGW で、OpenGL(GLUT) を利用した3Dグラフィックスプログラムがコンパイル実行できるように設定し、3次元に拡張したライフゲームを実行します。
GLUT のインストール
MinGW をインストールすると、OpenGL, GLU はインストールされているようなので、GLUT を追加でインストールします。
インターネット上の、http://web.cs.wpi.edu/~gogo/courses/mingw/ から、Installing GLUT の “this GLUT archive” をクリックして、”winglut.zip” をダウンロードします。ZIP ファイルを解凍して、以下のファイルを MinGW のインストールディレクトリにコピーします。
- GL/glut.h -> MinGW/include/GL/glut.h
- winlib/libglut32win.a -> MinGW/lib/libglut32.a
- glut32.dll -> MinGW/bin/glut32.dll
ここで、libglut32win.a という名前のライブラリファイルは、libglut32.a という名前に変更しました。glut32.dll は実行パスが通っているディレクトリにコピーしてください。
ライフゲームプログラム
GLUT を利用した3次元出力をする3次元ライフゲームのソースを以下に示します。
#include <stdio.h>
#include <windows.h>
#include <GL/glut.h> // cc life3g.c -lglut32 -lopengl32 -lglu32
#define MAXSTEP 500 // Step
#define BMX 24 // Max x size of board
#define BMY 24 // Max y size of board
#define BMZ 24 // Max z size of board
int b[BMX+2][BMY+2][BMZ+2]; // Board Empty:0 Marked:3
GLdouble vertexgl[][3] = {
{ 0.0, 0.0, 0.0},
{ 0.8, 0.0, 0.0},
{ 0.8, 0.8, 0.0},
{ 0.0, 0.8, 0.0},
{ 0.0, 0.0, 0.8},
{ 0.8, 0.0, 0.8},
{ 0.8, 0.8, 0.8},
{ 0.0, 0.8, 0.8}
};
GLdouble colorgl[][3] = {
{0.8, 0.2, 0.2},
{0.2, 0.8, 0.2},
{0.2, 0.2, 0.8},
{0.7, 0.7, 0.0},
{0.7, 0.0, 0.7},
{0.0, 0.7, 0.7}
};
int facegl[][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},
};
void cubegl() {
int i;
int j;
glBegin(GL_QUADS);
for(j = 0; j < 6; ++ j) {
glColor3dv(colorgl[j]);
for(i = 0; i < 4; ++ i) {
glVertex3dv(vertexgl[facegl[j][i]]);
}
}
glEnd();
}
void displaygl() {
int x;
int y;
int z;
static float ry = 0.0;
static float rx = 0.0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glRotatef(ry, 0.0, 1.0, 0.0);
glRotatef(rx, 1.0, 0.0, 0.0);
glTranslated(-0.5*BMX, -0.5*BMY, -0.5*BMZ);
for(z = 1; z <= BMZ; z++) {
for(y = 1; y <= BMY; y++) {
for(x = 1; x <= BMX; x++) {
if(b[x][y][z] != 0) {
glPushMatrix();
glTranslated(1.0*x, 1.0*y, 1.0*z);
cubegl();
glPopMatrix();
}
}
}
}
glPopMatrix();
glutSwapBuffers();
ry += 2.0;
rx += 1.5;
if(ry >= 360.0) ry -= 360.0;
if(rx >= 360.0) rx -= 360.0;
}
void keyboardgl(unsigned char key, int x, int y) {
switch(key) {
case '\033': // ESC key
exit(0);
break;
default:
break;
}
}
void resizegl(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (double)w / (double)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(BMX*1.2, BMY*1.2, BMZ*1.2, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
void inputboard() {
int x;
int y;
int z;
for(z = 0; z < BMZ+2; z++) {
for(y = 0; y < BMY+2; y++) {
for(x = 0; x < BMX+2; x++) {
b[x][y][z] = 0;
}
}
}
b[10][14][10] = 3;
b[10][15][10] = 3;
b[10][16][10] = 3;
b[11][14][10] = 3;
b[9][15][10] = 3;
}
int countalive(int x, int y, int z) {
int cal = 0;
// if(b[x-1][y-1][z-1] > 1) cal ++;
if(b[x-1][y][z-1] > 1) cal ++;
// if(b[x-1][y+1][z-1] > 1) cal ++;
if(b[x][y-1][z-1] > 1) cal ++;
if(b[x][y][z-1] > 1) cal ++;
if(b[x][y+1][z-1] > 1) cal ++;
// if(b[x+1][y-1][z-1] > 1) cal ++;
if(b[x+1][y][z-1] > 1) cal ++;
// if(b[x+1][y+1][z-1] > 1) cal ++;
if(b[x-1][y-1][z] > 1) cal ++;
if(b[x-1][y][z] > 1) cal ++;
if(b[x-1][y+1][z] > 1) cal ++;
if(b[x][y-1][z] > 1) cal ++;
if(b[x][y+1][z] > 1) cal ++;
if(b[x+1][y-1][z] > 1) cal ++;
if(b[x+1][y][z] > 1) cal ++;
if(b[x+1][y+1][z] > 1) cal ++;
// if(b[x-1][y-1][z+1] > 1) cal ++;
if(b[x-1][y][z+1] > 1) cal ++;
// if(b[x-1][y+1][z+1] > 1) cal ++;
if(b[x][y-1][z+1] > 1) cal ++;
if(b[x][y][z+1] > 1) cal ++;
if(b[x][y+1][z+1] > 1) cal ++;
// if(b[x+1][y-1][z+1] > 1) cal ++;
if(b[x+1][y][z+1] > 1) cal ++;
// if(b[x+1][y+1][z+1] > 1) cal ++;
return cal;
}
void nextstep() {
int x;
int y;
int z;
int cal;
for(z = 1; z <= BMZ; z++) {
for(y = 1; y <= BMY; y++) {
for(x = 1; x <= BMX; x++) {
cal = countalive(x, y, z);
if(b[x][y][z] == 0) {
if(cal == 3) b[x][y][z] = 1;
} else if(b[x][y][z] == 3) {
if(cal < 2) b[x][y][z] = 2;
if(cal > 3) b[x][y][z] = 2;
} else {
printf("Unknown code of board[%d][%d][%d]\n", x, y, z);
}
}
}
}
for(z = 1; z <= BMZ; z++) {
for(y = 1; y <= BMY; y++) {
for(x = 1; x <= BMX; x++) {
if(b[x][y][z] == 1) b[x][y][z] = 3;
if(b[x][y][z] == 2) b[x][y][z] = 0;
}
}
}
}
void idlegl() {
glutPostRedisplay();
nextstep();
}
void initgl(int argc, char* argv[]) {
glutInitWindowSize(640, 480);
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutCreateWindow(argv[0]);
glutDisplayFunc(displaygl);
glutReshapeFunc(resizegl);
glutIdleFunc(idlegl);
glutKeyboardFunc(keyboardgl);
glClearColor(0.0, 0.0, 0.0, 1.0);
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
}
int main(int argc, char* argv[]) {
inputboard();
initgl(argc, argv);
glutMainLoop();
return 0;
}
ソースプログラムを life3g.c とした場合、コンパイルは以下のように実行してください。
> cc life3g.c -lglut32 -lopengl32 -lglu32
実行してみると、単純に3次元に拡張しただけでは、いまひとつ結果が面白くない感じがします。