【正二十面体】【第2回c言語】
第0回で、2回分は直線的な図形にしようと思いますとか言っちゃったもんで…。ビジュ解禁と言って正二十面体描画する流れにしちゃったし…。でもやることはほぼ一緒なので今回は内容は進みません。ただ、前回端折ったメイン関数の内容とかを詳しく説明していけたらいいなと思います。
今回描画していくのは、前回の正二十面体バージョンです。前回作った正十二面体の骨組みの中に作っていこうと思います。
正二十面体の描画
今回も時間と大学の課題に追われているので、ほぼ何も考えずに座標を打ちまくる作戦です。
正二十面体(20)の頂点の数は、12個であります。そう!正十二面体(12)の面の数と同じです!正十二面体(12)の一つの面の重心(中心)に今回作りたい正二十面体(20)の頂点を定めればよいのです。
前回の正十二面体の面の一つの面の座標は、以下の通りです。
glBegin(GL_POLYGON);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(-0.3708f, 0.f, -0.975f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(-0.6f, -0.6f, -0.6f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.f, -0.9756f, -0.3708f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.6f, -0.6f, -0.6f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.3708f, 0.f, -0.975f);
glEnd();
これらの座標の平均値取ったら、(0.f,-0.43521f,0.70416f)ですね。これが正二十面体の頂点の一つの座標になります。頂点の位置の計算方法が分かったので、コードを書いていきます。
正二十面体の描画(正十二面体骨組みあり)
xyz軸の描画等は前回も行ったので、
void drawobjects(void)…からコードを載せます。
void drawObjects(void) {
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
//Icosahedron
//1
glBegin(GL_TRIANGLES);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.f, -0.435f, -0.70416f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.435f, -0.70416f, 0.f);
glColor3f(1.f, 0.f, 0.f);
glVertex3f(0.70416f, 0.f, -0.435f);
glEnd();
//2
glBegin(GL_TRIANGLES);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, -0.435f, -0.70416f);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.70416f, 0.f, -0.435f);
glColor3f(0.f, 0.f, 1.f);
glVertex3f(0.f, 0.435f, -0.70416f);
glEnd();
//以下省略(長すぎるので。三角形5個ずつ考えると楽です。)
//Dodecahedron(骨組み)
glBegin(GL_LINES);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, 0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, -0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, 0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.6f, -0.6f, 0.6);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, 0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(-0.6f, -0.6f, 0.6f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, -0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.6f, -0.6f, -0.6f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(0.f, -0.975f, -0.3708f);
glColor3f(1.f, 0.5f, 0.f);
glVertex3f(-0.6f, -0.6f, -0.6f);
//以下省略(長すぎるので)
glEnd();
glFlush();
}
解説
・前回とほぼ変わらないので解説もほとんどないのですが…。
・前回は五角形だったのでGL_POLYGONでしたが、今回は一つの面は三角形なので、GL_TRIANGLESで描画しました。
・初期化を忘れずに。
・glBeginではじめて、glEndで締めましょう。最後はglFlush!
reshape
前回端折ってしまった部分ですね。void reshape(int w,int h)の内容について解説していきたいと思います。
ウィンドウのサイズを変更したとき(小さくしたり大きくしたとき)に、物体を適切に表示させるために重要な個所です。(ウィンドウに対する物体の幅、高さを調節する。)
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, double(w) / h, 0.1, 200.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(1.0 + X, 2.5 + Y, 4.0 + Z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}
~解説~
・まず、wは、ウィンドウのサイズが変更されたときの変更後のウィンドウの幅で、hは、高さです。
・glViewportは、glViewport(左下のx座標 , 左下のy座標 , 幅 , 高さ)という仕組みになっています。
・glMatrixMode(GL_PROJECTION)は、投影行列にアクションを加えることを宣言しています。glLoadIdentityで、行列を一度リセットし、その後に投影行列をセットしています。glPerspectiveは、glPerspective(視野角 , ウィンドウのアスペクト比 , 描画される範囲の下限 , 描画される範囲の上限)という仕組みになっています。アスペクト人は、ウィンドウの幅と高さの比で、幅÷高さで表されます。
・glMatrixMode(GL_MIDELVIEW)は、モデルビュー行列にアクションを加えることを宣言しています。主にモデルの座標変換と視点の設定を行います。ここにおいても、まずリセットを行ってから、glLookAtで、カメラの位置、向き、注視点を決めます。glLookAt(視点のx座標 , 視点のy座標 , 視点のz座標 , 注視点のx座標 , 注視点のy座標 , 注視点のz座標 , ? , ? , ? )というシステムです。最後の三つの座標では、カメラの上向き方向(視点をカメラだと思ってください)を決めるための座標です。例えば、y軸正の向きが上向きだとすると、最後の3座標は、… , 0.0 , 1.0 , 0.0)となります。
main関数
int main(int argc, char* argv[]) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowSize(640, 640);
glutCreateWindow("Dodecahedron");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutSpecialFunc(specialKeys);
otherInit();
glutMainLoop();
return 0;
}
~解説~
・argcはコマンドライン引数(argument)の数を表し、argvは、コマンドライン引数の配列を表します。
・glutInit(&argc,argv)で、GLUTが初期化されます。
・glutInitDisplayMode(GLUT_RGB)で、RGBカラーモデルを指定します。
・ウィンドウのサイズや、ウィンドウのタイトルも設定していますね。
・glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutSpecialFunc(specialKeys);
以上の三つのコードで、描画関数、リサイズ関数、キーイベント処理関数を呼び出します。
ちなみに、今回作った正二十面体のビジュはこちらです(サムネイル?と変わらないけど…)
次回 : 曲線を描く
次回は曲線を描いていこうと思います。