/*!
 	@file
 	@brief	独自頂点構造体テンプレート
 */

#ifndef CCustomVertexTemplate_h
#define CCustomVertexTemplate_h


#include"../Setup/CompileMode.h"
#include"../Auxiliary/Debug/CAssert.h"
#include"../Auxiliary/Macro.h"
#include"../Auxiliary/mstring.h"
#include"../template/Mathematics.h"
#include"Color.h"

namespace Maid
{ 
	/*!
	 	@enum	VERTEXFORMAT CCustomVertexTemplate.h
	 	@brief	頂点フォーマットを識別するenum
	\n			IVideoCardDriver を継承したクラスはこの値を元に判別すること
	\n			インデックスブレンドを使う場合、ブレンドの必要のない頂点のインデックスは 0 にしておくこと 
	 
	 */
	enum VERTEXFORMAT
	{
		VERTEXFORMAT_NONE=-1,	//!<	エラー
		VERTEXFORMAT_COLOR=0,	//!< pos,rhw,color
		VERTEXFORMAT_SPRITE,	//!< pos,rhw,color,tex
		VERTEXFORMAT_SPRITE2,	//!< pos,rhw,color,texx2
		VERTEXFORMAT_SPRITE3,	//!< pos,rhw,color,texx3
		VERTEXFORMAT_SPRITE4,	//!< pos,rhw,color,texx4

		VERTEXFORMAT_XYZ,			//!< pos
		VERTEXFORMAT_NORMAL,		//!< normal
		VERTEXFORMAT_TEX1,			//!< tex1
		
		VERTEXFORMAT_3DCOLOR,			//!< pos,color
		VERTEXFORMAT_3DSPRITE,			//!< pos,color,tex
		VERTEXFORMAT_3DSPRITE2,			//!< pos,color,texx2
		VERTEXFORMAT_3DSPRITE3,			//!< pos,color,texx3
		VERTEXFORMAT_3DSPRITE4,			//!< pos,color,texx4
		VERTEXFORMAT_3DCOLORNORMAL,		//!< pos,color,normal
		VERTEXFORMAT_3DSPRITENORMAL,	//!< pos,color,tex,normal
		VERTEXFORMAT_3DSPRITENORMAL2,	//!< pos,color,texx2,normal

		VERTEXFORMAT_3DT0W1,	//!< pos,color,normal,weightx1
		VERTEXFORMAT_3DT0W2,	//!< pos,color,normal,weightx2
		VERTEXFORMAT_3DT0W3,	//!< pos,color,normal,weightx3
		VERTEXFORMAT_3DT0W4,	//!< pos,color,normal,weightx4
		VERTEXFORMAT_3DT1W1,	//!< pos,color,texx1,normal,weightx1
		VERTEXFORMAT_3DT1W2,	//!< pos,color,texx1,normal,weightx2
		VERTEXFORMAT_3DT1W3,	//!< pos,color,texx1,normal,weightx3
		VERTEXFORMAT_3DT1W4,	//!< pos,color,texx1,normal,weightx4
	};

	/*!
	 	@brief	独自頂点構造体テンプレート
	\n			頂点構造を記述した構造体にこのテンプレートをかますことによって
	\n			いちいちメンバ関数を書く必要がなくなる
	\n			条件としてメンバ変数の名前を同じにしておくこと
	 */
	template<class Struct, VERTEXFORMAT Format>
	struct CUSTOMVERTEX_TEMPLATE
	{
	public:
		const VERTEXFORMAT	GetVertexFormat() const{ return Format;			}	//!<	頂点フォーマットの取得
		const unt32		GetStructSize()   const{ return sizeof(Struct);	}	//!<	頂点サイズの取得
	};


