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(); }