////////////////////////////////////////////////////////
// filename: ChaResourceObject.cpp
// author: Chafumi Touji
// version: 1.0.0
// date: 2020/03/08
////////////////////////////////////////////////////////

#include "defcha3dcore.h"

CMaterialResource::CMaterialResource(){

	memset(&diffuse, 0, sizeof(float)* 4);
	memset(&ambient, 0, sizeof(float)* 4);
	memset(&specular, 0, sizeof(float)* 4);
	memset(&emmition, 0, sizeof(float)* 4);
	Texture = NULL;
	ShaderResourceView = NULL;
}

CMaterialResource::~CMaterialResource(){

	memset(&diffuse, 0, sizeof(float)* 4);
	memset(&ambient, 0, sizeof(float)* 4);
	memset(&specular, 0, sizeof(float)* 4);
	memset(&emmition, 0, sizeof(float)* 4);
}

CGeometryResource::CGeometryResource(){

	VertexBuffer = NULL;
	IndexBuffer = new CVector(sizeof(ID3D11Buffer **));
	Material = new CVector(sizeof(int));
	IndexCount = new CVector(sizeof(int));
	BindShapeMatrix = XMMatrixIdentity();
}

CGeometryResource::~CGeometryResource(){

	SAFE_RELEASE(VertexBuffer);
	for (int i = 0; i <= IndexBuffer->PushPos - 1; i++){
		ID3D11Buffer **index_buffer = (ID3D11Buffer **)IndexBuffer->GetData(i);
		SAFE_RELEASE(*index_buffer);
	}

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

	delete IndexBuffer;
	delete Material;
	delete IndexCount;
}

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

CBoneResource::CBoneResource(){

	wmemset(ID, 0, SIZE_CHAR_MAX);
	wmemset(Name, 0, SIZE_CHAR_MAX);
	JointParam = XMMatrixIdentity();
	InvBindMatrix = XMMatrixIdentity();
	JointParamTransformed = XMMatrixIdentity();
	BoneMatrix = XMMatrixIdentity();
	ChildBone = new CVector(sizeof(int));
	ParentBone = NULL;
	Type = BONE_TYPE_UNKNOWN;
	NowChangeFrameCount = 0;
	ChangeFrameCount = 0;
	ChangeNewAnimation = false;
}

CBoneResource::~CBoneResource(){

	delete ChildBone;
	ChildBone = NULL;
	ParentBone = NULL;
}

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

CBoneAnimationResource::CBoneAnimationResource(){

	wmemset(Target, 0, SIZE_CHAR_MAX);
	TargetBone = NULL;
	Refrain = true;
	ChangeFrameCount = 0;
	KeyTime = new CVector(sizeof(float));
	PoseMatrix = new CVector(sizeof(XMMATRIX));
}

CBoneAnimationResource::~CBoneAnimationResource(){

	delete KeyTime;
	delete PoseMatrix;
	TargetBone = NULL;
}

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

CAnimationResource::CAnimationResource(){

	wmemset(AnimationID, 0, SIZE_CHAR_MAX);
	BoneAnimation = new CVector(sizeof(int));
}

CAnimationResource::~CAnimationResource(){

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

	delete BoneAnimation;
}

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

CChaResourceObject::CChaResourceObject(){

	wmemset(ModelID, 0, SIZE_CHAR_MAX);
	FrameCount = 0;
	GeometryResource = new CVector(sizeof(int));
	TextureOrigin = new CVector(sizeof(int));
	ShaderResourceOrigin = new CVector(sizeof(int));
	ControlBone = new CVector(sizeof(int));
	BoneArray = new CVector(sizeof(int));
	AnimationList = new CVector(sizeof(int));
	CurrentAnimationNum = 0;
}

CChaResourceObject::~CChaResourceObject(){

	for (int i = 0; i <= GeometryResource->PushPos - 1; i++){
		CGeometryResource *gmt_res = *(CGeometryResource **)GeometryResource->GetData(i);
		delete gmt_res;
	}
	for (int i = 0; i <= TextureOrigin->PushPos - 1; i++){
		ID3D11Texture2D **texture = (ID3D11Texture2D **)TextureOrigin->GetData(i);
		SAFE_RELEASE(*texture);
	}
	for (int i = 0; i <= ShaderResourceOrigin->PushPos - 1; i++){
		ID3D11ShaderResourceView **res = (ID3D11ShaderResourceView **)ShaderResourceOrigin->GetData(i);
		SAFE_RELEASE(*res);
	}
	for (int i = 0; i <= BoneArray->PushPos - 1; i++){
		CBoneResource *bone = *(CBoneResource **)BoneArray->GetData(i);
		if (bone != NULL)
			delete bone;
		bone = NULL;
	}
	for (int i = 0; i <= ControlBone->PushPos - 1; i++){
		CBoneResource *bone = *(CBoneResource **)ControlBone->GetData(i);
		if ( bone != NULL)	
			delete bone;
		bone = NULL;
	}
	for (int i = 0; i <= AnimationList->PushPos - 1; i++){
		CAnimationResource *data = *(CAnimationResource **)AnimationList->GetData(i);
		delete data;
	}

	delete GeometryResource;
	delete TextureOrigin;
	delete ShaderResourceOrigin;
	delete ControlBone;
	delete BoneArray;
	delete AnimationList;
}

