|
Animation in Direct3D
An Example |
|
Prof. David Bernstein |
| Computer Science Department |
| bernstdh@jmu.edu |
#include "dxstdafx.h"
#include "resource.h"
/**
* An application that uses Direct3D to render a cube
* with textures
*
* @author Prof. David Bernstein, James Madison University
* @version 1.0
*/
// Globals
LPDIRECT3DVERTEXBUFFER9 vertexBuffer = NULL;
LPDIRECT3DTEXTURE9 texture[6];
float rotateX = 0.0f;
float rotateY = 0.0f;
int axis = 0;
// Specify the struct for a vertex
struct CUSTOMVERTEX
{
float x, y, z;
float u, v; // Texture coordinates
};
// Specify the flexible vertex format (FVF) for the struct above
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ | D3DFVF_TEX1)
// Color Definitions
DWORD colorBlue = 0xFF0000FF;
DWORD colorGold = 0xFFC2A14D; // JMU Gold
DWORD colorGray = 0xFFAAAAAA;
DWORD colorGreen = 0xFF00FF00;
DWORD colorPurple = 0xFF450084; // JMU Purple
DWORD colorRed = 0xFFFF0000;
DWORD colorYellow = 0xFFFFFF00;
// Create the vertex elements
CUSTOMVERTEX vertices[] =
{
{-1.0f, 1.0f,-1.0f, 0.0f, 0.0f}, // Front
{ 1.0f, 1.0f,-1.0f, 1.0f, 0.0f},
{-1.0f,-1.0f,-1.0f, 0.0f, 1.0f},
{ 1.0f,-1.0f,-1.0f, 1.0f, 1.0f},
{-1.0f, 1.0f, 1.0f, 1.0f, 0.0f}, // Back
{-1.0f,-1.0f, 1.0f, 1.0f, 1.0f},
{ 1.0f, 1.0f, 1.0f, 0.0f, 0.0f},
{ 1.0f,-1.0f, 1.0f, 0.0f, 1.0f},
{-1.0f, 1.0f, 1.0f, 0.0f, 0.0f}, // Top
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
{-1.0f, 1.0f,-1.0f, 0.0f, 1.0f},
{ 1.0f, 1.0f,-1.0f, 1.0f, 1.0f},
{-1.0f,-1.0f, 1.0f, 0.0f, 0.0f}, // Bottom
{-1.0f,-1.0f,-1.0f, 1.0f, 0.0f},
{ 1.0f,-1.0f, 1.0f, 0.0f, 1.0f},
{ 1.0f,-1.0f,-1.0f, 1.0f, 1.0f},
{ 1.0f, 1.0f,-1.0f, 0.0f, 0.0f}, // Right
{ 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
{ 1.0f,-1.0f,-1.0f, 0.0f, 1.0f},
{ 1.0f,-1.0f, 1.0f, 1.0f, 1.0f},
{-1.0f, 1.0f,-1.0f, 1.0f, 0.0f}, // Left
{-1.0f,-1.0f,-1.0f, 1.0f, 1.0f},
{-1.0f, 1.0f, 1.0f, 0.0f, 0.0f},
{-1.0f,-1.0f, 1.0f, 0.0f, 1.0f}
};
/**
* The function that is called when the timer "ticks"
*/
void CALLBACK exitFrame(UINT id, void* userContext)
{
if (axis == 0)
rotateX += (float)D3DX_PI/100.0f;
else
rotateY += (float)D3DX_PI/100.0f;
}
/**
* Checks to see if a device is acceptable
*
* @return false if the device isn't acceptable
*/
bool CALLBACK isDeviceAcceptable(D3DCAPS9* caps, D3DFORMAT adapterFormat,
D3DFORMAT backBufferFormat, bool windowed,
void* userContext )
{
// Skip backbuffer formats that don't support alpha blending
IDirect3D9* d3d = DXUTGetD3DObject();
if( FAILED(d3d->CheckDeviceFormat(caps->AdapterOrdinal, caps->DeviceType,
adapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
D3DRTYPE_TEXTURE, backBufferFormat)))
return false;
return true;
}
/**
* The function that is called when a key is pressed/released
*/
void CALLBACK keyPressed(UINT nChar, bool keyDown, bool altDown,
void* userContext )
{
}
/**
* Modify device settings (as needed)
*
* Note: This function is called before a device is created
*/
bool CALLBACK modifyDeviceSettings(DXUTDeviceSettings* deviceSettings,
const D3DCAPS9* caps, void* userContext )
{
// Nothing to change in this case
return true;
}
/**
* The function that is called when the mouse is
* moved or clicked
*/
void CALLBACK mouseEvent(bool leftDown, bool rightDown, bool middleDown,
bool side1Down, bool side2Down,
int wheelDelta, int x, int y, void* userContext)
{
if (leftDown)
{
axis = 0;
}
else if (rightDown)
{
axis = 1;
}
}
/**
* The function that is called to handle MS-Windows messages
*/
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
bool* pbNoFurtherProcessing, void* pUserContext )
{
return 0;
}
/**
* The function that is called when a device is created
*
* Note: This is where D3DPOOL_MANAGED resources should be created
*/
HRESULT CALLBACK onCreateDevice(IDirect3DDevice9* d3dDevice,
const D3DSURFACE_DESC* backBufferSurfaceDesc,
void* userContext )
{
// Create the vertex buffer
d3dDevice->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX),0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &vertexBuffer, NULL );
// Declare the source data for the buffer
VOID* data = NULL;
// Lock the vertex buffer
vertexBuffer->Lock( 0, sizeof(vertices), (void**)&data, 0 );
// Copy the vertices into the buffer
memcpy(data, vertices, sizeof(vertices));
// Unlock the vertex buffer
vertexBuffer->Unlock();
// Set rendering options
d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
d3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE);
// Use a perspective projection
D3DXMATRIX projection;
D3DXMatrixPerspectiveFovLH( &projection, D3DXToRadian( 45.0f ),
640.0f / 480.0f, 0.1f, 100.0f );
d3dDevice->SetTransform(D3DTS_PROJECTION, &projection);
ZeroMemory(texture, 6*sizeof(LPDIRECT3DTEXTURE9));
// Create one texture for each face
D3DXCreateTextureFromFile(d3dDevice, L"brick.bmp", &texture[0]);
D3DXCreateTextureFromFile(d3dDevice, L"brownpaper.bmp", &texture[1]);
D3DXCreateTextureFromFile(d3dDevice, L"flagstone.bmp", &texture[2]);
D3DXCreateTextureFromFile(d3dDevice, L"frostedglass.bmp", &texture[3]);
D3DXCreateTextureFromFile(d3dDevice, L"lake.bmp", &texture[4]);
D3DXCreateTextureFromFile(d3dDevice, L"oak.bmp", &texture[5]);
// Set texture-mapping properties
d3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
d3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
return S_OK;
}
/**
* The function that is called when the device is destroyed
*
* Note: This function should release resources created in the
* OnCreateDevice callback
*/
void CALLBACK onDestroyDevice(void* userContext )
{
if( vertexBuffer != NULL ) vertexBuffer->Release();
for (int i=0; i<6; i++)
{
if (texture[i] != NULL) texture[i]->Release();
}
}
/**
* The function that is called before the call to the
* rendering callback
*/
void CALLBACK onFrameMove(IDirect3DDevice9* d3dDevice,
double time, float elapsedTime,
void* userContext )
{
}
/**
* The function that is called when the device is lost
*
* Note: This function should release resources created in the
* OnResetDevice callback
*/
void CALLBACK onLostDevice(void* userContext)
{
}
/**
* The function that is called when a device is created
*
* Note: This is where D3DPOOL_DEFAULT resources should be created
*/
HRESULT CALLBACK onResetDevice(IDirect3DDevice9* d3dDevice,
const D3DSURFACE_DESC* backBufferSurfaceDesc,
void* userContext )
{
return S_OK;
}
/**
* The function that is called when the scene needs to be rendered
*/
void CALLBACK paint(IDirect3DDevice9* d3dDevice,
double time, float elapsedTime,
void* userContext )
{
HRESULT hr;
// Clear the render target and the zbuffer
V(d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_ARGB(0, 0xC2, 0xA1, 0x4D), 1.0f, 0) );
// Render the scene
if( SUCCEEDED(d3dDevice->BeginScene()))
{
// Transform the model
D3DXMATRIX rotate, translate, world;
D3DXMatrixTranslation(&translate, 0.0f, 0.0f, 5.0f );
D3DXMatrixRotationYawPitchRoll(&rotate, rotateX, rotateY, 0.0f);
D3DXMatrixMultiply(&world, &rotate, &translate);
d3dDevice->SetTransform(D3DTS_WORLD, &world );
// Starting to define the scene
d3dDevice->BeginScene();
// Bind the vertex buffer to the device
d3dDevice->SetStreamSource(0, vertexBuffer, 0, sizeof(CUSTOMVERTEX));
// Setup the vertex shader
d3dDevice->SetFVF(D3DFVF_CUSTOMVERTEX);
// Draw the various shapes (two triangles for each face)
d3dDevice->SetTexture(0, texture[0]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
d3dDevice->SetTexture(0, texture[1]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
d3dDevice->SetTexture(0, texture[2]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2);
d3dDevice->SetTexture(0, texture[3]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2);
d3dDevice->SetTexture(0, texture[4]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2);
d3dDevice->SetTexture(0, texture[5]);
d3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2);
V(d3dDevice->EndScene());
}
}
/**
* The entry-point of the application
*/
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
// Register the device-reated callbacks
DXUTSetCallbackDeviceCreated(onCreateDevice);
DXUTSetCallbackDeviceReset(onResetDevice);
DXUTSetCallbackDeviceLost(onLostDevice);
DXUTSetCallbackDeviceDestroyed(onDestroyDevice);
// Register message callbacks
DXUTSetCallbackMsgProc(MsgProc);
// Register the pre-rendering callback
DXUTSetCallbackFrameMove(onFrameMove);
// Register the render/display callback
DXUTSetCallbackFrameRender(paint);
// Register the keyboard callback
DXUTSetCallbackKeyboard(keyPressed);
// Register the mouse callback
bool includeMouseMoveEvents = false;
DXUTSetCallbackMouse(mouseEvent, includeMouseMoveEvents);
// Register the timer callback
DXUTSetTimer(exitFrame, 0.025f);
// Initialize DXUT and create the desired Win32 window
// and Direct3D device for the application
//
DXUTInit(true, // Parse the command line
true, // Handle default hotkeys
true); // Show msgboxes
// Setup the cursor
DXUTSetCursorSettings(true, // Show the cursor
true ); // Clip the cursor in full screen mode
// Create the window
DXUTCreateWindow(L"Cube"); // Title
// Create the device/renderer
DXUTCreateDevice(D3DADAPTER_DEFAULT, // Adapter
true, // Windowed
640, 480, // Width, Height
isDeviceAcceptable, // Acceptable Callback
modifyDeviceSettings); // Settings Callback
// Start the render loop
DXUTMainLoop();
return DXUTGetExitCode();
}