// ============================================================================
// Filename: MESH.cpp
// Description: Mesh Tutorial, from the 32Bits DirectX Techniques Series 1
// Tutorial 4.
//
// Found a bug in this code framework? Need some help? Come to www.32bits.co.uk
// for support, feedback and the best DirectX dev community on the net!
// ============================================================================
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <dxerr8.h>
// Include helper functions.
#include "D3DFuncs.h"
// TODO: Include any other header files here.
#include "CD3DMesh.h"
// Function declarations
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
HRESULT AppInit();
HRESULT AppLoop();
HRESULT AppShutDown();
HRESULT Render();
// Globals required for all apps
static char szAppname[]="[32Bits.co.uk] Simple Mesh Tutorial";
LPDIRECT3D8 g_pD3D;
LPDIRECT3DDEVICE8 g_pDevice;
HWND g_hWnd;
D3DCURRENTSETTINGS g_D3DSettings;
// Globals specifically for this source
// TODO: Add your globals here.
CD3DMesh g_Mesh;
float g_XRotation, g_YRotation, g_ZRotation;
// =====================================================================================
// Application code begins here
// =====================================================================================
// =====================================================================================
// Function Name: WinMain
// Purpose: Application entry point
// =====================================================================================
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc, sizeof(WNDCLASSEX));
wc.cbSize=sizeof(WNDCLASSEX); // size of the window struct in bytes
wc.style=CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // window styles to use
wc.lpfnWndProc=MsgProc; // function name of event handler
wc.hInstance=hInstance; // handle to this apps instance
wc.hbrBackground=(HBRUSH)GetStockObject(GRAY_BRUSH);// background colour of window
wc.hIcon= LoadIcon(NULL, IDI_APPLICATION); // icon for the app window
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION); // icon when minimized to taskbar
wc.hCursor=LoadCursor(NULL, IDC_ARROW); // cursor to use for this window
wc.lpszClassName=szAppname; // name for this class
// Register the window class
RegisterClassEx( &wc );
g_D3DSettings.m_nDeviceWidth=800;
g_D3DSettings.m_nDeviceHeight=600;
g_D3DSettings.m_fScreenAspect=(float)g_D3DSettings.m_nDeviceWidth / (float)g_D3DSettings.m_nDeviceHeight;
// Create the application's window
g_hWnd = CreateWindow(szAppname, szAppname, WS_OVERLAPPEDWINDOW, 10, 10,
g_D3DSettings.m_nDeviceWidth, g_D3DSettings.m_nDeviceHeight,
NULL, NULL, wc.hInstance, NULL );
// Show the window
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);
if(FAILED(AppInit()))
{
UnregisterClass(szAppname, wc.hInstance);
return -1;
}
// Enter the message loop
MSG msg;
ZeroMemory(&msg, sizeof(msg));
int count=0;
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
AppLoop();
}
}
AppShutDown();
UnregisterClass(szAppname, wc.hInstance);
return 0;
}
// =====================================================================================
// Function Name: MsgProc
// Purpose: Message handler for main app window
// =====================================================================================
LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch( msg )
{
case WM_KEYDOWN:
{
switch(wParam)
{
// Exit app on space or escape keypress
case VK_SPACE:
case VK_ESCAPE:
{
PostQuitMessage(0);
return 0;
}
break;
// Rotate the mesh on arrow key or home/end keypresses
case VK_LEFT:
g_XRotation += 0.1f;
break;
case VK_RIGHT:
g_XRotation -= 0.1f;
break;
case VK_UP:
g_YRotation += 0.1f;
break;
case VK_DOWN:
g_YRotation -= 0.1f;
break;
case VK_HOME:
g_ZRotation += 0.1f;
break;
case VK_END:
g_ZRotation -= 0.1f;
break;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
}
// =====================================================================================
// Function Name: AppInit
// Purpose: Initialisation for D3D and the app's global objects
// =====================================================================================
HRESULT AppInit()
{
HRESULT rslt=0;
g_pD3D=Direct3DCreate8(D3D_SDK_VERSION);
if(g_pD3D==NULL)
{
return D3DError(E_FAIL, __LINE__, __FILE__, "Failed to create a D3D9 object.");
}
// Populate our struct with how we want to set up D3D...
g_D3DSettings.m_bWindowed=TRUE;
g_D3DSettings.m_bMultiSampling=FALSE;
g_D3DSettings.m_D3DFormat=D3DFMT_X8R8G8B8;
// ...and pass it to our function to create the device!
rslt=InitDirect3DDevice(g_hWnd, g_D3DSettings, g_pD3D, &g_pDevice);
if(FAILED(rslt))
{
return E_FAIL;
}
// ===================================================================================
// Set up our Projection, View and World transformations
// ===================================================================================
// Create a matrix to store our Projection transform. Null all the fields.
D3DXMATRIX matProjection;
ZeroMemory(&matProjection, sizeof(matProjection));
// Use D3DX to create a left handed cartesian Field Of View transform
D3DXMatrixPerspectiveFovLH(&matProjection, D3DX_PI/4, g_D3DSettings.m_fScreenAspect,
1.0f, 100.0f);
// Tell D3D to use our Projection matrix for the projection transformation stage
rslt=g_pDevice->SetTransform(D3DTS_PROJECTION, &matProjection);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set Projection Transform."); }
// Create a matrix to store our View transform. Null all the fields.
D3DXMATRIX matView;
ZeroMemory(&matView, sizeof(matView));
// Use D3DX to create a Look At matrix from eye, lookat and up vectors.
D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3(0.0f, 0.0f, -5.0f),
&D3DXVECTOR3(0.0f, 0.0f, 0.0f),
&D3DXVECTOR3(0.0f, 1.0f, 0.0f));
// Tell D3D to use our View matrix for the view transformation stage
rslt=g_pDevice->SetTransform(D3DTS_VIEW, &matView);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set View Transform."); }
// Create a matrix to store our World transform
D3DXMATRIX matWorld;
// Set the matrix to an identity matrix (one that makes no change)
D3DXMatrixIdentity(&matWorld);
// Tell D3D to use our World matrix for the world transformation stage
rslt=g_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "Failed to set World Transform."); }
// ===================================================================================
// Set up our scene states
// ===================================================================================
// Set our culling & lighting renderstates
g_pDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);
g_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
// Load the sample mesh into the mesh class object
g_Mesh.Initialise("tiger.x", g_pDevice);
g_XRotation = 0.0f;
g_YRotation = 0.0f;
g_ZRotation = 0.0f;
return S_OK;
}
// =====================================================================================
// Function Name: AppLoop
// Purpose: Controls the flow of the app, called by the messageloop.
// =====================================================================================
HRESULT AppLoop()
{
// TODO: Add any non-rendering code to be completed every frame here.
// NOTE: If you change the return call, make sure you add a call to
// Render() elsewhere in this function.
return Render();
}
// =====================================================================================
// Function Name: AppShutDown
// Purpose: Called when the app exits. Releases all global COM interfaces.
// =====================================================================================
HRESULT AppShutDown()
{
// Release the mesh object
g_Mesh.Shutdown();
if(g_pDevice)
g_pDevice->Release();
if(g_pD3D)
g_pD3D->Release();
return S_OK;
}
// =====================================================================================
// Function Name: Render()
// Purpose: Main rendering function to perform D3D drawing
// =====================================================================================
HRESULT Render()
{
HRESULT rslt=NULL;
// ====================================================================================
// - Do all the usual checks to make sure we have the right pointers, etc...
// ====================================================================================
// Make sure we have a valid D3D Device
if(!g_pDevice) { return E_FAIL; }
// Return if the device is not ready
rslt=ValidateDevice(g_pDevice, g_D3DSettings);
// Clear the back buffer
g_pDevice->Clear(0,0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,55), 1.0f, 0);
rslt=g_pDevice->BeginScene();
if(FAILED(rslt)) { return D3DError(rslt, __LINE__, __FILE__, "BeginScene() failed."); }
// ====================================================================================
// - Do our drawing operations
// ====================================================================================
D3DXMATRIX matWorld;
D3DXMatrixRotationYawPitchRoll(&matWorld, g_XRotation, g_YRotation, g_ZRotation);
g_pDevice->SetTransform(D3DTS_WORLD, &matWorld);
// Render the mesh
g_Mesh.Render(g_pDevice);
// ====================================================================================
// - Clean up and present the back buffer to be page flipped
// ====================================================================================
g_pDevice->EndScene();
// Present the back buffer to the display adapter to be drawn
g_pDevice->Present(NULL, NULL, NULL, NULL);
return S_OK;
}