ポリゴンの集合による3D図形の描写

OpenGLライブラリーを使えば、3D図形を簡単に描写できるようになる。
今回は一番基礎の、ポイント座標セットを与えることによる3D描写を試してみた。
あと、単純な形だとつまらないので、それなりに複雑なドラゴンの形で。

初期設定

  • とりあえずライブラリの参照とグローバル変数の設定
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#include <GL/glut.h>

int angle = 0;
GLenum mode = GL_POLYGON;
float x_in=1, y_in=1, z_in=1, px_in=0, py_in=0, pz_in=0;
  • OpenGLの初期設定ようの関数を作る。
void init()
{
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(-10.0, 10.0, -10.0, 10.0, -10.0, 10.0);//正面から見た表示サイズの設定
	glEnable(GL_DEPTH_TEST);
}

図形描写

  • まずは、送られてきたサイズとポジションの点を描写するための関数とつくる
void print(float x, float y, float z, float px, float py, float pz)
{
	glVertex3f(x+px, y+py, z+pz);
}
  • それらの点に関する操作は、glBegin関数に送るモードによって決定。
    • 点を連結するポリゴンを表示したい場合は、glBegin(GL_POLYGON)とglEnd()の間で、繋がる点同士を描写。
      • 例えばポリゴンの代わりに線で結びたい場合は、GL_LINE_LOOPとかするとできる。
    • 今回は、ポリゴンの描写の繰り返しでドラゴンを描きたいため、以下の関数を作成。
    • 引数は、ドラゴンの大きさ変数のx,y,zと、場所を指定するpx,py,px
    • glColor3f(R, B, G)でカラーの指定もできる。
      • R,B,Gはそれぞれ0から1の間の値で指定
void dragon(float x, float y, float z, float px, float py, float pz)
{
	glBegin(mode);
	glColor3f(0.0, 0.7, 0.1);
	print(-0.5*x, 5.2*y, 3.0*z, px, py, pz);       
	print(0.5*x, 5.2*y, 3.0*z, px, py, pz);
	print(0.5*x, 4.7*y, 3.0*z, px, py, pz);
	print(-0.5*x, 4.7*y, 3.0*z, px, py, pz);
	glEnd();
	
	glBegin(mode);
	glColor3f(0.0, 0.8, 0.1);
	print(-0.8*x, 6.5*y, 1.0*z, px, py, pz);
	print(0.8*x, 6.5*y, 1.0*z, px, py, pz);
	print(0.5*x, 5.2*y, 3.0*z, px, py, pz);
	print(-0.5*x, 5.2*y, 3.0*z, px, py, pz);
	glEnd();
	
	//以下略
	//..
	//..
}
  • そして、display関数をつくってそこから描写
    • ウィンドウサイズを変更したり、再描写される度にドラゴンが5度ずつ回転するようにしてみた笑゛
void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glMatrixMode(GL_MODELVIEW);
	glRotatef(M_PI * angle / 180.0, 0.5, 1.0, 0.0);
	angle = (angle + 5) % 360;

	// Draw a dragon
	dragon(x_in,y_in,z_in,px_in,py_in,pz_in);
	glFlush();
}

ユーザー入力、描写

  • 以下がmainの中
int main(int argc, char *argv[])
{
	printf("* coordinates for polygon of dragon *\n");
	printf("height of the dragon?\n");
	y_in = input();
	printf("width of the dragon?\n");
	x_in = input();
	printf("depth of the dragon?\n");
	z_in = input();
	printf("x position\n");
	px_in = input();
	printf("y position?\n");
	py_in = input();
	printf("z position?\n");
	pz_in = input();
	glutInit(&argc, argv);
	glutInitWindowSize(500, 500);
	glutInitWindowPosition(250, 250);
	glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH);
	glutCreateWindow("Dragon");
	glutDisplayFunc(display);
	init();
	glutMainLoop();
	return 0;
}
  • 久しくcを使っていなくて、IOのこと曖昧だったから、適当にinput()関数つくって読み込んだ
float input()
{
	float input;
	char str[10], *trm ;
	int flag = 1;
	while(flag){
		flag = 0;
		scanf("%s", str);
		input = strtod(str, &trm) ; //convert str -> double
		if ((trm != NULL) && (*trm != '\0'))
		{
			printf("error: type any numbers\n") ;
			flag = 1;
		}
		rewind(stdin);
	}
	return input;
}

結果


こんな感じに表示された。