/* Triangle.cpp
Demonstration code showing how to draw a simple triangle using Direct3D.
See the site for details of each stage.
Written by Keith Ditchburn 2006
*/
#define VC_EXTRALEAN
#include <windows.h>
#include <d3d9.h> // Main Direct3D header
#include <d3dx9.h> // D3DX helper functions
// Forward declarations
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
bool InitialiseDirect3D(HWND hWnd);
void CloseDownDirect3D();
void RenderScene();
void DrawSprite();
// Globals
LPDIRECT3D9 gD3dObject=NULL;
LPDIRECT3DDEVICE9 gD3dDevice=NULL;
LPDIRECT3DTEXTURE9 gTexture = NULL;
LPD3DXSPRITE sprite = NULL;
// The main entry point of our Windows program
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Create and fill out a window class structure
WNDCLASS wcex;
ZeroMemory(&wcex,sizeof(WNDCLASS));
// Provide the address of the function Windows should call with messages
wcex.lpfnWndProc= (WNDPROC)WndProc;
wcex.style= CS_HREDRAW | CS_VREDRAW;
wcex.hInstance= hInstance;
wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszClassName= "MyWindowClass";
// Register my new window class with the Windows API
RegisterClass(&wcex);
// Create the window
HWND hWnd = CreateWindow("MyWindowClass", "D3D Triangle Demo",
WS_OVERLAPPEDWINDOW, 100, 100, 800, 600,
NULL, NULL, hInstance, NULL);
if (hWnd==0)
return -1;
// Set up Direct3D
if (!InitialiseDirect3D(hWnd))
return -1;
// Show the window for the first time
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Windows sends some messages directly to your callback function but others are placed in
// a queue. These tend to be keyboard messages or other input that may need translating. We
// enter a loop that checks for queued messages. If one is found it is translated and dispatched
// to our windows procedure. Once the application is closed a WM_QUIT message is received.
// When there are no messages to handle we draw our scene. This makes our program 'badly behaved'
// as we are hogging system resources so I tend to put in a sleep(0) that lets other threads have
// at least some time.
MSG msg;
ZeroMemory( &msg, sizeof(msg) );
while( msg.message!=WM_QUIT )
{
if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
RenderScene();
Sleep(0);
}
}
// Clean up before exiting
CloseDownDirect3D();
return (int)msg.wParam;
}
// Callback message handler function for our window
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
// We do not want to handle this message so pass it back to Windows
// to handle it in a default way
return DefWindowProc(hWnd, message, wParam, lParam);
break;
}
return 0;
}
// Set up Direct3D
// Requires creation of the Direct3D object and the Direct3D device
bool InitialiseDirect3D(HWND hWnd)
{
// Create the main Direct3D object. This object is used to initialise Direct3D
// and to provide us with a device interface object
gD3dObject=Direct3DCreate9(D3D_SDK_VERSION);
if (gD3dObject==0)
return false;
// Fill out the parameters for our required device
D3DPRESENT_PARAMETERS presParams;
ZeroMemory(&presParams,sizeof(presParams));
presParams.Windowed=TRUE;
presParams.SwapEffect=D3DSWAPEFFECT_DISCARD;
presParams.BackBufferFormat=D3DFMT_UNKNOWN;
presParams.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
// Get the Direct3D object to give us a pointer to a device interface object
// this device represents the graphics capabilities of the PC
HRESULT hr=gD3dObject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,&presParams,&gD3dDevice);
if (FAILED(hr))
{
// If we could not get a hardware vertex processing device fallback to a software one
hr=gD3dObject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,&presParams,&gD3dDevice);
if (FAILED(hr))
return false;
}
// Since we are providing a colour component per vertex we do not
// want Direct3D lighting to be on
gD3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
D3DXCreateTextureFromFile(gD3dDevice, "sprite_devil.bmp", &gTexture);
D3DXCreateSprite(gD3dDevice, &sprite);
return true;
}
// Release all the Direct3D interfaces in reverse order to their creation
// All Direct3D objects implement a Release interface
void CloseDownDirect3D()
{
if (gD3dDevice)
{
gD3dDevice->Release();
gD3dDevice=NULL;
}
if (gD3dObject)
{
gD3dObject->Release();
gD3dObject=NULL;
}
}
/* There are 3 matrices using by Direct3D
World Matrix - Transforms 3D data from Model Space into World Space.
You need to set this before rendering every entity in your world.
View Matrix - Transforms from World Space into View Space.
You need to set this each time your camera changes position
Projection Matrix - Transforms from View Space into Screen Space.
You normally set this just once during initialization.
*/
// Draw the scene
void RenderScene()
{
// Clear the back buffer to black
gD3dDevice->Clear(0,NULL,D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0),1.0f,0);
// Note: all drawing must occur between the BeginScene and EndScene calls
if (SUCCEEDED(gD3dDevice->BeginScene()))
{
// Draw out triangle
DrawSprite();
// Tell Direct3D that we have finished sending it 3D data
gD3dDevice->EndScene();
}
// Indicate that the scene should be shown
gD3dDevice->Present(0,0,0,0);
}
// Draw the triangle
void DrawSprite()
{
//D3DXVECTOR3 pos;
//pos.x=384.0f;
//pos.y=284.0f;
//pos.z=0.0f;
//
//sprite->Begin(D3DXSPRITE_ALPHABLEND);
//sprite->Draw(gTexture,NULL,NULL,&pos,0xFFFFFFFF);
//sprite->End();
sprite->Begin(D3DXSPRITE_ALPHABLEND);
// Texture being used is 32 by 32:
//D3DXVECTOR2 spriteCentre=D3DXVECTOR2(16.0f,16.0f);
// Screen position of the sprite
D3DXVECTOR2 trans=D3DXVECTOR2(384.0f,284.0f);
// Rotate based on the time passed
//float rotation=0.0f;
// Build our matrix to rotate, scale and position our sprite
D3DXMATRIX mat;
//D3DXVECTOR2 scaling(1.0f,1.0f);
// out, scaling centre, scaling rotation, scaling, rotation centre, rotation, translation
D3DXMatrixTransformation2D(&mat,NULL,NULL,NULL,NULL,NULL,&trans);
// Tell the sprite about the matrix
sprite->SetTransform(&mat);
// Draw the sprite
sprite->Draw(gTexture,NULL,NULL,NULL,0xFFFFFFFF);
// Thats it
sprite->End();
}