//=========================================================================
//	CSceneMeshクラス [ sceneMesh.cpp ]
//	作成日：2017/05/02
//	作成者：小暮大樹
//=========================================================================
//=========================================================================
//	インクルードファイル
//=========================================================================
#include	"k_field.h"
#include	"manager.h"
#include	"renderer.h"
#include	"camera.h"
#include	"light.h"

//=========================================================================
//	定数定義
//=========================================================================
#define	TEXTURE_NAME ("data/TEXTURE/field001.jpg")

//=========================================================================
//	グローバル変数
//=========================================================================
float	g_FieldHeight[ 11 ][ 11 ] =
{
	0
};

/*
//=========================================================================
//	インストラクタ
//=========================================================================
KField::KField( int sheetTate , int sheetYoko , D3DXVECTOR3 Size )
{
	
}
*/

//=========================================================================
//	初期化
//=========================================================================
void	KField::Init( void )
{
	//hrに関数がはいいているので、FAILEDマクロに入れれば横に長くならない
	if( FAILED( D3DXCreateTextureFromFile( CRenderer::GetDevice() , TEXTURE_NAME , &m_pTexture ) ) )
	{	//FALEDマクロ　失敗か成功かを判断する
		UINT nID = MessageBox( NULL , "ポリゴンファイルが読み込めません\n" , "ERROR[ k_field.cpp ]" , MB_OK | MB_ICONEXCLAMATION );		
	}
	//FAILEDマクロでエラーチェックする

	//中心位置
	SetPosition( D3DXVECTOR3( 0 , 0 , 0 ) );
	//大きさ
	SetSize( D3DXVECTOR3( 50.0f , 0.0f , 50.0f ) );

	SetSheet( 10.0f , 10.0f );

	float fLengthYoko = GetSize().x;
	float fLengthTate = GetSize().z;
	unsigned int nFieldYoko = ( unsigned int )GetSheet().x;
	unsigned int nFieldTate = ( unsigned int )GetSheet().z;

	m_pIndexBuffer = NULL;

	//対角線の長さ
	SetLength( sqrtf( ( fLengthYoko * nFieldYoko ) * ( fLengthTate * nFieldTate) /*/ 2*/ ) /*/ 2*/);

	SetAngle( (atan2f( fLengthTate * nFieldTate , fLengthYoko * nFieldYoko ) ) );

	//フィールドの左上
	SetStartPos( D3DXVECTOR3( -(GetLength() * cosf( GetAngle() )) , 0.0f , ( GetLength() * sinf( GetAngle() ) ) /2 ) );

	SetNumVertex( ( nFieldTate + 1 ) * ( nFieldYoko + 1 ) );

	SetNumIndex( ( ( nFieldYoko +1 ) * ( nFieldTate +1 ) ) * 2 -4 );

	SetNumPolygon( GetNumIndex() -2 );

	MakeVertex( CRenderer::GetDevice() );
}

//=========================================================================
//	終了処理
//=========================================================================
void	KField::Uninit( void )
{
	if(m_pVtxBuffer != NULL)
	{
		m_pVtxBuffer->Release();
		m_pVtxBuffer = NULL;
	}

	if(m_pTexture != NULL)
	{
		m_pTexture->Release();
		m_pTexture = NULL;
	}

	if( m_pIndexBuffer != NULL )
	{
		m_pIndexBuffer->Release();
		m_pIndexBuffer = NULL;
	}
}

//=========================================================================
//	更新処理
//=========================================================================
void	KField::Update( void )
{/*変化しないので無し*/}

//=========================================================================
//	描画処理
//=========================================================================
void	KField::Draw( void )
{

	D3DXMATRIX	mtxWorld;	//ワールドマトリクス
	D3DXMatrixIdentity( &mtxWorld );

	//拡大の処理
	D3DXMATRIX	mtxKakudai;	//拡大行列
	D3DXMatrixScaling( &mtxKakudai , 1.0f , 1.0f , 1.0f );

	//回転の処理
	D3DXMATRIX	mtxKaiten;	//回転行列
	D3DXMatrixRotationYawPitchRoll( &mtxKaiten , 0.0f , 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 );	

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

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

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

	//ライトの設定
	CRenderer::GetDevice()->SetLight( 0, &CManager::GetLight()->GetLight() );

	//CManager::GetLight()->OnLight();

	CRenderer::GetDevice()->SetStreamSource( 0 , m_pVtxBuffer , 0 , sizeof(VERTEX_3D) );

	CRenderer::GetDevice()->SetIndices( m_pIndexBuffer );

	CRenderer::GetDevice()->SetFVF( FVF_VERTEX_3D );

	CRenderer::GetDevice()->SetTexture( 0,  m_pTexture );

	//ポリゴンの描画
	CRenderer::GetDevice()->DrawIndexedPrimitive( 
		D3DPT_TRIANGLESTRIP ,
		0 , //最初の頂点インデックスまでのオフセット
		0 , //最小頂点インデックス
		GetNumIndex() ,	//頂点数
		0 , //スタートインデックス
		GetNumPolygon() //プリミティブ数
	 );

	CManager::GetLight()->OnLight();
}