bool CChaResourceObject::CreateResource( ID3D11Device *m_pDevice, CChaDataObject *object){
	
	if (object == NULL)
		return false;

	//////////////////////////////////////////////////////////////////
	// テクスチャリソース作成

	D3D11_TEXTURE2D_DESC desc_texture_2d;
	ZeroMemory(&desc_texture_2d, sizeof(D3D11_TEXTURE2D_DESC));
	desc_texture_2d.MipLevels = 1;
	desc_texture_2d.ArraySize = 1;
	desc_texture_2d.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	desc_texture_2d.SampleDesc.Count = 1;
	desc_texture_2d.SampleDesc.Quality = 0;
	desc_texture_2d.Usage = D3D11_USAGE_DEFAULT;
	desc_texture_2d.BindFlags = D3D11_BIND_SHADER_RESOURCE;
	desc_texture_2d.CPUAccessFlags = 0;
	desc_texture_2d.MiscFlags = 0;

	D3DX11_IMAGE_LOAD_INFO info;
	ZeroMemory(&info, sizeof(D3DX11_IMAGE_LOAD_INFO));
	info.Width = D3DX11_DEFAULT;
	info.Height = D3DX11_DEFAULT;
	info.Depth = D3DX11_DEFAULT;
	info.FirstMipLevel = D3DX11_DEFAULT;
	info.MipLevels = 1;
	info.Usage = D3D11_USAGE_DEFAULT;
	info.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
	info.CpuAccessFlags = 0;
	info.MiscFlags = 0;
	info.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
	info.Filter = D3DX11_FILTER_LINEAR;
	info.MipFilter = D3DX11_FILTER_LINEAR;
	info.pSrcInfo = NULL;

	D3D11_SHADER_RESOURCE_VIEW_DESC desc_shader_resource;
	ZeroMemory(&desc_shader_resource, sizeof(D3D11_SHADER_RESOURCE_VIEW_DESC));
	desc_shader_resource.Format = info.Format;
	desc_shader_resource.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
	desc_shader_resource.Texture2D.MipLevels = info.MipLevels;
	desc_shader_resource.Texture2D.MostDetailedMip = 0;

	size_t size;
	wchar_t name[SIZE_CHAR_MAX];
	for (int i = 0; i <= object->TextureName->PushPos - 1; i++){
		ID3D11Texture2D *texture = NULL;
		ID3D11ShaderResourceView *shader_res = NULL;
		CTextureName *tex_name = *(CTextureName **)object->TextureName->GetData(i);
		if (tex_name != NULL && tex_name->TextureName != NULL ){
			wcscpy_s( name, SIZE_CHAR_MAX, tex_name->TextureName );
			HRESULT hr = D3DX11CreateTextureFromFile(m_pDevice, name, &info, NULL, (ID3D11Resource **)&texture, NULL);
			if (hr == S_OK){
				m_pDevice->CreateShaderResourceView(texture, &desc_shader_resource, &shader_res);
				TextureOrigin->Push((void*)&texture);
				ShaderResourceOrigin->Push((void *)&shader_res);
			}
		}
	}

	//////////////////////////////////////////////////////////////////
	//コンスタントバッファ作成

	//////////////////////////////////////////////////////////////////
	// ConstantBuffer

	//マテリアル設定用バッファ作成
	D3D11_BUFFER_DESC desc_buffer;
	m_pConstantBuffer1 = NULL;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(ConstantBufferMaterial);
	desc_buffer.Usage = D3D11_USAGE_DEFAULT;
	desc_buffer.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	desc_buffer.CPUAccessFlags = 0;
	desc_buffer.MiscFlags = 0;
	desc_buffer.StructureByteStride = sizeof(float);
	m_pDevice->CreateBuffer(&desc_buffer, NULL, &m_pConstantBuffer1);

	//ボーンジョイントマトリクス設定用バッファ作成
	m_pConstantBuffer2 = NULL;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(ConstantBufferBoneJoint);
	desc_buffer.Usage = D3D11_USAGE_DEFAULT;
	desc_buffer.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	desc_buffer.CPUAccessFlags = 0;
	desc_buffer.MiscFlags = 0;
	desc_buffer.StructureByteStride = sizeof(float);
	m_pDevice->CreateBuffer(&desc_buffer, NULL, &m_pConstantBuffer2);

	//////////////////////////////////////////////////////////////////
	// バッファ作成

	wcscpy_s(ModelID, SIZE_CHAR_MAX, object->ModelID);

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

		CGeometry *gmt = *(CGeometry **)object->Geometry->GetData(i);
		CGeometryResource *gmt_res = new CGeometryResource();

		gmt_res->BindShapeMatrix = XMMatrixTranspose(XMMATRIX(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));

		int vertex_count = gmt->VertexCount;
		char *buffer = new char[sizeof( CVertex ) * (vertex_count)];
		memset(buffer, 0, sizeof(CVertex)* (vertex_count));
		char *data = new char[sizeof(CVertex)];
		int vertex_pos = 0;
		
		for (int j = 0; j <= gmt->PolygonData->PushPos - 1; j++){


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

			int tex_num = pgn_data->TexID->PushPos;
			int **tex_data = (int **) new int[tex_num];
			for (int k = 0; k <= tex_num - 1; k++)
				tex_data[k] = (int *) gmt->GetFloatArray((wchar_t *) pgn_data->TexID->GetData(k));

			CFloatArray *vertex_data = gmt->GetFloatArray(pgn_data->VertexID);
			CFloatArray *normal_data = gmt->GetFloatArray(pgn_data->NormalID);
			CFloatArray *color_data = gmt->GetFloatArray(pgn_data->ColorID);

			//Material取得
			CMaterial *material = object->GetMaterial(pgn_data->MaterialID);
			ID3D11Texture2D *texture = NULL;
			ID3D11ShaderResourceView *shader_res = NULL;
			CMaterialResource *material_resource = new CMaterialResource();
			if (material != NULL){
				int material_num = object->GetMaterialNum(pgn_data->MaterialID);
				int texture_num = object->GetTextureNum(material_num);
				if (texture_num >= 0){
					texture = (ID3D11Texture2D *)TextureOrigin->GetData(texture_num);
					shader_res = (ID3D11ShaderResourceView *)ShaderResourceOrigin->GetData(texture_num);
				}
				material_resource->diffuse = material->diffuse;
				material_resource->ambient = material->ambient;
				material_resource->emmition = material->emmition;
				material_resource->specular = material->specular;
				material_resource->Texture = texture;
				material_resource->ShaderResourceView = shader_res;
			}
			gmt_res->Material->Push((void *)&material_resource);

			int index_count = pgn_data->VertexIndex->PushPos;
			int *buffer_index = new int[index_count];
			memset(buffer_index, 0, ( index_count ) * sizeof(int));

			float3 vertex;
			float3 normal;
			float4 color;
			float2 tex;
			float2 weight[WEIGHT_BONE_APPLY_NUM];
			memset(weight, 0, sizeof(float2)* WEIGHT_BONE_APPLY_NUM);

			for (int k = 0; k <= pgn_data->VertexIndex->PushPos - 1; k++){
				memset(data, 0, sizeof(CVertex));
				memset( &vertex, 0, sizeof(float3));
				memset( &normal, 0, sizeof(float3));
				memset( &color, 0, sizeof(float4));
				memset( &tex, 0, sizeof(float2));
				memset(weight, 0, sizeof(float2)* WEIGHT_BONE_APPLY_NUM);
				if (vertex_data != NULL){
					int vertex_index = *(int *)pgn_data->VertexIndex->GetData(k);
					vertex = *(float3 *)vertex_data->FloatData->GetData(vertex_index);
					vertex_pos = vertex_index;
					if (gmt->Weights != NULL){
						int **weights = gmt->Weights[vertex_index];
						for (int l = 0; l <= WEIGHT_BONE_APPLY_NUM - 1; l++){
							float2 *w = (float2 *)weights[l];
							weight[l].x = w->x;
							weight[l].y = w->y;
						}
					}
				}
				if (normal_data != NULL){
					int normal_index = *(int *)pgn_data->NormalIndex->GetData(k);
					normal = *(float3 *)normal_data->FloatData->GetData(normal_index);
				}
				if (color_data != NULL){
					int color_index = *(int *)pgn_data->ColorIndex->GetData(k);
					color = *(float4 *)color_data->FloatData->GetData(color_index);
				}
				if (tex_data != NULL){
					int tex_index = *(int *)pgn_data->TexIndex->GetData(k);
					for (int l = 0; l <= tex_num - 1; l++){
						CFloatArray *float_array = (CFloatArray *)tex_data[l];
						float2 tex_tmp = *(float2 *)float_array->FloatData->GetData(tex_index);
						tex.x += tex_tmp.x;
						tex.y += tex_tmp.y;
					}
				}
				memcpy_s((char *)data, sizeof(float3), &vertex, sizeof(float3));
				memcpy_s((char *)data + sizeof(float3), sizeof(float3), &normal, sizeof(float3));
				memcpy_s((char *)data + sizeof(float3) + sizeof(float3), sizeof(float4), &color, sizeof(float4));
				memcpy_s((char *)data + sizeof(float3) + sizeof(float3) + sizeof(float4), sizeof(float2), &tex, sizeof(float2));
				memcpy_s((char *)data + sizeof(float3) + sizeof(float3) + sizeof(float4) + sizeof(float2), sizeof(float2) * WEIGHT_BONE_APPLY_NUM, weight, sizeof(float2) * WEIGHT_BONE_APPLY_NUM);
				memcpy_s((char *)buffer + vertex_pos * sizeof(CVertex), sizeof(CVertex), data, sizeof(CVertex));
				buffer_index[k] = *(int *) pgn_data->VertexIndex->GetData( k );
			}

			D3D11_BUFFER_DESC desc_index;
			ZeroMemory(&desc_index, sizeof(D3D11_BUFFER_DESC));
			desc_index.Usage = D3D11_USAGE_DEFAULT;
			desc_index.ByteWidth = sizeof(int)* index_count;
			desc_index.BindFlags = D3D11_BIND_INDEX_BUFFER;
			desc_index.CPUAccessFlags = 0;
			desc_index.MiscFlags = 0;

			D3D11_SUBRESOURCE_DATA res_data_index;
			res_data_index.pSysMem = &buffer_index[0];
			ID3D11Buffer *index_buffer = NULL;
			HRESULT hr = m_pDevice->CreateBuffer(&desc_index, &res_data_index, &index_buffer);

			gmt_res->IndexBuffer->Push((void *) &index_buffer);
			gmt_res->IndexCount->Push((void *) &index_count);

			delete[] buffer_index;
			if (tex_data != NULL){
				delete[] tex_data;
				tex_data = NULL;
			}
		}

		D3D11_BUFFER_DESC desc_buffer;
		ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
		desc_buffer.ByteWidth = sizeof(CVertex)* vertex_count;
		desc_buffer.Usage = D3D11_USAGE_DYNAMIC;
		desc_buffer.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		desc_buffer.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
		desc_buffer.MiscFlags = 0;
		desc_buffer.StructureByteStride = sizeof(float);

		D3D11_SUBRESOURCE_DATA res_data_buffer;
		res_data_buffer.pSysMem = &buffer[0];
		ID3D11Buffer *vertex_buffer = NULL;
		HRESULT hr = m_pDevice->CreateBuffer(&desc_buffer, &res_data_buffer, &vertex_buffer);

		gmt_res->VertexBuffer = vertex_buffer;
		GeometryResource->Push((void *)&gmt_res);

		delete[] data;
		delete[] buffer;
	}

	//コントロールボーンのコピー
	CopyControlBone(object);

	//アニメーションのコピー
	CopyAnimation(object);

	return true;
}

