////////////////////////////////////////////////////////
// filename: CParticle.cpp
// author: Chafumi Touji
// version: 1.0.0
// date: 2020/09/03
////////////////////////////////////////////////////////

#include "defcha3dcore.h"
#include "CParticle.h"

CParticleData::CParticleData(){

	Count = 0;
	CountMax = 0;
	x = y = z = 0.0f;
	rot_x = rot_y = rot_z = 0.0f;
	vec_x = vec_y = vec_z = 0.0f;
	r_vec_x = r_vec_y = r_vec_z = 0.0f;
	alpha = 0.0f;
}

CParticleData::~CParticleData(){
}

bool CParticleData::InitParticle( int id, int init_count, int count_max, XMFLOAT4 center, XMFLOAT4 field_range ){

	ID = id;
	Count = init_count;
	CountMax = count_max;
	alpha = sin(((float)Count / (float)CountMax) * 3.14159265f);

	x = ((float)(rand() % 10000 - 5000)) / 5000.0f;
	y = ((float)(rand() % 10000 - 5000)) / 5000.0f;
	z = ((float)(rand() % 10000 - 5000)) / 5000.0f;
	x *= field_range.x;
	y *= field_range.y;
	z *= field_range.z;
	x += center.x;
	y += center.y;
	z += center.z;
	rot_x = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 3.14159265f;
	rot_y = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 3.14159265f;
	rot_z = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 3.14159265f;

	vec_x = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 0.02f;
	vec_y = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 0.02f;
	vec_z = -0.1f;
	r_vec_x = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 0.2f;
	r_vec_y = 0.0f;
	r_vec_z = ((float)((rand() % 10000 - 5000) / 5000.0f)) * 0.2f;

	return true;
}

bool CParticleData::Update(){

	x += vec_x;
	y += vec_y;
	z += vec_z;

	float random1 = (float)((((ID + 365) * 10000 + 476) % 10000 ) / 10000.0f ) * 3.14159265f * 2.0f;
	float random2 = (float)((((ID + 256) * 10000 + 787) % 10000) / 10000.0f ) * 3.14159265f * 2.0f;
	vec_x = sin(((float)Count / (float)CountMax) * 3.14159265f * 3.0f + random1 ) * 0.15f;
	vec_y = cos(((float)Count / (float)CountMax) * 3.14159265f * 3.0f + random2 ) * 0.15f;
	rot_x += r_vec_x;
	rot_y += r_vec_y;
	rot_z += r_vec_z;
	alpha = pow(sin(((float)Count / (float)CountMax) * 3.14159265f), 4.0f);

	Count++;
	if (Count >= CountMax){
		Count = 0;
		return true;
	}

	return false;
}

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

CParticle::CParticle(){

	ParticleNum = 0;
	ParticleData = 0;
	Center = XMFLOAT4(0, 0, 0, 0);
	FieldRange = XMFLOAT4(0, 0, 0, 0);
	CountMax = 0;
}

CParticle::~CParticle(){

	if (ParticleNum > 0){
		delete[] ParticleData;
	}
}

