どうもです。皆さんはフラクタル図形をご存じでしょうか?簡単に言えば、拡大しても、同じ形をもつ図形です。私はこれらの図形が持つ複雑さと美しさが好きでプログラミングした次第です。
実はプログラミングとは言っても、基本的なプログラム程度なら自分で組まなくても、誰かが作ってネット上に公開されていることが多いです。コンピュータの世界は割とオープンだなぁ。
そこでコピペして作ったものがこちらです。
…サムネに完成品を載せているので正直しょぼく感じるかもしれませんね。
ですが、最初に一度作ってしまうというのも大事です。
ここからはこれを立体的に表示します。かっこよく言えば、三次元への拡張です。
ここからはコピペではできないので、それなりに仕組みを理解しなきゃならないです。
これまで三角形だったところがここでは三角錐となっています。
動画を撮ってはいなかったのですが、この図形の中を動き回るのはとても楽しいです。
使用したもの
chromebookでlinuxの仮想環境を構築すればだいたいのことはできます。
今回はその環境にC,C++言語用の環境を用意したので、OPENGLというライブラリによって動いています。
趣味のブログや大学の課題として体系的に学べることもあるのでおすすめです。
CGといえば、映画のような技術を想像するかもしれません。ただ、今回のようにどういう仕組みでグラフィックが作られているのかということを1から根本的なものを学べますよ。
OPENGLを使ったソースコード(いつかgithubにupしたい)
#pcで見ることをおすすめします
#include <GL/glut.h>
#include <stdlib.h>
void display(void)
{//HERE LOOPING
static float theta_ek;
static float theta_mk;
theta_mk += 3.0;
theta_ek+=1.0;
static float theta_e;
theta_e +=1;
float light0_position[4]={0.0, 0.0, 0.0, 1.0};
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(1.0, 0.0, 0.0);
glLightfv(GL_LIGHT0, GL_POSITION, light0_position);
glutSolidSphere(20.0, 36, 18);/* 太陽 */
glPushMatrix();/* ワールド座標系の行列をスタックに入れる */
{
glRotatef(theta_ek, 0.0, 0.0, 1.0);/* z軸周りにtheta_ek度回転 */
glTranslatef(60.0, 0.0, 0.0);/* x軸に60平行移動 */
/* ここまでで地球座標系 */
glPushMatrix();/* 地球座標系の行列をスタックに入れる */
{
glRotatef(theta_e, 0.0, 0.0, 1.0);/* z軸周りにtheta_e度回転 */
glColor3f(0.0, 0.0, 1.0);
glutSolidSphere(10.0, 36, 18);/* 地球 */
}
glPopMatrix();/* 地球座標系の行列を取り出す */
glRotatef(theta_mk, 0.0, 0.0, 1.0);/* z軸周りにtheta_mk度回転 */
glTranslatef(20.0, 0.0, 0.0);/* x軸に20平行移動 */
glColor3f(1.0, 1.0, 0.0);
glutSolidSphere(5.0, 36, 18);/* 月 */
}
glPopMatrix();/* ワールド座標系の行列を取り出す */
glLoadIdentity();
gluLookAt(100.0,0.0, 20.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
glFlush();
glutSwapBuffers();
}
void init(void)
{
float ambient[4]={0,100,0,0};
glLightfv(GL_LIGHT0, GL_AMBIENT, ambient);
glClearColor (0.0, 0.0, 0.0, 0.0); /*黒で画面クリア*/
glShadeModel (GL_SMOOTH); /*フラットシェーディング*/
glEnable(GL_DEPTH_TEST);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glEnable(GL_COLOR_MATERIAL);
}
void reshape(int w, int h) /*画面サイズ変更時に呼ばれる*/
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h); /*画面の出る範囲*/
glMatrixMode(GL_PROJECTION); /*視界変換宣言*/
glLoadIdentity(); /*単位行列代入*/
//glOrtho(-100.0, 100.0, -100.0, 100.0, -100.0, 100.0);/*視体積の設定*/
glFrustum(-50.0,50.0,-50.0,50.0,30.0,10000.0);
glMatrixMode(GL_MODELVIEW); /*モデル変換宣言*/
glLoadIdentity(); /*単位行列代入*/
}
int main(int argc, char** argv)
{
glutInit(&argc, argv); /*GLUT初期化*/
//glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);/*表示モード設定*/
glutInitDisplayMode (GLUT_DEPTH |GLUT_DOUBLE| GLUT_RGB);
glutInitWindowSize (500,500); /*画面の大きさ設定*/
glutInitWindowPosition (100, 100); /*画面の位置設定*/
glutCreateWindow (argv[0]); /*引数の名前のウインドウ作成*/
init ();
glutIdleFunc(display); /*アイドル時に呼ぶ関数*/
glutDisplayFunc(display); /*表示時に呼ぶ関数*/
glutReshapeFunc(reshape); /*画面サイズ変更時に呼ぶ関数*/
glutMainLoop(); /*描画開始*/
return 0;
}