bool CChaResourceObject::CopyControlBone(CChaDataObject *object){

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

		CBone *bone = *(CBone **)object->BoneArray->GetData(i);
		CBoneResource *bone_res = new CBoneResource();
		bone_res->BoneMatrix = XMMatrixIdentity();
		wcscpy_s(bone_res->ID, SIZE_CHAR_MAX, bone->ID);
		wcscpy_s(bone_res->Name, SIZE_CHAR_MAX, bone->Name);
		bone_res->InvBindMatrix = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParam = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParamTransformed = XMMatrixIdentity();
		bone_res->ParentBone = NULL;
		bone_res->Type = bone->Type;
		BoneArray->Push((void *)&bone_res);
	}

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

		CBone *bone = *(CBone **)object->ControlBone->GetData(i);
		CBoneResource *bone_res = FindBoneByID(bone->ID);
		if( bone_res == NULL )
			bone_res = new CBoneResource();
		bone_res->BoneMatrix = XMMatrixIdentity();
		wcscpy_s(bone_res->ID, SIZE_CHAR_MAX, bone->ID);
		wcscpy_s(bone_res->Name, SIZE_CHAR_MAX, bone->Name);
		bone_res->InvBindMatrix = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParam = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParamTransformed = XMMatrixIdentity();
		bone_res->ParentBone = NULL;
		bone_res->Type = bone->Type;
		CopyChildBone( bone, bone_res);
		ControlBone->Push((void *)&bone_res);
	}

	return true;
}

