////////////////////////////////////////////////////////
// filename: ChaDataObject.cpp
// author: Chafumi Touji
// version: 1.0.1
// date: 2020/03/05
//          2020/08/27
////////////////////////////////////////////////////////

#include "defcha3dcore.h"

////////////////////////////////////////////////////////////

CFloatArray::CFloatArray(){

	wmemset(ID, 0, SIZE_CHAR_MAX);
	FloatData = NULL;
}

CFloatArray::~CFloatArray(){

	delete FloatData;
	FloatData = NULL;
}

////////////////////////////////////////////////////////////

CPolygonData::CPolygonData(){

	wmemset(VertexID, 0, SIZE_CHAR_MAX);
	wmemset(NormalID, 0, SIZE_CHAR_MAX);
	wmemset(ColorID, 0, SIZE_CHAR_MAX);
	wmemset(MaterialID, 0, SIZE_CHAR_MAX);
	VertexIndex = new CVector(sizeof(int32_t));
	NormalIndex = new CVector(sizeof(int32_t));
	TexIndex = new CVector(sizeof(int32_t));
	ColorIndex = new CVector(sizeof(int32_t));
	TexID = new CVector(sizeof(wchar_t)* SIZE_CHAR_MAX);
}

CPolygonData::~CPolygonData(){

	delete VertexIndex;
	delete NormalIndex;
	delete TexIndex;
	delete ColorIndex;
	delete TexID;

	VertexIndex = NULL;
	NormalIndex = NULL;
	TexIndex = NULL;
	ColorIndex = NULL;
	TexID = NULL;

}

///////////////////////////////////////////////////////////////

