/***************************************************************/
//
//
//		DirectX	[ photo.cpp ]
//
//											Author	kazuki tanaka
//											Date	2017 2/7
/*---------------------------------------------------------------
■Update : 2017/2/7
			photo.cppの作成

/*---------------------------------------------------------------
	Include File
---------------------------------------------------------------*/


//#include <Windows.h>
//#include <stdio.h>
//#include <d3dx9.h>

#include "window.h"

#include "rendererdx9.h"
#include "photo.h"

#include "input.h"
#include "mouse.h"

#include "system_component.h"

#ifdef _DEBUG
//#include "d_font.h"
#endif // _DEBUG

//#pragma comment (lib,"d3d9.lib")
//#pragma comment (lib,"d3dx9.lib")
//#pragma comment (lib,"dxguid.lib")

/*---------------------------------------------------------------
	Macro Difinition
---------------------------------------------------------------*/

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


/*---------------------------------------------------------------
	Const Number Difinition
---------------------------------------------------------------*/

#define NUM_VERTEX  ( 4 )					
#define NUM_POLYGON ( 2 )					

#ifdef _VIEW_LINEAR_INTERPOLATION_
#define LINEAR_VALUE ( 4.5f )						// Linear Value 
#endif _VIEW_LINEAR_INTERPOLATION_
			
#define VIEW_NEAR (  1.0f )							// Near Clip 
#define VIEW_FAR  ( 10000 )							// Far  Clip

/*----------------------------------------------------------------
	static member variable Initialize
----------------------------------------------------------------*/

CPhoto* CPhoto::pPhoto[ PHOTO_MAX ] = { };
int     CPhoto::usingPhotoNumber = -1;




// CPhoto Constructor
CPhoto::CPhoto( )
{

	// Menber Clear Process
	D3DXMatrixIdentity( &mtxProj );
	D3DXMatrixIdentity( &viewMtx );
	D3DXMatrixIdentity( &mtxViewInverse );
	D3DXMatrixIdentity( &mtxUI );
	
	posEye = D3DXVECTOR3( 0, 0, 0 );
	posAt  = D3DXVECTOR3( 0, 0, 0 );
	vecUp  = D3DXVECTOR3( 0, 0, 0 );
	g_fFov = 60.0f;

	work = DEFAULT;
	//phy = 0.0f;

	obj = nullptr;

	// Registration Class( Photo )
	for( int index = 0; index < PHOTO_MAX; index++ ){
		if( pPhoto[index] == NULL ){
			pPhoto[index] = this;
			myNumber = index;
			usingPhotoNumber = myNumber;
			break;
		}
	}


}

// CPhoto Destructor
CPhoto::~CPhoto( )
{

	// Do Nothing!!

}

// CPhoto Create Instance
CPhoto* CPhoto::Create( const char* PHOTO_NAME )
{

	// Create Class Instance
	CPhoto* pObject;
	pObject = new CPhoto;

	// Setting Class Name for Access
	strcpy( pObject->photoName, PHOTO_NAME );

	return pObject;

}

// CPhoto Access Outside Function  
CPhoto* CPhoto::Access( const char* PHOTO_NAME )
{

	// Search CPhoto Class
	for( int index = 0; index < PHOTO_MAX; index ++ ){
		if( pPhoto[index] != NULL ){
			if( strcmp( pPhoto[index]->photoName, PHOTO_NAME ) == 0 ){

				return pPhoto[index];
				break;
			}
		}
	}

	return 0;

}

// CPhoto Initialize
void CPhoto::Init( void )
{

	const float cameraToAt  = 50.0f;

	// Initialize Process
	g_fFov = 60.0f;
	posEye = D3DXVECTOR3( 0, 30, -cameraToAt );
	posAt  = D3DXVECTOR3( 0, 0, 0 );
	vecUp  = D3DXVECTOR3( 0, 1.0f, 0 );
	aspect = (float)WINDOW_WIDTH/WINDOW_HEIGHT;

	//work   = ROLL_Y_AXIS;

	// Linear View Setting
	#ifdef _VIEW_LINEAR_INTERPOLATION_
	posEyeDef = posEye;
	#endif _VIEW_LINEAR_INTERPOLATION_
	
	// Viewport Setting
	viewPort.X = 0;
	viewPort.Y = 0;
	viewPort.Width  = WINDOW_WIDTH;
	viewPort.Height = WINDOW_HEIGHT;
	viewPort.MinZ   = 0.0;
	viewPort.MaxZ   = 1.0;


}