bool CChaResourceObject::CopyChildBone(CBone *parent, CBoneResource *parent_res){

	if ( parent == NULL || parent->ChildBone == NULL)
		return false;

	for (int i = 0; i <= parent->ChildBone->PushPos - 1; i++){
		CBone *bone = *(CBone **)parent->ChildBone->GetData(i);
		CBoneResource *bone_res = FindBoneByID(bone->ID);
		if( bone_res == NULL )
			bone_res = new CBoneResource();
		bone_res->BoneMatrix = XMMatrixIdentity();
		wcscpy_s(bone_res->ID, SIZE_CHAR_MAX, bone->ID);
		wcscpy_s(bone_res->Name, SIZE_CHAR_MAX, bone->Name);
		bone_res->InvBindMatrix = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParam = XMMatrixTranspose(XMMATRIX(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));
		bone_res->JointParamTransformed = XMMatrixIdentity();
		bone_res->BoneMatrix = XMMatrixIdentity();
		bone_res->ParentBone = parent_res;
		parent_res->ChildBone->Push((void *)&bone_res);
		CopyChildBone(bone, bone_res);
	}

	return true;
}

bool CChaResourceObject::CopyAnimation(CChaDataObject *object){

	for (int i = 0; i <= object->AnimationList->PushPos - 1; i++){
		CAnimation *anim = *(CAnimation **)object->AnimationList->GetData(i);
		CAnimationResource *anim_res = new CAnimationResource();
		wcscpy_s(anim_res->AnimationID, SIZE_CHAR_MAX, anim->AnimatonID);
		for (int j = 0; j <= anim->BoneAnimation->PushPos - 1; j++){
			CBoneAnimation *bone_anim = *(CBoneAnimation **)anim->BoneAnimation->GetData(j);
			CBoneAnimationResource *bone_anim_res = new CBoneAnimationResource();
			wcscpy_s(bone_anim_res->Target, SIZE_CHAR_MAX, bone_anim->Target);
			bone_anim_res->TargetBone = FindBoneByID(bone_anim->Target);
			for (int k = 0; k <= bone_anim->KeyTime->PushPos - 1; k++){
				bone_anim_res->KeyTime->Push((float*)bone_anim->KeyTime->GetData(k));
			}
			for (int k = 0; k <= bone_anim->PoseMatrix->PushPos - 1; k++){
				matrix *mtx = (matrix *)bone_anim->PoseMatrix->GetData(k);
				XMMATRIX pose_matrix = XMMatrixTranspose(XMMATRIX(mtx->m11, mtx->m12, mtx->m13, mtx->m14, mtx->m21, mtx->m22, mtx->m23, mtx->m24, mtx->m31, mtx->m32, mtx->m33, mtx->m34, mtx->m41, mtx->m42, mtx->m43, mtx->m44));
				bone_anim_res->PoseMatrix->Push((void *)&pose_matrix);
			}
			anim_res->BoneAnimation->Push((void *)&bone_anim_res);
		}
		AnimationList->Push((void *)&anim_res);
	}

	return true;
}

