お約束したように、前回のプログラム
にワイアーフレームを追加してみましょう。ソリッド画像との切り替えは’w | W'キーをトグル(押すたびに交代する)にし、's | S'キーは回転を止めて見れるようにします。(巻末の【TestGLUT003.cpp】参照)
それではTestGLUT002.cppをコンパイル(注)してみましょう。
注:書き忘れたかもしれませんが、ソースはTestGLUT002.cppですが、BatchGoodの"Lib"フォールダーにfreeglut.libを加えて
コンパイルしないと「参照先が分からない」エラーになるので注意してください。また、ソースでこの問題をクリアーするにはコンパイラーの参照パスに"-L@\..\lib\win32c\release"(ここにgreeglut.libを入れておく)が設定されていることを確認し、"#pragma comment(lib, "freeglut")"(パスの中の"freeglut.lib"を検索します)という一行を追加してください。
正常にコンパイルされたならば、マウスボタンで視点位置を変えながら'W'キーを押すと、
キチンとワイアーフレームでも表示できるようになりました。
さて、次でGLUTのお勉強を終了しますが、最後は簡単なライトの使用と質感の設定でもやりますか?
【TestGLUT003.cpp】
#include <stdio.h> //C言語ベースなのでprintf等を使う場合必要
#include <GL\freeglut.h> //Embarcadero C++ コンパイラーの"BCC102\include\windows\sdk\GL"に入れる
//外部変数
int g_w, g_h; //クライアント領域幅、高さ
GLdouble eyex = 0.0, eyey = 0.0, eyez = 0.9; //視点座標
bool Ortho_Perspect = TRUE; //平行投影か否か
bool g_WorS = TRUE; //Wire図形かSolid図形か(解説:追加しました。)
bool g_Stop = FALSE; //中止するか否かのグフラグ(解説:追加しました。)
GLdouble g_Qvertex[8][3] = {//四角形の8頂点(奥左下から反時計回り4点、手前左下から反時計回り4点)
{-0.5, -0.5, -0.5}, //A
{0.5, -0.5, -0.5}, //B
{0.5, 0.5, -0.5}, //C
{-0.5, 0.5, -0.5}, //D
{-0.5, -0.5, 0.5}, //E
{0.5, -0.5, 0.5}, //F
{0.5, 0.5, 0.5}, //G
{-0.5, 0.5, 0.5} //H
}; //解説:直方体の頂点データを追加しました。
int g_Qedge[12][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)
}; //解説:直方体の頂点と頂点を結ぶ線データを追加しました。
GLdouble g_Tvertex[4][3] = {//三角形の4頂点(上から下反時計回り4点)
{0.0f, 0.616f, 0.0f}, //A
{0.5f, -0.25f, -0.25f}, //B
{-0.5f, -0.25f, -0.25f},//C
{0.0f, -0.25f, 0.616f}, //D
}; //解説:正三角錐の頂点データを追加しました。
int g_Tedge[6][2] = {
{0, 1}, //(A-B)
{1, 2}, //(B-C)
{2, 0}, //(C-A)
{0, 3}, //(A-D)
{3, 2}, //(D-B)
{1, 3} //(C-D)
}; //解説:静三角錐の頂点と頂点を結ぶ線データを追加しました。
//投影設定
void SetProjection(void) {
//変換行列の初期化(座標変換行列に単位行列を設定)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//透視投射範囲の設定
if(Ortho_Perspect)
glOrtho(-1.4, 1.4, -1.4, 1.4, -1.4, 1.4); //平行投射範囲の設定(解説:切れないように大きくしました。)
else {
if(!g_h) g_h = 1; //高さが0の場合は1に設定
gluPerspective(60.0, (double)g_w /(double)g_h, 1.0, 100.0); //透視投射範囲の設定
}
//モデルビュー変換行列を指定
glMatrixMode(GL_MODELVIEW);
}
void DrawAxes(void) {
glPushMatrix();
glBegin(GL_LINES);
//X軸(青)
glColor3d(0.0, 0.0, 1.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.95, 0.0, 0.0);
glVertex3d(0.95, 0.0, 0.0);
glVertex3d(0.90, 0.03, 0.0);
glVertex3d(0.95, 0.0, 0.0);
glVertex3d(0.90, -0.03, 0.0);
//Y軸(緑)
glColor3d(0.0, 1.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.95, 0.0);
glVertex3d(0.0, 0.95, 0.0);
glVertex3d(0.03, 0.90, 0.0);
glVertex3d(0.0, 0.95, 0.0);
glVertex3d(-0.03, 0.90, 0.0);
//Z軸(赤)
glColor3d(1.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.0);
glVertex3d(0.0, 0.0, 0.95);
glVertex3d(0.0, 0.0, 0.95);
glVertex3d(0.0, 0.03, 0.90);
glVertex3d(0.0, 0.0, 0.95);
glVertex3d(0.0, -0.03, 0.90);
glEnd();
glPopMatrix();
}
void DrawPolygon() {
static float theta = 0.0f; //シータ値
//ポリゴン描画
glPushMatrix();
glTranslated(0.5, 0.0, 0.0);
glScaled(0.5, 0.5, 0.5);
glRotated(theta, 0.0, 1.0, 0.0);
theta += 0.05;
if(g_WorS) { //解説:ワイアーとソリッドを切り返るg_WorSフラグで条件を設定します。
glBegin(GL_LINES); //解説:ワイアーの場合は線になります。
glColor3d(0.0, 1.0, 1.0); //シアン
for (int i = 0; i < 6; i++) { //解説:正三角錐の頂点を結ぶ線は6本あります。
glVertex3dv(g_Tvertex[g_Tedge[i][0]]); //解説:正三角錐の始点となる頂点データ
glVertex3dv(g_Tvertex[g_Tedge[i][1]]); //解説:正三角錐の終点となる頂点データ
}
glEnd();
}
else {
glBegin(GL_TRIANGLES); //解説:ここは前のままです。
//奥の面
glColor3f(1.0f, 0.0f, 0.0f);
glVertex3f(-0.500f, -0.272f, -0.289f); glVertex3f(0.500f, -0.272f, -0.289f); glVertex3f(0.000f, 0.544f, 0.000f);
//右手前面
glColor3f(0.0f, 1.0f, 0.0f);
glVertex3f(0.500f, -0.272f, -0.289f); glVertex3f(0.000f, -0.272f, 0.577f); glVertex3f(0.000f, 0.544f, 0.000f);
//左手前面
glColor3f(0.0f, 0.0f, 1.0f);
glVertex3f(0.000f, -0.272f, 0.577f); glVertex3f(-0.500f, -0.272f, -0.289f); glVertex3f(0.000f, 0.544f, 0.000f);
//底面
glColor3f(1.0f, 1.0f, 1.0f);
glVertex3f(0.500f, -0.272f, -0.289f); glVertex3f(0.500f, -0.272f, -0.289f); glVertex3f(0.000f, -0.272f, 0.577f); //解説:2024年6月4日修正
glEnd();
}
glPopMatrix();
glPushMatrix();
glTranslated(-0.5, 0.0, 0.0);
glScaled(0.5, 0.5, 0.5);
glRotated(theta, 0.0, 1.0, 0.0);
glRotated(theta, 1.0, 0.0, 0.0);
//描画処理
if(g_WorS) {
glBegin(GL_LINES);
glColor3d(1.0, 1.0, 0.0); //黄
for (int i = 0; i < 12; i++) { //解説:直方体の頂点を結ぶ線は12本あります。
glVertex3dv(g_Qvertex[g_Qedge[i][0]]); //解説:直方体の始点となる頂点データ
glVertex3dv(g_Qvertex[g_Qedge[i][1]]); //解説:直方体の終点となる頂点データ
}
glEnd();
}
else { //解説:ここも前のままです。
/* 図形の回転 */
glBegin(GL_QUADS);
//手前正面
glColor3d(0.0, 0.0, 1.0);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(-0.5, 0.5, 0.5);
//右側面
glColor3d(0.0, 1.0, 1.0);
glVertex3d(0.5, -0.5, -0.5);
glVertex3d(0.5,- 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, -0.5);
//奥正面
glColor3d(1.0, 0.0, 0.0);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(0.5, -0.5, -0.5);
glVertex3d(0.5, 0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
//左側面
glColor3d(0.0, 1.0, 0.0);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(-0.5, -0.5, 0.5);
//天面
glColor3d(1.0, 0.0, 1.0);
glVertex3d(-0.5, 0.5, -0.5);
glVertex3d(-0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, 0.5);
glVertex3d(0.5, 0.5, -0.5);
//底面
glColor3d(1.0, 1.0, 0.0);
glVertex3d(-0.5, -0.5, -0.5);
glVertex3d(-0.5, -0.5, 0.5);
glVertex3d(0.5, -0.5, 0.5);
glVertex3d(0.5, -0.5, -0.5);
glEnd();
}
theta += 0.1;
glPopMatrix();
}
//アイドル時処理関数
void idle(void) {
glutPostRedisplay(); //再描画関数
}
//描画関数
void display(void) {
if(g_Stop) return; //描画中止(解説:g_StopがTRUEとなると何もしません。)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //色とZ(深度)バッファを初期化
glLoadIdentity(); //変換行列を初期化
gluLookAt( eyex, eyey, eyez, //eyex, eyey, eyez
0.0, 0.0, 0.0, //targetx, targety, targetz
0.0, 1.0, 0.0); //アップベクター(上方向)
DrawAxes(); //x, y, z軸を描画
DrawPolygon(); //三角錐と直方体を描画
glFlush(); //glutSwapBuffersで行われるので不要かも
glutSwapBuffers(); //glutInitDisplayMode(GLUT_DOUBLE)でダブルバッファリングを利用可
}
//ウィンドウサイズ変更時関数
static void resize(int width, int height)
{
//クライアントエリアサイズを記録
g_w = width; g_h = height;
//クライアントエリア全体に表示
glViewport(0, 0, g_w, g_h);
//投影設定
SetProjection();
gluLookAt( eyex, eyey, eyez, //eyex, eyey, eyez
0.0, 0.0, 0.0, //targetx, targety, targetz
0.0, 1.0, 0.0); //アップベクター(上方向)
}
//マウス入力処理関数
void mouse(int button, int state, int x, int y) {
switch(button) {
case GLUT_LEFT_BUTTON:
//視点位置と視線方向の設定
eyex = 1.0; eyey = 1.0; eyez = 1.0;
Ortho_Perspect = FALSE;
break;
case GLUT_MIDDLE_BUTTON:
//変換行列の初期化(座標変換行列に単位行列を設定)
glLoadIdentity();
//視点位置と視線方向の設定
eyex = 0.0; eyey = 0.0; eyez = 0.9;
Ortho_Perspect = TRUE;
break;
case GLUT_RIGHT_BUTTON:
//視点位置と視線方向の設定
eyex = -1.0; eyey = 1.0; eyez = 1.0;
Ortho_Perspect = FALSE;
break;
default:
break;
}
//投影設定
SetProjection();
display();
}
//キーボード入力処理関数
void keyboard(unsigned char key, int x, int y) {
/* ESC か q をタイプしたら終了 */
if(key == '\033' || key == 'q') {
exit(0);
}
else if(key == 'w' || key == 'W') {
g_WorS = !g_WorS;
} //解説:wまたはWキーを押されたらg_WorSフラグが反転します。
else if(key == 's' || key == 'S') {
g_Stop = !g_Stop;
} //解説:sまたはSキーを押されたらg_Stopフラグが反転します。
}
//メイン(エントリーポイント)関数
int main(int argc, char *argv[]) {
glutInit(&argc, argv); //GLUTの初期化
glutInitDisplayMode(GLUT_RGBA | //ディスプレーの初期化
GLUT_DOUBLE |
GLUT_DEPTH);
glutInitWindowPosition(100, 100); //ウィンドウ位置指定
glutInitWindowSize(640, 640); //ウィンドウサイズ指定
//ファイル名だけを表示する
char* fn;
for(char* pt = argv[0]; *pt; pt++) {
if(*pt == '\\')
fn = ++pt;
}
glutCreateWindow(fn); //タイトル付ウィンドウ生成
glShadeModel(GL_SMOOTH); //既定値の滑らかな網かけ
glEnable(GL_DEPTH_TEST); //深度テストを有効にする
glClearColor(0.0, 0.0, 0.0, 1.0); //画面消去色(黒)
glutDisplayFunc(display); //描画関数の指定
glutReshapeFunc(resize); //ウィンドウサイズ変更時関数の指定
glutIdleFunc(idle); //アイドル時処理関数の指定
glutMouseFunc(mouse); //マウス入力処理関数
glutKeyboardFunc(keyboard); //キーボード入力処理関数
glutMainLoop(); //メインループ関数
return 0;
}