// CPhoto Uninitialize
void CPhoto::Uninit( void )
{

	// Uninitialize Process


}

// CPhoto Setup Rendering Info
void CPhoto::SetPhoto( void )
{

	// デバイスの受け取り
	LPDIRECT3DDEVICE9 pDevice = GetDevice( );

	// Camera Work
	/*
	if( work == PLAYER_COMPLIANCE ){
		
		if( obj ){
			posAt = obj->lookAt;
			SetViewPosition( &obj->parts[0].pos );
		}else{
			work = DEFAULT;
		}
	}*/

	if( work == ROLL_Y_AXIS ){
	
		const float LENGTH = 50;
	
		D3DXVECTOR3 length = posEye - posAt;
		float theta = atan2f( length.z, length.y );

		theta -= 0.1f;

		phy += 0.01f;

		posEye.x = (cosf( phy ) * LENGTH ) + posAt.x;
		posEye.z = (sinf( phy ) * LENGTH ) + posAt.z;

		Console::DebugLog("eye : %f %f %f \n", posEye.x, posEye.y, posEye.z );

		//SetViewPosition( &posEye );
	
	}

	// カメラの線形補間
	#ifdef _VIEW_LINEAR_INTERPOLATION_

	const float CAMERA_VALUE = LINEAR_VALUE;

	if( posEye != posEyeDef ){
		
		float angle = atan2f( posEyeDef.z, posEyeDef.x );
		float arc   = atan2f( posEye.z,    posEye.x    );

		if( posEye.x > posEyeDef.x ){
		
			posEye.x -= CAMERA_VALUE;
			//posEye.x = posEye.x * cosf( arc - 0.01f );
			if( posEye.x < posEyeDef.x ){
				posEye.x = posEyeDef.x;
			}
		}
		if( posEye.x < posEyeDef.x ){
			
			posEye.x += CAMERA_VALUE;
			//posEye.x = posEye.x * cosf( arc + 0.01f );
			if( posEye.x > posEyeDef.x ){
				posEye.x = posEyeDef.x;
			}
		}
		if( posEye.z > posEyeDef.z ){
		
			posEye.z -= CAMERA_VALUE;
			//posEye.z = posEye.z * sinf( arc - 0.01f );
			if( posEye.z < posEyeDef.z ){
				posEye.z = posEyeDef.z;
			}
		}
		if( posEye.z < posEyeDef.z ){
		
			posEye.z += CAMERA_VALUE;
			//posEye.z = posEye.z * sinf( arc + 0.01f );
			if( posEye.z > posEyeDef.z ){
				posEye.z = posEyeDef.z;
			}
		}
		if( posEye.y > posEyeDef.y ){
		
			posEye.y -= CAMERA_VALUE;
			if( posEye.y < posEyeDef.y ){
				posEye.y = posEyeDef.y;
			}
		}
		if( posEye.y < posEyeDef.y ){
		
			posEye.y += CAMERA_VALUE;
			if( posEye.y > posEyeDef.y ){
				posEye.y = posEyeDef.y;
			}
		}


		
		if( posEye.x > posEyeDef.x ){
		
			posEye.x -= CAMERA_VALUE;
			if( posEye.x < posEyeDef.x ){
				posEye.x = posEyeDef.x;
			}
		}
		if( posEye.x < posEyeDef.x ){
		
			posEye.x += CAMERA_VALUE;
			if( posEye.x > posEyeDef.x ){
				posEye.x = posEyeDef.x;
			}
		}
		if( posEye.z > posEyeDef.z ){
		
			posEye.z -= CAMERA_VALUE;
			if( posEye.z < posEyeDef.z ){
				posEye.z = posEyeDef.z;
			}
		}
		if( posEye.z < posEyeDef.z ){
		
			posEye.z += CAMERA_VALUE;
			if( posEye.z > posEyeDef.z ){
				posEye.z = posEyeDef.z;
			}
		}
		if( posEye.y > posEyeDef.y ){
		
			posEye.y -= CAMERA_VALUE;
			if( posEye.y < posEyeDef.y ){
				posEye.y = posEyeDef.y;
			}
		}
		if( posEye.y < posEyeDef.y ){
		
			posEye.y += CAMERA_VALUE;
			if( posEye.y > posEyeDef.y ){
				posEye.y = posEyeDef.y;
			}
		}
	}
	#endif // _VIEW_LINEAR_INTERPOLATION_


	// ビュー行列の変換
	D3DXMatrixLookAtLH( &viewMtx, &posEye, &posAt, &vecUp );

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

	{ // BIllboard用行列の更新
	
		// 逆行列の作成
		D3DXMatrixInverse( &mtxViewInverse, NULL, &viewMtx );
	
		// 平行成分の初期化
		mtxViewInverse._41 = 0.0f;
		mtxViewInverse._42 = 0.0f;
		mtxViewInverse._43 = 0.0f;

	} // -> END

	{ // UserInterface用行列の更新
	
		// 逆行列の作成
		D3DXMatrixInverse( &mtxUI, NULL, &viewMtx );
	
		// 平行成分の初期化
		//mtxViewInverse._41 = viewMtx._41;
		//mtxViewInverse._42 = viewMtx._42;
		//mtxViewInverse._43 = viewMtx._43;
		mtxViewInverse._41 = -mtxViewInverse._41;
		mtxViewInverse._42 = -mtxViewInverse._42;
		mtxViewInverse._43 = -mtxViewInverse._43;

	} // -> END

	// プロジェクション行列の作成	
	D3DXMatrixPerspectiveFovLH( &mtxProj,	 
		D3DXToRadian(g_fFov),					// パース( 視野角 )
		aspect,									// アスペクト比
		VIEW_NEAR,								// 前クリップ面( 0 < Zn )※0はNG( クリップ面は、カメラがどれだけの視界があるか、つまり0にすると演算がバグる)
		VIEW_FAR								// 後クリップ面
		);

	// デバイスにプロジェクション行列の設定
	pDevice ->SetTransform( D3DTS_PROJECTION, &mtxProj );

	// ビューポート変換
	pDevice ->SetViewport( &viewPort );

	// Setting Use Photo Number
	usingPhotoNumber = myNumber;


	#ifdef _DEBUG
	/*
	CDebugFont::IndexAccess( 0 )->SetRenderData( C_RENDER, \
		"< Photo Setting > myNumber : %d  \n\
		pos : %f, %f, %f \n\
		At :  %f, %f, %f \n\
		Vecup : %f, %f, %f \n\
		work : %d, phy : %f \n\
		Aspect : %f \n\
		usingNumber : %d\n"
		, myNumber,
		posEye.x, posEye.y, posEye.z,
		posAt.x, posAt.y, posAt.z,
		vecUp.x, vecUp.y, vecUp.z,
		work, phy,
		aspect,
		usingPhotoNumber );
		*/
	#endif // _DEBUG


}

