// include the basic windows header files and the Direct3D header file #include #include #include #include // define the screen resolution and keyboard macros #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define KEY_DOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEY_UP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) // include the Direct3D Library files #pragma comment (lib, "d3d9.lib") #pragma comment (lib, "d3dx9.lib") // global declarations LPDIRECT3D9 d3d; // the pointer to our Direct3D interface LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class LPDIRECT3DVERTEXBUFFER9 t_buffer = NULL; // the pointer to the vertex buffer // texture declarations LPDIRECT3DTEXTURE9 texture_1; // our first texture // function prototypes void initD3D(HWND hWnd); // sets up and initializes Direct3D void render_frame(void); // renders a single frame void cleanD3D(void); // closes Direct3D and releases memory void init_graphics(void); // 3D declarations void init_light(void); struct CUSTOMVERTEX {FLOAT X, Y, Z; D3DVECTOR NORMAL; FLOAT U, V;}; #define CUSTOMFVF (D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1) // the WindowProc function prototype LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); // the entry point for any Windows program int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { HWND hWnd; WNDCLASSEX wc; ZeroMemory(&wc, sizeof(WNDCLASSEX)); wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = (WNDPROC)WindowProc; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.lpszClassName = L"WindowClass"; RegisterClassEx(&wc); hWnd = CreateWindowEx(NULL, L"WindowClass", L"Our Direct3D Program", WS_EX_TOPMOST | WS_POPUP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); // set up and initialize Direct3D initD3D(hWnd); // enter the main loop: MSG msg; while(TRUE) { DWORD starting_point = GetTickCount(); if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) break; TranslateMessage(&msg); DispatchMessage(&msg); } render_frame(); // check the 'escape' key if(KEY_DOWN(VK_ESCAPE)) PostMessage(hWnd, WM_DESTROY, 0, 0); while ((GetTickCount() - starting_point) < 25); } // clean up DirectX and COM cleanD3D(); return static_cast(msg.wParam); } // this is the main message handler for the program LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: { PostQuitMessage(0); return 0; } break; } return DefWindowProc (hWnd, message, wParam, lParam); } // this function initializes and prepares Direct3D for use void initD3D(HWND hWnd) { d3d = Direct3DCreate9(D3D_SDK_VERSION); D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = FALSE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.hDeviceWindow = hWnd; d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8; d3dpp.BackBufferWidth = SCREEN_WIDTH; d3dpp.BackBufferHeight = SCREEN_HEIGHT; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D16; // create a device class using this information and the info from the d3dpp stuct d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &d3ddev); init_graphics(); // call the function to initialize the square init_light(); // call the function to initialize the light and material d3ddev->SetRenderState(D3DRS_LIGHTING, TRUE); // turn off the 3D lighting d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE); // turn on the z-buffer d3ddev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(0, 0, 70)); // ambient light return; } // this is the function used to render a single frame void render_frame(void) { d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0); d3ddev->BeginScene(); // select which vertex format we are using d3ddev->SetFVF(CUSTOMFVF); // set the view transform D3DXMATRIX matView; // the view transform matrix D3DXMatrixLookAtLH(&matView, &D3DXVECTOR3 (0.0f, 8.0f, 25.0f), // the camera position &D3DXVECTOR3 (0.0f, 0.0f, 0.0f), // the look-at position &D3DXVECTOR3 (0.0f, 1.0f, 0.0f)); // the up direction d3ddev->SetTransform(D3DTS_VIEW, &matView); // set the view transform to matView // set the projection transform D3DXMATRIX matProjection; // the projection transform matrix D3DXMatrixPerspectiveFovLH(&matProjection, D3DXToRadian(45), // the horizontal field of view (FLOAT)SCREEN_WIDTH / (FLOAT)SCREEN_HEIGHT, // aspect ratio 1.0f, // the near view-plane 100.0f); // the far view-plane d3ddev->SetTransform(D3DTS_PROJECTION, &matProjection); // set the projection // set the world transform static float index = 0.0f; index+=0.03f; // an ever-increasing float value D3DXMATRIX matRotateY; // a matrix to store the rotation for each triangle D3DXMatrixRotationY(&matRotateY, index); // the rotation matrix d3ddev->SetTransform(D3DTS_WORLD, &(matRotateY)); // set the world transform // select the vertex buffer to display d3ddev->SetStreamSource(0, t_buffer, 0, sizeof(CUSTOMVERTEX)); // set the texture d3ddev->SetTexture(0, texture_1); // draw the textured square d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2); d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 8, 2); d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 12, 2); d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 16, 2); d3ddev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 20, 2); d3ddev->EndScene(); d3ddev->Present(NULL, NULL, NULL, NULL); return; } // this is the function that cleans up Direct3D and COM void cleanD3D(void) { t_buffer->Release(); // close and release the vertex buffer texture_1->Release(); // close and release the texture d3ddev->Release(); // close and release the 3D device d3d->Release(); // close and release Direct3D return; } // this is the function that puts the 3D models into video RAM void init_graphics(void) { // load the texture we will use D3DXCreateTextureFromFile(d3ddev, L"Wood1.png", &texture_1); // create the vertices using the CUSTOMVERTEX struct CUSTOMVERTEX t_vert[] = { { -3.0f, 3.0f, -3.0f, 0, 0, -1, 0, 1, }, { 3.0f, 3.0f, -3.0f, 0, 0, -1, 1, 1, }, { -3.0f, -3.0f, -3.0f, 0, 0, -1, 0, 0, }, { 3.0f, -3.0f, -3.0f, 0, 0, -1, 1, 0, }, // side 2 { -3.0f, 3.0f, 3.0f, 0, 0, 1, 0, 1, }, { -3.0f, -3.0f, 3.0f, 0, 0, 1, 0, 0, }, { 3.0f, 3.0f, 3.0f, 0, 0, 1, 1, 1, }, { 3.0f, -3.0f, 3.0f, 0, 0, 1, 1, 0, }, // side 3 { -3.0f, 3.0f, 3.0f, 0, 1, 0, 0, 1, }, { 3.0f, 3.0f, 3.0f, 0, 1, 0, 1, 1, }, { -3.0f, 3.0f, -3.0f, 0, 1, 0, 0, 0, }, { 3.0f, 3.0f, -3.0f, 0, 1, 0, 1, 0, }, // side 4 { -3.0f, -3.0f, 3.0f, 0, -1, 0, 0, 1, }, { -3.0f, -3.0f, -3.0f, 0, -1, 0, 0, 0, }, { 3.0f, -3.0f, 3.0f, 0, -1, 0, 1, 1, }, { 3.0f, -3.0f, -3.0f, 0, -1, 0, 1, 0, }, // side 5 { 3.0f, 3.0f, -3.0f, 1, 0, 0, 1, 0, }, { 3.0f, 3.0f, 3.0f, 1, 0, 0, 1, 1, }, { 3.0f, -3.0f, -3.0f, 1, 0, 0, 0, 0, }, { 3.0f, -3.0f, 3.0f, 1, 0, 0, 0, 1, }, // side 6 { -3.0f, 3.0f, -3.0f, -1, 0, 0, 1, 0, }, { -3.0f, -3.0f, -3.0f, -1, 0, 0, 0, 0, }, { -3.0f, 3.0f, 3.0f, -1, 0, 0, 1, 1, }, { -3.0f, -3.0f, 3.0f, -1, 0, 0, 0, 1, }, }; // create a vertex buffer interface called t_buffer d3ddev->CreateVertexBuffer(24*sizeof(CUSTOMVERTEX), 0, CUSTOMFVF, D3DPOOL_MANAGED, &t_buffer, NULL); VOID* pVoid; // a void pointer // lock t_buffer and load the vertices into it t_buffer->Lock(0, 0, (void**)&pVoid, 0); memcpy(pVoid, t_vert, sizeof(t_vert)); t_buffer->Unlock(); return; } // this is the function that sets up the lights and meterials void init_light(void) { D3DLIGHT9 light; // create the light struct D3DMATERIAL9 material; // create the material struct ZeroMemory(&light, sizeof(light)); // clear out the light struct for use light.Type = D3DLIGHT_DIRECTIONAL; // make the light type 'directional light' light.Diffuse.r = 0.5f; // .5 red light.Diffuse.g = 0.5f; // .5 green light.Diffuse.b = 0.5f; // the .5 blue light.Diffuse.a = 1.0f; // full alpha (we'll get to that soon) D3DVECTOR vecDirection = {-1.0f, -0.3f, -1.0f}; // the direction of the light light.Direction = vecDirection; // set the direction d3ddev->SetLight(0, &light); // send the light struct properties to light d3ddev->LightEnable(0, TRUE); // turn on the light ZeroMemory(&material, sizeof(D3DMATERIAL9)); // clear out the struct for use material.Diffuse.r = material.Ambient.r = 1.0f; // set the material to full red material.Diffuse.g = material.Ambient.g = 1.0f; // set the material to full green material.Diffuse.b = material.Ambient.b = 1.0f; // set the material to full blue material.Diffuse.a = material.Ambient.a = 1.0f; // set the material to full alpha d3ddev->SetMaterial(&material); // set the globaly-used material to &material return; }