CBone::CBone(){

	wmemset(ID, 0, SIZE_CHAR_MAX);
	wmemset(Name, 0, SIZE_CHAR_MAX);
	MatrixSet(&JointParam, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
	MatrixSet(&InvBindMatrix, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
	ChildBone = new CVector(sizeof(int64_t));
	ParentBone = NULL;
	Type = BONE_TYPE_UNKNOWN;
}

CBone::~CBone(){

	delete ChildBone;
	ChildBone = NULL;
}

///////////////////////////////////////////////////////////////

CAnimation::CAnimation(){

	wmemset(AnimatonID, 0, SIZE_CHAR_MAX);
	BoneAnimation = new CVector(sizeof(int64_t));
}

CAnimation::~CAnimation(){

	for (int i = 0; i <= BoneAnimation->PushPos - 1; i++){
		CBoneAnimation *bone_anim = *(CBoneAnimation **)BoneAnimation->GetData(i);
		delete bone_anim;
		bone_anim = NULL;
	}
	delete BoneAnimation;
	BoneAnimation = NULL;
}

///////////////////////////////////////////////////////////////

CBoneAnimation::CBoneAnimation(){

	wmemset(Target, 0, SIZE_CHAR_MAX);
	TargetBone = NULL;
	KeyTime = new CVector(sizeof(float));
	PoseMatrix = new CVector(sizeof(matrix));
}

CBoneAnimation::~CBoneAnimation(){

	delete KeyTime;
	delete PoseMatrix;
	TargetBone = NULL;
	KeyTime = NULL;
	PoseMatrix = NULL;
}

///////////////////////////////////////////////////////////////

CGeometry::CGeometry(){

	wmemset(GeometryID, 0, SIZE_CHAR_MAX);
	VertexCount = 0;
	VecFloatArray = new CVector(sizeof(int64_t));
	PolygonData = new CVector(sizeof(int64_t));
	MatrixSet(&BindShapeMatrix, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
	Weights = NULL;
	WeightCount = 0;
}

CGeometry::~CGeometry(){

	for (int i = 0; i <= VecFloatArray->PushPos - 1; i++){
		CFloatArray *data = *(CFloatArray **)VecFloatArray->GetData(i);
		delete data;
		data = NULL;
	}
	for (int i = 0; i <= PolygonData->PushPos - 1; i++){
		CPolygonData *data = *(CPolygonData **)PolygonData->GetData(i);
		delete data;
		data = NULL;
	}
	if (Weights != NULL){
		for (int i = 0; i <= WeightCount - 1; i++){
			for (int j = 0; j <= WEIGHT_BONE_APPLY_NUM - 1; j++){
				delete[] Weights[i][j];
				Weights[i][j] = NULL;
			}
			delete[] Weights[i];
			Weights[i] = NULL;
		}
		delete[] Weights;
		Weights = NULL;
	}
}

CFloatArray *CGeometry::GetFloatArray(wchar_t *id){

	for (int i = 0; i <= VecFloatArray->PushPos - 1; i++){
		if (wcscmp((*(CFloatArray **)VecFloatArray->GetData(i))->ID, id) == 0)
			return *(CFloatArray **)VecFloatArray->GetData(i);
	}

	return NULL;
}

///////////////////////////////////////////////////////////////


CChaDataObject::CChaDataObject(){

	wmemset(ModelID, 0, SIZE_CHAR_MAX);
	wmemset(ColliderFilePath, 0, SIZE_CHAR_MAX);
	Geometry = new CVector(sizeof(int64_t));
	Material = new CVector(sizeof(int64_t));
	TextureName = new CVector(sizeof(int64_t));
	ControlBone = new CVector(sizeof(int64_t));
	BoneArray = new CVector(sizeof(int64_t));
	AnimationList = new CVector(sizeof(int64_t));

	::CoInitialize(NULL);
}

CChaDataObject::~CChaDataObject(){

	for (int i = 0; i <= Geometry->PushPos - 1; i++){
		CGeometry *data = *(CGeometry **)Geometry->GetData(i);
		delete data;
		data = NULL;
	}

	for (int i = 0; i <= Material->PushPos - 1; i++){
		CMaterial *data = *(CMaterial **)Material->GetData(i);
		delete data;
		data = NULL;
	}

	for (int i = 0; i <= TextureName->PushPos - 1; i++){
		CTextureName *data = *(CTextureName **)TextureName->GetData(i);
		delete data;
		data = NULL;
	}

	for (int i = 0; i <= BoneArray->PushPos - 1; i++){
		CBone *bone = *(CBone **)BoneArray->GetData(i);
		if (bone != NULL)
			delete bone;
		bone = NULL;
	}

	for (int i = 0; i <= ControlBone->PushPos - 1; i++){
		CBone *bone = *(CBone **)ControlBone->GetData(i);
		if (bone != NULL)
			delete bone;
		bone = NULL;
	}

	for (int i = 0; i <= AnimationList->PushPos - 1; i++){
		CAnimation *anim = *(CAnimation **)AnimationList->GetData(i);
		delete anim;
		anim = NULL;
	}

	delete Geometry;
	delete Material;
	delete TextureName;
	delete ControlBone;
	delete BoneArray;
	delete AnimationList;

	Geometry = NULL;
	Material = NULL;
	TextureName = NULL;
	ControlBone = NULL;
	BoneArray = NULL;
	AnimationList = NULL;

	::CoUninitialize();
}

CMaterial *CChaDataObject::GetMaterial(wchar_t *id){

	for (int i = 0; i <= Material->PushPos - 1; i++){
		if (wcscmp((*(CMaterial **)Material->GetData(i))->MaterialName, id) == 0)
			return *(CMaterial **)Material->GetData(i);
	}

	return NULL;
}

int CChaDataObject::GetMaterialNum(wchar_t *id){

	for (int i = 0; i <= Material->PushPos - 1; i++){
		if (wcscmp((*(CMaterial **)Material->GetData(i))->MaterialName, id) == 0)
			return i;
	}

	return -1;
}

CTextureName *CChaDataObject::GetTextureName(wchar_t *id){

	for (int i = 0; i <= TextureName->PushPos - 1; i++){
		if (wcscmp((*(CTextureName **)TextureName->GetData(i))->TextureID, id) == 0)
			return *(CTextureName **)TextureName->GetData(i);
	}

	return NULL;
}

int CChaDataObject::GetTextureNum(int material_num){

	CMaterial *material = *(CMaterial **)Material->GetData(material_num);
	wchar_t *texture_id = material->TextureName;

	for (int i = 0; i <= TextureName->PushPos - 1; i++){

		CTextureName *texture = *(CTextureName **)TextureName->GetData(i);
		if (wcscmp(texture->TextureID, texture_id) == 0)
			return i;
	}

	return -1;
}

bool CChaDataObject::LoadDAE(const wchar_t *filename, const wchar_t *ext_dae){

	MSXML2::IXMLDOMDocumentPtr pDoc("MSXML2.DOMDocument");
	pDoc->validateOnParse = VARIANT_FALSE;
	pDoc->put_async(VARIANT_FALSE);

	pDoc->validateOnParse = VARIANT_FALSE;
	pDoc->put_async(VARIANT_FALSE);

	size_t size;
	char name[SIZE_CHAR_MAX];
	memset(name, 0, SIZE_CHAR_MAX);
	wcstombs_s(&size, name, filename, SIZE_CHAR_MAX);

	HRESULT hr = pDoc->load(name);
	if (hr == 0){

		return false;
	}

	wchar_t ext[16];
	wmemset(ext, 0, 16);
	wmemcpy_s(ext, SIZE_CHAR_MAX, &filename[wcslen(filename) - 4], 4);

	wchar_t id_name[SIZE_CHAR_MAX];
	wmemset(id_name, 0, SIZE_CHAR_MAX);

	if (wcscmp(ext, ext_dae) == 0)
		wmemcpy_s(id_name, SIZE_CHAR_MAX, filename, wcslen(filename) - 4);
	else
		wcscpy_s(id_name, SIZE_CHAR_MAX, filename);

	wchar_t model_id[SIZE_CHAR_MAX];
	wmemset(model_id, 0, SIZE_CHAR_MAX);
	wchar_t* w_ctx = NULL;

	wchar_t* tmp = wcstok_s(id_name, L"/\\\n", &w_ctx);
	wcscpy_s(model_id, SIZE_CHAR_MAX, tmp);
	do {
		tmp = wcstok_s(NULL, L"/\\\n", &w_ctx);
		if (tmp == NULL)
			break;
		wcscpy_s(model_id, SIZE_CHAR_MAX, tmp);
	} while (tmp != NULL);

	wcscpy_s(ModelID, SIZE_CHAR_MAX, model_id);

	LoadTextureName(pDoc);
	LoadMaterial(pDoc);
	LoadMesh(pDoc);
	LoadController(pDoc);
	LoadTransform(pDoc);
	LoadAnimation(pDoc);

	return true;
}

bool CChaDataObject::LoadMaterial(MSXML2::IXMLDOMDocumentPtr pDoc){

	MSXML2::IXMLDOMNodeListPtr node_list = pDoc->selectNodes(L"COLLADA/library_materials/material");

	size_t size;
	CMaterial *Mat = NULL;
	wchar_t path[SIZE_CHAR_MAX];
	for (int i = 0; i <= (int)node_list->Getlength() - 1; i++){

		Mat = new CMaterial();

		MSXML2::IXMLDOMElementPtr material = node_list->Getitem(i);
		wcscpy_s(Mat->MaterialName, SIZE_CHAR_MAX, material->getAttribute("id").bstrVal);

		wmemset(path, 0, SIZE_CHAR_MAX);
		MSXML2::IXMLDOMElementPtr material_source = material->selectSingleNode(L"instance_effect");
		wcscpy_s(path, SIZE_CHAR_MAX, L"COLLADA/library_effects/effect[@id='");
		wcscat_s(path, SIZE_CHAR_MAX, material_source->getAttribute("url").bstrVal + 1);
		wcscat_s(path, SIZE_CHAR_MAX, L"']");

		MSXML2::IXMLDOMNodeListPtr effect_list = pDoc->selectNodes(path);
		for (int j = 0; j <= (int)effect_list->Getlength() - 1; j++){

			MSXML2::IXMLDOMElementPtr effect = effect_list->Getitem(j);
			if (effect == NULL)
				continue;

			//マテリアルのテクスチャ取得
			MSXML2::IXMLDOMElementPtr tex = effect->selectSingleNode("profile_COMMON/technique/phong/diffuse/texture");
			if (tex == NULL)
				tex = effect->selectSingleNode("profile_COMMON/technique/lambert/diffuse/texture");
			if (tex != NULL){
				wmemset(path, 0, SIZE_CHAR_MAX);
				wcscpy_s(path, SIZE_CHAR_MAX, L"profile_COMMON/newparam[@sid='");
				wcscat_s(path, SIZE_CHAR_MAX, tex->getAttribute("texture").bstrVal);
				wcscat_s(path, SIZE_CHAR_MAX, L"']/sampler2D/source");
				MSXML2::IXMLDOMElementPtr sampler = effect->selectSingleNode(path);
				if (sampler != NULL){
					wmemset(path, 0, SIZE_CHAR_MAX);
					wcscpy_s(path, SIZE_CHAR_MAX, L"profile_COMMON/newparam[@sid='");
					wcscat_s(path, SIZE_CHAR_MAX, sampler->Gettext());
					wcscat_s(path, SIZE_CHAR_MAX, L"']/surface/init_from");
					MSXML2::IXMLDOMElementPtr surface = effect->selectSingleNode(path);
					if (surface != NULL){
						wcscpy_s(Mat->TextureName, SIZE_CHAR_MAX, surface->Gettext());
					}
				}
			}

			//マテリアルのディフューズカラー取得
			MSXML2::IXMLDOMElementPtr col = effect->selectSingleNode("profile_COMMON/technique/phong/diffuse/color");
			if (col == NULL)
				col = effect->selectSingleNode("profile_COMMON/technique/lambert/diffuse/color");
			if (col != NULL){
				char *ctx;
				char diffuse_text[SIZE_CHAR_MAX];
				memset(diffuse_text, 0, SIZE_CHAR_MAX);
				wcstombs_s(&size, diffuse_text, col->Gettext(), SIZE_CHAR_MAX);
				char *tmp = strtok_s(diffuse_text, " ", &ctx);
				if (tmp != NULL){
					Mat->diffuse.x = (float) atof(tmp);
					tmp = strtok_s(NULL, " ", &ctx);
				}
				if (tmp != NULL){
					Mat->diffuse.y = (float)atof(tmp);
					tmp = strtok_s(NULL, " ", &ctx);
				}
				if (tmp != NULL){
					Mat->diffuse.z = (float)atof(tmp);
					tmp = strtok_s(NULL, " ", &ctx);
				}
				if (tmp != NULL){
					Mat->diffuse.w = (float) atof(tmp);
					tmp = strtok_s(NULL, " ", &ctx);
				}
			}
		}

		Material->Push((void *)&Mat);
	}

	return true;
}

bool CChaDataObject::LoadTextureName(MSXML2::IXMLDOMDocumentPtr pDoc){

	MSXML2::IXMLDOMNodeListPtr node_list = pDoc->selectNodes(L"COLLADA/library_images/image");

	CTextureName *Tex = NULL;

	for (int i = 0; i <= (int)node_list->Getlength() - 1; i++){

		MSXML2::IXMLDOMElementPtr tex = node_list->Getitem(i);

		Tex = new CTextureName();

		wcscpy_s(Tex->TextureID, SIZE_CHAR_MAX, tex->getAttribute("id").bstrVal);
		wcscpy_s(Tex->TextureName, SIZE_CHAR_MAX, tex->selectSingleNode("init_from")->Gettext());

		TextureName->Push((void *)&Tex);
	}

	return true;
}

bool CChaDataObject::LoadMesh(MSXML2::IXMLDOMDocumentPtr pDoc){

	size_t size;
	char array_text[SIZE_CHAR_MAX];
	char stride_text[SIZE_CHAR_MAX];
	char offset_text[SIZE_CHAR_MAX];
	wchar_t semantic_text[SIZE_CHAR_MAX];
	wchar_t source_text[SIZE_CHAR_MAX];
	int array_count = 0;
	int stride = 0;
	int face_count = 0;
	CVector *float_data = NULL;
	char *ctx = NULL;
	char *value_text = NULL;
	CFloatArray *float_array = NULL;
	CPolygonData *pgn_data = NULL;
	CGeometry *gmt = NULL;

	MSXML2::IXMLDOMNodeListPtr geometry_list = pDoc->selectNodes(L"COLLADA/library_geometries/geometry");
	for (int i = 0; i <= (int)geometry_list->Getlength() - 1; i++){

		gmt = new CGeometry();

		//ジオメトリid取得
		MSXML2::IXMLDOMElementPtr geometry = geometry_list->Getitem(i);
		wcscpy_s(gmt->GeometryID, SIZE_CHAR_MAX, geometry->getAttribute("id").bstrVal);

		MSXML2::IXMLDOMElementPtr mesh = geometry->selectSingleNode("mesh");
		MSXML2::IXMLDOMNodeListPtr mesh_list = mesh->selectNodes(L"source");

		///////////////////////////////////////////////////////////
		// vertex ID取得

		MSXML2::IXMLDOMElementPtr node_vertics = mesh->selectSingleNode(L"vertices");
		MSXML2::IXMLDOMElementPtr node_vertics_input = node_vertics->selectSingleNode(L"input");

		wchar_t vertics_id[SIZE_CHAR_MAX];
		wmemset(vertics_id, 0, SIZE_CHAR_MAX);
		wcscpy_s(vertics_id, SIZE_CHAR_MAX, node_vertics->getAttribute("id").bstrVal);

		wchar_t vertics_source[SIZE_CHAR_MAX];
		wmemset(vertics_source, 0, SIZE_CHAR_MAX);
		wcscpy_s(vertics_source, SIZE_CHAR_MAX, node_vertics_input->getAttribute("source").bstrVal + 1);

		////////////////////////////////////////////////////////////////

		bool is_vertex = false;
		for (int k = 0; k <= (int)mesh_list->Getlength() - 1; k++){

			//Vertex, Nomal, UVの座標データを取得

			float_array = new CFloatArray();

			is_vertex = false;
			MSXML2::IXMLDOMElementPtr source = mesh_list->Getitem(k);
			wcscpy_s(float_array->ID, SIZE_CHAR_MAX, source->getAttribute("id").bstrVal);
			if (wcscmp(float_array->ID, vertics_source) == 0){
				wmemset(float_array->ID, 0, SIZE_CHAR_MAX);
				wcscpy_s(float_array->ID, SIZE_CHAR_MAX, vertics_id);
				is_vertex = true;
			}

			MSXML2::IXMLDOMElementPtr node = source->selectSingleNode(L"float_array");

			array_count = 0;
			memset(array_text, 0, SIZE_CHAR_MAX);
			wcstombs_s(&size, array_text, node->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
			array_count = atoi(array_text);
			if (array_count <= 0)
				continue;

			memset(stride_text, 0, SIZE_CHAR_MAX);
			MSXML2::IXMLDOMElementPtr node_format = source->selectSingleNode(L"technique_common/accessor");
			wcstombs_s(&size, stride_text, node_format->getAttribute("stride").bstrVal, SIZE_CHAR_MAX);
			stride = atoi(stride_text);

			int value_count = array_count / stride;
			if (is_vertex == true)
				gmt->VertexCount = value_count;

			int length = array_count * FLOAT_STRING_SIZE;
			float_data = new CVector(sizeof(float));

			value_text = new char[length];
			memset(value_text, 0, length);
			wcstombs_s(&size, value_text, length, node->Gettext(), length - 1);
			char *tmp = strtok_s(value_text, " ", &ctx);
			float value = (float)atof(tmp);
			float_data->Push((void *)&value);
			for (int m = 1; m <= array_count; m++){
				tmp = strtok_s(NULL, " ", &ctx);
				if (tmp == NULL)
					break;
				value = (float)atof(tmp);
				float_data->Push((void *)&value);
			}
			delete[] value_text;

			if (stride == 3){
				CVector *vector_float3 = new CVector(sizeof(float3));
				int cnt = 0;
				while (cnt < array_count){
					float3 value;
					value.x = *(float *)float_data->GetData(cnt);
					value.y = *(float *)float_data->GetData(cnt + 1);
					value.z = *(float *)float_data->GetData(cnt + 2);
					cnt += 3;
					vector_float3->Push((void *)&value);

					value.x = 0.0f;
					value.y = 0.0f;
					value.z = 0.0f;
				}
				float_array->FloatData = vector_float3;
			}
			else if (stride == 2){
				CVector *vector_float2 = new CVector(sizeof(float2));
				int cnt = 0;
				while (cnt < array_count){
					float2 value;
					value.x = *(float *)float_data->GetData(cnt);
					value.y = *(float *)float_data->GetData(cnt + 1);
					cnt += 2;
					vector_float2->Push((void *)&value);

					value.x = 0.0f;
					value.y = 0.0f;
				}
				float_array->FloatData = vector_float2;
			}

			gmt->VecFloatArray->Push((void *)&float_array);

			delete float_data;
		}

		//////////////////////////////////////////////////////////

		mesh_list = mesh->selectNodes(L"polylist");
		if ((int)mesh_list->Getlength() <= 0)
			mesh_list = mesh->selectNodes(L"triangles");
		for (int k = 0; k <= (int)mesh_list->Getlength() - 1; k++){

			//ポリゴンのインデックス取得

			MSXML2::IXMLDOMElementPtr polylist = mesh_list->Getitem(k);

			pgn_data = new CPolygonData();
			int vertex_offset = -1;
			int normal_offset = -1;
			int tex_offset = -1;
			int color_offset = -1;

			if (polylist->getAttribute("material").bstrVal != NULL)
				wcscpy_s(pgn_data->MaterialID, SIZE_CHAR_MAX, polylist->getAttribute("material").bstrVal);

			MSXML2::IXMLDOMNodeListPtr input_list = polylist->selectNodes(L"input");
			int max_offset = 0;
			for (int l = 0; l <= (int)input_list->Getlength() - 1; l++){
				MSXML2::IXMLDOMElementPtr input = input_list->Getitem(l);

				memset(semantic_text, 0, SIZE_CHAR_MAX);
				memset(source_text, 0, SIZE_CHAR_MAX);
				memset(offset_text, 0, SIZE_CHAR_MAX);

				wcscpy_s(semantic_text, SIZE_CHAR_MAX, input->getAttribute("semantic").bstrVal);
				wcscpy_s(source_text, SIZE_CHAR_MAX, input->getAttribute("source").bstrVal + 1);
				wcstombs_s(&size, offset_text, input->getAttribute("offset").bstrVal, SIZE_CHAR_MAX);
				int offset = atoi(offset_text);

				if (wcscmp(semantic_text, L"VERTEX") == 0){
					wcscpy_s(pgn_data->VertexID, SIZE_CHAR_MAX, source_text);
					vertex_offset = offset;
				}
				if (wcscmp(semantic_text, L"NORMAL") == 0){
					wcscpy_s(pgn_data->NormalID, SIZE_CHAR_MAX, source_text);
					normal_offset = offset;
				}
				if (wcscmp(semantic_text, L"TEXCOORD") == 0){
					pgn_data->TexID->Push((void *)source_text); //メッシュに複数のTEXCOORDが登録されているケースを想定。
					tex_offset = offset;
				}
				if (wcscmp(semantic_text, L"COLOR") == 0){
					wcscpy_s(pgn_data->ColorID, SIZE_CHAR_MAX, source_text);
					color_offset = offset;
				}
				if (offset > max_offset)
					max_offset = offset;
			}
			max_offset += 1;

			int p_count = polylist->getAttribute("count");
			MSXML2::IXMLDOMElementPtr index_array = polylist->selectSingleNode(L"p");
			CVector *index_tmp = new CVector(sizeof(int));

			int length = p_count * INDEX_STRING_SIZE;
			char *p_text = new char[length];
			memset(p_text, 0, length);
			wcstombs_s(&size, p_text, length, index_array->Gettext(), length - 1);

			char *tmp = strtok_s(p_text, " ", &ctx);
			int index = atoi(tmp);
			index_tmp->Push((void *)&index);
			do{
				tmp = strtok_s(NULL, " ", &ctx);
				if (tmp == NULL){
					break;
				}
				index = atoi(tmp);
				index_tmp->Push((void *)&index);
			} while (tmp != NULL);

			delete[] p_text;

			for (int j = 0; j <= index_tmp->PushPos - 1; j += max_offset){
				if (vertex_offset >= 0){
					pgn_data->VertexIndex->Push(index_tmp->GetData(j + vertex_offset));
				}
				if (normal_offset >= 0){
					pgn_data->NormalIndex->Push(index_tmp->GetData(j + normal_offset));
				}
				if (tex_offset >= 0){
					pgn_data->TexIndex->Push(index_tmp->GetData(j + tex_offset));
				}
				if (color_offset >= 0){
					pgn_data->ColorIndex->Push(index_tmp->GetData(j + color_offset));
				}
			}

			gmt->PolygonData->Push((void *)&pgn_data);

			delete index_tmp;
		}
		Geometry->Push((void *)&gmt);
	}

	return true;
}

bool CChaDataObject::LoadTransform(MSXML2::IXMLDOMDocumentPtr pDoc){

	//ボーンツリーをロードする。

	MSXML2::IXMLDOMNodeListPtr node_list = NULL;
	node_list = pDoc->selectNodes(L"COLLADA/library_visual_scenes/visual_scene/node");
	for (int i = 0; i <= (int)node_list->Getlength() - 1; i++){

		MSXML2::IXMLDOMElementPtr node = node_list->Getitem(i);
		if (node == NULL)
			continue;

		wchar_t *val = node->getAttribute("sid").bstrVal;
		CBone *bone = FindBone(val);
		if (bone == NULL)
			bone = new CBone();

		wchar_t *str = node->getAttribute("id").bstrVal;
		wcscpy_s(bone->ID, SIZE_CHAR_MAX, str);

		str = node->getAttribute("type").bstrVal;
		if (str != NULL){
			if (wcscmp(str, L"NODE") == 0)
				bone->Type = BONE_TYPE_NODE;
			else if (wcscmp(str, L"JOINT") == 0)
				bone->Type = BONE_TYPE_JOINT;
			else
				bone->Type = BONE_TYPE_UNKNOWN;
		}

		MSXML2::IXMLDOMElementPtr joint_matrix = node->selectSingleNode(L"matrix[@sid='transform']");
		if (joint_matrix != NULL){

			char matrix_text[SIZE_CHAR_MAX];

			size_t size;
			wcstombs_s(&size, matrix_text, joint_matrix->Gettext(), SIZE_CHAR_MAX);
			if ((int)strlen(matrix_text) > 0){

				float array[16];
				memset(array, 0, 16 * sizeof(float));
				char *ctx;
				char *tmp = strtok_s(matrix_text, " ", &ctx);
				int count = 0;
				array[count] = (float)atof(tmp);
				do{
					tmp = strtok_s(NULL, " ", &ctx);
					if (tmp == NULL)
						break;
					count++;
					array[count] = (float)atof(tmp);
				} while (tmp != NULL);

				memcpy_s(&bone->JointParam, sizeof(matrix), array, sizeof(matrix));
			}
		}
		ControlBone->Push((void *)&bone);

		LoadTransform(node, bone);
	}

	return true;
}

bool CChaDataObject::LoadTransform(MSXML2::IXMLDOMElementPtr parent_node, CBone *parent){

	MSXML2::IXMLDOMNodeListPtr node_list = parent_node->selectNodes(L"node");
	for (int i = 0; i <= (int)node_list->Getlength() - 1; i++){

		MSXML2::IXMLDOMElementPtr node = node_list->Getitem(i);
		if (node == NULL)
			continue;

		wchar_t *val = node->getAttribute("sid").bstrVal;
		CBone *bone = FindBone(val);
		if (bone == NULL)
			bone = new CBone();

		wchar_t *str = node->getAttribute("id").bstrVal;
		wcscpy_s(bone->ID, SIZE_CHAR_MAX, str);

		str = node->getAttribute("type").bstrVal;
		if (str != NULL){
			if (wcscmp(str, L"NODE") == 0)
				bone->Type = BONE_TYPE_NODE;
			else if (wcscmp(str, L"JOINT") == 0)
				bone->Type = BONE_TYPE_JOINT;
			else
				bone->Type = BONE_TYPE_UNKNOWN;
		}

		MSXML2::IXMLDOMElementPtr joint_matrix = node->selectSingleNode(L"matrix[@sid='transform']");
		if (joint_matrix != NULL){

			char matrix_text[SIZE_CHAR_MAX];

			size_t size;
			wcstombs_s(&size, matrix_text, joint_matrix->Gettext(), SIZE_CHAR_MAX);
			if ((int)strlen(matrix_text) > 0){

				float array[16];
				memset(array, 0, 16 * sizeof(float));
				char *ctx;
				char *tmp = strtok_s(matrix_text, " ", &ctx);
				int count = 0;
				array[count] = (float)atof(tmp);
				do{
					tmp = strtok_s(NULL, " ", &ctx);
					if (tmp == NULL)
						break;
					count++;
					array[count] = (float)atof(tmp);
				} while (tmp != NULL);

				memcpy_s(&bone->JointParam, sizeof(matrix), array, sizeof(matrix));
			}
		}

		bone->ParentBone = parent;
		parent->ChildBone->Push((void *)&bone);
		LoadTransform(node, bone);
	}

	return true;
}

CBone *CChaDataObject::FindBone(wchar_t *search_name){

	if (search_name == NULL)
		return NULL;

	for (int i = 0; i <= (int)BoneArray->PushPos - 1; i++){
		CBone *bone = *(CBone **)BoneArray->GetData(i);
		if (wcscmp(bone->Name, search_name) == 0)
			return bone;
	}

	return NULL;
}

bool CChaDataObject::LoadAnimation(MSXML2::IXMLDOMNodePtr pDoc){

	//アニメーションのロード

	CVector *float_array = new CVector(sizeof(CVector));
	CVector *name_array = new CVector(SIZE_CHAR_MAX);
	CVector *source_id = new CVector(SIZE_CHAR_MAX);

	MSXML2::IXMLDOMNodeListPtr animation_list = pDoc->selectNodes(L"COLLADA/library_animations/animation/animation");
	if (animation_list->Getlength() <= 0)
		animation_list = pDoc->selectNodes(L"COLLADA/library_animations/animation");

	CAnimation *anim = new CAnimation();
	wcscpy_s(anim->AnimatonID, SIZE_CHAR_MAX, COLLADA_ANIMATION_ID_DEFAULT);

	for (int i = 0; i <= (int)animation_list->Getlength() - 1; i++){

		source_id->Clear();
		name_array->Clear();
		float_array->Clear();

		MSXML2::IXMLDOMElementPtr animation = animation_list->Getitem(i);
		if (animation == NULL)
			continue;

		char animation_id[SIZE_CHAR_MAX];
		size_t size;
		memset(animation_id, 0, SIZE_CHAR_MAX);
		wcstombs_s(&size, animation_id, animation->getAttribute("id").bstrVal, SIZE_CHAR_MAX);

		char str[SIZE_CHAR_MAX];
		int float_array_count = -1;
		MSXML2::IXMLDOMNodeListPtr source_list = animation->selectNodes(L"source");

		for (int j = 0; j <= (int)source_list->Getlength() - 1; j++){

			MSXML2::IXMLDOMElementPtr source = source_list->Getitem(j);
			if (source == NULL)
				continue;

			CVector *vec = new CVector(sizeof(float));

			wchar_t src_id[SIZE_CHAR_MAX];
			wmemset(src_id, 0, SIZE_CHAR_MAX);
			wcscpy_s(src_id, SIZE_CHAR_MAX, source->getAttribute("id").bstrVal);
			source_id->Push((void *)src_id);

			MSXML2::IXMLDOMElementPtr array = source->selectSingleNode(L"float_array");
			if (array != NULL){
				int float_count = 0;
				memset(str, 0, SIZE_CHAR_MAX);
				wcstombs_s(&size, str, array->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
				float_count = atoi(str);

				int length = float_count * FLOAT_STRING_SIZE;
				char *text = new char[length];
				memset(text, 0, length);
				wcstombs_s(&size, text, length, array->Gettext(), length - 1);

				char *ctx;
				char *tmp = strtok_s(text, " ", &ctx);
				float value = (float)atof(tmp);
				vec->Push((void *)&value);
				for (int i = 0; i <= float_count - 1; i++){
					tmp = strtok_s(NULL, " ", &ctx);
					if (tmp == NULL)
						break;
					value = (float)atof(tmp);
					vec->Push((void *)&value);
				}
				delete[] text;

			}
			float_array->Push((void *)vec);

			array = source->selectSingleNode(L"Name_array");
			if (array != NULL){

				int float_count = 0;
				memset(str, 0, SIZE_CHAR_MAX);
				wcstombs_s(&size, str, array->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
				float_count = atoi(str);

				int length = float_count * SIZE_CHAR_MAX;
				wchar_t *text = new wchar_t[length];
				wmemset(text, 0, length);
				wcscpy_s(text, length - 1, array->Gettext());
				if ((int)wcslen(text) <= 0)
					continue;

				int count = 0;
				wchar_t *ctx;
				wchar_t *tmp = wcstok_s(text, L" ", &ctx);
				wchar_t name[SIZE_CHAR_MAX];
				wmemset(name, 0, SIZE_CHAR_MAX);
				wcscpy_s(name, SIZE_CHAR_MAX, tmp);
				name_array->Push((void *)name);
				do{
					tmp = wcstok_s(NULL, L" ", &ctx);
					if (tmp == NULL)
						break;
					wchar_t name[SIZE_CHAR_MAX];
					wmemset(name, 0, SIZE_CHAR_MAX);
					wcscpy_s(name, SIZE_CHAR_MAX, tmp);
					name_array->Push((void *)name);
				} while (tmp != NULL);

				delete[] text;
			}
		}

		MSXML2::IXMLDOMElementPtr channel = animation->selectSingleNode(L"channel");
		if (channel != NULL){
			wchar_t target[SIZE_CHAR_MAX];
			wmemset(target, 0, SIZE_CHAR_MAX);
			wcscpy_s(target, SIZE_CHAR_MAX, channel->getAttribute("target").bstrVal);

			wchar_t path[SIZE_CHAR_MAX];

			wmemset(path, 0, SIZE_CHAR_MAX);
			wcscpy_s(path, SIZE_CHAR_MAX, L"sampler[@id='");
			wcscat_s(path, SIZE_CHAR_MAX, channel->getAttribute("source").bstrVal + 1);
			wcscat_s(path, SIZE_CHAR_MAX, L"']/input[@semantic='INPUT']");
			MSXML2::IXMLDOMElementPtr input = animation->selectSingleNode(path);

			wmemset(path, 0, SIZE_CHAR_MAX);
			wcscpy_s(path, SIZE_CHAR_MAX, L"sampler[@id='");
			wcscat_s(path, SIZE_CHAR_MAX, channel->getAttribute("source").bstrVal + 1);
			wcscat_s(path, SIZE_CHAR_MAX, L"']/input[@semantic='OUTPUT']");
			MSXML2::IXMLDOMElementPtr output = animation->selectSingleNode(path);

			CBoneAnimation *bone_anim = new CBoneAnimation();

			int input_num = -1;
			if (input != NULL)
				input_num = FindName(source_id, input->getAttribute("source").bstrVal + 1);

			CVector *input_vec = (CVector *)float_array->GetData(input_num);
			if (input_vec == NULL)
				continue;

			for (int k = 0; k <= (int)input_vec->PushPos - 1; k++){
				float t = *(float *)input_vec->GetData(k);
				bone_anim->KeyTime->Push((void *)&t);
			}

			int output_num = -1;
			if (output != NULL)
				output_num = FindName(source_id, output->getAttribute("source").bstrVal + 1);

			CVector *output_vec = (CVector *)float_array->GetData(output_num);
			if (output_vec == NULL)
				continue;

			int p = 0;
			matrix pose_matrix;
			while (p < (int)output_vec->PushPos - 1){
				MatrixSet(&pose_matrix, *(float *)output_vec->GetData(p), *(float *)output_vec->GetData(p + 1), *(float *)output_vec->GetData(p + 2), *(float *)output_vec->GetData(p + 3),
					*(float *)output_vec->GetData(p + 4), *(float *)output_vec->GetData(p + 5), *(float *)output_vec->GetData(p + 6), *(float *)output_vec->GetData(p + 7),
					*(float *)output_vec->GetData(p + 8), *(float *)output_vec->GetData(p + 9), *(float *)output_vec->GetData(p + 10), *(float *)output_vec->GetData(p + 11),
					*(float *)output_vec->GetData(p + 12), *(float *)output_vec->GetData(p + 13), *(float *)output_vec->GetData(p + 14), *(float *)output_vec->GetData(p + 15));
				bone_anim->PoseMatrix->Push((void *)&pose_matrix);
				p += 16;
			}
			wcscpy_s(bone_anim->Target, SIZE_CHAR_MAX, target);
			for (int k = 0; k <= (int)wcslen(bone_anim->Target) - 1; k++){
				if (bone_anim->Target[k] == L'/'){
					wmemset(bone_anim->Target + k, 0, (int)wcslen(bone_anim->Target) - k);
				}
			}
			bone_anim->TargetBone = FindBoneByID(bone_anim->Target);

			anim->BoneAnimation->Push((void *)&bone_anim);
		}
	}
	AnimationList->Push((void *)&anim);

	delete float_array;
	delete name_array;
	delete source_id;

	return true;
}

int CChaDataObject::FindName(CVector *name_list, wchar_t *search_name){

	if (search_name == NULL || name_list == NULL)
		return NULL;

	for (int i = 0; i <= (int)name_list->PushPos - 1; i++){
		wchar_t *name = (wchar_t*)name_list->GetData(i);
		if (wcscmp(name, search_name) == 0)
			return i;
	}

	return -1;
}

CBone *CChaDataObject::FindBoneByID(wchar_t *search_name){

	if (search_name == NULL)
		return NULL;

	for (int i = 0; i <= (int)BoneArray->PushPos - 1; i++){
		CBone *bone = *(CBone **)BoneArray->GetData(i);
		if (wcscmp(bone->ID, search_name) == 0)
			return bone;
	}

	return NULL;
}

bool CChaDataObject::LoadController(MSXML2::IXMLDOMNodePtr pDoc){

	CVector *float_array = new CVector(sizeof(CVector));
	CVector *name_array = new CVector(SIZE_CHAR_MAX);
	CVector *source_id = new CVector(SIZE_CHAR_MAX);
	CVector *bind_array = new CVector(sizeof(float));

	MSXML2::IXMLDOMNodeListPtr controller_list = pDoc->selectNodes(L"COLLADA/library_controllers/controller");
	for (int i = 0; i <= (int)controller_list->Getlength() - 1; i++){

		float_array->Clear();
		name_array->Clear();
		source_id->Clear();
		bind_array->Clear();

		MSXML2::IXMLDOMElementPtr ctl = controller_list->Getitem(i);
		if (ctl == NULL)
			continue;

		MSXML2::IXMLDOMNodeListPtr mesh_list = ctl->selectNodes(L"skin");
		for (int j = 0; j <= (int)mesh_list->Getlength() - 1; j++){

			MSXML2::IXMLDOMElementPtr mesh = mesh_list->Getitem(j);

			int joint_count = 0;
			CGeometry *geometry = FindGeometry(mesh->getAttribute("source").bstrVal + 1);
			if (geometry == NULL)
				continue;

			MSXML2::IXMLDOMNodePtr bind_matrix = mesh->selectSingleNode(L"bind_shape_matrix");
			if (bind_matrix != NULL){

				int length = FLOAT_STRING_SIZE * 16;
				char *array_text = new char[length];
				memset(array_text, 0, length);

				size_t size;
				wcstombs_s(&size, array_text, length, bind_matrix->Gettext(), length);
				if ((int)strlen(array_text) <= 0)
					continue;

				char *ctx;
				char *tmp = strtok_s(array_text, " ", &ctx);
				float value = (float)atof(tmp);
				bind_array->Push((void *)&value);
				do{
					tmp = strtok_s(NULL, " ", &ctx);
					if (tmp == NULL)
						break;
					float value = (float)atof(tmp);
					bind_array->Push((void *)&value);
				} while (tmp != NULL);

				delete[] array_text;

				MatrixSet(&geometry->BindShapeMatrix, *(float *)bind_array->GetData(0), *(float *)bind_array->GetData(1), *(float *)bind_array->GetData(2), *(float *)bind_array->GetData(3),
					*(float *)bind_array->GetData(4), *(float *)bind_array->GetData(5), *(float *)bind_array->GetData(6), *(float *)bind_array->GetData(7),
					*(float *)bind_array->GetData(8), *(float *)bind_array->GetData(9), *(float *)bind_array->GetData(10), *(float *)bind_array->GetData(11),
					*(float *)bind_array->GetData(12), *(float *)bind_array->GetData(13), *(float *)bind_array->GetData(14), *(float *)bind_array->GetData(15));
				bind_array->Clear();
			}

			MSXML2::IXMLDOMNodeListPtr source_list = mesh->selectNodes(L"source");
			for (int k = 0; k <= (int)source_list->Getlength() - 1; k++){

				MSXML2::IXMLDOMElementPtr source = source_list->Getitem(k);
				if (source == NULL)
					continue;

				wchar_t source_name[SIZE_CHAR_MAX];
				wmemset(source_name, 0, SIZE_CHAR_MAX);
				wcscpy_s(source_name, SIZE_CHAR_MAX, source->getAttribute("id").bstrVal);
				source_id->Push((void *)source_name);

				CVector *vec = new CVector(sizeof(float));

				MSXML2::IXMLDOMElementPtr array = source->selectSingleNode(L"float_array");
				if (array != NULL){

					char str[SIZE_CHAR_MAX];
					memset(str, 0, SIZE_CHAR_MAX);

					size_t size;
					wcstombs_s(&size, str, SIZE_CHAR_MAX, array->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
					int float_count = atoi(str);

					int length = float_count * FLOAT_STRING_SIZE;
					char *array_text = new char[length];
					memset(array_text, 0, length);
					wcstombs_s(&size, array_text, length, array->Gettext(), length - 1);
					if ((int)strlen(array_text) <= 0)
						continue;

					char *ctx;
					char *tmp = strtok_s(array_text, " ", &ctx);
					float value = (float)atof(tmp);
					vec->Push((void *)&value);
					for (int m = 0; m <= float_count - 1; m++){
						tmp = strtok_s(NULL, " ", &ctx);
						if (tmp == NULL)
							break;
						float value = (float)atof(tmp);
						vec->Push((void *)&value);
					}
					delete[] array_text;
				}
				float_array->Push((void *)vec);

				array = source->selectSingleNode(L"Name_array");
				if (array != NULL){

					char str[SIZE_CHAR_MAX];
					memset(str, 0, SIZE_CHAR_MAX);

					size_t size;
					wcstombs_s(&size, str, array->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
					joint_count = atoi(str);

					int length = joint_count * FLOAT_STRING_SIZE;
					wchar_t *array_text = new wchar_t[length];
					wmemset(array_text, 0, length);
					wcscpy_s(array_text, length - 1, array->Gettext());
					if ((int)wcslen(array_text) <= 0){
						delete[] array_text;
						continue;
					}

					wchar_t *ctx;
					wchar_t *tmp = wcstok_s(array_text, L" ", &ctx);
					wchar_t name[SIZE_CHAR_MAX];
					wmemset(name, 0, SIZE_CHAR_MAX);
					wcscpy_s(name, SIZE_CHAR_MAX, tmp);
					name_array->Push((void *)name);
					do{
						tmp = wcstok_s(NULL, L" ", &ctx);
						if (tmp == NULL)
							break;
						wchar_t name[SIZE_CHAR_MAX];
						wmemset(name, 0, SIZE_CHAR_MAX);
						wcscpy_s(name, SIZE_CHAR_MAX, tmp);
						name_array->Push((void *)name);
					} while (tmp != NULL);
					delete[] array_text;
				}
			}

			MSXML2::IXMLDOMElementPtr joints = mesh->selectSingleNode(L"joints/input[@semantic='JOINT']");
			MSXML2::IXMLDOMElementPtr inv_matrix = mesh->selectSingleNode(L"joints/input[@semantic='INV_BIND_MATRIX']");
			MSXML2::IXMLDOMElementPtr vertex_weights = mesh->selectSingleNode(L"vertex_weights");
			MSXML2::IXMLDOMElementPtr vtx_joint = mesh->selectSingleNode(L"vertex_weights/input[@semantic='JOINT']");
			MSXML2::IXMLDOMElementPtr vtx_weight = mesh->selectSingleNode(L"vertex_weights/input[@semantic='WEIGHT']");
			MSXML2::IXMLDOMElementPtr vcount = mesh->selectSingleNode(L"vertex_weights/vcount");

			wchar_t joints_url[SIZE_CHAR_MAX];
			wmemset(joints_url, 0, SIZE_CHAR_MAX);
			wcscpy_s(joints_url, SIZE_CHAR_MAX, joints->getAttribute("source").bstrVal + 1);

			wchar_t inv_matrix_url[SIZE_CHAR_MAX];
			wmemset(inv_matrix_url, 0, SIZE_CHAR_MAX);
			wcscpy_s(inv_matrix_url, SIZE_CHAR_MAX, inv_matrix->getAttribute("source").bstrVal + 1);

			char str[SIZE_CHAR_MAX];
			memset(str, 0, SIZE_CHAR_MAX);

			size_t size;
			wcstombs_s(&size, str, vertex_weights->getAttribute("count").bstrVal, SIZE_CHAR_MAX);
			int weight_count = atoi(str);

			wchar_t joints_source[SIZE_CHAR_MAX];
			wmemset(joints_source, 0, SIZE_CHAR_MAX);
			wcscpy_s(joints_source, SIZE_CHAR_MAX, vtx_joint->getAttribute("source").bstrVal + 1);

			wchar_t weight_source[SIZE_CHAR_MAX];
			wmemset(weight_source, 0, SIZE_CHAR_MAX);
			wcscpy_s(weight_source, SIZE_CHAR_MAX, vtx_weight->getAttribute("source").bstrVal + 1);

			memset(str, 0, SIZE_CHAR_MAX);
			wcstombs_s(&size, str, vtx_joint->getAttribute("offset").bstrVal, SIZE_CHAR_MAX);
			int joint_offset = atoi(str);

			memset(str, 0, SIZE_CHAR_MAX);
			wcstombs_s(&size, str, vtx_weight->getAttribute("offset").bstrVal, SIZE_CHAR_MAX);
			int weight_offset = atoi(str);

			int offset = (joint_offset > weight_offset) ? joint_offset : weight_offset;
			int w_count = vertex_weights->getAttribute("count");

			//各ウェイトの保存領域を確保
			geometry->WeightCount = weight_count;
			geometry->Weights = (int64_t ***) new int64_t**[weight_count];
			for (int k = 0; k <= weight_count - 1; k++){
				geometry->Weights[k] = (int64_t **) new int64_t*[WEIGHT_BONE_APPLY_NUM];
				for (int l = 0; l <= WEIGHT_BONE_APPLY_NUM - 1; l++){
					geometry->Weights[k][l] = (int64_t *) new float2();
					memset(geometry->Weights[k][l], 0, sizeof(float2));
				}
			}

			int length = w_count * FLOAT_STRING_SIZE;
			char *v_count_text = new char[length];
			memset(v_count_text, 0, length);
			wcstombs_s(&size, v_count_text, length, vcount->Gettext(), length - 1);
			if ((int)strlen(v_count_text) <= 0)
				continue;

			int joint_num = FindName(source_id, joints_source);
			int weight_num = FindName(source_id, weight_source);

			int inv_matrix_num = FindName(source_id, inv_matrix_url);
			CVector *vec_inv = (CVector *)float_array->GetData(inv_matrix_num);
			int inv_count = 0;
			for (int l = 0; l <= (int)name_array->PushPos - 1; l++){

				CBone *bone = FindBone((wchar_t *)name_array->GetData(l));
				if (bone == NULL){
					bone = new CBone();
					wcscpy_s(bone->Name, SIZE_CHAR_MAX, (wchar_t *)name_array->GetData(l));
					int matrix_num = 0;
					if (inv_matrix_num >= 0){
						MatrixSet(&bone->InvBindMatrix, *((float *)vec_inv->GetData(inv_count)), *((float*)vec_inv->GetData(inv_count + 1)), *((float*)vec_inv->GetData(inv_count + 2)), *((float*)vec_inv->GetData(inv_count + 3)),
							*((float*)vec_inv->GetData(inv_count + 4)), *((float*)vec_inv->GetData(inv_count + 5)), *((float*)vec_inv->GetData(inv_count + 6)), *((float*)vec_inv->GetData(inv_count + 7)),
							*((float*)vec_inv->GetData(inv_count + 8)), *((float*)vec_inv->GetData(inv_count + 9)), *((float*)vec_inv->GetData(inv_count + 10)), *((float*)vec_inv->GetData(inv_count + 11)),
							*((float*)vec_inv->GetData(inv_count + 12)), *((float*)vec_inv->GetData(inv_count + 13)), *((float*)vec_inv->GetData(inv_count + 14)), *((float*)vec_inv->GetData(inv_count + 15)));
						inv_count += 16;
					}
					BoneArray->Push((void *)&bone);
				}
			}

			MSXML2::IXMLDOMElementPtr vtx = vertex_weights->selectSingleNode(L"v");
			length = FLOAT_STRING_SIZE * weight_count;
			char *v_text = new char[length];
			memset(v_text, 0, length);
			wcstombs_s(&size, v_text, length, vtx->Gettext(), length - 1);

			CVector *v_count_array = new CVector(sizeof(int));
			char *ctx;
			char *v_count_tmp = strtok_s(v_count_text, " ", &ctx);
			while (v_count_tmp != NULL){
				int value = atoi(v_count_tmp);
				v_count_array->Push((void *)&value);
				v_count_tmp = strtok_s(NULL, " ", &ctx);
				if (v_count_tmp == NULL)
					break;
			}

			CVector *v_array = new CVector(sizeof(int));
			char *v_tmp = strtok_s(v_text, " ", &ctx);
			while (v_tmp != NULL){
				int value = atoi(v_tmp);
				v_array->Push((void *)&value);
				v_tmp = strtok_s(NULL, " ", &ctx);
				if (v_tmp == NULL)
					break;
			}

			int count = 0;
			int index = 0;
			CVector *vec_weight = (CVector *)float_array->GetData(weight_num);
			for (int k = 0; k <= (int)v_count_array->PushPos - 1; k++){
				int v_count = *(int *)v_count_array->GetData(k);
				for (int l = 0; l <= v_count - 1; l++){
					int joint_num = *(int*)v_array->GetData(count);
					int w_num = *(int*)v_array->GetData(count + 1);
					float weight = *(float *)vec_weight->GetData(w_num);
					count += 2;
					InsertWeight(geometry, index, joint_num, weight);
				}
				index++;
			}

			delete v_array;
			delete v_count_array;
			delete[] v_count_text;
			delete[] v_text;
		}
	}

	return true;
}

bool CChaDataObject::InsertWeight(CGeometry *geometry, int index, int joint_num, float weight){

	int64_t ***weights = geometry->Weights;
	for (int i = 0; i <= WEIGHT_BONE_APPLY_NUM - 1; i++){
		float2 *w = (float2 *)weights[index][i];
		if (w->y + 0.000001f < weight){
			int j = WEIGHT_BONE_APPLY_NUM - 1;
			while (j > i){
				float2 *w_tmp1 = (float2 *)weights[index][j];
				float2 *w_tmp2 = (float2 *)weights[index][j - 1];
				w_tmp1->x = w_tmp2->x;
				w_tmp1->y = w_tmp2->y;
				j--;
			}
			w = (float2 *)weights[index][j];
			w->x = (float)joint_num;
			w->y = weight;
			break;
		}
	}

	return true;
}

CGeometry *CChaDataObject::FindGeometry(wchar_t *search_name){

	if (search_name == NULL)
		return NULL;

	for (int i = 0; i <= (int)Geometry->PushPos - 1; i++){
		if (wcscmp((wchar_t *)(*(CGeometry **)Geometry->GetData(i))->GeometryID, search_name) == 0)
			return *(CGeometry **)Geometry->GetData(i);
	}

	return NULL;
}

////////////////////////////////////////////////////////////////////////////

bool CChaDataObject::WriteModel(const wchar_t *modelname, const wchar_t *filename){

	//Chaモデルファイルを書き出す。

	FILE *fp = NULL;

	wchar_t out_file_name[SIZE_CHAR_MAX];
	wmemset(out_file_name, 0, SIZE_CHAR_MAX);
	wcscpy_s(out_file_name, SIZE_CHAR_MAX, filename);

	wchar_t ext[16];
	wmemset(ext, 0, 16);
	wmemcpy(ext, &out_file_name[wcslen(out_file_name) - 4], 4);
	if (wcscmp(ext, CHAMODEL_EXT_NAME) != 0 || wcscmp(ext, CHAMODEL_EXT_NAME) != 0){
		wcscat_s(out_file_name, SIZE_CHAR_MAX, CHAMODEL_EXT_NAME);
	}

	_wfopen_s(&fp, out_file_name, L"w");

	if (fp == NULL)
		return false;

	fwprintf_s(fp, L"[MODEL_ID]\n%s\n\n", modelname);

	fwprintf_s(fp, L"[COLLIDER_FILE_PATH]\n\n");

	fwprintf_s(fp, L"/////////////////////////// material //////////////////////////\n\n");

	for (int i = 0; i <= (int)Material->PushPos - 1; i++){
		CMaterial *material = *(CMaterial **)Material->GetData(i);
		fwprintf_s(fp, L"<MATERIAL_BEGIN>\n");
		fwprintf_s(fp, L"<MATERIAL_NAME>%s\n", material->MaterialName);
		fwprintf_s(fp, L"<TEXTURE_NAME>%s\n", material->TextureName);
		fwprintf_s(fp, L"<DIFFUSE>\n%.6f %.6f %.6f %.6f\n", material->diffuse.x, material->diffuse.y, material->diffuse.z, material->diffuse.w);
		fwprintf_s(fp, L"<AMBIENT>\n%.6f %.6f %.6f %.6f\n", material->ambient.x, material->ambient.y, material->ambient.z, material->ambient.w);
		fwprintf_s(fp, L"<SPECULAR>\n%.6f %.6f %.6f %.6f\n", material->specular.x, material->specular.y, material->specular.z, material->specular.w);
		fwprintf_s(fp, L"<EMMITION>\n%.6f %.6f %.6f %.6f\n", material->emmition.x, material->emmition.y, material->emmition.z, material->emmition.w);
		fwprintf_s(fp, L"<MATERIAL_END>\n\n");
	}

	fwprintf_s(fp, L"/////////////////////////// texture //////////////////////////\n\n");

	for (int i = 0; i <= (int)TextureName->PushPos - 1; i++){
		CTextureName *texture_name = *(CTextureName **)TextureName->GetData(i);
		fwprintf_s(fp, L"<TEXTURE_BEGIN>\n");
		fwprintf_s(fp, L"<TEXTURE_ID>%s\n", texture_name->TextureID);
		fwprintf_s(fp, L"<TEXTURE_NAME>%s\n", texture_name->TextureName);
		fwprintf_s(fp, L"<TEXTURE_END>\n\n");
	}

	fwprintf_s(fp, L"/////////////////////////// geometry //////////////////////////\n\n");

	for (int i = 0; i <= (int)Geometry->PushPos - 1; i++){

		CGeometry *gmt = *(CGeometry **)Geometry->GetData(i);

		fwprintf_s(fp, L"<GEOMETRY_BEGIN>\n");
		fwprintf_s(fp, L"<GEOMETRY_ID>%s\n", gmt->GeometryID);
		fwprintf_s(fp, L"<VERTEX_COUNT>%d\n", gmt->VertexCount);
		fwprintf_s(fp, L"<BIND_SHAPE_MATRIX>\n%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n",
			gmt->BindShapeMatrix.m11, gmt->BindShapeMatrix.m12, gmt->BindShapeMatrix.m13, gmt->BindShapeMatrix.m14,
			gmt->BindShapeMatrix.m21, gmt->BindShapeMatrix.m22, gmt->BindShapeMatrix.m23, gmt->BindShapeMatrix.m24,
			gmt->BindShapeMatrix.m31, gmt->BindShapeMatrix.m32, gmt->BindShapeMatrix.m33, gmt->BindShapeMatrix.m34,
			gmt->BindShapeMatrix.m41, gmt->BindShapeMatrix.m42, gmt->BindShapeMatrix.m43, gmt->BindShapeMatrix.m44);
		fwprintf_s(fp, L"<FLOAT_ARRAY_SIZE>%d\n", (int) gmt->VecFloatArray->PushPos);

		for (int j = 0; j <= (int)gmt->VecFloatArray->PushPos - 1; j++){
			CFloatArray *float_data = *(CFloatArray **)gmt->VecFloatArray->GetData(j);
			int float_count = (int)(float_data->FloatData->DataSize / sizeof(float));
			fwprintf_s(fp, L"<FLOAT_ARRAY_BEGIN>\n");
			fwprintf_s(fp, L"<FLOAT_ARRAY_ID>%s\n", float_data->ID);
			fwprintf_s(fp, L"<FLOAT_ARRAY_FLOAT_COUNT>%d\n", float_count);
			fwprintf_s(fp, L"<FLOAT_ARRAY_COUNT>%d\n", (int) float_data->FloatData->PushPos);
			fwprintf_s(fp, L"<FLOAT_ARRAY>\n");
			for (int k = 0; k <= float_data->FloatData->PushPos - 1; k++){
				if (float_count == 2){
					float2 *data = (float2*)float_data->FloatData->GetData(k);
					fwprintf_s(fp, L"%.6f %.6f ", data->x, data->y);
				}
				else if (float_count == 3){
					float3 *data = (float3*)float_data->FloatData->GetData(k);
					fwprintf_s(fp, L"%.6f %.6f %.6f ", data->x, data->y, data->z);
				}
				else if (float_count == 4){
					float4 *data = (float4*)float_data->FloatData->GetData(k);
					fwprintf_s(fp, L"%.6f %.6f %.6f %.6f ", data->x, data->y, data->z, data->w);
				}
			}
			fwprintf_s(fp, L"\n<FLOAT_ARRAY_END>\n");
			fwprintf_s(fp, L"\n");
		}
		fwprintf_s(fp, L"\n");

		for (int j = 0; j <= (int)gmt->PolygonData->PushPos - 1; j++){

			CPolygonData *pgn_data = *(CPolygonData **)gmt->PolygonData->GetData(j);

			fwprintf_s(fp, L"<POLYGON_DATA_BEGIN>\n");
			fwprintf_s(fp, L"<MATERIAL_ID>%s\n", pgn_data->MaterialID);
			fwprintf_s(fp, L"<VERTEX_ID>%s\n", pgn_data->VertexID);
			fwprintf_s(fp, L"<NORMAL_ID>%s\n", pgn_data->NormalID);
			fwprintf_s(fp, L"<COLOR_ID>%s\n", pgn_data->ColorID);

			fwprintf_s(fp, L"<VERTEX_INDEX_COUNT>%d\n", (int) pgn_data->VertexIndex->PushPos);
			for (int k = 0; k <= pgn_data->VertexIndex->PushPos - 1; k++){
				int index = *(int*)pgn_data->VertexIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<NORMAL_INDEX_COUNT>%d\n", (int) pgn_data->NormalIndex->PushPos);
			for (int k = 0; k <= pgn_data->NormalIndex->PushPos - 1; k++){
				int index = *(int*)pgn_data->NormalIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<COLOR_INDEX_COUNT>%d\n", (int) pgn_data->ColorIndex->PushPos);
			for (int k = 0; k <= pgn_data->ColorIndex->PushPos - 1; k++){
				int index = *(int*)pgn_data->ColorIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<TEX_INDEX_COUNT>%d\n", (int) pgn_data->TexIndex->PushPos);
			for (int k = 0; k <= pgn_data->TexIndex->PushPos - 1; k++){
				int index = *(int*)pgn_data->TexIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<TEX_ID_COUNT>%d\n", (int) pgn_data->TexID->PushPos);
			for (int k = 0; k <= pgn_data->TexID->PushPos - 1; k++){
				wchar_t *tex_id = (wchar_t *)pgn_data->TexID->GetData(k);
				fwprintf_s(fp, L"%s ", tex_id);
			}
			fwprintf_s(fp, L"\n");
			fwprintf_s(fp, L"<POLYGON_DATA_END>\n\n");
		}
		fwprintf_s(fp, L"\n");

		fwprintf_s(fp, L"/////////////////////////// weights //////////////////////////\n\n");

		fwprintf_s(fp, L"<WEIGHTS_BEGIN>\n");
		fwprintf_s(fp, L"<WEIGHTS_SIZE>%d\n", gmt->WeightCount);
		fwprintf_s(fp, L"<APPLY_BONE_NUM>%d\n", WEIGHT_BONE_APPLY_NUM);
		for (int j = 0; j <= (int)gmt->WeightCount - 1; j++){
			for (int k = 0; k <= WEIGHT_BONE_APPLY_NUM - 1; k++){
				float2 *weight = (float2 *)gmt->Weights[j][k];
				fwprintf_s(fp, L"%.6f %.6f ", weight->x, weight->y);
			}
		}
		fwprintf_s(fp, L"\n<WEIGHTS_END>\n");
		fwprintf_s(fp, L"\n<GEOMETRY_END>\n\n");
	}

	fwprintf_s(fp, L"/////////////////////////// bone //////////////////////////\n\n");

	fwprintf_s(fp, L"<BONE_ARRAY>\n");
	for (int i = 0; i <= BoneArray->PushPos - 1; i++){
		CBone *bone = *(CBone **)BoneArray->GetData(i);
		fwprintf_s(fp, L"%s ", bone->Name);
	}
	fwprintf_s(fp, L"\n");
	int tab = 0;
	for (int i = 0; i <= (int)ControlBone->PushPos - 1; i++){
		CBone *bone = *(CBone **)ControlBone->GetData(i);

		fwprintf_s(fp, L"<BONE>\n");
		fwprintf_s(fp, L"<BONE_BEGIN>\n");
		fwprintf_s(fp, L"<BONE_NAME>%s\n", bone->Name);
		fwprintf_s(fp, L"<BONE_ID>%s\n", bone->ID);
		fwprintf_s(fp, L"<BONE_TYPE>%d\n", bone->Type);
		fwprintf_s(fp, L"<INV_BIND_MATRIX>\n%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n",
			bone->InvBindMatrix.m11, bone->InvBindMatrix.m12, bone->InvBindMatrix.m13, bone->InvBindMatrix.m14,
			bone->InvBindMatrix.m21, bone->InvBindMatrix.m22, bone->InvBindMatrix.m23, bone->InvBindMatrix.m24,
			bone->InvBindMatrix.m31, bone->InvBindMatrix.m32, bone->InvBindMatrix.m33, bone->InvBindMatrix.m34,
			bone->InvBindMatrix.m41, bone->InvBindMatrix.m42, bone->InvBindMatrix.m43, bone->InvBindMatrix.m44);
		fwprintf_s(fp, L"<JOINT_MATRIX>\n%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n",
			bone->JointParam.m11, bone->JointParam.m12, bone->JointParam.m13, bone->JointParam.m14,
			bone->JointParam.m21, bone->JointParam.m22, bone->JointParam.m23, bone->JointParam.m24,
			bone->JointParam.m31, bone->JointParam.m32, bone->JointParam.m33, bone->JointParam.m34,
			bone->JointParam.m41, bone->JointParam.m42, bone->JointParam.m43, bone->JointParam.m44);
		fwprintf_s(fp, L"<CHILD_COUNT>%d\n", (int) bone->ChildBone->PushPos);
		for (int i = 0; i <= (int)bone->ChildBone->PushPos - 1; i++){
			CBone *child_bone = *(CBone **)bone->ChildBone->GetData(i);
			WriteChildBone(fp, child_bone, tab + 1);
		}
		fwprintf_s(fp, L"<BONE_END>\n");
	}
	fwprintf_s(fp, L"\n\n");

	fclose(fp);

	return true;
}

bool CChaDataObject::WriteChildBone(FILE *fp, CBone *bone, int tab){

	wchar_t TAB[SIZE_CHAR_MAX];
	wmemset(TAB, 0, SIZE_CHAR_MAX);
	for (int i = 0; i <= tab; i++){
		wcscat_s(TAB, SIZE_CHAR_MAX, L"\t");
	}

	fwprintf_s(fp, L"%s<BONE_BEGIN>\n", TAB);
	fwprintf_s(fp, L"%s<BONE_NAME>%s\n", TAB, bone->Name);
	fwprintf_s(fp, L"%s<BONE_ID>%s\n", TAB, bone->ID);
	fwprintf_s(fp, L"%s<BONE_TYPE>%d\n", TAB, bone->Type);
	fwprintf_s(fp, L"%s<INV_BIND_MATRIX>\n%s%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n", TAB, TAB,
		bone->InvBindMatrix.m11, bone->InvBindMatrix.m12, bone->InvBindMatrix.m13, bone->InvBindMatrix.m14,
		bone->InvBindMatrix.m21, bone->InvBindMatrix.m22, bone->InvBindMatrix.m23, bone->InvBindMatrix.m24,
		bone->InvBindMatrix.m31, bone->InvBindMatrix.m32, bone->InvBindMatrix.m33, bone->InvBindMatrix.m34,
		bone->InvBindMatrix.m41, bone->InvBindMatrix.m42, bone->InvBindMatrix.m43, bone->InvBindMatrix.m44);
	fwprintf_s(fp, L"%s<JOINT_MATRIX>\n%s%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n", TAB, TAB,
		bone->JointParam.m11, bone->JointParam.m12, bone->JointParam.m13, bone->JointParam.m14,
		bone->JointParam.m21, bone->JointParam.m22, bone->JointParam.m23, bone->JointParam.m24,
		bone->JointParam.m31, bone->JointParam.m32, bone->JointParam.m33, bone->JointParam.m34,
		bone->JointParam.m41, bone->JointParam.m42, bone->JointParam.m43, bone->JointParam.m44);
	fwprintf_s(fp, L"%s<CHILD_COUNT>%d\n", TAB, (int) bone->ChildBone->PushPos);
	for (int i = 0; i <= (int)bone->ChildBone->PushPos - 1; i++){
		CBone *child_bone = *(CBone **)bone->ChildBone->GetData(i);
		WriteChildBone(fp, child_bone, tab + 1);
	}
	fwprintf_s(fp, L"%s<BONE_END>\n", TAB);

	return true;
}

bool CChaDataObject::LoadModel(wchar_t *filename){

	//Chaモデルファイルを読み込む。

	FILE *fp = NULL;

	wchar_t out_file_name[SIZE_CHAR_MAX];
	wmemset(out_file_name, 0, SIZE_CHAR_MAX);
	wcscpy_s(out_file_name, SIZE_CHAR_MAX, filename);

	_wfopen_s(&fp, out_file_name, L"r");

	if (fp == NULL)
		return false;

	CMaterial *material = NULL;
	CTextureName *texture = NULL;
	CGeometry *gmt = NULL;
	CFloatArray *float_array = NULL;
	CPolygonData *pgn_data = NULL;
	CBone *bone = NULL;

	char line[SIZE_CHAR_MAX];
	wchar_t* w_ctx = NULL;
	wchar_t w_line[SIZE_CHAR_MAX];
	wchar_t param1[SIZE_CHAR_MAX];
	wchar_t param2[SIZE_CHAR_MAX];

	wmemset(ColliderFilePath, 0, SIZE_CHAR_MAX);

	int mode = READ_MODE_INIT;
	size_t size;
	while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

		wmemset(param1, 0, SIZE_CHAR_MAX);
		wmemset(param2, 0, SIZE_CHAR_MAX);
		GetParamW(w_line, param1, param2, L" []<>\n");

		if (wcscmp(param1, L"MODEL_ID") == 0){
			fgetws(w_line, SIZE_CHAR_MAX, fp);
			GetParamW(w_line, param1, param2, L" \n");
			wcscpy_s(ModelID, SIZE_CHAR_MAX, param1);

			continue;
		}
		if (wcscmp(param1, L"COLLIDER_FILE_PATH") == 0) {
			fgetws(w_line, SIZE_CHAR_MAX, fp);
			GetParamW(w_line, param1, param2, L" \n");
			wcscpy_s(ColliderFilePath, SIZE_CHAR_MAX, param1);

			continue;
		}
		if (wcscmp(param1, L"MATERIAL_BEGIN") == 0){

			//マテリアルブロックをロード
			material = new CMaterial();

			while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

				wmemset(param1, 0, SIZE_CHAR_MAX);
				wmemset(param2, 0, SIZE_CHAR_MAX);
				GetParamW(w_line, param1, param2, L" []<>\n");

				float r = 0.0f;
				float g = 0.0f;
				float b = 0.0f;
				float a = 0.0f;

				if (wcscmp(param1, L"MATERIAL_NAME") == 0)
					wcscpy_s(material->MaterialName, SIZE_CHAR_MAX, param2);
				if (wcscmp(param1, L"TEXTURE_NAME") == 0)
					wcscpy_s(material->TextureName, SIZE_CHAR_MAX, param2);
				if (wcscmp(param1, L"DIFFUSE") == 0){

					char* ctx = NULL;
					fgets(line, SIZE_CHAR_MAX, fp);
					char *tmp = strtok_s(line, " \n", &ctx);
					r = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					g = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					b = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					a = (float)atof(tmp);
					material->diffuse.x = r;
					material->diffuse.y = g;
					material->diffuse.z = b;
					material->diffuse.w = a;
				}
				if (wcscmp(param1, L"AMBIENT") == 0){

					char* ctx = NULL;
					fgets(line, SIZE_CHAR_MAX, fp);
					char *tmp = strtok_s(line, " \n", &ctx);
					r = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					g = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					b = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					a = (float)atof(tmp);
					material->ambient.x = r;
					material->ambient.y = g;
					material->ambient.z = b;
					material->ambient.w = a;
				}
				if (wcscmp(param1, L"SPECULAR") == 0){

					char* ctx = NULL;
					fgets(line, SIZE_CHAR_MAX, fp);
					char *tmp = strtok_s(line, " \n", &ctx);
					r = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					g = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					b = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					a = (float)atof(tmp);
					material->specular.x = r;
					material->specular.y = g;
					material->specular.z = b;
					material->specular.w = a;
				}
				if (wcscmp(param1, L"EMMITION") == 0){

					char* ctx = NULL;
					fgets(line, SIZE_CHAR_MAX, fp);
					char *tmp = strtok_s(line, " \n", &ctx);
					r = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					g = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					b = (float)atof(tmp);
					tmp = strtok_s(NULL, " \n", &ctx);
					a = (float)atof(tmp);
					material->emmition.x = r;
					material->emmition.y = g;
					material->emmition.z = b;
					material->emmition.w = a;
				}
				if (wcscmp(param1, L"MATERIAL_END") == 0){
					Material->Push((void *)&material);
					break;
				}
			}

			continue;
		}
		if (wcscmp(param1, L"TEXTURE_BEGIN") == 0){

			//テクスチャブロックをロード

			texture = new CTextureName();

			while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

				memset(param1, 0, SIZE_CHAR_MAX);
				memset(param2, 0, SIZE_CHAR_MAX);
				GetParamW(w_line, param1, param2, L" []<>\n");

				if (wcscmp(param1, L"TEXTURE_ID") == 0)
					wcscpy_s(texture->TextureID, SIZE_CHAR_MAX, param2);
				if (wcscmp(param1, L"TEXTURE_NAME") == 0)
					wcscpy_s(texture->TextureName, SIZE_CHAR_MAX, param2);
				if (wcscmp(param1, L"TEXTURE_END") == 0){
					TextureName->Push((void *)&texture);
					break;
				}
			}
		}
		if (wcscmp(param1, L"GEOMETRY_BEGIN") == 0){

			//ジオメトリをロード

			gmt = new CGeometry();

			while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

				wmemset(param1, 0, SIZE_CHAR_MAX);
				wmemset(param2, 0, SIZE_CHAR_MAX);
				GetParamW(w_line, param1, param2, L" []<>\n");

				if (wcscmp(param1, L"GEOMETRY_ID") == 0)
					wcscpy_s(gmt->GeometryID,SIZE_CHAR_MAX, param2);
				if (wcscmp(param1, L"VERTEX_COUNT") == 0)
					gmt->VertexCount = _wtoi(param2);
				if (wcscmp(param1, L"BIND_SHAPE_MATRIX") == 0){
					char tmp_line[FLOAT_STRING_SIZE * 16];
					memset(tmp_line, 0, FLOAT_STRING_SIZE * 16);
					fgets(tmp_line, FLOAT_STRING_SIZE * 16, fp);

					float m[16];
					char* ctx = NULL;
					memset(m, 0, sizeof(float)* 16);
					char *tmp = strtok_s(tmp_line, " \n", &ctx);
					m[0] = (float)atof(tmp);
					for (int i = 1; i <= 15; i++){
						tmp = strtok_s(NULL, " \n", &ctx);
						m[i] = (float)atof(tmp);
					}
					MatrixSet(&gmt->BindShapeMatrix, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
				}
				if (wcscmp(param1, L"FLOAT_ARRAY_BEGIN") == 0){

					//バーテックス値をロード

					float_array = new CFloatArray();
					int float_count = -1;
					int vertex_count = -1;

					while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

						wmemset(param1, 0, SIZE_CHAR_MAX);
						wmemset(param2, 0, SIZE_CHAR_MAX);
						GetParamW(w_line, param1, param2, L" <>\n");

						if (wcscmp(param1, L"FLOAT_ARRAY_ID") == 0)
							wcscpy_s(float_array->ID, SIZE_CHAR_MAX, param2);
						if (wcscmp(param1, L"FLOAT_ARRAY_FLOAT_COUNT") == 0)
							float_count = _wtoi(param2);
						if (wcscmp(param1, L"FLOAT_ARRAY_COUNT") == 0)
							vertex_count = _wtoi(param2);
						if (wcscmp(param1, L"FLOAT_ARRAY") == 0){
							if (float_count >= 0 && vertex_count >= 0){

								CVector *float_data = NULL;
								if (float_count == 2)
									float_data = new CVector(sizeof(float2));
								else if (float_count == 3)
									float_data = new CVector(sizeof(float3));
								else if (float_count == 4)
									float_data = new CVector(sizeof(float4));
								else
									float_data = new CVector(sizeof(float));

								char *tmp_line = new char[FLOAT_STRING_SIZE * vertex_count * float_count];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * vertex_count * float_count);
								fgets(tmp_line, FLOAT_STRING_SIZE * vertex_count * float_count, fp);

								float *data = new float[vertex_count * float_count];
								memset(data, 0, sizeof(float)* vertex_count * float_count);

								char* ctx = NULL;
								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int count = 0;
								data[count] = (float)atof(tmp);
								while (count <= vertex_count * float_count){
									count++;
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									data[count] = (float)atof(tmp);
								}

								for (int i = 0; i <= vertex_count * float_count - 1; i += float_count){
									if (float_count == 2){
										float2 value;
										value.x = data[i];
										value.y = data[i + 1];
										float_data->Push((void *)&value);
									}
									if (float_count == 3){
										float3 value;
										value.x = data[i];
										value.y = data[i + 1];
										value.z = data[i + 2];
										float_data->Push((void *)&value);
									}
									if (float_count == 4){
										float4 value;
										value.x = data[i];
										value.y = data[i + 1];
										value.z = data[i + 2];
										value.w = data[i + 3];
										float_data->Push((void *)&value);
									}
								}
								float_array->FloatData = float_data;

								delete[] data;
								delete[] tmp_line;
							}
						}
						if (wcscmp(param1, L"FLOAT_ARRAY_END") == 0){
							gmt->VecFloatArray->Push((void *)&float_array);
							break;
						}
					}
				}

				if (wcscmp(param1, L"POLYGON_DATA_BEGIN") == 0){

					//ポリゴンブロックをロード

					pgn_data = new CPolygonData();

					while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

						wmemset(param1, 0, SIZE_CHAR_MAX);
						wmemset(param2, 0, SIZE_CHAR_MAX);
						GetParamW(w_line, param1, param2, L" <>\n");
						if (wcscmp(param1, L"MATERIAL_ID") == 0)
							wcscpy_s(pgn_data->MaterialID, SIZE_CHAR_MAX, param2);
						if (wcscmp(param1, L"VERTEX_ID") == 0)
							wcscpy_s(pgn_data->VertexID, SIZE_CHAR_MAX, param2);
						if (wcscmp(param1, L"NORMAL_ID") == 0)
							wcscpy_s(pgn_data->NormalID,SIZE_CHAR_MAX, param2);
						if (wcscmp(param1, L"COLOR_ID") == 0)
							wcscpy_s(pgn_data->ColorID,SIZE_CHAR_MAX, param2);
						if (wcscmp(param1, L"VERTEX_INDEX_COUNT") == 0){
							int count = _wtoi(param2);
							if (count > 0){
								char* ctx = NULL;
								char *tmp_line = new char[FLOAT_STRING_SIZE * count];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * count);
								fgets(tmp_line, FLOAT_STRING_SIZE * count, fp);
								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int index = atoi(tmp);
								pgn_data->VertexIndex->Push((void *)&index);
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									index = atoi(tmp);
									pgn_data->VertexIndex->Push((void *)&index);
								} while (tmp != NULL);
								delete[] tmp_line;
							}
						}
						if (wcscmp(param1, L"NORMAL_INDEX_COUNT") == 0){
							int count = _wtoi(param2);
							if (count > 0){
								char* ctx = NULL;
								char *tmp_line = new char[FLOAT_STRING_SIZE * count];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * count);
								fgets(tmp_line, FLOAT_STRING_SIZE * count, fp);
								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int index = atoi(tmp);
								pgn_data->NormalIndex->Push((void *)&index);
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									index = atoi(tmp);
									pgn_data->NormalIndex->Push((void *)&index);
								} while (tmp != NULL);
								delete[] tmp_line;
							}
						}
						if (wcscmp(param1, L"COLOR_INDEX_COUNT") == 0){
							int count = _wtoi(param2);
							if (count > 0){
								char* ctx = NULL;
								char *tmp_line = new char[FLOAT_STRING_SIZE * count];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * count);
								fgets(tmp_line, FLOAT_STRING_SIZE * count, fp);
								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int index = atoi(tmp);
								pgn_data->ColorIndex->Push((void *)&index);
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									index = atoi(tmp);
									pgn_data->ColorIndex->Push((void *)&index);
								} while (tmp != NULL);
								delete[] tmp_line;
							}
						}
						if (wcscmp(param1, L"TEX_INDEX_COUNT") == 0){
							int count = _wtoi(param2);
							if (count > 0){
								char* ctx = NULL;
								char *tmp_line = new char[FLOAT_STRING_SIZE * count];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * count);
								fgets(tmp_line, FLOAT_STRING_SIZE * count, fp);
								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int index = atoi(tmp);
								pgn_data->TexIndex->Push((void *)&index);
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									index = atoi(tmp);
									pgn_data->TexIndex->Push((void *)&index);
								} while (tmp != NULL);
								delete[] tmp_line;
							}
						}
						if (wcscmp(param1, L"TEX_ID_COUNT") == 0){
							int count = _wtoi(param2);
							if (count > 0){
								char* ctx = NULL;
								wchar_t *tmp_line_w = new wchar_t[(SIZE_CHAR_MAX + 1) * count];
								wmemset(tmp_line_w, 0, (SIZE_CHAR_MAX + 1) * count);
								fgetws(tmp_line_w, SIZE_CHAR_MAX, fp);

								char tmp_line[SIZE_CHAR_MAX * 3 * TEX_ID_SIZE_MAX];
								memset(tmp_line, 0, SIZE_CHAR_MAX * 3 * TEX_ID_SIZE_MAX);
								wcstombs_s(&size, tmp_line, tmp_line_w, SIZE_CHAR_MAX * 3 * TEX_ID_SIZE_MAX);

								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								wchar_t id_name[SIZE_CHAR_MAX];
								wmemset(id_name, 0, SIZE_CHAR_MAX);
								mbstowcs_s(&size, id_name, tmp, SIZE_CHAR_MAX);
								pgn_data->TexID->Push((void *)id_name);
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									wmemset(id_name, 0, SIZE_CHAR_MAX);
									mbstowcs_s(&size, id_name, tmp, SIZE_CHAR_MAX);
									pgn_data->TexID->Push((void *)id_name);
								} while (tmp != NULL);
								delete[] tmp_line_w;
							}
						}
						if (wcscmp(param1, L"POLYGON_DATA_END") == 0){
							gmt->PolygonData->Push((void *)&pgn_data);
							break;
						}
					}
				}
				if (wcscmp(param1, L"WEIGHTS_BEGIN") == 0){

					//ウェイトのロード

					int weight_count = -1;
					int apply_bone_num = -1;
					while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

						wmemset(param1, 0, SIZE_CHAR_MAX);
						wmemset(param2, 0, SIZE_CHAR_MAX);
						GetParamW(w_line, param1, param2, L" <>\n");
						if (wcscmp(param1, L"WEIGHTS_SIZE") == 0){
							weight_count = _wtoi(param2);
							gmt->WeightCount = weight_count;
						}
						if (wcscmp(param1, L"APPLY_BONE_NUM") == 0){
							apply_bone_num = _wtoi(param2);
							if (weight_count > 0 && apply_bone_num > 0){
								gmt->Weights = (int64_t ***) new int64_t**[weight_count];
								for (int i = 0; i <= weight_count - 1; i++){
									gmt->Weights[i] = (int64_t **) new int64_t*[apply_bone_num];
									for (int j = 0; j <= apply_bone_num - 1; j++){
										gmt->Weights[i][j] = (int64_t *) new float2();
										memset(gmt->Weights[i][j], 0, sizeof(float2));
									}
								}

								char* ctx = NULL;
								char *tmp_line = new char[FLOAT_STRING_SIZE * weight_count * apply_bone_num];
								memset(tmp_line, 0, FLOAT_STRING_SIZE * weight_count * apply_bone_num);
								fgets(tmp_line, FLOAT_STRING_SIZE * weight_count * apply_bone_num, fp);

								float *data = new float[weight_count * apply_bone_num * 2];
								memset(data, 0, sizeof(float)* weight_count * apply_bone_num * 2);

								char *tmp = strtok_s(tmp_line, " \n", &ctx);
								int count = 0;
								data[count] = (float)atof(tmp);
								count++;
								do{
									tmp = strtok_s(NULL, " \n", &ctx);
									if (tmp == NULL)
										break;
									data[count] = (float)atof(tmp);
									count++;
								} while (tmp != NULL);

								count = 0;
								for (int i = 0; i <= weight_count - 1; i++){
									for (int j = 0; j <= apply_bone_num - 1; j++){
										float2 *value = (float2 *)gmt->Weights[i][j];
										value->x = data[count] + 0.00001f;
										value->y = data[count + 1];
										count += 2;
									}
								}

								delete[] tmp_line;
								delete[] data;
							}
						}
						if (wcscmp(param1, L"WEIGHTS_END") == 0){
							break;
						}
					}
				}
				if (wcscmp(param1, L"GEOMETRY_END") == 0){

					Geometry->Push((void *)&gmt);
					break;
				}
			}
		}
		if (wcscmp(param1, L"BONE_ARRAY") == 0){

			wchar_t tmp_line_w[BONE_NAME_CHAR_MAX * BONE_JOINT_NUM_MAX];
			wmemset(tmp_line_w, 0, BONE_NAME_CHAR_MAX* BONE_JOINT_NUM_MAX);
			fgetws(tmp_line_w, BONE_NAME_CHAR_MAX* BONE_JOINT_NUM_MAX, fp);

			wchar_t *tmp = wcstok_s(tmp_line_w, L" \n", &w_ctx);
			if (tmp != NULL){
				CBone *bone = new CBone();
				wcscpy_s(bone->Name,SIZE_CHAR_MAX, tmp);
				BoneArray->Push((void *)&bone);
				do{
					wchar_t *tmp = wcstok_s(NULL, L" \n", &w_ctx);
					if (tmp == NULL)
						break;
					bone = new CBone();
					wcscpy_s(bone->Name, SIZE_CHAR_MAX, tmp);
					BoneArray->Push((void *)&bone);
				} while (tmp != NULL);
			}
		}
		if (wcscmp(param1, L"BONE") == 0){

			LoadBone(fp, NULL);
		}
	}

	fclose(fp);

	return true;
}

