【OpenGL】エンジンを使わないゲーム開発 -GLUTによるアニメーション-


緒論

前回描画した図形にアニメーションをつけることを目的とする.

理論

1. idle関数

これは何もしてないときに呼ばれる関数.暇になるたびに呼び出される.

    void glutIdleFunc(void (*func)(void));

2. 再描画関数

再描画をさせる関数.これが呼ばれるとglutDisplayFunc()で指定されている描画関数が実行される.

    void glutPostRedisplay(void)

3. 回転させる関数

描画したものを指定した軸方向にangle度回転する.

    void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);

方法

idle関数を作ってglutPostRedisplay()を入れる.こうすることで,暇なときに再描画するという処理が行われる.

void idle()
{
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    // -省略-
    glutIdleFunc(idle);
    // -省略-
}

よって呼び出される関数glutDisplayFunc()の中身に回転するプログラムを書けばアニメーションが行われるということである

void Display()
{
    // (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) 指定した軸方向にangle度回転する関数
    glRotatef(1, 1, 1, 0);
    // -省略-
}

結果

今回,ディスプレイの表示モードをGLUT_RGBAからGLUT_DOUBLEに変更した.ダブルバッファリングというもので,表示のちらつきを抑えるためのものらしい.
詳しくは9.2 ダブルバッファリングを参照.

なぜか私はダブルバッファリングをしなくても画面がチラつかず,表示モードを変えても特に実行結果は変わらなかったが,とりあえず,ダブルバッファリングを使用するプログラムに変更した.

main.cpp
main.cpp
#include <OpenGL/OpenGL.h>
#include <GLUT/GLUT.h>
#include "polygon.hpp"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

// この中に描画したいものを入れる
void Display()
{
    // (GLfloat angle, GLfloat x, GLfloat y, GLfloat z) 指定した軸方向にangle度回転する関数
    glRotatef(1, 1, 1, 0);
    // (GLbitfield mask)ウィンドウを塗りつぶす maskは塗りつぶすためのバッファを指定する
    glClear(GL_COLOR_BUFFER_BIT);

    // ▼図形を描くためのプログラム▼
    // (GLdouble r, GLdouble g, GLdouble b)これから描画するものの色を指定する
    glColor3d(1.0, 0.0, 0.0);
    // (GLnum mode)modeに図形タイプを入力 LINE_LOOPは折れ線を描く
    glBegin(GL_LINE_LOOP);
    // (GLdouble x, GLdouble y)二次元の座標値を設定する
    Polygon(5);
    // (void)Begin~Endまでに図形の各頂点の座標値を指定する
    glEnd();
    // ▲図形を描くためのプログラム▲

    // (void)まだ実行されていないOpenGLの命令を実行
    glutSwapBuffers();
}

// 初期化処理を行う関数
void init(void)
{
    // (GLclampf R, GLclampf G, GLclampf B, GLclampf A)glclearでウィンドウを塗りつぶす際の色の指定
    glClearColor(0.0, 0.0, 0.0, 1.0);
}

void idle()
{
    // 再描画の関数 glutDisplayFunc()が実行される.
    glutPostRedisplay();
}

int main(int argc, char *argv[])
{
    // (int *argcp, char **argv)GLUTとOpenGL環境の初期化
    glutInit(&argc, argv);
    // (unsigned int mode)ディスプレイの表示モードを設定 GLUT_RGBAを指定すると色の指定を三原色で行える
    glutInitDisplayMode(GLUT_DOUBLE);
    // (char *name)ウィンドウを開く関数
    glutCreateWindow("Title");
    // (void (*func)(void))ウィンドウが開かれたり再描画の際に実行
    glutDisplayFunc(Display);
    init();
    // (void (*func)(void))暇なときに呼ばれる関数.暇になるたび実行
    glutIdleFunc(idle);
    // (void)無限ループの関数,イベント待ち状態
    glutMainLoop();
    return 0;
}

ここまで制作して思ったのが,暇になるたびidle関数が呼び出され,Display関数内のrotate関数によって図形が1度ずつフレーム単位で回転していると思うのだが,再描画をしたら回転情報はリセットされないのだろうか.前の回転状態がなんで残っているのか不思議である.

結論

  • アニメーションができた!
  • 描画図形の回転情報は再描画しても残り続ける.