bool CParticle::CreateResource( CCommonDevice *device, wchar_t *path, wchar_t *texture_particle_name, XMFLOAT4 center, XMFLOAT4 field_range, int particle_num, int count_max, float size ){

	Center = center;
	FieldRange = field_range;
	CountMax = count_max;
	ParticleNum = particle_num;
	ParticleData = new CParticleData[ParticleNum];
	for (int i = 0; i <= ParticleNum - 1; i++){
		int init_count = (int)rand() % count_max;
		ParticleData[i].InitParticle(i, init_count, count_max, center, field_range);
	}

	////////////////////////////////////////////////////////////////////
	//テクスチャ作成

	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_R8G8B8A8_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_R8G8B8A8_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;

	ID3D11Resource *resource = NULL;

	/*-----------------------------------------------------*/

	wchar_t filepath[SIZE_CHAR_MAX];
	wmemset(filepath, 0, SIZE_CHAR_MAX);
	wcscpy_s(filepath, SIZE_CHAR_MAX, path);
	wcscat_s(filepath, _T("/"));
	wcscat_s(filepath, texture_particle_name);
	m_pParticleTexture = NULL;
	D3DX11CreateTextureFromFile(device->m_pDevice, filepath, &info, NULL, &resource, NULL);
	m_pParticleTexture = (ID3D11Texture2D *)resource;
	device->m_pDevice->CreateShaderResourceView(m_pParticleTexture, &desc_shader_resource, &m_pParticleShaderResourceView);

	CVertex *VtxData = new CVertex[4];
	SetVertex(&VtxData[0], size, 0, size, 0, 0, 0, 0, 0, 0, 0, 0, 0);
	SetVertex(&VtxData[1], size, 0, -size, 0, 0, 0, 0, 0, 0, 0, 0, 1);
	SetVertex(&VtxData[2], -size, 0, size, 0, 0, 0, 0, 0, 0, 0, 1, 0);
	SetVertex(&VtxData[3], -size, 0, -size, 0, 0, 0, 0, 0, 0, 0, 1, 1);

	D3D11_BUFFER_DESC desc_buffer;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(CVertex)* 4;
	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(CVertex);
	D3D11_SUBRESOURCE_DATA msr;
	msr.pSysMem = VtxData;
	device->m_pDevice->CreateBuffer(&desc_buffer, &msr, &ParticleBuffer);

	delete[] VtxData;

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

	m_pConstantBufferParticle = NULL;
	ZeroMemory(&desc_buffer, sizeof(D3D11_BUFFER_DESC));
	desc_buffer.ByteWidth = sizeof(ConstantBufferParticle);
	desc_buffer.Usage = D3D11_USAGE_DYNAMIC;
	desc_buffer.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
	desc_buffer.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
	desc_buffer.MiscFlags = 0;
	desc_buffer.StructureByteStride = sizeof(float);
	device->m_pDevice->CreateBuffer(&desc_buffer, NULL, &m_pConstantBufferParticle);

	return true;
}

bool CParticle::Update(){

	for (int i = 0; i <= ParticleNum - 1; i++){
		bool finished = ParticleData[i].Update();
		if ( finished == true )
			ParticleData[i].InitParticle(i, 0, CountMax, Center, FieldRange);
	}

	return true;
}

bool CParticle::Draw(CCommonDevice *device){

	device->m_pDeviceContext->VSSetShader(device->m_pVtxShader1_6, NULL, 0);
	device->m_pDeviceContext->PSSetShader(device->m_pPxShader14, NULL, 0);
	device->m_pDeviceContext->PSSetShaderResources(0, 1, &m_pParticleShaderResourceView);
	device->m_pDeviceContext->PSSetSamplers(0, 1, &device->m_pSampleState);

	Update();

	for (int i = 0; i <= ParticleNum - 1; i++){

		XMMATRIX matrix = XMMatrixRotationZ(ParticleData[i].rot_z) * XMMatrixRotationX(ParticleData[i].rot_x) * XMMatrixRotationY(ParticleData[i].rot_y) * XMMatrixTranslation(ParticleData[i].x, ParticleData[i].y, ParticleData[i].z);

		ConstantBufferParticle		constant_buffer_particle;

		XMStoreFloat4x4(&constant_buffer_particle.MatParticle, XMMatrixTranspose(matrix));
		constant_buffer_particle.ParticleParam1 = XMFLOAT4( ParticleData[i].alpha, 0, 0, 0);

		//コンスタントバッファ設定
		D3D11_MAPPED_SUBRESOURCE resource;
		device->m_pDeviceContext->Map(m_pConstantBufferParticle, 0, D3D11_MAP_WRITE_DISCARD, 0, &resource);
		memcpy(resource.pData, &constant_buffer_particle, sizeof(ConstantBufferParticle));
		device->m_pDeviceContext->Unmap(m_pConstantBufferParticle, 0);

		UINT stride = sizeof(CVertex);
		UINT offset = 0;

		device->m_pDeviceContext->VSSetConstantBuffers(3, 1, &m_pConstantBufferParticle);
		device->m_pDeviceContext->PSSetConstantBuffers(3, 1, &m_pConstantBufferParticle);

		device->m_pDeviceContext->IASetInputLayout(device->m_pLayout2);
		device->m_pDeviceContext->RSSetState(device->m_pRasterizeState);
		device->m_pDeviceContext->OMSetBlendState(device->m_pBlendState2, NULL, 0xffffffff);
		device->m_pDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);

		device->m_pDeviceContext->IASetVertexBuffers(0, 1, &ParticleBuffer, &stride, &offset);
		device->m_pDeviceContext->Draw(4, 0);
	}

	return true;
}
