お約束したように、前回のプログラム

にワイアーフレームを追加してみましょう。ソリッド画像との切り替えは’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;
}