www.pudn.com > Direct3D_ZBuffer.zip > Game.cpp


// Game.cpp: implementation of the CGame class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "Game.h" 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CGame::CGame() 
{ 
	m_fEnableLogging = false; 
 
	m_pD3D = NULL; 
	m_pD3DDevice = NULL; 
	m_dwFrames = 0; 
	m_dwStartTime = 0; 
	m_dwEndTime = 0; 
 
	m_pCube1 = NULL; 
	m_pCube2 = NULL; 
	m_pCube3 = NULL; 
	m_pCube4 = NULL; 
	m_pCube5 = NULL; 
	m_pCube6 = NULL; 
} 
 
CGame::~CGame() 
{ 
	//Game finished, so record time 
	m_dwEndTime = timeGetTime(); 
 
	DWORD dwDuration = (m_dwEndTime - m_dwStartTime) / 1000; 
	 
	//Log stats 
	WriteToLog("Statistics:"); 
	WriteToLog("\tStart Time (ms): %d", m_dwStartTime); 
	WriteToLog("\tEnd Time (ms): %d", m_dwEndTime); 
	WriteToLog("\tDuration (s): %d", dwDuration); 
	WriteToLog("\tTotal Frame Count: %d", m_dwFrames); 
	WriteToLog("\tAverage FPS: %d", (m_dwFrames / dwDuration)); 
 
	//Clean up objects/interfaces 
	SafeDelete(m_pCube1); 
	SafeDelete(m_pCube2); 
	SafeDelete(m_pCube3); 
	SafeDelete(m_pCube4); 
	SafeDelete(m_pCube5); 
	SafeDelete(m_pCube6); 
 
	SafeRelease(m_pD3DDevice); 
	SafeRelease(m_pD3D); 
} 
 
bool CGame::Initialise(HWND hWnd, UINT nWidth, UINT nHeight) 
{ 
	if(SUCCEEDED(InitialiseD3D(hWnd, nWidth, nHeight))) 
	{ 
		return InitialiseGame(); 
	} 
	else 
	{ 
		return false; 
	} 
 
	return true; 
} 
 
bool CGame::InitialiseGame() 
{ 
	//Setup games objects here 
	m_pCube1 = new CCuboid(m_pD3DDevice); 
	m_pCube1->SetPosition(0.0, 0.0, 0.0); 
 
	m_pCube2 = new CCuboid(m_pD3DDevice); 
	m_pCube2->SetPosition(15.0, 0.0, 0.0); 
 
	m_pCube3 = new CCuboid(m_pD3DDevice); 
	m_pCube3->SetPosition(-15.0, 0.0, 0.0); 
 
	m_pCube4 = new CCuboid(m_pD3DDevice); 
	m_pCube4->SetSize(40.0, 10.0, 10.0); 
	m_pCube4->SetPosition(0.0, 0.0, 15.0); 
 
	m_pCube5 = new CCuboid(m_pD3DDevice); 
	m_pCube5->SetSize(17.5, 10.0, 10.0); 
	m_pCube5->SetPosition(-12.5, 0.0, -15.0); 
 
	m_pCube6 = new CCuboid(m_pD3DDevice); 
	m_pCube6->SetSize(17.5, 10.0, 10.0); 
	m_pCube6->SetPosition(12.5, 0.0, -15.0); 
 
	return true; 
} 
 
D3DFORMAT CGame::CheckDisplayMode(UINT nWidth, UINT nHeight, UINT nDepth) 
{ 
	UINT x; 
	D3DDISPLAYMODE d3ddm; 
 
	WriteToLog("adapterCount = %d", m_pD3D->GetAdapterModeCount(0)); 
 
	for(x = 0; x < m_pD3D->GetAdapterModeCount(0); x++) 
	{ 
		m_pD3D->EnumAdapterModes(0, x, &d3ddm); 
		if(d3ddm.Width == nWidth) 
		{ 
			if(d3ddm.Height == nHeight) 
			{ 
				if((d3ddm.Format == D3DFMT_R5G6B5) || (d3ddm.Format == D3DFMT_X1R5G5B5) || (d3ddm.Format == D3DFMT_X4R4G4B4)) 
				{ 
					if(nDepth == 16) 
					{ 
						return d3ddm.Format; 
					} 
				} 
				else if((d3ddm.Format == D3DFMT_R8G8B8) || (d3ddm.Format == D3DFMT_X8R8G8B8)) 
				{ 
					if(nDepth == 32) 
					{ 
						return d3ddm.Format; 
					} 
				} 
			} 
		} 
	} 
 
	return D3DFMT_UNKNOWN; 
} 
 
