GPUPPURUT開発2

GPUPPURUTにはDirect3D用のGDXUTとOpenGL用のGGLUTがあって、両者のインターフェースは同じものとなっています。(というかなる予定です)


typdef GDXUT GUT;

GUT ut;

ut.initialize(500, 500, std::string("title")); //縦横が500x500のサイズでウィンドウのタイトルが"title"となるウィンドウを作成
...ut使った処理を行う。

というふうにGDXUTの機能を使ったプログラムをあなたが開発したとして、GGLUTを使うように変更したい場合は

//typedef GGLUT GUT;
typedef GDXUT GUT;
のようにGUTのtypedefを変更するだけで済みます。
もちろん、Direct3Dに直接関係する部分はGPUPPURUTは関知しないのでそこらへんは自力でなんとかしてもらうことになりますが・・・
(GPUPPURのほうはDirect3DOpenGLの両方で実装する予定ですので、こちらのほうもtypedefでDirect3DにするかOpenGLにするか選択できるようになる予定です。)

GDXUTとGGLUTのどっちを使うかを実行時に決めるように変更したい場合はどうなるでしょうか。
GDXUTとGGLUTの共通のメンバ関数がvirtualになっていて、両者のクラスが基底クラスGBaseUTを継承していたとします。


GDXUT dx;
GGLUT gl;
GBaseUT* ut = which() ? &dx : ≷

ut->initialize(...);
...以下、ut.メンバ関数→ut->メンバ関数へ置換する

この場合、ut.をut->に置換しなければいけないという欠点がありますがとりあえず目標は達成できます。

ところがこのソフトを使う人の96%がOpenGLしか使ってないことが明らかになりました。
Direct3Dは使わないから、virtual関数を無くして少しでもパフォーマンスを良くしてくれという人がいます。
でも、残り4%の人のため、GGLUTのみを使うバイナリとGGLUTとGDXUTを実行時に切り替えるバイナリの二つを配布することに決めました。

GDXUTとGGLUTは実はテンプレートクラスになっていて、


//すべてのメンバ関数がvirtualではない
class StaticGBaseUT
{
bool initialize(...);
...
};

//すべてのメンバ関数がvirtual
class DynamicGBaseUT
{
virtual bool initialize(...);
...
};

template
class TGGLUT : public Base
{
//このメンバ関数がvirtualかそうでないかは基底クラスのBase次第
bool initialize(...)
{
//実装
}
};

#ifdef FOR_OPENGL_MANIA
typepdef TGGLUT GGLUT; //virtual関数呼び出しのないGGLUT
#else
typepdef TGGLUT GGLUT; //virtual関数呼び出しのできるGGLUT
#endif

このようにvirtual関数版と非virtual関数版を作ることができます。

GGLUTを使うときはどのようになるでしょうか。


#ifdef FOR_OPENGL_MANIA
GGLUT ut;
#else
GDXUT dx; //もちろんGDXUTはvirtual関数呼び出しができるようになっている。
GGLUT gl;
GBaseUT* ut;
if(which())
ut = &dx;
else
ut = ≷

#endif

#ifdef FOR_OPENGL_MANIA
ut->initialize(...);
#else
ut.initialize(...);
#endif

このようにutを使うときにvirtualだと"->"を非virtaulの場合"."を使うことになります。
そのせいで#ifdefの嵐となってしまいます。
"->"と"."の部分を#defineを使って切り替えることもできそうですがvirtualなほうも"."を使ってメンバ関数を呼ぶことができれば一番いいでしょう。

#ifdef FOR_OPENGL_MANIA
typedef GGLUT GUT;
#else
typedef DynamicImpl, DynamicGBaseUT> GUT;
#endif

//DynamicImplならデフォルトでGDXUTの実装が使われる。
GUT ut;

ut.initialize(...);

#ifndef FOR_OPENGL_MANIA

//utの実装をGDXUTからGGLUTに切り替える。
ut.uninitialzie();
ut.set(1);
ut.initalize(...);

#endif

こんな感じで実装を切り替えることができ、"."でメンバ関数にアクセスできるテンプレートクラスのDynamicImplをつくりました。
boostライブラリにこんな感じのクラスがないかなと思ったのですが、すぐにみつからなかったので自分でつくることにしました。
今日はもう寝たいので、数日したらソースコードを公開する予定です。