//------------------------------------------------------------
// Tony Hyun Kim
// Spring 2007
// 18.354 Project: Lattice gas
// DIRECT3D RESOURCES MANAGER IMPLEMENTATION
//------------------------------------------------------------

#include "d3d_ResourceManager.h"

D3D_ResourceManager myD3D;

D3D_ResourceManager::D3D_ResourceManager()
{
	NodeMesh	 = NULL;
	ParticleMesh = NULL;
	CylinderMesh = NULL;

	cxWidth		 = 0;
	cyHeight	 = 0;
}


bool D3D_ResourceManager::SetupResources()
{	
	// Colors
	D3DXCOLOR white		= D3DCOLOR_XRGB(255,255,255);
	D3DXCOLOR lightgray = D3DCOLOR_XRGB(200,200,200);
	D3DXCOLOR red		= D3DCOLOR_XRGB(255,  0,  0);
	D3DXCOLOR blue		= D3DCOLOR_XRGB(  0,  0,255);
	D3DXCOLOR black		= D3DCOLOR_XRGB(  0,  0,  0);

	// Materials
	NetworkMaterial  = InitMtrl(lightgray,lightgray,lightgray,black,5.0f);
	RedMaterial		 = InitMtrl(red,red,red,black,5.0f);
	BlueMaterial	 = InitMtrl(blue,blue,blue,black,5.0f);
	SelectedMaterial = RedMaterial;	

	// CreateSphere(...,radius,slices,stacks,...)
	D3DXCreateSphere(d3dDevice,0.1f,10,10,&NodeMesh,0);
	D3DXCreateSphere(d3dDevice,1.0f,10,10,&ParticleMesh,0);

	// To denote the connections
	D3DXCreateCylinder(d3dDevice,0.1f,0.1f,1.0f,5,1,&CylinderMesh,0);
	D3DXMATRIX R1, R2, T;
	D3DXMatrixRotationX(&R1, D3DX_PI/2);
	D3DXMatrixRotationZ(&R2,-D3DX_PI/2);
	D3DXMatrixTranslation(&T,0,g_spacing/2.0f,0);
	CylinderMatrix = R1*T*R2;

	// Set the projection matrix
	D3DXMATRIX p;
	D3DXMatrixPerspectiveFovLH(&p,
							   D3DX_PI*0.3f, // FOV
							   (float)cxWidth/(float)cyHeight,
							   1.0f,
							   1000.0f);
	d3dDevice->SetTransform(D3DTS_PROJECTION,&p);

	// Lighting
	D3DLIGHT9 light;
	ZeroMemory(&light, sizeof(light));
	light.Type		= D3DLIGHT_DIRECTIONAL;
	light.Diffuse	= white;
	light.Specular  = white * 0.3f;
	light.Ambient	= white * 0.6f;
	light.Direction = D3DXVECTOR3(1.0f,0.0f,0.5f);
	
	d3dDevice->SetLight(0,&light);
	d3dDevice->LightEnable(0,true);

	// Rendering state
	d3dDevice->SetRenderState(D3DRS_NORMALIZENORMALS, true);
	d3dDevice->SetRenderState(D3DRS_SPECULARENABLE, true);
	
	return (NodeMesh && ParticleMesh);
}


D3D_ResourceManager::~D3D_ResourceManager()
{
	ReleaseCOM(NodeMesh);
	ReleaseCOM(ParticleMesh);
	ReleaseCOM(CylinderMesh);
	ReleaseCOM(d3dDevice);
}

bool D3D_ResourceManager::InitD3D(HWND hwnd, int w, int h)
{
	cxWidth  = w;
	cyHeight = h;

	// Step 1: Create the IDirect3D9 object
	IDirect3D9* d3d9 = 0;
	d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
	if(!d3d9)
	{
		MessageBox(0,"Failed: Direct3DCreate9 (in InitD3D)",0,MB_ICONERROR);
		return false;
	}

	// Step 2: Check for hardware vertex-processing
	D3DCAPS9 caps;
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,&caps);
	int vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
	if(caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT)
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;

	// Step 3: Fill out the D3DPRESENT_PARAMETERS structure
	D3DPRESENT_PARAMETERS d3dPP;
	d3dPP.BackBufferWidth				= cxWidth;
	d3dPP.BackBufferHeight				= cyHeight;
	d3dPP.BackBufferFormat				= D3DFMT_UNKNOWN; // Note, the application won't run on my
														  // laptop otherwise; 
													      // i.e. D3DFMT_A8R8G8B8, D3DFMT_X8R8G8B8
	d3dPP.BackBufferCount				= 1;
	d3dPP.MultiSampleType				= D3DMULTISAMPLE_NONE;
	d3dPP.MultiSampleQuality			= 0;
	d3dPP.SwapEffect					= D3DSWAPEFFECT_DISCARD;
	d3dPP.hDeviceWindow					= hwnd;
	d3dPP.Windowed						= true;
	d3dPP.EnableAutoDepthStencil		= true;
	d3dPP.AutoDepthStencilFormat		= D3DFMT_D24S8;
	d3dPP.Flags							= 0;
	d3dPP.FullScreen_RefreshRateInHz	= D3DPRESENT_RATE_DEFAULT;
	d3dPP.PresentationInterval			= D3DPRESENT_INTERVAL_IMMEDIATE;

	// Step 4: Create the device
	d3d9->CreateDevice(D3DADAPTER_DEFAULT,
					   D3DDEVTYPE_HAL,
					   hwnd,
					   vp,
					   &d3dPP,
					   &d3dDevice);

	d3d9->Release();

	if(!d3dDevice)
	{
		MessageBox(0,"Failed: CreateDevice (in InitD3D)",0,0);
		return false;
	}

	if(!SetupResources())
	{
		MessageBox(0,"Failed: LoadResources (called from InitD3D)",0,0);
		return false;
	}

	return true;
}

D3DMATERIAL9 D3D_ResourceManager::InitMtrl(D3DXCOLOR a, D3DXCOLOR d, D3DXCOLOR s, D3DXCOLOR e, float p)
{
	D3DMATERIAL9 mtrl;
	mtrl.Ambient  = a;
	mtrl.Diffuse  = d;
	mtrl.Specular = s;
	mtrl.Emissive = e;
	mtrl.Power    = p;
	return mtrl;
}