// CPhoto Set View Position
void CPhoto::SetViewPosition( const LPD3DXVECTOR3 pos )
{

	const int   Z_FAR   = 180;
	const float VIEW_UP = 80.0f;


	// カメラ位置算出
	D3DXVECTOR3 posEye = ((posAt - (*pos)) );
	D3DXVec3Normalize( &posEye, &posEye );
	posEye *= Z_FAR;

	posEye = (*pos) - posEye;

	posEye.y += VIEW_UP;

	// カメラ位置設定
	#ifdef _VIEW_LINEAR_INTERPOLATION_
	CPhoto::posEyeDef = posEye;
	#else
	CPhoto::posEye = posEye;
	#endif _VIEW_LINEAR_INTERPOLATION_


}

// CPhoto Compliance Player
CPhoto* CPhoto::SetPlayerCompliance( CBasePlayer* player )
{

	// SetPlayerPointer
	obj = player;

	return this;

}

// CPhoto Set Work
void CPhoto::SetPhotoWork( WORK work )
{

	CPhoto::work = work;
	posAt = D3DXVECTOR3( 0, 0, 0 );

}

// CPhoto for Billboard InvViewMtx
D3DXMATRIX CPhoto::GetMtxView( void )
{

	return pPhoto[ usingPhotoNumber ]->mtxViewInverse;

}

