fltk

OpenGLが簡単に使えて、しかもWindows/Linux/OSXマルチプラットフォームなツールキット fltkで遊んでみた。

基本

  1. FL/Fl.hをinclude
  2. イベントループ実行は Fl::run();
  3. ほとんどのwidgetは同じコンストラクタ引数を持つ。new Widget(x, y, width, height, label)
  4. Group系(他のwidgetを子に持てる親widget)のインスタンスを作ると自動的に begin()が実行される。
    1. システムグローバルなCurrentGroupを持っていて、GroupWidgetインスタンス化以降に作成したWidgetはこの親widgetの子になる*1
    2. end()でCurrentから抜ける。
    3. 親の直接指定は add(), insert()
  5. 上記仕様のため、簡単なことはかなり簡単に書ける。
#include <FL/Fl.h>
#include <FL/Fl_Window.h>
#include <FL/Fl_Box.h>

int main(int argc, char** argv)
{
    Fl_Window* win = new Fl_Window(200,100);
    (new Fl_Box(25, 40, 150, 30, "Hello! FLTK"))->box(FL_UP_BOX);
    win->end();
    win->show(argc, argv);
    Fl::run();
}


OpenGL使ってみる

OpenGLを使うには Fl_Gl_Windowを継承すれば良いらしい。
なんも考えなくてもこれの draw()メソッドはコンテキストがMakeCurrent()された状態で呼び出されるのでここで書けばおK。と思ったけど、PixelFormat とか Depth/Doubleの設定とかどうするんだろう???←説明書嫁

//// gltest.h
#include <FL/Fl.h>
#include <FL/Fl_Gl_Window.h>

#include <GL/glut.h>

class GlTest : public Fl_Gl_Window { 
    	float rot ;
    public:
	GlTest(int x, int y, int w, int h, char* label)
	    : Fl_Gl_Window(x, y, w, h, label), rot(0) {
	    int dummy = 0;
	    glutInit(&dummy, NULL); // only for geometory functions
	}
	void draw();
	void rotate(float);
};

//// gltest.cpp
#include "gltest.h"

void GlTest::draw() 
{
    if (!valid()) {
	int h = this->w(), v = this->h();
	glViewport(0, 0, h, v);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(30, (float)h/(float)v, 0.0, 10.0);
	valid(1);
    }
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(0, 4, 5, 0, 0, 0, 0, 1, 0);
    glRotatef(rot, 0, 1, 0);
    glutWireTeapot(1.0);
}

void GlTest::rotate(float r) 
{
    rot = r;
    redraw();
}

とか作っておけば、

#include <FL/Fl.h>
#include <FL/Fl_Window.h>
#include <FL/Fl_Slider.h>

#include "gltest.h"


void foo(Fl_Widget* w,  void *t )
{
    Fl_Slider *s = static_cast<Fl_Slider*>(w);
    GlTest *g = static_cast<GlTest*>(t);

    g->rotate(s->value());
}



int main(int argc, char** argv)
{
    Fl_Window* win = new Fl_Window(300, 300);
    GlTest* t = new GlTest(10, 10, 200, 200, NULL);

    Fl_Slider*  slider = new Fl_Slider(10, 220, 200, 20, "rot");
    slider->type(FL_HORIZONTAL);
    slider->callback(foo, t);
    slider->bounds(0, 360);
    win->end();
    win->show(argc, argv);
    Fl::run();
}

こんな感じで GlTestを貼るだけでぐるーりぐるーり。

本来の目的

[つづく]

*1:人によっては激しく嫌いそうなシステムかも