// PhilVaz OpenGL Demo // Render one 3D cube // July 9, 2004 // INCLUDES /////////////////////////////////////////////// #define WIN32_LEAN_AND_MEAN #include // include all the windows headers #include // include useful macros #include // for rand functions #include #include #include // OpenGL32 library #include // GLU32 library #include // GLAUX library // DEFINES //////////////////////////////////////////////// // defines for windows #define WINDOW_CLASS_NAME "WINCLASS1" #define WINDOW_WIDTH 800 // size of game window #define WINDOW_HEIGHT 600 #define WINDOW_BPP 16 #define GAME_SPEED 30 // speed of game (increase to go slower) // MACROS ///////////////////////////////////////////////// #define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0) #define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1) // GLOBALS //////////////////////////////////////////////// HWND game_window = NULL; // global game window handle HINSTANCE game_instance = NULL; // global game instance handle HDC game_dc = NULL; // global device context (GDI) handle DEVMODE game_screen; // global for full screen mode HGLRC game_rc = NULL; // global rendering context (OpenGL) handle bool draw_ok; // for whether OpenGL init ok GLdouble xcam, ycam, zcam; // camera (eye) position // FUNCTIONS ////////////////////////////////////////////// bool GameInit(); void GameMain(); void GameQuit(); // WINPROC //////////////////////////////////////////////// LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { // this is the main message handler of the system HDC hdc; // handle to a device context PAINTSTRUCT ps; // used in WM_PAINT switch(msg) // what is the message { case WM_CREATE: { // do initialization stuff here return(0); // return success } break; case WM_PAINT: { hdc = BeginPaint(hwnd, &ps); // validate the window EndPaint(hwnd, &ps); return(0); // return success } break; case WM_DESTROY: { PostQuitMessage(0); // kill the application, sends a WM_QUIT message return(0); // return success } break; default:break; } // end switch // process any messages that we didn't take care of return (DefWindowProc(hwnd, msg, wparam, lparam)); } // end WinProc // WINMAIN //////////////////////////////////////////////// int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { WNDCLASSEX winclass; // this will hold the class we create HWND hwnd; // generic window handle MSG msg; // generic message // first fill in the window class structure winclass.cbSize = sizeof(WNDCLASSEX); winclass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW; winclass.lpfnWndProc = WinProc; winclass.cbClsExtra = 0; winclass.cbWndExtra = 0; winclass.hInstance = hinstance; winclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); winclass.hIconSm = LoadIcon(NULL, IDI_APPLICATION); winclass.hCursor = LoadCursor(NULL, IDC_ARROW); winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); winclass.lpszMenuName = NULL; winclass.lpszClassName = WINDOW_CLASS_NAME; // save the game instance handle game_instance = hinstance; // register the window class if (!RegisterClassEx(&winclass)) return(0); // create the window if (!(hwnd = CreateWindowEx(NULL, // extended style WINDOW_CLASS_NAME, // class "OpenGL Demo", // title WS_POPUP | WS_VISIBLE, // use POPUP for full screen 0,0, // initial game window x,y WINDOW_WIDTH, // initial game width WINDOW_HEIGHT, // initial game height NULL, // handle to parent NULL, // handle to menu hinstance, // instance of this application NULL))) // extra creation parms return(0); // save the game window handle game_window = hwnd; draw_ok = GameInit(); // game initialization function called here // enter main event loop using PeekMessage() to retrieve messages while(TRUE) { // get initial tick count to keep game speed constant DWORD start_tick = GetTickCount(); // is there a message in queue, if so get it if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { // test if this is a quit if (msg.message == WM_QUIT) break; // translate any accelerator keys TranslateMessage(&msg); // send the message to WinProc DispatchMessage(&msg); } // end if GameMain(); // game main processing function called here // check for key and send quit game if (KEYDOWN(VK_ESCAPE)) SendMessage (hwnd, WM_CLOSE, 0, 0); // wait until we hit correct game speed frame rate while ((GetTickCount() - start_tick) < GAME_SPEED); } // end while GameQuit(); // game quit function and clean up before exit called here return(msg.wParam); // return to Windows } // end WinMain // BEGIN GAME CODE //////////////////////////////////////// /////////////////////////////////////////////////////////// // // GAME INITIALIZATION // /////////////////////////////////////////////////////////// bool GameInit() { int pf; // pixel format // temporary change to full screen mode ZeroMemory(&game_screen, sizeof(game_screen)); // clear out size of DEVMODE struct game_screen.dmSize = sizeof(game_screen); game_screen.dmPelsWidth = WINDOW_WIDTH; game_screen.dmPelsHeight = WINDOW_HEIGHT; game_screen.dmBitsPerPel = WINDOW_BPP; game_screen.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; ChangeDisplaySettings(&game_screen, CDS_FULLSCREEN); game_dc = GetDC(game_window); // get the GDI device context // set up the pixel format desc struct PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this PFD 1, // version number PFD_DRAW_TO_WINDOW | // supports window PFD_SUPPORT_OPENGL | // supports OpenGL PFD_DOUBLEBUFFER, // support double buff PFD_TYPE_RGBA, // request RGBA format WINDOW_BPP, // select color depth 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buff 0, // shift bit ignored 0, // no accum buff 0, 0, 0, 0, // accum bits ignored 16, // 16-bit Z-buff (depth buff) 0, // no stencil buff 0, // no aux buff PFD_MAIN_PLANE, // main drawing layer 0, // reserved 0, 0, 0 // layer masks ignored }; if (!(pf = ChoosePixelFormat(game_dc, &pfd))) // match the pixel format { MessageBox(game_window, "OpenGL could not be initialized -- ChoosePixelFormat Error","OpenGL Error",MB_OK); return FALSE; // error returned } if (!SetPixelFormat(game_dc, pf, &pfd)) // set the pixel format { MessageBox(game_window, "OpenGL could not be initialized -- SetPixelFormat Error","OpenGL Error",MB_OK); return FALSE; // error returned } if (!(game_rc = wglCreateContext(game_dc))) // create the rendering context { MessageBox(game_window, "OpenGL could not be initialized -- CreateContext Error","OpenGL Error",MB_OK); return FALSE; // error returned } if (!wglMakeCurrent(game_dc, game_rc)) // make it current { MessageBox(game_window, "OpenGL could not be initialized -- MakeCurrent Error","OpenGL Error",MB_OK); return FALSE; // error returned } MessageBox(game_window, "OpenGL Initialized Okay -- One Cube will be drawn -- use arrow keys and A/Z to move camera -- press space to reset -- Entering GameMain Loop","OpenGL OK",MB_OK); // set up viewport and perspective glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(90.0, WINDOW_WIDTH / WINDOW_HEIGHT, 1, 100.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); xcam = 0.0; ycam = 0.0; zcam = 10.0; // initial position of camera return TRUE; // success since previous IFs all TRUE } // END OF GameInit /////////////////////////////////////////////////////////// // // GAME MAIN LOOP AND PROCESSING // /////////////////////////////////////////////////////////// void GameMain() { // set up camera, clear screen, and render one 3D cube glLoadIdentity(); gluLookAt(xcam,ycam,zcam, 0,0,0, 0,1,0); // eye, origin, up glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_CULL_FACE); // remove hidden faces glBegin(GL_QUADS); glColor3f(1,0,0); // red glVertex3f( 3, 3,-3); // face 1 glVertex3f(-3, 3,-3); glVertex3f(-3, 3, 3); glVertex3f( 3, 3, 3); glColor3f(0,1,0); // green glVertex3f( 3,-3, 3); // face 2 glVertex3f(-3,-3, 3); glVertex3f(-3,-3,-3); glVertex3f( 3,-3,-3); glColor3f(0,0,1); // blue glVertex3f( 3, 3, 3); // face 3 glVertex3f(-3, 3, 3); glVertex3f(-3,-3, 3); glVertex3f( 3,-3, 3); glColor3f(1,1,0); // red/green glVertex3f( 3,-3,-3); // face 4 glVertex3f(-3,-3,-3); glVertex3f(-3, 3,-3); glVertex3f( 3, 3,-3); glColor3f(0,1,1); // green/blue glVertex3f(-3, 3, 3); // face 5 glVertex3f(-3, 3,-3); glVertex3f(-3,-3,-3); glVertex3f(-3,-3, 3); glColor3f(1,0,1); // red/blue glVertex3f( 3, 3,-3); // face 6 glVertex3f( 3, 3, 3); glVertex3f( 3,-3, 3); glVertex3f( 3,-3,-3); glEnd(); glDisable(GL_CULL_FACE); SwapBuffers(game_dc); if (KEYDOWN(VK_RIGHT)) { xcam += 1.0; if (xcam > 50.0) xcam = 50.0; } if (KEYDOWN(VK_LEFT)) { xcam -= 1.0; if (xcam < -50.0) xcam = -50.0; } if (KEYDOWN(VK_DOWN)) { zcam += 1.0; if (zcam > 50.0) zcam = 50.0; } if (KEYDOWN(VK_UP)) { zcam -= 1.0; if (zcam < -50.0) zcam = -50.0; } if (KEYDOWN(VK_SPACE)) { xcam = 0.0; ycam = 0.0; zcam = 10.0; } if (KEYDOWN(65)) { ycam += 1.0; if (ycam > 50.0) ycam = 50.0; } if (KEYDOWN(90)) { ycam -= 1.0; if (ycam < -50.0) ycam = -50.0; } } // END OF GameMain /////////////////////////////////////////////////////////// // // GAME QUIT AND CLEAN UP // /////////////////////////////////////////////////////////// void GameQuit() { if (game_rc) // if rendering context (OpenGL) exists, delete it { wglMakeCurrent(NULL,NULL); wglDeleteContext(game_rc); } // release the device context (GDI) from the game window ReleaseDC(game_window, game_dc); // return to original display settings ChangeDisplaySettings(NULL,NULL); } // END OF GameQuit // END GAME CODE //////////////////////////////////////////