bool CChaResourceObject::CopyAnimation(CChaDataObject *object, int anim_num){

	CAnimation *anim = *(CAnimation **)object->AnimationList->GetData( anim_num );
	if (anim == NULL)
		return false;

	CAnimationResource *anim_res = new CAnimationResource();
	wcscpy_s(anim_res->AnimationID, SIZE_CHAR_MAX, anim->AnimatonID);
	for (int j = 0; j <= anim->BoneAnimation->PushPos - 1; j++){
		CBoneAnimation *bone_anim = *(CBoneAnimation **)anim->BoneAnimation->GetData(j);
		CBoneAnimationResource *bone_anim_res = new CBoneAnimationResource();
		wcscpy_s(bone_anim_res->Target, SIZE_CHAR_MAX, bone_anim->Target);
		bone_anim_res->TargetBone = FindBoneByID(bone_anim->Target);
		for (int k = 0; k <= bone_anim->KeyTime->PushPos - 1; k++){
			bone_anim_res->KeyTime->Push((float*)bone_anim->KeyTime->GetData(k));
		}
		for (int k = 0; k <= bone_anim->PoseMatrix->PushPos - 1; k++){
			matrix *mtx = (matrix *)bone_anim->PoseMatrix->GetData(k);
			XMMATRIX pose_matrix = XMMatrixTranspose(XMMATRIX(mtx->m11, mtx->m12, mtx->m13, mtx->m14, mtx->m21, mtx->m22, mtx->m23, mtx->m24, mtx->m31, mtx->m32, mtx->m33, mtx->m34, mtx->m41, mtx->m42, mtx->m43, mtx->m44));
			bone_anim_res->PoseMatrix->Push((void *)&pose_matrix);
		}
		anim_res->BoneAnimation->Push((void *)&bone_anim_res);
	}
	AnimationList->Push((void *)&anim_res);

	return true;
}