//=========================================================================
//	頂点の編集
//=========================================================================
HRESULT	KField::MakeVertex( LPDIRECT3DDEVICE9 pDevice )
{
	unsigned int nFieldTate = ( unsigned int )GetSheet().z;
	unsigned int nFieldYoko = ( unsigned int )GetSheet().x;

	float	fLengthTate = GetSize().z;
	float	fLengthYoko = GetSize().x;

	//頂点バッファの生成
	//FALEDマクロでくくる
	if( FAILED(pDevice->CreateVertexBuffer( sizeof(VERTEX_3D) * GetNumVertex() , //確保するバッファサイズ(byte)
											D3DUSAGE_WRITEONLY , //メモリの使用方法  とりあえずこれだけ書いておけば早い　絵を描くだけのやつ
											FVF_VERTEX_3D , //使用する頂点フォーマット でも実は０で大丈夫
											D3DPOOL_MANAGED , //バッファの管理方法　今回のはおまかせのやつ
											&m_pVtxBuffer , //ポインタの格納先
											NULL ))) //なんだかわかんないやつ)
	{										
		UINT nID = MessageBox( NULL , "頂点バッファが生成できません\n" , "ERROR[ k_field.cpp ]" , MB_OK | MB_ICONEXCLAMATION );		
		return E_FAIL;
	}

	//VERTEX_2D型のポインタ
	VERTEX_3D* pVtx = NULL;

	//バッファをロックし仮想アドレスを取得する
	if(FAILED( m_pVtxBuffer->Lock( 0 , 0 , (void**)&pVtx , 0 ) ) )
	{
		UINT nID = MessageBox( NULL , "頂点バッファをロックできません\n" , "ERROR[ field.cpp ]" , MB_OK | MB_ICONEXCLAMATION );
		return E_FAIL;
	}

	
	//頂点座標の設定				 X		   Y		Z
	//縦のやつ
	for( unsigned int numTate = 0 ; numTate < nFieldTate+1 ; numTate++ )
	{
		for( unsigned int numYoko = 0 ; numYoko < nFieldYoko+1 ; numYoko++ )
		{
			pVtx[ numTate * ( nFieldYoko + 1 ) + numYoko ].pos = D3DXVECTOR3( GetStartPos().x + ( fLengthYoko * numYoko ) , g_FieldHeight[numTate][numYoko] , GetStartPos().z - ( numTate * fLengthTate ) );
			pVtx[ numTate * ( nFieldYoko + 1 ) + numYoko ].tex = D3DXVECTOR2( (float)numYoko , (float)numTate );
			pVtx[ numTate * ( nFieldYoko + 1 ) + numYoko ].color = D3DCOLOR_RGBA( 255 , 255 , 255 , 255 );
		}
	}

	for( unsigned int numTate = 1 ; numTate < nFieldTate ; numTate++ )
	{
		//横のやつ
		for( unsigned int numYoko = 1 ; numYoko < nFieldYoko ; numYoko++ )
		{
			
			D3DXVECTOR3	directionX;
			D3DXVECTOR3 directionZ;

			D3DXVECTOR3	normalX;
			D3DXVECTOR3	normalZ;

			D3DXVECTOR3 normal;

			directionX = pVtx[ numTate * ( nFieldYoko +1 ) + numYoko+1  ].pos - pVtx[ numTate * ( nFieldYoko +1 ) + numYoko -1 ].pos; 
			normalX.x = -directionX.y;
			normalX.y = directionX.x; 
			normalX.z = 0.0f;

			directionZ =  pVtx[ (numTate + 1 ) * ( nFieldTate +1 ) + numYoko ].pos - pVtx[( numTate -1 )* ( nFieldTate + 1  ) + numYoko  ].pos; 
			normalZ.x = -directionZ.y;
			normalZ.y = directionZ.x; 
			normalZ.z = 0.0f;

			normal =  normalX + normalZ;

			D3DXVec3Normalize( &normal , &normal );

			pVtx[ numTate * ( nFieldYoko + 1 ) + numYoko ].normal = normal;

			//
			
		}
	}

	m_pVtxBuffer->Unlock();
	
	//■インデックスバッファの作成
	if( pDevice->CreateIndexBuffer(
	sizeof( DWORD ) * GetNumIndex(),	//バッファ量(32にしたらDWORDにする)
	D3DUSAGE_WRITEONLY ,		//使用方法フラグ
	D3DFMT_INDEX16 ,			//インデックスフォーマット
	D3DPOOL_MANAGED ,			//メモリ管理方法
	&m_pIndexBuffer ,		//インデックスバッファーインターフェースへのポインタのアドレス
	NULL ) )
	{
		UINT nID = MessageBox( NULL , "インデックスバッファが生成できません\n" , "ERROR[ field.cpp ]" , MB_YESNO | MB_ICONEXCLAMATION );		
		return E_FAIL;
	}


	
	WORD* pIdx;
	m_pIndexBuffer->Lock( 0 , 0 , (void**)&pIdx , 0 );	//引数の意味はバーテックスバッファーのときと同じ

	int	index = 0;
	for( unsigned int nCntZ = 0 ; nCntZ < nFieldYoko ; nCntZ++ )
	{
		if( nCntZ != 0  )
		{
			pIdx[ index ] = (nFieldYoko + 1) * nCntZ+ (nFieldYoko + 1);
			index++;
		}
		pIdx[ index ] = (nFieldYoko+1)  * ( nCntZ + 1 );
		index++;
		pIdx[ index ] = (nFieldYoko+1) * nCntZ ;
		index++;
	
		for( unsigned int nCntX = 0 ; nCntX < nFieldTate ; nCntX++ )
		{
			pIdx[ index ] = ( nFieldYoko + 1 ) * (nCntZ + 1) + (nCntX + 1);
			index++;
			pIdx[ index ] = ( nFieldYoko + 1 ) * nCntZ + (nCntX +1);
			index++;
		}
		if(nCntZ != (nFieldTate -1) )
		{
			pIdx[ index ] = nFieldYoko + ( nCntZ * (nFieldYoko+1) );
			index++;
 		}
	}

	m_pIndexBuffer->Unlock();
	

	return	S_OK;
}

