最小主義者のための、OpenGLプログラミングテンプレート for Windows, Mac OSX, and Linux

1. はじめに

このページでは、Mac OSX, Windows, Linux用、OpenGLプログラミングテンプレートをダウンロードできる。このテンプレートは、簡単に一枚のウィンドウを開いて、キーストロークやマウス状態のチェックができる。最近流行りの、メインループをフレームワークに明け渡すなんてことはしない。簡単なテスト用のプログラムを書くために、わざわざ大規模なフレームワークを使って、一大プロジェクトを作らなきゃいけないような昨今のシステムは、まるで、ネズミ一匹退治するために、F-15E Strike Eagleに爆弾満載して出撃させるようで、滑稽に見える。とくに、研究用プログラムを書いてるときなんてのは、それが偉いことで、アルゴリズムの実証用に本当に書いたコードは数十KB程度なのに、フレームワークがメガバイト単位でファイルを生産するなんてことがよく起こって、思わず、冗談でやってるの?と、PCに向かって話しかけて、変な目で見られるようなことになる。その点、このフレームワークは、OpenGLが使えるウィンドウを一枚開いて、簡単なポーリングベースのメインループを組んで、プログラムを走らせるということに特化してるので、機動性が高い。

世の中の流行ってそういうものらしくて、誰か偉い人が「これからは何でもかんでもイベント・ドリブンだ!」って言うと、まるで、親鴨の後ろを着いて歩く小鴨のように、みんなでなんでもかんでもイベント・ドリブンにしようとしてしまうのね。ポーリング・ベースのプログラムを書いたって、何も悪いことは無くて、むしろ、必要も無いのに大規模なフレームワークを持ち出すことの方が害が多い。

実際、最近は、自分の研究でアルゴリズムの実証用プログラムにはこのフレームワークを使って書いてるし、もともとYSFLIGHT用に書いたコードをベースにしているので、結構テストもされていて、さらに、授業で使って、さらに鍛えたんで、バグとか大体取れてると思う。けど、Linux版を使った学生さんが一人もいなかったから、それだけちょっとまだ鍛え方が足りない鴨。

多分、次のような問題に直面している、あるいは、直面した、または、これから直面しそうな人には役に立つと思う。

  • C++とOpenGLを授業で教えようと思ったら、ウィンドウを開くだけで学期の半分が過ぎてしまった。
  • C++とOpenGLを授業で教えようと思ったら、イベントドリブンプログラミングの話をしてるうちに残りの半分の学期が終わってしまった。
  • C++とOpenGLを授業で教えようと思って、Windows必須にしたら、30人いた学生のうち6人が履修を断念してしまった。
  • C++とOpenGLを授業で教えようと思って、Mac OSX必須にしたら、30人いた学生のうち5人しか残らなかった。
  • C++とOpenGLを授業で教えようと思って、Linux必須にしたら、30人いた学生のうち1人しか残らなかった。
  • C++とOpenGLを授業で教えようと思って、プラットフォームに特化したくなかったからGLUTを使ったら、大したことができなかった。
  • アルゴリズムの実証のために、何本もプログラムを書くけど、たかが100〜200行のプログラムのために、そのたびにソリューションを作って、プロジェクトを作って、メガバイト単位のファイルを作るのがあまりにも滑稽で背中がムズムズしてくる。
  • Mac OSXでプログラム書いてみたいけど、Objective-Cが嫌い。

また、OpenGLの唯一の弱点(だと思う)が、標準でASCII文字列も描画できないってことなんだけど、一緒に入ってるビットマップフォントライブラリを使うことで、ASCIIテキストは簡単に描画できる。

一応、説明は書いたけど、例題をいくつか作ったので、それを読んだ方が多分早い。例えば、次の例題なんかは、何も説明はいらないんじゃないかと思う。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#ifdef WIN32
#include <windows.h>
#endif

#ifndef MACOSX
#include <GL/gl.h>
#include <GL/glu.h>
#else
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#endif

#include <fssimplewindow.h>

int main(void)
{
    FsOpenWindow(800,600,0); // 800x600 pixels, useDoubleBuffer=0

    glDisable(GL_DEPTH_TEST);
    glDisable(GL_LIGHTING);
    glDepthFunc(GL_ALWAYS);

    glClear(GL_COLOR_BUFFER_BIT);

    srand(time(NULL));

    while(FsInkey()==0)
    {
        FsPollDevice();

        int wid,hei;
        FsGetWindowSize(wid,hei);

        glViewport(0,0,wid,hei);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(-0.5,(GLdouble)wid-0.5,(GLdouble)hei-0.5,-0.5,-1,1);

        int x1,y1,x2,y2;
        int r,g,b;

        x1=rand()%wid;
        y1=rand()%hei;
        x2=rand()%wid;
        y2=rand()%hei;
        r=rand()%256;
        g=rand()%256;
        b=rand()%256;

        glColor3ub(r,g,b);
        glBegin(GL_LINES);
        glVertex2i(x1,y1);
        glVertex2i(x2,y2);
        glEnd();
        glFlush();

        FsSleep(10);
    }

    return 0;
}