CBoneResource *CChaResourceObject::FindBoneByID(wchar_t *search_name){

	if (search_name == NULL)
		return NULL;

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

	return NULL;
}
	
///////////////////////////////////////////////////////////////////////////////

bool CChaResourceObject::Draw(ID3D11DeviceContext *m_pDeviceContext ){

	ConstantBufferBoneJoint constant_buffer2;
	
	for (int i = 0; i <= BoneArray->PushPos - 1; i++){

		CBoneResource *bone_res = *(CBoneResource **)BoneArray->GetData(i);
		XMMATRIX mtx = bone_res->BoneMatrix;
		XMStoreFloat4x4( &constant_buffer2.BoneMatrix[i], XMMatrixTranspose( mtx ));
	}

	ConstantBufferMaterial constant_buffer1;

	UINT stride = sizeof(CVertex);
	UINT offset = 0;
	m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

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

		CGeometryResource *gmt_res = *(CGeometryResource **)GeometryResource->GetData(i);
		m_pDeviceContext->IASetVertexBuffers(0, 1, &gmt_res->VertexBuffer, &stride, &offset);

		XMStoreFloat4x4( &constant_buffer2.BindShapeMatrix, XMMatrixTranspose( gmt_res->BindShapeMatrix ));
		m_pDeviceContext->UpdateSubresource(m_pConstantBuffer2, 0, NULL, &constant_buffer2, 0, 0);
		m_pDeviceContext->VSSetConstantBuffers(2, 1, &m_pConstantBuffer2);
		m_pDeviceContext->PSSetConstantBuffers(2, 1, &m_pConstantBuffer2);

		for (int j = 0; j <= gmt_res->IndexBuffer->PushPos - 1; j++){

			ID3D11Buffer **index_buffer = (ID3D11Buffer **)gmt_res->IndexBuffer->GetData(j);
			m_pDeviceContext->IASetIndexBuffer(*index_buffer, DXGI_FORMAT_R32_UINT, 0);

			CMaterialResource *material = *(CMaterialResource **)gmt_res->Material->GetData(j);
			if (material != NULL){

				constant_buffer1.Ambient = XMFLOAT4(material->ambient.x, material->ambient.y, material->ambient.z, material->ambient.w );
				constant_buffer1.Diffuse = XMFLOAT4(material->diffuse.x, material->diffuse.y, material->diffuse.z, material->diffuse.w);
				constant_buffer1.Specular = XMFLOAT4(material->specular.x, material->specular.y, material->specular.z, material->specular.w);
				m_pDeviceContext->UpdateSubresource(m_pConstantBuffer1, 0, NULL, &constant_buffer1, 0, 0);
				m_pDeviceContext->PSSetConstantBuffers(1, 1, &m_pConstantBuffer1);

				if (material->ShaderResourceView != NULL)
					m_pDeviceContext->PSSetShaderResources(0, 1, (ID3D11ShaderResourceView **)material->ShaderResourceView);
			}

			int *index_count = (int *)gmt_res->IndexCount->GetData(j);
			m_pDeviceContext->DrawIndexed(*index_count, 0, 0);
		}
	}

	return true;
}

