//--------------------------------------------------------------------------------------
// 主程序: Alpha_blend.cpp ， 作者：曾凡喜
//
// 本程序示例演示如何渲染半透明物体
//
// 场景由两个物体组成，一个小房子和一个半透明的玻璃球
//
// 完成时间：2008-05-11
//--------------------------------------------------------------------------------------

#include "zfxd3dUtility.h"
#include "zfxMesh.h"
#include <stdio.h>



// D3D对象接口
IDirect3D9* g_pd3d;
// D3D设备接口
IDirect3DDevice9* g_pd3dDevice;
// Cell模型
CZFXMesh g_cell;
// 球体模型
ID3DXMesh* g_sphere;
// 半透明材质
D3DMATERIAL9* g_transMtrl;
// 灯光
D3DLIGHT9 g_dirLight;


// 字体
ID3DXFont* g_pFont = NULL;


// 建立渲染环境
bool Setup()
{

	// 装载模型
	if(FAILED(g_cell.LoadMeshFromFile(g_pd3dDevice, L"cell.x")))
		return false;
	// 创建球体模型
	D3DXCreateSphere(g_pd3dDevice, 1.0f, 20, 20, &g_sphere, 0);
	// 创建透明材质
	g_transMtrl = new D3DMATERIAL9(GREEN_MTRL);
	g_transMtrl->Ambient.a = 0.5f;
	g_transMtrl->Diffuse.a = 0.5f;
	g_transMtrl->Specular.a = 0.5f;

	// 设定渲染状态
	// 设置灯光
	g_dirLight = InitDirectionalLight(&D3DXVECTOR3(1, -1, 1), &D3DXCOLOR(0xff88bb88));
//	g_pd3dDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff);
	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

	g_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE);
	g_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	g_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	g_pd3dDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD);
	g_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE);

	// 设置投影矩阵
	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
			&proj,
			D3DX_PI * 0.25f, // 45 - degree
			1024.0f/768.0f,
			1.0f,
			1000.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);
	
	return true;
}

bool DrawTextX()
{
	//用于渲染侦FPS
	static int tmLastTime = GetTickCount();
	int tmNow = GetTickCount();
	//用于计算渲染FPS
	static int nFrameCount = 0;
	static int nFPS = 0;
	if(tmNow - tmLastTime > 1000)
	{
		//计算FPS
		tmLastTime = tmNow;
		nFPS = nFrameCount;
		nFrameCount = 0;
	}
	nFrameCount ++;

	char str[500];
	RECT rect;
	rect.left = rect.top = 10;
	rect.bottom = rect.top + 30;
	rect.right = rect.left + 260;
	sprintf_s(str, 500, "Current FPS:%d, ", nFPS);
	g_pFont->DrawTextA(NULL, str, (int)strlen(str), &rect, DT_LEFT|DT_NOCLIP|DT_WORDBREAK, 0xffffff00);
	return true;
}


bool Display()
{
	// 获取两次进入函数入口的时间间隔
	static float lastTime = (float)timeGetTime();
	float curTime  = (float)timeGetTime();
	float timeDelta = (curTime - lastTime)*0.001f;
	lastTime = curTime;

	// 设定视口矩阵，你可以通过按下上下左右键改变视角
	static float angle  = (3.0f * D3DX_PI) / 2.0f;
	static float height = 1.0f;

	if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
		angle -= 0.5f * timeDelta;

	if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
		angle += 0.5f * timeDelta;

	if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
		height += 1.5f * timeDelta;

	if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
		height -= 1.5f * timeDelta;

	D3DXVECTOR3 eyept( cosf(angle) * 5.0f, height, sinf(angle) * 5.0f );
	D3DXVECTOR3 lookAt(0.0f, 0.5f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
	D3DXMATRIX view_mat;
	D3DXMatrixLookAtLH(&view_mat, &eyept, &lookAt, &up);

	g_pd3dDevice->SetTransform(D3DTS_VIEW, &view_mat);


	// 绘制场景
	g_pd3dDevice->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
	g_pd3dDevice->BeginScene();

	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
	g_cell.Render(g_pd3dDevice);

	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, true);
	g_pd3dDevice->SetLight(0, &g_dirLight);
	g_pd3dDevice->LightEnable(0, true);
	g_pd3dDevice->SetMaterial(g_transMtrl);
	g_pd3dDevice->SetTexture(0, 0);
	g_sphere->DrawSubset(0);

	
	// 在屏幕上写字
	if(g_pFont)
		DrawTextX(); 

	g_pd3dDevice->EndScene();
	g_pd3dDevice->Present(0, 0, 0, 0);

	return true;
}

bool CleanUp()
{
	g_sphere->Release();
	g_cell.Release();
	SAFE_DELETE(g_transMtrl);
	SAFE_RELEASE(g_pd3dDevice);
	SAFE_RELEASE(g_pd3d);
	
	
	return true;
}


int WINAPI WinMain(HINSTANCE hInstance,
				   HINSTANCE prevInstance, 
				   PSTR cmdLine,
				   int showCmd)
{
	// 应用程序初始化
	if(!InitD3DApp(hInstance, false/*true代表窗口模式*/, 
		D3DDEVTYPE_HAL, &g_pd3d, &g_pd3dDevice, L"Alpha_blend"/*窗口标题*/, 1024, 768))
	{
		MessageBoxW(0, L"应用程序初始化失败", 0, 0);
		return 0;
	}
	// 创建字体
	if(!InitDXFont(g_pd3dDevice, &g_pFont, L"Times New Roman"))
		g_pFont = NULL;

	Setup();

	// 进入消息循环
	MSG msg;
	ZeroMemory(&msg, sizeof(msg));
	while(msg.message != WM_QUIT)
	{
		if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
		else
		{
			Display();
		}
	}
	CleanUp();
	return 0;
}


// 消息循环函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	static bool bWireFrame = false;
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
	
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	case WM_CHAR:
		if(wParam == 'q'|| wParam == 'Q')
			bWireFrame = !bWireFrame;
		if(bWireFrame)
			g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
		else
			g_pd3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}