簡単でしょ? ひとつ説明が必要だとすれば、多分FsPollDevice()関数だと思う。この関数は、内部でイベントをチェックして、キーの状態とか、マウスの状態をかをテンプレートのバッファに記録する。これをループの中で毎回やっておかないと、FsInkey()とかFsGetMouseState()とか、デバイスの状態を問い合わせる関数が正しく機能しない。

それから、ダウンロードパッケージには、同じ関数セットのWindows用とLinux用も入っている。なので、このテンプレートをそのまま利用してプログラムを作ると、そのままWindowsやLinuxに持っていってコンパイルして実行できる。移植に関しては、既に、Sword EdgeとPlanet Attacker 2009で実験済み。

なお、このページからダウンロードできるソースコード、プログラムは、それを利用した結果について、使用者が全責任を負うものとして、作者は責任を負わないという点に同意していただけるのであれば、フリー、商用、オープンソース、プロプライエタリなプロジェクトを問わず、自由に組み込んでいただいても構わない。この点に同意できないのであれば、このページからダウンロードできるソースコード、プログラムの利用は禁止する 。また、このページからダウンロードできるソースコードは、組み込んだからといって、ソースコードの公開の義務は発生しない

2. ダウンロード

[ダウンロード]

3. 例題について

ダウンロードパッケージには、6本の例題プログラムが入っている。1980年代にプログラミングを勉強した人だと、懐かしく思うかも。なお、例題のいくつかは、ここの自作ビットマップフォント関数を使用している。詳しくは、このページを参照してほしい。

最初の例題、Line Artはひたすらウィンドウにランダムな直線をランダムな色で描く。これは、僕がプログラミングの勉強を始めたころ初めて見たプログラムのうちのひとつだった。あれはF-BASICで書かれてたけど。

次の例題は、スカッシュ。ボールがウィンドウの左右と上のヘリでバウンドするので、下のヘリから落ちないように、マウスでラケットを移動してボールを打ち返す。

三番目の例題は、"Echo"。タイプした文字を単に画面にエコーバックするだけ。テンプレートには、FsInkeyとFsInkeyCharのふたつの関数があって、前者は生のキーストロークのチェック、後者はタイプした文字を取得する。

四番目の例題は、単にひし形がマウスの位置を追っていくだけ。マウスの状態の取得の例題。考えてみたらスカッシュでもうやってたっけ。

五番目の例題は、OpenGLにつきものの、回転立方体。ウィンドウの中心から見たマウスカーソルの方向に立方体が回転するというもの。

六番目の例題は、キーの状態の取得。簡単なシューティングゲームになっている。FsInkeyだとキーを押した瞬間を検出できるけど、その後キーが押されたままなのか離されたのかわからない。FM-7っていう8ビットPCはそうだった。だから、ゲームとかで動き出したものを止めるためにテンキーの5を押さなきゃならなかった。僕は初めて使ったPCがFM-7だったから、そういうもんだと思ってたもんで、5を押して動きを止めるのに慣れちゃったんだけど、他のPCを使ってる人にはそれが難しかったらしい。Breakキーだけ、オン/オフがわかったから、よくゲームなんかで、Breakキーでミサイル発射とかになってたんだよね。逆にFM-77AVになったとき、キーのオン/オフを検出できるようになって、5を押さなくてもキーを放すだけで止まるようになっちゃって、結構慣れるまで時間がかかったもんだった。このテンプレートでは、FsGetKeyStateという関数で、キーが押されているか放されているかチェックできる。パラメータに渡すキーコードはfskeycode.hを参照。ちなみに、YSFLIGHT内部では、これと同じキーコードを使っている。


4. 関数リファレンス

関数リファレンスはこちら。2010/12/11バージョン以後のZipファイル内にも含まれている。(現在英語版のみ)

[更新履歴]

2010/12/12
YsGlWriteStringToSingleBitBitmapとYsGlWriteStringToRGBA8Bitmapのパラメータの中でconstの位置を間違ってたので修正。

2010/12/11
バグフィックス。それから、リファレンスマニュアルを追加。

2010/01/04 [このバージョンをダウンロード]
AltキーをFsInkey, FsGetKeyStateで検出可能にした。

2009/12/25 [このバージョンをダウンロード]
公開。