// CPhoto for UserInterface Matrix
D3DXMATRIX CPhoto::GetMtxUserInterface( void )
{

	return pPhoto[ usingPhotoNumber ]->mtxUI;

}

// CPhoto Screen Split ( Viewport Setting )
void CPhoto::ScreenSplit( const int splits )
{


	switch( splits ){
	
	case 1:

		// Viewport Setting
		pPhoto[0]->viewPort.X      = 0;
		pPhoto[0]->viewPort.Y      = 0;
		pPhoto[0]->viewPort.Width  = WINDOW_WIDTH;
		pPhoto[0]->viewPort.Height = WINDOW_HEIGHT;
		pPhoto[0]->viewPort.MinZ   = 0.0;
		pPhoto[0]->viewPort.MaxZ   = 1.0;
		break;
	case 2:{

			const int SPLIT_WIDTH = 2;

			// Viewport Setting
			for( int index = 0; index < SPLIT_WIDTH; index++ ){
				pPhoto[index]->viewPort.X      = (WINDOW_WIDTH>>1)*index;
				pPhoto[index]->viewPort.Y      = 0;
				pPhoto[index]->viewPort.Width  = WINDOW_WIDTH>>1;
				pPhoto[index]->viewPort.Height = WINDOW_HEIGHT;
				pPhoto[index]->viewPort.MinZ   = 0.0;
				pPhoto[index]->viewPort.MaxZ   = 1.0;
				pPhoto[index]->aspect = (float)(WINDOW_WIDTH>>1)/WINDOW_HEIGHT;
			}
		}
		break;
	case 3:{

			// forth Photo Create Process, Using for Various Player 
			CPhoto::Create( "variousPhoto" )->Init( );
			CPhoto::Access( "variousPhoto" )->SetPhotoWork( CPhoto::ROLL_Y_AXIS );

			const int SPLIT_WIDTH  = 2;
			const int SPLIT_HEIGHT = 2;

			// Viewport Setting
			for( int y = 0; y < SPLIT_HEIGHT; y++ ){
				for( int x = 0; x < SPLIT_WIDTH; x++ ){
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.X      = (WINDOW_WIDTH  >>1)*x;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Y      = (WINDOW_HEIGHT >>1)*y;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Width  = WINDOW_WIDTH>>1;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Height = WINDOW_HEIGHT>>1;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.MinZ   = 0.0;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.MaxZ   = 1.0;
					pPhoto[ y*SPLIT_WIDTH + x ]-> aspect = (float)( WINDOW_WIDTH >> 1 )/( WINDOW_HEIGHT >> 1 );
				}
			}

		}
		break;
	case 4:{

			const int SPLIT_WIDTH  = 2;
			const int SPLIT_HEIGHT = 2;

			// Viewport Setting
			for( int y = 0; y < SPLIT_HEIGHT; y++ ){
				for( int x = 0; x < SPLIT_WIDTH; x++ ){
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.X      = (WINDOW_WIDTH  >>1)*x;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Y      = (WINDOW_HEIGHT >>1)*y;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Width  = WINDOW_WIDTH>>1;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.Height = WINDOW_HEIGHT>>1;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.MinZ   = 0.0;
					pPhoto[ y*SPLIT_WIDTH + x ]-> viewPort.MaxZ   = 1.0;
					pPhoto[ y*SPLIT_WIDTH + x ]-> aspect = (float)( WINDOW_WIDTH >> 1 )/( WINDOW_HEIGHT >> 1 );
				}
			}

		}
	default:
		break;
	
	}

}

// CPhoto Release Class All
void CPhoto::ReleaseAll( void )
{

	// Release CPhoto All
	for( int index = 0; index < PHOTO_MAX; index ++ ){
		if( pPhoto[ index ] ){

			pPhoto[ index ] ->Uninit( );
			SAFE_DELETE( pPhoto[ index ] )
		}
	}


}