XMMATRIX CChaResourceObject::GetAnimationMatrix(CBoneAnimationResource *anim, float sec){

	XMMATRIX matrix = XMMatrixIdentity();

	if ((int)anim->PoseMatrix->PushPos <= 0)
		return matrix;

	float end_time = *(float*) anim->KeyTime->GetData( anim->KeyTime->PushPos - 1 );

	if (end_time < sec){
		FrameCount = 0;
		sec = 0;
	}

	if (anim->Refrain == false && end_time < sec)
		sec = 0;

	int sec_int = (int)(sec * 10000);
	int sec_end = (int)(end_time * 10000);
	int time_int = sec_int % sec_end;
	float time = ((float)time_int) / 10000.000f;

	int matrix_num = 0;
	while (*(float *) anim->KeyTime->GetData( matrix_num ) < time){
		matrix_num++;
	}
	if (matrix_num > (int)anim->KeyTime->PushPos - 1)
		return matrix;

	XMMATRIX matrix1 = XMMatrixIdentity();
	XMMATRIX matrix2 = XMMatrixIdentity();
	if (matrix_num == 0){
		return *(XMMATRIX *) anim->PoseMatrix->GetData( 0 );
	}
	matrix1 = *(XMMATRIX *) anim->PoseMatrix->GetData(matrix_num - 1);
	matrix2 = *(XMMATRIX *) anim->PoseMatrix->GetData(matrix_num);

	float key_time1, key_time2;
	key_time1 = *(float*)anim->KeyTime->GetData( matrix_num - 1 );
	key_time2 = *(float*)anim->KeyTime->GetData( matrix_num );
	float pos = (time - key_time1) / (key_time2 - key_time1);
	XMMATRIX matrix_out = CalcInterPauseLinear(matrix1, matrix2, pos);

	return matrix_out;
}

XMMATRIX CChaResourceObject::CalcInterPauseLinear(XMMATRIX matrix1, XMMATRIX matrix2, float t){

	XMMATRIX matrix_out;
	matrix_out._11 = matrix1._11 + (matrix2._11 - matrix1._11) * t;
	matrix_out._12 = matrix1._12 + (matrix2._12 - matrix1._12) * t;
	matrix_out._13 = matrix1._13 + (matrix2._13 - matrix1._13) * t;
	matrix_out._14 = matrix1._14 + (matrix2._14 - matrix1._14) * t;
	matrix_out._21 = matrix1._21 + (matrix2._21 - matrix1._21) * t;
	matrix_out._22 = matrix1._22 + (matrix2._22 - matrix1._22) * t;
	matrix_out._23 = matrix1._23 + (matrix2._23 - matrix1._23) * t;
	matrix_out._24 = matrix1._24 + (matrix2._24 - matrix1._24) * t;
	matrix_out._31 = matrix1._31 + (matrix2._31 - matrix1._31) * t;
	matrix_out._32 = matrix1._32 + (matrix2._32 - matrix1._32) * t;
	matrix_out._33 = matrix1._33 + (matrix2._33 - matrix1._33) * t;
	matrix_out._34 = matrix1._34 + (matrix2._34 - matrix1._34) * t;
	matrix_out._41 = matrix1._41 + (matrix2._41 - matrix1._41) * t;
	matrix_out._42 = matrix1._42 + (matrix2._42 - matrix1._42) * t;
	matrix_out._43 = matrix1._43 + (matrix2._43 - matrix1._43) * t;
	matrix_out._44 = matrix1._44 + (matrix2._44 - matrix1._44) * t;

	return matrix_out;
}

////////////////////////////////////////////////////////////////////////////
// ボーンの変形

bool CChaResourceObject::BoneTransform(CBoneResource *bone){

	XMVECTOR vec;
	if (bone->ParentBone == NULL){
		bone->BoneMatrix = bone->InvBindMatrix * bone->JointParamTransformed * XMMatrixInverse(&vec, bone->InvBindMatrix * bone->JointParam);
	}
	else{
		bone->BoneMatrix = bone->InvBindMatrix * bone->JointParamTransformed * XMMatrixInverse(&vec, bone->InvBindMatrix * bone->JointParam) * bone->ParentBone->BoneMatrix;
	}
	for (int i = 0; i <= (int)bone->ChildBone->PushPos - 1; i++){
		BoneTransform(*(CBoneResource **)bone->ChildBone->GetData(i));
	}

	return true;
}