//=========================================================================
//	フィールドとの当たり判定
//=========================================================================
float	KField::Collision(	const D3DXVECTOR3& pos )
{
	//VERTEX_2D型のポインタ
	VERTEX_3D* pVtx = NULL;

	//バッファをロックし仮想アドレスを取得する
	m_pVtxBuffer->Lock( 0 , 0 , (void**)&pVtx ,0 );	//引数の最初２つに００を指定すると全部

	D3DXVECTOR3 p0 , p1 , p2;
	D3DXVECTOR3 v01, v20 , v12 ;
	D3DXVECTOR3 v0p, v1p , v2p;
	D3DXVECTOR3 vC0, vC1 , vC2;
	D3DXVECTOR3 vn;

	float	fReturnNum = 0.0f;

	//内外判定
	for( int nTate = 0 ; nTate < ( int )GetSheet().z  ; nTate++ )
	{
		for( int nYoko = 0 ; nYoko < ( int )GetSheet().x  ; nYoko++ )
		{
			//上の三角形との当たり判定
			p0 = pVtx[ (int)GetSheet().x * ( nTate +1 ) + nYoko ].pos;
			p2 = pVtx[ (int)GetSheet().x * ( nTate ) + nYoko ].pos;
			p1 = pVtx[ (int)GetSheet().x * ( nTate ) + nYoko +1 ].pos;

			v01 = p1 - p0;
			v0p = pos - p0;

			D3DXVec3Cross( &vC0 , &v01 , &v0p );

			//角度内
			if( vC0.y >= 0.0f )
			{
				v12 = p2 - p1;
				v1p = pos - p1;
				D3DXVec3Cross( &vC1 , &v12 , &v1p );

				if( vC1.y >= 0.0f )
				{
					v20 = p0 - p2;
					v2p = pos- p2;
					D3DXVec3Cross( &vC2 , &v20 , &v2p );

					//ここまできたら中入ってまーす
					if( vC2.y >= 0.0f )
					{
						D3DXVec3Cross( &vn , &v01 , &v20 );
						D3DXVec3Normalize( &vn , &vn );

						fReturnNum = p0.y - ( ( pos.x - p0.x ) * vn.x + ( pos.z - p0.z ) * vn.z ) / vn.y ;

						m_pVtxBuffer->Unlock();
						return fReturnNum;

					}
				}

			}

			//下の三角形との
			p0 = pVtx[ (int)GetSheet().x * ( nTate ) + nYoko +1 ].pos;
			p1 = pVtx[ (int)GetSheet().x * ( nTate +1 ) + nYoko +1 ].pos;
			p2 = pVtx[ (int)GetSheet().x * ( nTate ) + nYoko ].pos;
			v01 = p1 - p0;
			v0p = pos - p0;

			D3DXVec3Cross( &vC0 , &v01 , &v0p );

			//角度内
			if( vC0.y >= 0.0f )
			{
				v12 = p2 - p1;
				v1p = pos - p1;
				D3DXVec3Cross( &vC1 , &v12 , &v1p );

				if( vC1.y >= 0.0f )
				{
					v20 = p0 - p2;
					v2p = pos- p2;
					D3DXVec3Cross( &vC2 , &v20 , &v2p );

					//ここまできたら中入ってまーす
					if( vC2.y >= 0.0f )
					{
						D3DXVec3Cross( &vn , &v01 , &v20 );
						D3DXVec3Normalize( &vn , &vn );

						fReturnNum = p0.y - ( ( pos.x - p0.x ) * vn.x + ( pos.z - p0.z ) * vn.z ) / vn.y ;

						m_pVtxBuffer->Unlock();
						return fReturnNum;

					}
				}

			}
		}	
	}

	return fReturnNum;
}