
#ifndef  __JBXL_CPP_MESHOBJECTDATA_H_
#define  __JBXL_CPP_MESHOBJECTDATA_H_


#include  "xtools++.h"
#include  "txml.h"

#include  "TriBrep.h"
#include  "Rotation.h"
#include  "FacetBaseData.h"
#include  "MaterialParam.h"




namespace jbxl {



class  MeshObjectNode;
class  MeshObjectData;




/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MeshObjectNode: for Facet Data 
//

/**
@brief MeshObject の Polygonデータを格納するクラス．リスト構造を取る．

*/
class  MeshObjectNode
{
public:
	Buffer 	material_id;			///< マテリアルを識別するID
	bool	same_material;			///< 他の Node が既に同じマテリアルを使用している．

	int		facet_no;				///< 面番号
	MaterialParam material_param;	///< マテリアルパラメータ

	int  	num_vertex;				///< 頂点のデータ数．（vertex_value, normal_value の要素数）
	int  	num_texcrd;				///< テクスチャ画像の座標数．通常は num_vertex に等しい．（texcrd_value の要素数）
	int  	num_polygon;			///< ポリゴンの数
	int  	num_index;				///< 頂点の延べ数．num_polygon*MeshObjectData::num_vcount （data_index の要素数）

	int* 	data_index; 			///< インデックスデータ

	Vector<double>* vertex_value;
	Vector<double>* normal_value;
	UVMap<double>*  texcrd_value;

	MeshObjectNode*	next;
	MeshObjectNode*	prev;

public:
	MeshObjectNode(void) { init();}
	virtual ~MeshObjectNode(void) {}

	void  init(void);
	void  free(void);
	void  free_value(void);
	void  clear(void);

	void  set (int vertex,   int polygon,   int vcount=3);
	bool  getm(int vertex=0, int polygon=0, int vcount=0);

	//
	void  setFacetNo(int no) { if (no>=0) facet_no = no;}
	void  setMaterialParam(MaterialParam param) { setMaterial(param);}
	void  setMaterial(MaterialParam param);
	void  delMaterialParam(void) { delMaterial();}
	void  delMaterial(void) { material_param.clear();}

	void  setMaterialID (const char* str=NULL);
	void* getMaterialID (void) { return _tochar(material_id.buf);}

public:
	bool  computeVertexDirect(FacetBaseData* facetdata);
	bool  computeVertexDirect(Vector<double>* vtx, Vector<double>* nml, UVMap<double>* map, int num, int vcount=3);
	bool  computeVertexByBREP(Vector<double>* vtx, Vector<double>* nml, UVMap<double>* map, int num, int vcount=3);
};




inline void  freeMeshObjectNode(MeshObjectNode*& node) { if(node!=NULL) { node->free(); delete node; node=NULL;} }
void  freeMeshObjectList(MeshObjectNode*& node);

MeshObjectNode*  DelMeshObjectNode(MeshObjectNode* node);
MeshObjectNode*  AddMeshObjectNode(MeshObjectNode* list, MeshObjectNode* node);





/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// MeshObject Data: for Object
//

/**

*/
class  MeshObjectData
{
public:
	Buffer 	data_name;				///< データ名

	int  	ttl_vertex;				///< 頂点の総数．
	int  	ttl_texcrd;				///< テクスチャ画像の座標総数．
	int		num_node;				///< テクスチャー単位の面の数（nodelistの数）
	int  	num_vcount;				///< 1ポリゴン あたりの頂点数．現在は 3のみサポート
	int		num_import;				///< 入力データの数

	Vector<double>* impvtx_value;	///< 入力された頂点データ．3個で 1ポリゴンを表現．法線方向は右手順．
	Vector<double>* impnrm_value;	///< 入力された頂点の法線ベクトル．impvtx_value と対応．
	UVMap<double>*  impmap_value;	///< 入力されたテクスチャ座標データ．impvtx_value と対応．
	//
	AffineTrans* 	affine_trans;	///< アフィン変換．ここで使用するのは，shift, rotate, scale(size) のみ

	MeshObjectNode* nodelist;		///< テクスチャー単位の面のデータのリストへのポインタ
	MeshObjectNode* endplist;		///< テクスチャー単位の面のデータのリストの最後のデータへのポインタ

public:
	MeshObjectData(const char* name=NULL) { init(name);}
	virtual	~MeshObjectData(void)   {}

	void	init(const char* name=NULL);
	void	free(void);
	void	free_value(void);
	void	clear(void);

	//
	void	setName(const char* str) { free_Buffer(&data_name); data_name=make_Buffer_str(str);}
	char*	getName(void) { return _tochar(data_name.buf);}
	
	void	setAffineTrans(AffineTrans a) { delAffineTrans(); affine_trans = new AffineTrans(); affine_trans->dup(a);}
	void	delAffineTrans(void) { freeAffineTrans(affine_trans);}

public:
	bool	addData(FacetBaseData* facetdata, MaterialParam* param=NULL);
	bool	addData(Vector<double>* vct, Vector<double>* nrm, UVMap<double>* map, int vnum, MaterialParam* param=NULL);
	bool	addData(TriPolyData* tridata, int tnum, int fnum=-1, MaterialParam* param=NULL);		///< 処理するFACETを選択できる

	void	joinData(MeshObjectData*& data);	///< data は削除される．
	void	setMaterial(MaterialParam param, int num=-1);
	void	setMaterialParam(MaterialParam param, int num=-1) { setMaterial(param, num);}
	//
	bool	importTriData(TriPolyData* tridata, int tnum, int fnum=-1);
	bool	importTriData(Vector<double>* vct, Vector<double>* nrm, UVMap<double>* map, int vnum);
	bool	addNode(FacetBaseData* facetdata);
	bool	addNode(void);
};



inline void  freeMeshObjectData(MeshObjectData*& data) { if(data!=NULL) { data->free(); delete data; data=NULL;} }







}		// namespace

#endif