bool CChaResourceObject::SetCurrentAnimation(int num, int change_frame_count ){
	
	if (num < 0 || num > AnimationList->PushPos)
		return false;

	if (num == CurrentAnimationNum)
		return false;

	////////////////////////////////////////////////////////////////////////
	//現在のアニメーションから新しいアニメーションへ補完しながら移行。

	CAnimationResource *anim_res_prev = *(CAnimationResource **)AnimationList->GetData(CurrentAnimationNum);
	CAnimationResource *anim_res_new = *(CAnimationResource **)AnimationList->GetData(num);

	float sec = (float)FrameCount / 50.00f;

	for (int i = 0; i <= BoneArray->PushPos - 1; i++){
		CBoneResource *bone = *(CBoneResource **)BoneArray->GetData(i);
		bone->NowChangeFrameCount = 0;
		bone->ChangeFrameCount = 0;
		bone->ChangeNewAnimation = false;
	}

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

		CBoneAnimationResource *bone_anim_new = *(CBoneAnimationResource **)anim_res_new->BoneAnimation->GetData(i);
		XMMATRIX mtx = GetAnimationMatrix(bone_anim_new, sec);

		for (int j = 0; j <= (int)BoneArray->PushPos - 1; j++){
			CBoneResource *bone = *(CBoneResource **)BoneArray->GetData(j);
			if (bone_anim_new->TargetBone == bone && bone_anim_new->TargetBone != NULL){
				bone->ChangeFrameCount = change_frame_count;
				bone->PrevJointParamTransformed = mtx;
				bone->ChangeNewAnimation = true;
				bone->ChangeFrameCount = change_frame_count;
				bone->NowChangeFrameCount = 0;
			}
		}
	}

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

		CBoneAnimationResource *bone_anim_prev = *(CBoneAnimationResource **)anim_res_prev->BoneAnimation->GetData(i);
		XMMATRIX mtx = GetAnimationMatrix(bone_anim_prev, sec);
		
		for (int j = 0; j <= (int)BoneArray->PushPos - 1; j++){
			CBoneResource *bone = *(CBoneResource **)BoneArray->GetData(j);
			if (bone_anim_prev->TargetBone == bone && bone_anim_prev->TargetBone != NULL){
				bone->ChangeFrameCount = change_frame_count;
				bone->PrevJointParamTransformed = mtx;
				bone->ChangeNewAnimation = true;
				bone->ChangeFrameCount = change_frame_count;
				bone->NowChangeFrameCount = 0;
			}
		}
	}

	CurrentAnimationNum = num;

	return true;
}


bool CChaResourceObject::UpdateTransform(ID3D11Device *m_pDevice, CChaDataObject *object){

	if (CurrentAnimationNum < 0 || CurrentAnimationNum > AnimationList->PushPos - 1 )
		return false;

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

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

	CAnimationResource *anim_res = *(CAnimationResource **) AnimationList->GetData(CurrentAnimationNum);

	float sec = (float)FrameCount / 50.00f;

	for (int i = 0; i <= ControlBone->PushPos - 1; i++)
		BoneInit(*(CBoneResource **)ControlBone->GetData(i));

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

		CBoneResource *bone = *(CBoneResource **)BoneArray->GetData(i);
		XMMATRIX mtx = bone->JointParam;

		for (int j = 0; j <= anim_res->BoneAnimation->PushPos - 1; j++){

			CBoneAnimationResource *bone_anim = *(CBoneAnimationResource **)anim_res->BoneAnimation->GetData(j);
			if (bone_anim->TargetBone != NULL && bone_anim->TargetBone == bone){
				mtx = GetAnimationMatrix(bone_anim, sec);
			}
		}
			
		//現在のアニメーションから新しいアニメーションへ移行中の場合
		if (bone->ChangeNewAnimation == true){
			bone->NowChangeFrameCount++;
			if (bone->NowChangeFrameCount >= bone->ChangeFrameCount){
				bone->NowChangeFrameCount = 0;
				bone->ChangeFrameCount = 0;
				bone->ChangeNewAnimation = false;
			}
			else{
				float rate = (float)bone->NowChangeFrameCount / (float)bone->ChangeFrameCount;
				mtx = CalcInterPauseLinear(bone->PrevJointParamTransformed, mtx, rate);
			}
		}

		bone->JointParamTransformed = mtx;
	}

	for (int i = 0; i <= ControlBone->PushPos - 1; i++){
		CBoneResource *parent = *(CBoneResource**)ControlBone->GetData(i);
		BoneTransform(parent);
	}

	return true;
}

bool CChaResourceObject::BoneInit(CBoneResource *bone){

	bone->BoneMatrix = XMMatrixIdentity();

	if (bone->ParentBone != NULL){
		bone->JointParamTransformed = bone->JointParam;
	}
	for (int i = 0; i <= (int)bone->ChildBone->PushPos - 1; i++){
		BoneInit(*(CBoneResource ** ) bone->ChildBone->GetData( i ));
	}

	return true;
}
