//=========================================================================
//	スミクラス	[ k_sumi.cpp ]
//	作成日：2017/06/05
//	作成者：小暮大樹
//=========================================================================
#include	"k_sumi.h"
#include	"main.h"
#include	<time.h>
#include	"renderer.h"
#include	"manager.h"
#include	"camera.h"
#include	"light.h"

//=========================================================================
//	定数定義
//=========================================================================
#define NUM_VERTEX (4)								// 頂点数
#define NUM_INDEX  (6)								// 頂点インデックス数

//カメラの仕様が違かった場合、ここ変更してパーティクルを回す
#define ROT_KAMERA_Y	( 180.0f )							
	
#define NUM_POLYGON (2)								// ポリゴン数

#define TEXTURENAME "data/TEXTURE/smoke.jpg"

#define PARTICLE_LIFE ( 100 )						// エフェクトの寿命

#define PARTICLE_RADIUS (30)						// 背景の幅

#define RADIAN(arc) (((arc) * D3DX_PI ) / 180)		// ラジアンの計算に必要

#define SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }

//=========================================================================
//	初期化
//=========================================================================
void	KSumi::Init( void )
{
	srand( ( unsigned int ) time( NULL ) );

	LPDIRECT3DDEVICE9	pDevice;
	pDevice = CRenderer::GetDevice();


	// パーティクルパラメーター初期化
	for( int index = 0; index < PARTICLE_MAX ; index++ ){

		m_aParticle[ index ].life   = 0; 
		m_aParticle[ index ].radius = PARTICLE_RADIUS;
		m_aParticle[ index ].arc.x    = RADIAN( 10 * index );

		m_aParticle[ index ].ambientPower = D3DXVECTOR3( 0, 0 , 0 );

		m_nCountBuf[ index ] = 0;
	}

	m_nNumber = 0;

	// VERTEX_2Dの設定
	MakeVertex( pDevice );

		// テクスチャの読み込み
	if( FAILED(D3DXCreateTextureFromFile( pDevice, TEXTURENAME, &m_pTexture )))
	{
#ifdef _DEBUG
		MessageBox( NULL , "ポリゴンファイルが読み込めません\n" , "ERROR[ k_sumi.cpp ]" , MB_OK | MB_ICONEXCLAMATION );		
#endif
	}

	//スミっぽいパーティクルのせってい

}
//=========================================================================
//	終了
//=========================================================================
// パーティクル終了処理
void KSumi::Uninit( void )
{
	// テクスチャインターフェースの開放
	SAFE_RELEASE( m_pTexture )

	// インデックスバッファの開放
	SAFE_RELEASE( m_pIndexBuffer )

	// 頂点バッファインターフェースの開放
	SAFE_RELEASE( m_pVtxBuffer )
}

//=========================================================================
//	更新
//=========================================================================
void	KSumi::Update( void )
{
	//スミ出すやつ
	//SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	
	/*
	SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	SetParticle( D3DXVECTOR3( 0.0f , 0.0f , 0.0f) );
	*/
// 仮想アドレス
	VERTEX_3D *pVtx;


	// 使用中エフェクトの初期化
	m_nNumber = 0;


	// パーティクルの更新
	for( int index = 0; index < PARTICLE_MAX; index++ ){

		// 使用したバッファの初期化( 本来なら別処理で行うのがスマートだが処理速度高速化のためここで初期化 )
		m_nCountBuf[ index ] = 0;

		if( m_aParticle[ index ].life ){


			// 使用中エフェクトのカウント
			m_nCountBuf[ m_nNumber ] = index;
			m_nNumber++;
				

			{ // パーティクルパラメーターの更新


				// パーティクル存在フレームの更新
				m_aParticle[ index ].life -= 1 ;
				m_aParticle[ index ].age  += 1;

				// 色の設定
				m_aParticle[ index ].color.r -= m_aParticle[ index ].amountOfChangeInColor.r;
				m_aParticle[ index ].color.g -= m_aParticle[ index ].amountOfChangeInColor.g;
				m_aParticle[ index ].color.b -= m_aParticle[ index ].amountOfChangeInColor.b;
				m_aParticle[ index ].color.a -= m_aParticle[ index ].amountOfChangeInColor.a;
				if( m_aParticle[ index ].color.a < 0.0f ){
					m_aParticle[ index ].color.a = 0.0f;
				}

				/*// 半径の更新と設定
				particle[ index ].radius -= particle[ index ].amountOfChangeInRadius;
				if( particle[ index ].radius < 0.0f ){
					particle[ index ].radius = 0.0f;
				}*/

				// 加速度の加算
				m_aParticle[ index ].speed.x *= m_aParticle[ index ].velocity.x;
				m_aParticle[ index ].speed.y *= m_aParticle[ index ].velocity.y;
				m_aParticle[ index ].speed.z *= m_aParticle[ index ].velocity.z;

				// パーティクルの移動
				m_aParticle[ index ].center.x += m_aParticle[ index ].speed.x * sinf( m_aParticle[ index ].arc.x )* cosf(m_aParticle[ index ].arc.y) ;
				m_aParticle[ index ].center.y += m_aParticle[ index ].speed.y * cosf( m_aParticle[ index ].arc.x );
				m_aParticle[ index ].center.z += m_aParticle[ index ].speed.z * sinf( m_aParticle[ index ].arc.x )* cosf(m_aParticle[ index ].arc.y)  ;

				// 環境力によるベクトル変換
				if( m_aParticle[ index ].age > 10 ){
					m_aParticle[ index ].center += m_aParticle[ index ].ambientPower;
				}


			} // -> END ( PARTICLE UPDATE )
			
		}	// if( particle[ index ].life ) -> END
	}	// for -> END


	// バッファをロックし仮想アドレスを取得する
	m_pVtxBuffer -> Lock(0,0,(void**)&pVtx,0);

	// 頂点情報の格納
	for( int index = 0; index < m_nNumber; index++ ){

		// エフェクトの設置
		SetVertexColor( pVtx, index );
		SetVertexCoord( pVtx, index );
	}

	// バッファのアンロック
	m_pVtxBuffer->Unlock();

}

