
/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/

	FILE	: Renderer.cpp

+ ------ Explanation of file --------------------------------------------------------------------------

+ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */

#include "Common.h"

#include "windowManager.h"
#include "systemManager.h"

#include "Scene.h"

#include "Renderer.h"

// デフォルトコンストラクタ
Renderer::Renderer()
{
    m_pD3D = NULL; 
}

// デストラクタ
Renderer::~Renderer()
{
	release();
}

//! 初期化
void Renderer::init(bool isFullScr)
{
	m_pWinMan = WindowManager::getInstance();
	m_pCamera = SystemManager::getInstance()->getCamera();

    D3DDISPLAYMODE d3ddm;
    
	// Direct3D9オブジェクトの作成
	if((m_pD3D = ::Direct3DCreate9(D3D_SDK_VERSION)) == 0) { return; }	// 取得失敗

	// 現在のディスプレイモードを取得
    if(FAILED(m_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { return; }
	m_dispHeight = d3ddm.Height;

	// デバイスのプレゼンテーションパラメータを初期化
	ZeroMemory(&m_D3DPP, sizeof(D3DPRESENT_PARAMETERS));
	m_D3DPP.BackBufferCount	= 1;

	if(isFullScr){ 
		m_D3DPP.Windowed			= FALSE;		// フルスクリーン表示の指定
		m_D3DPP.BackBufferWidth		= WINDOW_W;		// フルスクリーン時の横幅
		m_D3DPP.BackBufferHeight	= WINDOW_H;		// フルスクリーン時の縦幅
	}else{
		m_D3DPP.Windowed			= TRUE;				// ウインドウ内表示の指定
	}

	m_D3DPP.BackBufferFormat		= d3ddm.Format;			    // カラーモードの指定
	m_D3DPP.SwapEffect				= D3DSWAPEFFECT_DISCARD;	// 
	m_D3DPP.EnableAutoDepthStencil	= TRUE;						// エラー対策
//	m_D3DPP.AutoDepthStencilFormat	= D3DFMT_D16;
	m_D3DPP.AutoDepthStencilFormat	= D3DFMT_D24S8;				// 画像フォーマット、ステンシルバッファ対応
//	m_D3DPP.PresentationInterval	= D3DPRESENT_INTERVAL_IMMEDIATE;
	
	// ディスプレイアダプタを表すためのデバイスを作成
	// 描画と頂点処理をハードウェアで行なう
	if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
									  D3DDEVTYPE_HAL, 
									  getWinMan()->getHWnd(), 
									  D3DCREATE_HARDWARE_VERTEXPROCESSING, 
									  &m_D3DPP, &m_pD3DDevice))) 
    {
		// 上記の設定が失敗したら
		// 描画をハードウェアで行い、頂点処理はCPUで行なう
		if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
										  D3DDEVTYPE_HAL, 
										  getWinMan()->getHWnd(), 
										  D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
										  &m_D3DPP, &m_pD3DDevice))) 
        {
			// 上記の設定が失敗したら
			// 描画と頂点処理をCPUで行なう
			if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, 
											  D3DDEVTYPE_REF, getWinMan()->getHWnd(), 
											  D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
											  &m_D3DPP, &m_pD3DDevice))) 
            {
				// 初期化失敗
				return;
			}
		}
	}

	// レンダリングステートパラメータの設定
	// 両面描画モードの指定
    m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	// Ｚ比較を行なう
    m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
	// ディザリングを行なう（高品質描画）
	m_pD3DDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
	// ノーライティングモード 	
    m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	// テクスチャステージの設定
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA);
	m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	m_pD3DDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
	m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2);
	m_pD3DDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
	// アルファ値の設定
	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
    m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
    m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	// テクスチャー補完設定
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_ANISOTROPIC);
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_ANISOTROPIC);
	m_pD3DDevice->SetSamplerState(0, D3DSAMP_MAXANISOTROPY, 4);

	// ビューイング行列の初期化
	D3DXMatrixIdentity(&m_view);
	D3DXMatrixLookAtLH(&m_view, &VEC3(0.0f, 10.0f, 0.0f), 
								 &VEC3(0.0f, 0.0f, 0.0f), 
								 &VEC3(0.0f, 1.0f, 0.0f));

	set3D();
}


/* _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
|
|   Finalize
|       終了処理
+ -------------------------------------------------------------------------------------------------
|	IN --->	NON
|   OUT --> NON
+ _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ */
void Renderer::release(void)
{
	// デバイスオブジェクトの解放
	SAFE_RELEASE(m_pD3DDevice);

	// DirectXGraphicsの解放
	SAFE_RELEASE(m_pD3D);
}

//! 描画開始
void Renderer::drawStart(void)
{
	// 描画開始宣言
	if(SUCCEEDED(m_pD3DDevice->BeginScene())){
		// 画面クリア
		if(FAILED(m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
										D3DCOLOR_XRGB(64,64,64), 1.0f, 0)))
		{
			return;
		}
	}
}

//! 描画終了
void Renderer::drawEnd(void)
{
	// 描画終了宣言
	m_pD3DDevice->EndScene();

	// 描画結果の転送
	if(FAILED(m_pD3DDevice->Present(0, 0, 0, 0))){
		// デバイス消失から復帰
		m_pD3DDevice->Reset(&m_D3DPP);
	}
}


// 3D描画設定
void Renderer::set3D(void)
{
	if(!m_pD3DDevice) { return; }

	// ビューポートをゲーム画面に変更
	D3DVIEWPORT9 vp={MENU_W,0,WINDOW_W-MENU_W,WINDOW_H,0.0f,1.0f};
	m_pD3DDevice->SetViewport(&vp);
//	if(FAILED(m_pD3DDevice->GetViewport(&vp))) { return; }

	// アスペクト比の計算
	float aspect;
	aspect = (float)vp.Width / (float)vp.Height;

	// 透視法射影
	D3DXMatrixIdentity(&m_proj);
	D3DXMatrixPerspectiveFovLH(&m_proj, D3DXToRadian(45.0f), aspect, NEAR_CLIP, FAR_CLIP);
	m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &m_proj);

	// ビュー
	D3DXMatrixIdentity(&m_view);
	D3DXMatrixLookAtLH(&m_view, &getCamera()->m_eye, &getCamera()->m_look, &getCamera()->m_up);
	m_pD3DDevice->SetTransform(D3DTS_VIEW, &m_view);
}
// 2D描画設定
void Renderer::set2D(void)
{
	if(!m_pD3DDevice) { return; }

	// ビューポートを画面全体に変更
	D3DVIEWPORT9 vp={0,0,WINDOW_W,WINDOW_H,0.0f,1.0f};
	m_pD3DDevice->SetViewport(&vp);

	// 正射影
	D3DXMatrixIdentity(&m_proj);
	D3DXMatrixOrthoLH(&m_proj, WINDOW_W, WINDOW_H, 1.0f, 1.0f);
	m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &m_proj);

	// ビュー
	D3DXMatrixIdentity(&m_view);
	m_pD3DDevice->SetTransform(D3DTS_VIEW, &m_view);
}

// ワールド座標toスクリーン座標
VEC3 Renderer::conv3Dto2D(VEC3 pos)
{
	VEC3 ret;
	D3DVIEWPORT9 vp;
	D3DXMATRIX mat;
	D3DXMatrixIdentity(&mat);
	GetDevice()->GetViewport(&vp);
	D3DXVec3Project(&ret, &pos, &vp, &m_proj, &m_view, &mat);

	return(ret);
}