CBone *CChaDataObject::LoadBone(FILE *fp, CBone *parent){

	char *ctx = NULL;
	wchar_t* w_ctx = NULL;
	wchar_t w_line[SIZE_CHAR_MAX];
	wchar_t param1[SIZE_CHAR_MAX];
	wchar_t param2[SIZE_CHAR_MAX];
	int mode = READ_MODE_INIT;
	CBone *bone = NULL;

	while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

		wmemset(param1, 0, SIZE_CHAR_MAX);
		wmemset(param2, 0, SIZE_CHAR_MAX);

		GetParamW(w_line, param1, param2, L" \t<>\n");
		if (wcscmp(param1, L"BONE_BEGIN") == 0){
		}
		if (wcscmp(param1, L"BONE_NAME") == 0){

			bone = FindBone(param2);
			if (bone == NULL)
				bone = new CBone();
			if (parent == NULL)
				ControlBone->Push((void *)&bone);
			bone->ParentBone = parent;

			wcscpy_s(bone->Name, SIZE_CHAR_MAX, param2);
		}
		if (wcscmp(param1, L"BONE_ID") == 0){
			wcscpy_s(bone->ID, SIZE_CHAR_MAX, param2);
		}
		if (wcscmp(param1, L"BONE_TYPE") == 0){
			bone->Type = _wtoi(param2);
		}
		if (wcscmp(param1, L"INV_BIND_MATRIX") == 0){

			char tmp_line[FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE];
			memset(tmp_line, 0, FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE);
			fgets(tmp_line, FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE, fp);

			float m[16];
			memset(m, 0, sizeof(float)* 16);
			char *tmp = strtok_s(tmp_line, " \n", &ctx);
			m[0] = (float)atof(tmp);
			for (int i = 1; i <= 15; i++){
				tmp = strtok_s(NULL, " \n", &ctx);
				m[i] = (float)atof(tmp);
			}
			MatrixSet(&bone->InvBindMatrix, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
		}
		if (wcscmp(param1, L"JOINT_MATRIX") == 0){

			char tmp_line[FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE];
			memset(tmp_line, 0, FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE);
			fgets(tmp_line, FLOAT_STRING_SIZE * 16 + TAB_MARGIN_SIZE, fp);

			float m[16];
			memset(m, 0, sizeof(float)* 16);
			char *tmp = strtok_s(tmp_line, " \n", &ctx);
			m[0] = (float)atof(tmp);
			for (int i = 1; i <= 15; i++){
				tmp = strtok_s(NULL, " \n", &ctx);
				m[i] = (float)atof(tmp);
			}
			MatrixSet(&bone->JointParam, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
		}
		if (wcscmp(param1, L"CHILD_COUNT") == 0){

			int child_num = _wtoi(param2);
			for (int i = 0; i <= child_num - 1; i++){
				CBone *child_bone = LoadBone(fp, bone);
				bone->ChildBone->Push((void *)&child_bone);
			}
			break;
		}
	}

	return bone;
}

bool CChaDataObject::WriteAnimation(wchar_t *target_modelname, wchar_t *animation_id, wchar_t *filename){

	//アニメーションを書き出す。

	FILE *fp = NULL;

	wchar_t out_file_name[SIZE_CHAR_MAX];
	wmemset(out_file_name, 0, SIZE_CHAR_MAX);
	wcscpy_s(out_file_name, SIZE_CHAR_MAX, filename);

	wchar_t ext[16];
	wmemset(ext, 0, 16);
	wmemcpy(ext, &out_file_name[wcslen(out_file_name) - 4], 4);
	if (wcscmp(ext, CHAANIMATION_EXT_NAME) != 0 || wcscmp(ext, CHAANIMATION_EXT_NAME) != 0){
		wcscat_s(out_file_name, SIZE_CHAR_MAX, CHAANIMATION_EXT_NAME);
	}

	_wfopen_s(&fp, out_file_name, L"w");

	if (fp == NULL)
		return false;

	if (AnimationList->PushPos <= 0)
		return false;

	fwprintf_s(fp, L"[TARGET_MODEL_ID]\n%s\n\n", target_modelname);
	fwprintf_s(fp, L"[ANIMATION_ID]\n%s\n\n", animation_id);

	CAnimation *Animation = *(CAnimation **)AnimationList->GetData(0);

	fwprintf_s(fp, L"/////////////////////////// animation //////////////////////////\n\n");

	for (int i = 0; i <= (int)Animation->BoneAnimation->PushPos - 1; i++){
		CBoneAnimation *anim = *(CBoneAnimation **)Animation->BoneAnimation->GetData(i);
		fwprintf_s(fp, L"<ANIMATION_BEGIN>\n");
		fwprintf_s(fp, L"<TARGET>%s\n", anim->Target);
		fwprintf_s(fp, L"<KEY_TIME>\n");
		for (int j = 0; j <= anim->KeyTime->PushPos - 1; j++){
			float key_time = *(float *)anim->KeyTime->GetData(j);
			fwprintf_s(fp, L"%.6f ", key_time);
		}
		fwprintf_s(fp, L"\n");
		fwprintf_s(fp, L"<POSE_MATRIX>\n");
		for (int j = 0; j <= anim->PoseMatrix->PushPos - 1; j++){
			matrix mat = *(matrix *)anim->PoseMatrix->GetData(j);
			fwprintf_s(fp, L"%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f \n",
				mat.m11, mat.m12, mat.m13, mat.m14, mat.m21, mat.m22, mat.m23, mat.m24, mat.m31, mat.m32, mat.m33, mat.m34, mat.m41, mat.m42, mat.m43, mat.m44);
		}
		fwprintf_s(fp, L"<POSE_MATRIX_END>\n");
		fwprintf_s(fp, L"<ANIMATION_END>\n\n");
	}

	fclose(fp);

	return true;
}

bool CChaDataObject::LoadAnimation(wchar_t *filename){

	//アニメーションファイルを読み込む。

	FILE *fp = NULL;

	wchar_t out_file_name[SIZE_CHAR_MAX];
	wmemset(out_file_name, 0, SIZE_CHAR_MAX);
	wcscpy_s(out_file_name, SIZE_CHAR_MAX, filename);

	_wfopen_s(&fp, out_file_name, L"r");

	if (fp == NULL)
		return false;

	CAnimation *anim = new CAnimation();
	CBoneAnimation *bone_anim = NULL;

	wchar_t *w_ctx = NULL;
	wchar_t w_line[SIZE_CHAR_MAX];
	wchar_t param1[SIZE_CHAR_MAX];
	wchar_t param2[SIZE_CHAR_MAX];
	int mode = READ_MODE_INIT;

	while (fgetws(w_line, SIZE_CHAR_MAX, fp) != NULL){

		memset(param1, 0, SIZE_CHAR_MAX);
		memset(param2, 0, SIZE_CHAR_MAX);
		GetParamW(w_line, param1, param2, L" []<>\n");

		if (wcscmp(param1, L"TARGET_MODEL_ID") == 0){

			wchar_t target_model_id[SIZE_CHAR_MAX];
			wmemset(target_model_id, 0, SIZE_CHAR_MAX);

			fgetws(w_line, SIZE_CHAR_MAX, fp);
			GetParamW(w_line, param1, param2, L" \n");
			wcscpy_s(target_model_id, SIZE_CHAR_MAX, param1);

			if (wcscmp(target_model_id, ModelID) != 0)
				return false;
		}
		if (wcscmp(param1, L"ANIMATION_ID") == 0){

			wchar_t target_model_id[SIZE_CHAR_MAX];
			wmemset(target_model_id, 0, SIZE_CHAR_MAX);

			fgetws(w_line, SIZE_CHAR_MAX, fp);
			GetParamW(w_line, param1, param2, L" \n");
			wcscpy_s(anim->AnimatonID, SIZE_CHAR_MAX, param1);

			continue;
		}
		if (wcscmp(param1, L"ANIMATION_BEGIN") == 0){

			bone_anim = new CBoneAnimation();
		}
		if (wcscmp(param1, L"TARGET") == 0){
			wcscpy_s(bone_anim->Target, SIZE_CHAR_MAX, param2);
			bone_anim->TargetBone = FindBoneByID(bone_anim->Target);
		}
		if (wcscmp(param1, L"KEY_TIME") == 0){
			wchar_t tmp_line_w[ANIMATION_KEY_TIME_SIZE_MAX * sizeof(float)];
			fgetws(tmp_line_w, ANIMATION_KEY_TIME_SIZE_MAX * sizeof(float), fp);
			wchar_t *tmp = wcstok_s(tmp_line_w, L" \n", &w_ctx);
			float time = (float)_wtof(tmp);
			bone_anim->KeyTime->Push((void *)&time);
			do{
				tmp = wcstok_s(NULL, L" \n", &w_ctx);
				if (tmp == NULL)
					break;
				time = (float)_wtof(tmp);
				bone_anim->KeyTime->Push((void *)&time);
			} while (tmp != NULL);
		}
		if (wcscmp(param1, L"POSE_MATRIX") == 0){

			char tmp_line[FLOAT_STRING_SIZE * 16];
			memset(tmp_line, 0, FLOAT_STRING_SIZE * 16);
			while (fgets(tmp_line, SIZE_CHAR_MAX, fp) != NULL) {

				char line[SIZE_CHAR_MAX];
				memset(line, 0, SIZE_CHAR_MAX);
				char param1[SIZE_CHAR_MAX];
				char param2[SIZE_CHAR_MAX];
				strcpy_s(line, SIZE_CHAR_MAX, tmp_line);
				memset(param1, 0, SIZE_CHAR_MAX);
				memset(param2, 0, SIZE_CHAR_MAX);
				GetParam(line, param1, param2, " []<>\n");
				if (strcmp(param1, "POSE_MATRIX_END") == 0) {
					break;
				}

				char* ctx = NULL;
				float m[16];
				memset(m, 0, sizeof(float) * 16);
				char* tmp = strtok_s(tmp_line, " \n", &ctx);
				m[0] = (float)atof(tmp);
				for (int i = 1; i <= 15; i++) {
					tmp = strtok_s(NULL, " \n", &ctx);
					m[i] = (float)atof(tmp);
				}
				matrix mtx;
				MatrixSet(&mtx, m[0], m[1], m[2], m[3], m[4], m[5], m[6], m[7], m[8], m[9], m[10], m[11], m[12], m[13], m[14], m[15]);
				bone_anim->PoseMatrix->Push((void*)&mtx);
			}
		}
		if (wcscmp(param1, L"ANIMATION_END") == 0){
			anim->BoneAnimation->Push((void *)&bone_anim);
		}
	}
	AnimationList->Push((void *)&anim);

	fclose(fp);

	return true;
}

bool CChaDataObject::WriteCollider(const wchar_t* modelname, const wchar_t* filename) {

	//Colliderモデルファイルを書き出す。

	FILE* fp = NULL;

	wchar_t out_file_name[SIZE_CHAR_MAX];
	wmemset(out_file_name, 0, SIZE_CHAR_MAX);
	wcscpy_s(out_file_name, SIZE_CHAR_MAX, filename);

	wchar_t ext[16];
	wmemset(ext, 0, 16);
	wmemcpy(ext, &out_file_name[wcslen(out_file_name) - 4], 4);
	if (wcscmp(ext, CHACOLLIDER_EXT_NAME) != 0) {
		wcscat_s(out_file_name, SIZE_CHAR_MAX, CHACOLLIDER_EXT_NAME);
	}

	_wfopen_s(&fp, out_file_name, L"w");

	if (fp == NULL)
		return false;

	fwprintf_s(fp, L"[MODEL_ID]\n%s\n\n", modelname);

	fwprintf_s(fp, L"/////////////////////////// geometry //////////////////////////\n\n");

	for (int i = 0; i <= (int)Geometry->PushPos - 1; i++) {

		CGeometry* gmt = *(CGeometry**)Geometry->GetData(i);

		fwprintf_s(fp, L"<GEOMETRY_BEGIN>\n");
		fwprintf_s(fp, L"<GEOMETRY_ID>%s\n", gmt->GeometryID);
		fwprintf_s(fp, L"<VERTEX_COUNT>%d\n", gmt->VertexCount);
		fwprintf_s(fp, L"<BIND_SHAPE_MATRIX>\n%.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f %.6f\n",
			gmt->BindShapeMatrix.m11, gmt->BindShapeMatrix.m12, gmt->BindShapeMatrix.m13, gmt->BindShapeMatrix.m14,
			gmt->BindShapeMatrix.m21, gmt->BindShapeMatrix.m22, gmt->BindShapeMatrix.m23, gmt->BindShapeMatrix.m24,
			gmt->BindShapeMatrix.m31, gmt->BindShapeMatrix.m32, gmt->BindShapeMatrix.m33, gmt->BindShapeMatrix.m34,
			gmt->BindShapeMatrix.m41, gmt->BindShapeMatrix.m42, gmt->BindShapeMatrix.m43, gmt->BindShapeMatrix.m44);
		if (gmt->VertexCount <= 1)
			fwprintf_s(fp, L"<COLLIDER_TYPE>COLLIDER_TYPE_SPHERE\n");
		else if (gmt->VertexCount <= 2)
			fwprintf_s(fp, L"<COLLIDER_TYPE>COLLIDER_TYPE_CAPSULE\n");
		else
			fwprintf_s(fp, L"<COLLIDER_TYPE>COLLIDER_TYPE_MESH\n");
		fwprintf_s(fp, L"<R>%.5f\n", COLLIDER_DEFAULT_R);

		fwprintf_s(fp, L"<FLOAT_ARRAY_SIZE>%d\n", (int)gmt->VecFloatArray->PushPos);
		for (int j = 0; j <= (int)gmt->VecFloatArray->PushPos - 1; j++) {
			CFloatArray* float_data = *(CFloatArray**)gmt->VecFloatArray->GetData(j);
			int float_count = (int)(float_data->FloatData->DataSize / sizeof(float));

			if (float_count == 3) {
				fwprintf_s(fp, L"<FLOAT_ARRAY_BEGIN>\n");
				fwprintf_s(fp, L"<FLOAT_ARRAY_ID>%s\n", float_data->ID);
				fwprintf_s(fp, L"<FLOAT_ARRAY_FLOAT_COUNT>%d\n", float_count);
				fwprintf_s(fp, L"<FLOAT_ARRAY_COUNT>%d\n", (int)float_data->FloatData->PushPos);
				fwprintf_s(fp, L"<FLOAT_ARRAY>\n");
				for (int k = 0; k <= float_data->FloatData->PushPos - 1; k++) {
					float3* data = (float3*)float_data->FloatData->GetData(k);
					fwprintf_s(fp, L"%.6f %.6f %.6f ", data->x, data->y, data->z);
				}
			}
			fwprintf_s(fp, L"\n<FLOAT_ARRAY_END>\n");
		}
		fwprintf_s(fp, L"\n");

		for (int j = 0; j <= (int)gmt->PolygonData->PushPos - 1; j++) {

			CPolygonData* pgn_data = *(CPolygonData**)gmt->PolygonData->GetData(j);
			int index_num = (int)pgn_data->VertexIndex->PushPos;

			fwprintf_s(fp, L"<POLYGON_DATA_BEGIN>\n");
			fwprintf_s(fp, L"<VERTEX_ID>%s\n", pgn_data->VertexID);
			fwprintf_s(fp, L"<NORMAL_ID>%s\n", pgn_data->NormalID);
			fwprintf_s(fp, L"<VERTEX_INDEX_COUNT>%d\n", (int)pgn_data->VertexIndex->PushPos);
			for (int k = 0; k <= pgn_data->VertexIndex->PushPos - 1; k++) {
				int32_t index = *(int32_t*)pgn_data->VertexIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<NORMAL_INDEX_COUNT>%d\n", (int)pgn_data->NormalIndex->PushPos);
			for (int k = 0; k <= pgn_data->NormalIndex->PushPos - 1; k++) {
				int32_t index = *(int32_t*)pgn_data->NormalIndex->GetData(k);
				fwprintf_s(fp, L"%d ", index);
			}
			fwprintf_s(fp, L"\n");

			fwprintf_s(fp, L"<POLYGON_DATA_END>\n\n");
		}

		fwprintf_s(fp, L"<WEIGHTS_BEGIN>\n");
		fwprintf_s(fp, L"<WEIGHTS_SIZE>%d\n", gmt->WeightCount);
		fwprintf_s(fp, L"<APPLY_BONE_NUM>%d\n", WEIGHT_BONE_APPLY_NUM);
		for (int j = 0; j <= (int)gmt->WeightCount - 1; j++) {
			for (int k = 0; k <= WEIGHT_BONE_APPLY_NUM - 1; k++) {
				float2* weight = (float2*)gmt->Weights[j][k];
				fwprintf_s(fp, L"%.6f %.6f ", weight->x, weight->y);
			}
		}
		fwprintf_s(fp, L"\n<WEIGHTS_END>\n");
		fwprintf_s(fp, L"\n<GEOMETRY_END>\n\n");

		fwprintf_s(fp, L"/////////////////////////////////////////////////////\n\n");
	}

	fwprintf_s(fp, L"\n\n");

	fclose(fp);

	return true;
}