//=========================================================================
//	描画
//=========================================================================	
void	KSumi::Draw( void )
{
	LPDIRECT3DDEVICE9	pDevice;
	pDevice = CRenderer::GetDevice();

	//ワールドマトリクスの作成
	D3DXMATRIX	mtxWorld , mtxRot;
	//↑４＊４行列クラス

	//単位行列の作成
	D3DXMatrixIdentity( &mtxWorld );	//行列を単位行列にする
	
	//拡大の処理
	D3DXMATRIX	mtxKakudai;	//拡大行列
	D3DXMatrixScaling( &mtxKakudai , 1.0f , 1.0f , 1.0f );

	//回転の処理
	D3DXMATRIX	mtxKaiten;	//回転行列
	D3DXMatrixRotationYawPitchRoll( &mtxKaiten , D3DXToRadian( ROT_KAMERA_Y ) , 0.0f , 0.0f );	
	
	D3DXMATRIX	mtxHeikou;	//並行移動行列
	D3DXMatrixTranslation( &mtxHeikou , 0.0f , 0.0f , 0.0f );

	//行列の掛け算
	D3DXMatrixMultiply( &mtxWorld , &mtxWorld , &mtxKakudai );	
	D3DXMatrixMultiply( &mtxWorld , &mtxWorld , &mtxKaiten );	
	D3DXMatrixMultiply( &mtxWorld , &mtxWorld , &mtxHeikou );	

	//デバイスにワールド変換行列を登録
	pDevice->SetTransform( D3DTS_WORLD , &mtxWorld );

	//ビュー行列の作成
	D3DXMATRIX	mtxView = CManager::GetCamera()->GetView();

	//デバイスにビュー変換行列を設定
	pDevice->SetTransform( D3DTS_VIEW , &mtxView);

	pDevice->SetLight( 0, &CManager::GetLight()->GetLight() );

	//統合的なライトをOFFにしておく
	pDevice->SetRenderState( D3DRS_LIGHTING , FALSE );

	pDevice ->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT );
	pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );	
	pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );

	pDevice ->SetRenderState( D3DRS_ZWRITEENABLE, false );


	// ストリーム
	pDevice->SetStreamSource(0,					
		m_pVtxBuffer,								// どの頂点バッファ―と結ぶか...
		0,													// データのオフセット
		sizeof( VERTEX_3D ));								// ストライド値(バイト)

	// 頂点フォーマットの設定
	pDevice->SetFVF( FVF_VERTEX_3D );

	// インデックスバッファの設定
	pDevice ->SetIndices( m_pIndexBuffer );

	// テクスチャの設定
	pDevice->SetTexture( 0, m_pTexture );
	
	// ポリゴンの描画
	pDevice ->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 0, NUM_INDEX * m_nNumber, 0, NUM_POLYGON * m_nNumber );

	// 元の状態に戻す
	pDevice->SetRenderState( D3DRS_BLENDOP , D3DBLENDOP_ADD); //default
	pDevice ->SetRenderState( D3DRS_ZWRITEENABLE, true );

	//pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	pDevice->SetRenderState( D3DRS_DESTBLEND,D3DBLEND_INVSRCALPHA );
}