HRESULT CGame::InitialiseD3D(HWND hWnd, UINT nWidth, UINT nHeight) 
{ 
	WriteToLog("InitialiseD3D Started..."); 
 
    //First of all, create the main D3D object. If it is created successfully we  
    //should get a pointer to an IDirect3D8 interface. 
    m_pD3D = Direct3DCreate8(D3D_SDK_VERSION); 
    if(m_pD3D == NULL) 
    { 
		WriteToLog("\tUnable to create DirectX8 interface."); 
        return E_FAIL; 
    } 
 
    //Get the current display mode 
    D3DDISPLAYMODE d3ddm; 
 
	d3ddm.Format = CheckDisplayMode(nWidth, nHeight, 32); 
	if(d3ddm.Format != D3DFMT_UNKNOWN) 
	{ 
		//Width x Height x 32bit has been selected 
		d3ddm.Width = nWidth; 
		d3ddm.Height = nHeight; 
 
		WriteToLog("\t%d x %d x 32bit back buffer format selected. Format = %d.", nWidth, nHeight, d3ddm.Format); 
	} 
	else 
	{ 
		d3ddm.Format = CheckDisplayMode(nWidth, nHeight, 16); 
		if(d3ddm.Format != D3DFMT_UNKNOWN) 
		{ 
            //Width x Height x 16bit has been selected 
			d3ddm.Width = nWidth; 
			d3ddm.Height = nHeight; 
 
			WriteToLog("\t%d x %d x 16bit back buffer format selected. Format = %d.", nWidth, nHeight, d3ddm.Format); 
		} 
        else 
		{ 
			WriteToLog("\tUnable to select back buffer format for %d x %d.", nWidth, nHeight); 
            return E_FAIL; 
        } 
	} 
 
 
    //Create a structure to hold the settings for our device 
    D3DPRESENT_PARAMETERS d3dpp;  
    ZeroMemory(&d3dpp, sizeof(d3dpp)); 
 
	d3dpp.Windowed = FALSE; 
    d3dpp.BackBufferCount = 1; 
    d3dpp.BackBufferFormat = d3ddm.Format; 
    d3dpp.BackBufferWidth = d3ddm.Width; 
    d3dpp.BackBufferHeight = d3ddm.Height; 
    d3dpp.hDeviceWindow = hWnd; 
    d3dpp.SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; 
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT; 
    d3dpp.FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; 
 
	//Select the best depth buffer, select 32, 24 or 16 bit 
    if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D32) == D3D_OK) 
	{ 
        d3dpp.AutoDepthStencilFormat = D3DFMT_D32; 
        d3dpp.EnableAutoDepthStencil = TRUE; 
 
		WriteToLog("\t32bit depth buffer selected"); 
    } 
    else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D24X8) == D3D_OK) 
    { 
		d3dpp.AutoDepthStencilFormat = D3DFMT_D24X8; 
        d3dpp.EnableAutoDepthStencil = TRUE; 
 
		WriteToLog("\t24bit depth buffer selected"); 
	} 
    else if(m_pD3D->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3ddm.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, D3DFMT_D16) == D3D_OK) 
    { 
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16; 
        d3dpp.EnableAutoDepthStencil = TRUE; 
 
		WriteToLog("\t16bit depth buffer selected"); 
	} 
    else 
	{ 
        d3dpp.EnableAutoDepthStencil = FALSE; 
		WriteToLog("\tUnable to select depth buffer."); 
	} 
 
 
    //Create a Direct3D device. 
    if(FAILED(m_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,  
                                   D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &m_pD3DDevice))) 
    { 
		WriteToLog("\tUnable to create device."); 
        return E_FAIL; 
    } 
     
	//Turn on back face culling. This is becuase we want to hide the back of our polygons 
    m_pD3DDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 
 
	//Turn off lighting becuase we are specifying that our vertices have colour 
    m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 
 
	//Turn on Depth Buffering 
    m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); 
 
	WriteToLog("InitialiseD3D Finished OK"); 
 
    return S_OK; 
} 
 