	/*!
	 	@struct	CUSTOMVERTEX_COLOR DenCustomVertexTemplate.h
	 	@brief	頂点変換済みカラー
	 */
	struct CUSTOMVERTEX_COLOR : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_COLOR,VERTEXFORMAT_COLOR>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_COLOR(){};
		CUSTOMVERTEX_COLOR( const POINT3DF& pos, float32 rhw, const COLOR_A08R08G08B08I& color )
			: Position(pos), RHW(rhw), Color(color){}
		POINT3DF			Position;	//!< 頂点座標
		float32				RHW;		//!< 頂点変換値
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};

	/*!
	 	@struct	CUSTOMVERTEX_SPRITE DenCustomVertexTemplate.h
	 	@brief	頂点変換済みテクスチャ
	 */
	struct CUSTOMVERTEX_SPRITE : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_SPRITE,VERTEXFORMAT_SPRITE>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_SPRITE(){};
		CUSTOMVERTEX_SPRITE( const POINT3DF& pos, float32 rhw, const COLOR_A08R08G08B08I& color, const POINT2DF& tex)
			: Position(pos), RHW(rhw), Color(color)
		{
			Texture[0] = tex;
		}
		POINT3DF			Position;	//!< 頂点座標
		float32				RHW;		//!< 頂点変換値
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_SPRITE2 DenCustomVertexTemplate.h
	 	@brief	頂点変換済みテクスチャ
	 */
	struct CUSTOMVERTEX_SPRITE2 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_SPRITE2,VERTEXFORMAT_SPRITE2>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_SPRITE2(){};
		CUSTOMVERTEX_SPRITE2( const POINT3DF& pos, float32 rhw, const COLOR_A08R08G08B08I& color, const POINT2DF& tex1, const POINT2DF& tex2 )
			: Position(pos), RHW(rhw), Color(color)
		{
			Texture[0] = tex1;
			Texture[1] = tex2;
		}
		POINT3DF			Position;	//!< 頂点座標
		float32				RHW;		//!< 頂点変換値
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[2];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_SPRITE3 DenCustomVertexTemplate.h
	 	@brief	頂点変換済みテクスチャ
	 */
	struct CUSTOMVERTEX_SPRITE3 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_SPRITE3,VERTEXFORMAT_SPRITE3>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_SPRITE3(){};
		CUSTOMVERTEX_SPRITE3( const POINT3DF& pos, float32 rhw, const COLOR_A08R08G08B08I& color, const POINT2DF& tex1, const POINT2DF& tex2, const POINT2DF& tex3 )
			: Position(pos), RHW(rhw), Color(color)
		{
			Texture[0] = tex1;
			Texture[1] = tex2;
			Texture[2] = tex3;
		}
		POINT3DF			Position;	//!< 頂点座標
		float32				RHW;		//!< 頂点変換値
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[3];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_SPRITE4 DenCustomVertexTemplate.h
	 	@brief	頂点変換済みテクスチャ
	 */
	struct CUSTOMVERTEX_SPRITE4 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_SPRITE4,VERTEXFORMAT_SPRITE4>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_SPRITE4(){};
		CUSTOMVERTEX_SPRITE4( const POINT3DF& pos, float32 rhw, const COLOR_A08R08G08B08I& color, const POINT2DF& tex1, const POINT2DF& tex2, const POINT2DF& tex3, const POINT2DF& tex4 )
			: Position(pos), RHW(rhw), Color(color)
		{
			Texture[0] = tex1;
			Texture[1] = tex2;
			Texture[2] = tex3;
			Texture[3] = tex4;
		}
		POINT3DF			Position;	//!< 頂点座標
		float32				RHW;		//!< 頂点変換値
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[4];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DCOLOR DenCustomVertexTemplate.h
	 	@brief	頂点変換前カラー
	 */
	struct CUSTOMVERTEX_3DCOLOR : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DCOLOR,VERTEXFORMAT_3DCOLOR>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DCOLOR(){};
		CUSTOMVERTEX_3DCOLOR( const POINT3DF& pos, const COLOR_A08R08G08B08I& color)
			: Position(pos), Color(color){}
		POINT3DF			Position;	//!< 頂点座標
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DSPRITE DenCustomVertexTemplate.h
	 	@brief	頂点変換前テクスチャ
	 */
	struct CUSTOMVERTEX_3DSPRITE : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DSPRITE,VERTEXFORMAT_3DSPRITE>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DSPRITE(){};
		CUSTOMVERTEX_3DSPRITE( const POINT3DF& pos, const COLOR_A08R08G08B08I& color, const POINT2DF& tex)
			: Position(pos), Color(color)
		{
			Texture[0] = tex;
		}

		POINT3DF			Position;	//!< 頂点座標
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DSPRITE2 DenCustomVertexTemplate.h
	 	@brief	頂点変換前テクスチャ
	 */
	struct CUSTOMVERTEX_3DSPRITE2 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DSPRITE2,VERTEXFORMAT_3DSPRITE2>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DSPRITE2(){};
		CUSTOMVERTEX_3DSPRITE2( const POINT3DF& pos, const COLOR_A08R08G08B08I& color, const POINT2DF& tex1, const POINT2DF& tex2 )
			: Position(pos), Color(color)
		{
			Texture[0] = tex1;
			Texture[1] = tex2;
		}
		POINT3DF			Position;	//!< 頂点座標
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[2];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DCOLORNORMAL DenCustomVertexTemplate.h
	 	@brief	頂点変換前カラー法線付
	 */
	struct CUSTOMVERTEX_3DCOLORNORMAL : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DCOLORNORMAL,VERTEXFORMAT_3DCOLORNORMAL>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DCOLORNORMAL(){};
		CUSTOMVERTEX_3DCOLORNORMAL( const POINT3DF& pos, const VECTOR3DF& nom, const COLOR_A08R08G08B08I& color )
			: Position(pos), Normal(nom), Color(color){}
		POINT3DF			Position;	//!< 頂点座標
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DSPRITENORMAL DenCustomVertexTemplate.h
	 	@brief	頂点変換前テクスチャ法線付
	 */
	struct CUSTOMVERTEX_3DSPRITENORMAL : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DSPRITENORMAL,VERTEXFORMAT_3DSPRITENORMAL>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DSPRITENORMAL(){};
		CUSTOMVERTEX_3DSPRITENORMAL( const POINT3DF& pos, const VECTOR3DF& nom, const COLOR_A08R08G08B08I& color, const POINT2DF& tex)
			: Position(pos), Normal(nom), Color(color)
		{
			Texture[0] = tex;
		}

		POINT3DF			Position;	//!< 頂点座標
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DSPRITENORMAL2 DenCustomVertexTemplate.h
	 	@brief	頂点変換前テクスチャ法線付
	 */
	struct CUSTOMVERTEX_3DSPRITENORMAL2 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DSPRITENORMAL2,VERTEXFORMAT_3DSPRITENORMAL2>
	{
		//!	コンストラクタ
		CUSTOMVERTEX_3DSPRITENORMAL2(){};
		CUSTOMVERTEX_3DSPRITENORMAL2( const POINT3DF& pos, const VECTOR3DF& nom, const COLOR_A08R08G08B08I& color, const POINT2DF& tex1 , const POINT2DF& tex2 )
			: Position(pos), Normal(nom), Color(color)
		{
			Texture[0] = tex1;
			Texture[1] = tex2;
		}
		POINT3DF			Position;	//!< 頂点座標
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[2];	//!< テクスチャ座標
	};

	/*!
	 	@struct	CUSTOMVERTEX_3DT0W1 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ０、ウェイト１)
	 */
	struct CUSTOMVERTEX_3DT0W1 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT0W1,VERTEXFORMAT_3DT0W1>
	{
		POINT3DF			Position;	//!< 頂点座標
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT0W2 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ０、ウェイト２)
	 */
	struct CUSTOMVERTEX_3DT0W2 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT0W2,VERTEXFORMAT_3DT0W2>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[1];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT0W3 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ０、ウェイト３)
	 */
	struct CUSTOMVERTEX_3DT0W3 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT0W3,VERTEXFORMAT_3DT0W3>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[2];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT0W4 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ０、ウェイト４)
	 */
	struct CUSTOMVERTEX_3DT0W4 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT0W4,VERTEXFORMAT_3DT0W4>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[3];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT1W1 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ１、ウェイト１)
	 */
	struct CUSTOMVERTEX_3DT1W1 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT1W1,VERTEXFORMAT_3DT1W1>
	{
		POINT3DF			Position;	//!< 頂点座標
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT1W2 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ１、ウェイト２)
	 */
	struct CUSTOMVERTEX_3DT1W2 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT1W2,VERTEXFORMAT_3DT1W2>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[1];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT1W3 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ１、ウェイト３)
	 */
	struct CUSTOMVERTEX_3DT1W3 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT1W3,VERTEXFORMAT_3DT1W3>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[2];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};
	/*!
	 	@struct	CUSTOMVERTEX_3DT1W4 DenCustomVertexTemplate.h
	 	@brief	モデル用頂点フォーマット（テクスチャ１、ウェイト４)
	 */
	struct CUSTOMVERTEX_3DT1W4 : public CUSTOMVERTEX_TEMPLATE<CUSTOMVERTEX_3DT1W4,VERTEXFORMAT_3DT1W4>
	{
		POINT3DF			Position;	//!< 頂点座標
		float32				Blend[3];	//!< ブレンド
		unt08				Index[4];	//!< インデックス
		VECTOR3DF			Normal;		//!< 法線ベクトル
		COLOR_A08R08G08B08I	Color;		//!< 頂点色
		POINT2DF			Texture[1];	//!< テクスチャ座標
	};


	inline unt32 GetFVFSize( VERTEXFORMAT Format )
	{
		switch( Format )
		{
		case VERTEXFORMAT_COLOR: { return sizeof(CUSTOMVERTEX_COLOR); }break;
		case VERTEXFORMAT_SPRITE: { return sizeof(CUSTOMVERTEX_SPRITE); }break;
		case VERTEXFORMAT_SPRITE2: { return sizeof(CUSTOMVERTEX_SPRITE2); }break;
		case VERTEXFORMAT_3DSPRITE: { return sizeof(CUSTOMVERTEX_3DSPRITE); }break;
		case VERTEXFORMAT_3DCOLOR: { return sizeof(CUSTOMVERTEX_3DCOLOR); }break;
		case VERTEXFORMAT_3DSPRITENORMAL: { return sizeof(CUSTOMVERTEX_3DSPRITENORMAL); }break;
		case VERTEXFORMAT_3DSPRITENORMAL2: { return sizeof(CUSTOMVERTEX_3DSPRITENORMAL2); }break;
		case VERTEXFORMAT_3DCOLORNORMAL: { return sizeof(CUSTOMVERTEX_3DCOLORNORMAL); }break;

		case VERTEXFORMAT_3DT0W1: { return sizeof(CUSTOMVERTEX_3DT0W1); }break;
		case VERTEXFORMAT_3DT0W2: { return sizeof(CUSTOMVERTEX_3DT0W2); }break;
		case VERTEXFORMAT_3DT0W3: { return sizeof(CUSTOMVERTEX_3DT0W3); }break;
		case VERTEXFORMAT_3DT0W4: { return sizeof(CUSTOMVERTEX_3DT0W4); }break;
		case VERTEXFORMAT_3DT1W1: { return sizeof(CUSTOMVERTEX_3DT1W1); }break;
		case VERTEXFORMAT_3DT1W2: { return sizeof(CUSTOMVERTEX_3DT1W2); }break;
		case VERTEXFORMAT_3DT1W3: { return sizeof(CUSTOMVERTEX_3DT1W3); }break;
		case VERTEXFORMAT_3DT1W4: { return sizeof(CUSTOMVERTEX_3DT1W4); }break;

		case VERTEXFORMAT_XYZ:		{ return sizeof(POINT3DF); }break;
		case VERTEXFORMAT_NORMAL:	{ return sizeof(VECTOR3DF); }break;
		case VERTEXFORMAT_TEX1:		{ return sizeof(POINT2DF); }break;

		}

		MAID_ASSERT( true, MAIDTEXT("定義されていないＦＶＦです ") << Format );
		return 0;
	}

	struct FVFINFO	//	頂点の各メンバが何バイト目にあるかをしるした構造体
	{
		enum
		{
			NOT_CONTAIN = -1,
		};

		FVFINFO();
		VERTEXFORMAT Format;
		int32 StructSize;
		int32 OffsetPosition;
		int32 OffsetColor;
		int32 OffsetWeight;
		int32 OffsetWeightIndex;
		int32 OffsetNormal;
		int32 OffsetUV1;

		int32 IndexBlendMax;
	};

	FVFINFO GetFVFInfo( VERTEXFORMAT Format );


}

#endif
