//////////////////////////////////////////////////////////////////////////////////////////////////
// 
// File: teapot.cpp
// 
// Author: Frank Luna (C) All Rights Reserved
//
// System: AMD Athlon 1800+ XP, 512 DDR, Geforce 3, Windows XP, MSVC++ 7.0 
//
// Desc: Renders a teapot in wireframe mode.  Shows how to create a teapot 
//       using the D3DXCreateTeapot function and how to render the teapot
//       using the ID3DXMesh::DrawSubset method.
//          
//////////////////////////////////////////////////////////////////////////////////////////////////

#include "d3dUtility.h"
#include "box.h"
#include "sphere.h"
#include "cylinder.h"

//
// Globals
//

IDirect3DDevice9* Device = 0; 

const int Width  = 640;
const int Height = 480;

// Mesh interface that will store the teapot data and contains
// ma method to render the teapot data.
CBK::Shapes::Box* tBox;
CBK::Shapes::Sphere* tSphere;
CBK::Shapes::Cylinder* tCylinder;
CBK::Shape** myShapes;

//
// Framework Functions
//
bool Setup()
{
	//
	// Create the teapot geometry.
	//

	myShapes = new CBK::Shape*[3];

	tBox = new CBK::Shapes::Box(Device);
	tSphere = new CBK::Shapes::Sphere(Device);
	tCylinder = new CBK::Shapes::Cylinder(Device);
	

	//
	// Position and aim the camera.
	//

	D3DXVECTOR3 position(0.0f, 0.0f, -3.0f);
	D3DXVECTOR3 target(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 up(0.0f, 1.0f, 0.0f);
    D3DXMATRIX V;
	D3DXMatrixLookAtLH(&V, &position, &target, &up);
	Device->SetTransform(D3DTS_VIEW, &V);

	//
	// Set projection matrix.
	//

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(
			&proj,
			D3DX_PI * 0.5f, // 90 - degree
			(float)Width / (float)Height,
			1.0f,
			1000.0f);
	Device->SetTransform(D3DTS_PROJECTION, &proj);

	//
	// Switch to wireframe mode.
	//

	Device->SetRenderState(D3DRS_FILLMODE, D3DFILL_WIREFRAME);

	return true;
}
void Cleanup()
{
	delete tBox;
	delete tSphere;
	delete tCylinder;
	delete [] myShapes;
}

bool Display(float timeDelta)
{
	if( Device )
	{
		//
		// Spin the teapot:
		//

		D3DXMATRIX Ry;
		D3DXMATRIX tmp;
		D3DXMATRIX rotate;
		D3DXMATRIX scale;
		static float y = 0.0f;
		D3DXMatrixScaling(&scale, 0.1f * y, 0.1f * y, 0.1f * y);
		D3DXMatrixRotationX(&rotate, 0.5f * y);
		D3DXMatrixRotationY(&tmp, 1.0f * y);
		rotate *= tmp;
		D3DXMatrixRotationZ(&tmp, 1.5f * y);
		rotate *= tmp;

		y += timeDelta;
		if(y >= 6.28f)
			y = 0.0f;

		//
		// Draw the Scene:
		//
		Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0f, 0);
		Device->BeginScene();

		// Draw teapot using DrawSubset method with 0 as the argument.
		D3DXMatrixTranslation(&tmp, -1.5f, -1.5f, 1.0f);
		Ry = scale * rotate * tmp;
		tBox->setMatrix(Ry);
		tBox->draw(0);

		D3DXMatrixTranslation(&tmp, -1.5f, 1.5f, 1.0f);
		Ry = scale * rotate * tmp;
		tSphere->setMatrix(Ry);
		tSphere->draw(0);

		D3DXMatrixTranslation(&tmp, 1.5f, 1.5f, 1.0f);
		Ry = scale * rotate * tmp;
		tCylinder->setMatrix(Ry);
		tCylinder->draw(0);

		Device->EndScene();
		Device->Present(0, 0, 0, 0);
	}
	return true;
}


//
// WndProc
//
LRESULT CALLBACK d3d::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
		
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

//
// WinMain
//
int WINAPI WinMain(HINSTANCE hinstance,
				   HINSTANCE prevInstance, 
				   PSTR cmdLine,
				   int showCmd)
{
	if(!d3d::InitD3D(hinstance,
		Width, Height, true, D3DDEVTYPE_HAL, &Device))
	{
		::MessageBox(0, "InitD3D() - FAILED", 0, 0);
		return 0;
	}
		
	if(!Setup())
	{
		::MessageBox(0, "Setup() - FAILED", 0, 0);
		return 0;
	}

	d3d::EnterMsgLoop( Display );

	Cleanup();

	Device->Release();

	return 0;
}