LPDIRECT3DDEVICE8 CGame::GetDevice() 
{ 
	return m_pD3DDevice; 
} 
 
void CGame::GameLoop() 
{ 
    //Enter the game loop 
    MSG msg;  
    BOOL fMessage; 
 
    PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE); 
 
	//Game started, so record time 
	m_dwStartTime = timeGetTime(); 
 
    while(msg.message != WM_QUIT) 
    { 
        fMessage = PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE); 
 
        if(fMessage) 
        { 
            //Process message 
            TranslateMessage(&msg); 
            DispatchMessage(&msg); 
        } 
        else 
        { 
            //No message to process, so render the current scene 
            Render(); 
        } 
 
    } 
} 
 
void CGame::Render() 
{ 
    if(m_pD3DDevice == NULL) 
    { 
        return; 
    } 
 
    //Clear the back buffer and depth buffer 
    m_pD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); 
     
    //Begin the scene 
    m_pD3DDevice->BeginScene(); 
     
	//Setup the rotation, camera, and perspective matrices 
    SetupRotation(); 
	SetupCamera(); 
	SetupPerspective(); 
 
 
    //Rendering our objects 
    m_pCube1->Render(); 
	m_pCube2->Render(); 
	m_pCube3->Render(); 
	m_pCube4->Render(); 
	m_pCube5->Render(); 
	m_pCube6->Render(); 
 
 
    //End the scene 
    m_pD3DDevice->EndScene(); 
     
    //Filp the back and front buffers so that whatever has been rendered on the back buffer 
    //will now be visible on screen (front buffer). 
    m_pD3DDevice->Present(NULL, NULL, NULL, NULL); 
 
	//Count Frames 
	m_dwFrames++; 
} 
 
void CGame::SetupRotation() 
{ 
    //Here we will rotate our world. 
    D3DXMATRIX matWorld, matWorldX, matWorldY, matWorldZ; 
     
	//Create the transformation matrices 
	D3DXMatrixRotationX(&matWorldX, timeGetTime()/400.0f); 
	D3DXMatrixRotationY(&matWorldY, timeGetTime()/400.0f);	 
	D3DXMatrixRotationZ(&matWorldZ, timeGetTime()/400.0f);	 
 
	//Combine the transformations by multiplying them together 
	D3DXMatrixMultiply(&matWorld, &matWorldX, &matWorldY); 
	D3DXMatrixMultiply(&matWorld, &matWorld, &matWorldZ); 
 
	//Apply the tansformation 
    m_pD3DDevice->SetTransform(D3DTS_WORLD, &matWorld); 
} 
 
void CGame::SetupCamera() 
{ 
	//Here we will setup the camera. 
	//The camera has three settings: "Camera Position", "Look at Position" and "Up Direction" 
	//We have set the following: 
	//Camera Position:	(0, 0, -100) 
	//Look at Position: (0, 0, 0) 
	//Up direction:		Y-Axis. 
    D3DXMATRIX matView; 
    D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f,-100.0f),		//Camera Position 
                                 &D3DXVECTOR3(0.0f, 0.0f, 0.0f),		//Look At Position 
                                 &D3DXVECTOR3(0.0f, 1.0f, 0.0f));		//Up Direction 
    m_pD3DDevice->SetTransform(D3DTS_VIEW, &matView); 
} 
 
void CGame::SetupPerspective() 
{ 
	//Here we specify the field of view, aspect ration and near and far clipping planes. 
    D3DXMATRIX matProj; 
    D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 500.0f); 
    m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj); 
} 
 
void CGame::WriteToLog(char *lpszText, ...) 
{ 
	if(m_fEnableLogging) 
	{ 
		va_list argList; 
		FILE *pFile; 
 
		//Initialize variable argument list 
		va_start(argList, lpszText); 
 
		//Open the log file for appending 
		pFile = fopen("log.txt", "a+"); 
 
		//Write the text and a newline 
		vfprintf(pFile, lpszText, argList); 
		putc('\n', pFile); 
 
		//Close the file 
		fclose(pFile); 
		va_end(argList); 
	} 
} 
 
void CGame::EnableLogging() 
{ 
	m_fEnableLogging = true; 
	 
	FILE* pFile; 
 
	//Clear the file contents 
	pFile = fopen("log.txt", "wb"); 
 
	//Close it up and return success 
	fclose(pFile); 
}