// SC3D.cpp // // Barebones win32 / direct3d9 application #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #include #include #include #include // Definitions const unsigned long CVERT_FVF = (D3DFVF_XYZ | D3DFVF_DIFFUSE); struct CVERT { float x, y, z; unsigned long color; }; // Globals HINSTANCE hInst = 0; // current application instance HWND hWnd = 0; // main window handle IDirect3D9* pD3D = 0; // direct3d interface IDirect3DDevice9* pDevice = 0; // d3d device interface IDirect3DVertexBuffer9* pVB = 0; // vertex buffer interface // Forward declarations ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT WndProc(HWND, UINT, WPARAM, LPARAM); void InitializeDirect3D( HWND hwnd ); void InitializeScene(); void ShutdownDirect3D(); void Render3DEnvironment(); int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // Initialize global strings MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) return FALSE; InitializeDirect3D( hWnd ); InitializeScene(); // Now we're ready to recieve and process Windows messages. bool bGotMsg; MSG msg; msg.message = WM_NULL; PeekMessage( &msg, NULL, 0U, 0U, PM_NOREMOVE ); while( WM_QUIT != msg.message ) { // Use PeekMessage() if the app is active, so we can use idle time to // render the scene. Else, use GetMessage() to avoid eating CPU time. bGotMsg = ( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) != 0 ); if( bGotMsg ) { { TranslateMessage( &msg ); DispatchMessage( &msg ); } } else { Render3DEnvironment(); } } ShutdownDirect3D(); return (int) msg.wParam; } // PURPOSE: Registers the window class. ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = 0; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = 0; wcex.lpszClassName = "SimpleWindow"; wcex.hIconSm = 0; return RegisterClassEx(&wcex); } // PURPOSE: Saves instance handle and creates main window BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow("SimpleWindow", "Simple3D", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // PURPOSE: Processes messages for the main window. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } void InitializeDirect3D( HWND hwnd ) { pD3D = Direct3DCreate9( D3D_SDK_VERSION ); assert(pD3D); D3DPRESENT_PARAMETERS d3dpp; memset( &d3dpp, 0, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; HRESULT hr = pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDevice ); assert(hr == D3D_OK); } void ShutdownDirect3D() { if(pVB) pVB->Release(); if(pDevice) pDevice->Release(); if(pD3D) pD3D->Release(); } void InitializeScene() { pDevice->CreateVertexBuffer( sizeof(CVERT)*3, 0, CVERT_FVF, D3DPOOL_MANAGED, &pVB, 0 ); // Fill in the vertex buffer CVERT* VertPtr; pVB->Lock( 0, sizeof(CVERT)*3, reinterpret_cast(&VertPtr), 0 ); VertPtr->x = -5.0f; VertPtr->y = 0.0f; VertPtr->z = 0.0f; VertPtr->color = 0xff000000; VertPtr++; VertPtr->x = 0.0f; VertPtr->y = 10.0f; VertPtr->z = 0.0f; VertPtr->color = 0xff00ff00; VertPtr++; VertPtr->x = 5.0f; VertPtr->y = 0.0f; VertPtr->z = 0.0f; VertPtr->color = 0xff808080; pVB->Unlock(); pDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); pDevice->SetRenderState( D3DRS_COLORVERTEX, TRUE ); pDevice->SetRenderState( D3DRS_COLORWRITEENABLE, 0xffffffff ); pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); } void SetMatrices() { D3DXMATRIX WorldTransform; D3DXMatrixIdentity( &WorldTransform ); pDevice->SetTransform( D3DTS_WORLD, &WorldTransform ); D3DXMATRIX ViewTransform; D3DXMatrixLookAtLH( &ViewTransform, &D3DXVECTOR3( 0.0f, 5.0f, 10.0f ), &D3DXVECTOR3( 0.0f, 5.0f, 0.0f ), &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) ); pDevice->SetTransform( D3DTS_VIEW, &ViewTransform ); D3DXMATRIX ProjectionTransform; D3DXMatrixPerspectiveFovLH( &ProjectionTransform, D3DX_PI/2.0f, 1.0f, 1.0f, 100.0f ); pDevice->SetTransform( D3DTS_PROJECTION, &ProjectionTransform ); } void Render3DEnvironment() { SetMatrices(); pDevice->BeginScene(); pDevice->Clear( 0, 0, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, 0xff444444, 1.0f, 0 ); pDevice->SetStreamSource( 0, pVB, 0, sizeof(CVERT) ); pDevice->SetFVF( CVERT_FVF ); pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 1 ); pDevice->EndScene(); pDevice->Present( 0, 0, 0, 0 ); }