ゲームや日記を公開中。 --- a blog about games, life. my handle is 'd_of_i'.
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
3年くらい前に思いついた技法です。
書くこと無いので発表してみます。


Direct3Dでは、頂点は、カスタム頂点構造体および対応するカスタム 柔軟な頂点フォーマット (FVF) を指定することによって定義できます。

struct CUSTOMVERTEX{
FLOAT x, y, z, rhw; // The transformed position for the vertex.
DWORD color; // The vertex color.
};
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)




このような風にですね。

ある時、これを一々作るのが面倒に感じたことがあります。

そもそもFVFは定数なのだから、テンプレートによるメタプログラミングで定義できるのではないかと考えました、

そこで実際に作って出来たものが次です。
ちょっと長いです。

namespace detail{
template <bool>
struct If{
template <class T,class U>
struct Inner
{ typedef T type; };
};

template <>
struct If<false>{
template <class T,class U>
struct Inner
{ typedef U type; };
};
}

template <bool B,class T,class U>
struct If{
typedef typename ::detail::If<B>::template Inner<T,U>::type type;
};

struct EMPTY{};

struct XYZ{
D3DXVECTOR3 p;
};

struct XYZRHW{
D3DXVECTOR4 p;
};

template <int N>
struct XYZB{
D3DXVECTOR3 p;
float b[N];
};

template <DWORD FVF_FORMAT>
struct SELECT_POSITION{
typedef
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZ,
XYZ,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZRHW,
XYZRHW,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZB1,
XYZB<1>,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZB2,
XYZB<2>,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZB3,
XYZB<3>,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZB4,
XYZB<4>,
typename If<(FVF_FORMAT & D3DFVF_POSITION_MASK)==D3DFVF_XYZB5,
XYZB<5>,
EMPTY
>::type
>::type
>::type
>::type
>::type
>::type
>::type type;
};

template <DWORD FVF_FORMAT>
struct NORMAL : public SELECT_POSITION<FVF_FORMAT>::type{
D3DXVECTOR3 n;
};

template <DWORD FVF_FORMAT>
struct DIFFUSE
: public
If<(FVF_FORMAT & D3DFVF_NORMAL)!=0,
NORMAL<FVF_FORMAT>,
typename SELECT_POSITION<FVF_FORMAT>::type
>::type{
DWORD c;
};

template <DWORD FVF_FORMAT>
struct SPECULAR
: public
If<(FVF_FORMAT & D3DFVF_DIFFUSE)!=0,
DIFFUSE<FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_NORMAL)!=0,
NORMAL<FVF_FORMAT>,
SELECT_POSITION<FVF_FORMAT>::type
>::type
>::type{
DWORD s;
};

template <int N,DWORD FVF_FORMAT>
struct TEXTURE
: public
If<(FVF_FORMAT & D3DFVF_SPECULAR)!=0,
SPECULAR<FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_DIFFUSE)!=0,
DIFFUSE<FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_NORMAL)!=0,
NORMAL<FVF_FORMAT>,
typename SELECT_POSITION<FVF_FORMAT>::type
>::type
>::type
>::type{
D3DXVECTOR2 t[N];
};

template <DWORD FVF_FORMAT>
struct Vertex : public
If<((FVF_FORMAT & D3DFVF_TEXCOUNT_MASK)>>D3DFVF_TEXCOUNT_SHIFT)!=0,
TEXTURE<((FVF_FORMAT & D3DFVF_TEXCOUNT_MASK)>>D3DFVF_TEXCOUNT_SHIFT),FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_SPECULAR)!=0,
SPECULAR<FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_DIFFUSE)!=0,
DIFFUSE<FVF_FORMAT>,
typename If<(FVF_FORMAT & D3DFVF_NORMAL)!=0,
NORMAL<FVF_FORMAT>,
typename SELECT_POSITION<FVF_FORMAT>::type
>::type
>::type
>::type
>::type{
enum { FVF=FVF_FORMAT };
};




これを使えば最初のカスタム頂点の定義は次のようにかけます。

typedef Vertex<D3DFVF_XYZRHW|D3DFVF_DIFFUSE> CUSTOMVERTEX;





各要素のアクセスの方法は次のとおりです。

CUSTOMVERTEX::FVF でFVFの取得

CUSTOMVERTEX v;
v.p で座標を表すメンバ変数アクセス(D3DFVF_XYZRHWやD3DFVF_XYZが指定されたときだけ存在する

v.n で法線を表すメンバ変数アクセス(D3DFVF_NORMALが指定されたときだけ存在する

v.c でディフューズ色を表すメンバ変数アクセス(D3DFVF_DIFFUSEが指定されたときだけ存在する

v.s でスペキュラ色を表すメンバ変数アクセス(D3DFVF_SPECULARが指定されたときだけ存在する

v.t[N] でテクスチャ座標を表すメンバ変数アクセス(D3DFVF_TEX1~が指定されたときだけ存在する




 
スポンサーサイト
C++はなぜ人気がないのか

男モロ白かったかも。

C++は世間一般ではそんな人気無い言語だったのか。
私の周り一般ではC++以外ほとんど考えられないんで知らんかったよ。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。