//=========================================================================
// 頂点の作成
//=========================================================================
HRESULT KSumi::MakeVertex( LPDIRECT3DDEVICE9 pDevice )
{


	VERTEX_3D *pVtx;										// 仮想アドレス
	unsigned int *pIndex;									// 仮想インデックスアドレス


	if(FAILED(pDevice->CreateVertexBuffer(
			sizeof(VERTEX_3D) * NUM_VERTEX * PARTICLE_MAX,	// 確保するバッファサイズ(頂点数分確保) 単位:バイト
			D3DUSAGE_WRITEONLY,								// 使用方法
			FVF_VERTEX_3D,									// 使用する頂点フォーマット(特殊な処理をしない限り参照されないので0でよい)
			D3DPOOL_MANAGED,								// バッファの管理方法(バッファの中に書き込んだものの管理方法)
			&m_pVtxBuffer,							// 格納するポインタ先
			NULL)))
	{
		#ifdef _DEBUG
		MessageBox(NULL,"バッファへの書き込みに失敗しました!!","vertex buffer ERROR!!",MB_OK);
		#endif	// _DEBUG
		return E_FAIL;
	}


	// インデックスバッファの定義
	if( FAILED( pDevice ->CreateIndexBuffer(
		sizeof( VERTEX_3D ) * NUM_INDEX * PARTICLE_MAX,
		D3DUSAGE_WRITEONLY,
		D3DFMT_INDEX32,
		D3DPOOL_MANAGED,
		&m_pIndexBuffer,
		NULL)))
	{
	
		#ifdef _DEBUG
		MessageBox( NULL, "Indexへの書き込みに失敗しました!!", "ERROR[ k_sumi.cpp ]", MB_OK | MB_ICONWARNING );
		#endif	// -> _DEBUG
		return E_FAIL;
	}


	// バッファをロックし仮想アドレスを取得する	
	m_pVtxBuffer -> Lock(0,0,(void**)&pVtx,0);		// GPUからのVRAMへの操作をロックする


	// 頂点バッファーの設定
	for( int index = 0; index < PARTICLE_MAX ; index++ ){


		// 頂点座標の設定
		SetVertexCoord( pVtx , index );

		// 頂点色の設定
		SetVertexColor( pVtx , index );

		// 頂点UV値の設定
		SetVertexSpriteUV( pVtx , index );

		// 頂点のRHW
		pVtx[ 0 + ( NUM_VERTEX * index ) ].normal = D3DXVECTOR3(  0.0f , 0.0f , 0.0f );
		pVtx[ 1 + ( NUM_VERTEX * index ) ].normal = D3DXVECTOR3(  0.0f , 0.0f , 0.0f );
		pVtx[ 2 + ( NUM_VERTEX * index ) ].normal = D3DXVECTOR3(  0.0f , 0.0f , 0.0f );
		pVtx[ 3 + ( NUM_VERTEX * index ) ].normal = D3DXVECTOR3(  0.0f , 0.0f , 0.0f );

	}

	// バッファのアンロック
	m_pVtxBuffer->Unlock( );

	// インデックスをロックし仮想アドレスを取得する
	m_pIndexBuffer->Lock( 0, 0, (void**)&pIndex, 0 );


	// 頂点座標の設定
	for( int index = 0; index < PARTICLE_MAX ; index++ ){

		pIndex[ 0 + ( NUM_INDEX * index ) ] = 0 + ( NUM_VERTEX * index );
		pIndex[ 1 + ( NUM_INDEX * index ) ] = 1 + ( NUM_VERTEX * index );
		pIndex[ 2 + ( NUM_INDEX * index ) ] = 2 + ( NUM_VERTEX * index );
		pIndex[ 3 + ( NUM_INDEX * index ) ] = 2 + ( NUM_VERTEX * index );
		pIndex[ 4 + ( NUM_INDEX * index ) ] = 1 + ( NUM_VERTEX * index );
		pIndex[ 5 + ( NUM_INDEX * index ) ] = 3 + ( NUM_VERTEX * index );

	}

	// バッファのアンロック
	m_pIndexBuffer ->Unlock( );


	return S_OK;

}

// パーティクル座標設置
void KSumi::SetVertexCoord( VERTEX_3D *pVtx , const int index )
{


	// pVtx     >> 仮想アドレス
	// arryycenter >> どの番目のエフェクトか...


	D3DXVECTOR3 start,end;			//始点と終点


	// 座標計算particle
	start.x = m_aParticle[ index ].center.x - m_aParticle[ index ].radius;
	start.y = m_aParticle[ index ].center.y - m_aParticle[ index ].radius;
	start.z = m_aParticle[ index ].center.z - m_aParticle[ index ].radius;
	end.x   = m_aParticle[ index ].center.x + m_aParticle[ index ].radius;
	end.y   = m_aParticle[ index ].center.y + m_aParticle[ index ].radius;
	end.z   = m_aParticle[ index ].center.z + m_aParticle[ index ].radius;

	// 頂点座標の設定
	pVtx[ 0 + (index * NUM_VERTEX) ].pos = D3DXVECTOR3( start.x, start.y, start.z );
	pVtx[ 1 + (index * NUM_VERTEX) ].pos = D3DXVECTOR3( end.x,   start.y, start.z );
	pVtx[ 2 + (index * NUM_VERTEX) ].pos = D3DXVECTOR3( start.x, end.y,   start.z );
	pVtx[ 3 + (index * NUM_VERTEX) ].pos = D3DXVECTOR3( end.x,   end.y,   start.z );


}

// パーティクル色変更関数
void KSumi::SetVertexColor( VERTEX_3D *pVtx , const int index )
{
	
	// αの変更
	pVtx[ 0 + (index * NUM_VERTEX) ].color = m_aParticle[ index ].color;
	pVtx[ 1 + (index * NUM_VERTEX) ].color = m_aParticle[ index ].color;
	pVtx[ 2 + (index * NUM_VERTEX) ].color = m_aParticle[ index ].color;
	pVtx[ 3 + (index * NUM_VERTEX) ].color = m_aParticle[ index ].color;
	

}

// パーティクルUV値のセット
void KSumi::SetVertexSpriteUV( VERTEX_3D *pVtx , const int index  )
{

	pVtx[ 0 + (index * NUM_VERTEX) ].tex = D3DXVECTOR2( 0.0f, 0.0f );
	pVtx[ 1 + (index * NUM_VERTEX) ].tex = D3DXVECTOR2( 1.0f, 0.0f );
	pVtx[ 2 + (index * NUM_VERTEX) ].tex = D3DXVECTOR2( 0.0f, 1.0f );
	pVtx[ 3 + (index * NUM_VERTEX) ].tex = D3DXVECTOR2( 1.0f, 1.0f );

}

// パーティクル発射(オールランダム)
void KSumi::SetParticle( const D3DXVECTOR3 center )
{


	//srand( ( unsigned int ) time( NULL ) );

	// エフェクトの設置
	for( int index = 0; index < PARTICLE_MAX; index++ ){

		if( !m_aParticle[ index ].life ){
			

			{ // パーティクルパラメーターの設定


				// パーティクル中心座標
				m_aParticle[ index ].center   =  center;

				// パーティクルの速度
				m_aParticle[ index ].speed    =  D3DXVECTOR3( 0.5f, 0.5f , 0.5f ); 

				// パーティクルの加速度
				m_aParticle[ index ].velocity =
				D3DXVECTOR3( 1.0f + ((( rand( )%200 ) - 100  ) * 0.001f ), 1.0f + ((( rand( )%200 ) - 100  ) * 0.001f ) , 1.0f + ((( rand( )%200 ) - 100  ) * 0.001f ) ); 

				// パーティクル移動方向の設定
				m_aParticle[ index ].arc.x      =  (( rand( )%628 ) - 314 ) * 0.01f;
				m_aParticle[ index ].arc.y      =  (( rand( )%628 ) - 314 ) * 0.01f;

				// パーティクル色
				m_aParticle[ index ].color    =  D3DXCOLOR( rand()%50 * 0.02f, rand()%50 * 0.02f, rand()%50 * 0.02f , 1.0f );

				// パーティクル半径
				m_aParticle[ index ].radius   =  rand( )%100 + 5;

				// パーティクルの存在フレーム数
				m_aParticle[ index ].life     =  rand( )%100 + 200;

				// パーティクル変化量定数
				m_aParticle[ index ].amountOfChangeInColor.a  = m_aParticle[ index ].color.a / m_aParticle[ index ].life;
				m_aParticle[ index ].amountOfChangeInColor.r  = m_aParticle[ index ].color.r / m_aParticle[ index ].life;
				m_aParticle[ index ].amountOfChangeInColor.g  = m_aParticle[ index ].color.g / m_aParticle[ index ].life;
				m_aParticle[ index ].amountOfChangeInColor.b  = m_aParticle[ index ].color.b / m_aParticle[ index ].life;
				m_aParticle[ index ].amountOfChangeInRadius   = (m_aParticle[ index ].radius - 10) / m_aParticle[ index ].life;
				
			
			} // -> END ( PARTICLE SET )

			break;

		}
	}

}
