//---------------------------------------------------------------- // // This windows program draws a rotating red triangle using openGL. // //----------------------------------------------------------------- #define WIN32_LEAN_AND_MEAN #include #include #include #include //---------------------------------------------------------------- // globals (YUCK!) //---------------------------------------------------------------- HDC gHDC; // the device context //---------------------------------------------------------------- // function prototypes //---------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); void SetupPixelFormat(HDC hDC); void Init(); void Render(); //----------------------------------------------------------------- // WinMain // WinMain creates the window and then enters the message loop. // In the message loop we redraw our scene and then process // message from the OS. //----------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { // complete window class structure WNDCLASSEX windowClass; windowClass.cbSize = sizeof(WNDCLASSEX); windowClass.style = CS_HREDRAW | CS_VREDRAW; windowClass.lpfnWndProc= (WNDPROC) WndProc; windowClass.cbClsExtra = 0; windowClass.cbWndExtra = 0; windowClass.hInstance = hInstance; windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); windowClass.hCursor = LoadCursor(NULL, IDC_ARROW); windowClass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); windowClass.lpszMenuName = NULL; windowClass.lpszClassName = "MyClass"; windowClass.hIconSm = LoadIcon(NULL,IDI_WINLOGO); //register the class if (!RegisterClassEx(&windowClass)) return 0; //create the window HWND hwnd; hwnd = CreateWindowEx(NULL, "MyClass", "OpenGL", WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 100, 100, 400, 400, NULL, NULL, hInstance, NULL); if (!hwnd) return 0; // initialize openGL parameters Init(); // go into a message loop MSG msg; // structure for storing messages bool done = false; // done is false until we get a // message to quit while (!done) { // read next message PeekMessage(&msg, hwnd, NULL, NULL, PM_REMOVE); // if message says to quit we are done if (msg.message == WM_QUIT) done = true; // otherwise do a render loop else { // render scene Render(); // process the message TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } //-------------------------------------------------------------- // Init // Init initializes openGL parameters //--------------------------------------------------------------- void Init() { // the background is black glClearColor(0.0f, 0.0f, 0.0f, 0.0f); } //-------------------------------------------------------------- // Render // Render draws a rotating red triangle //--------------------------------------------------------------- void Render() { // we're going to rotate a triangle by angle static float angle = 0; // clear the modelview matrix glLoadIdentity(); // clear the frame buffer glClear(GL_COLOR_BUFFER_BIT); // translate the triangle into the view volume glTranslatef(0.0f, 0.0f, -2.0f); // rotate the triangle by angle glRotatef(angle, 0.0f, 0.0f, 1.0f); // update angle angle += 0.1f; // draw a red triangle glColor3f(1.0f, 0.0f, 0.0f); glBegin(GL_TRIANGLES); glVertex3f(0.0f, 0.0f, 0.0f); glVertex3f(1.0f, 0.0f, 0.0f); glVertex3f(1.0f, 1.0f, 0.0f); glEnd(); // tell openGL to finish glFlush(); // swap the buffers SwapBuffers(gHDC); return; } //------------------------------------------------------------------ // WndProc // WndProc processes message in the message queue. // We handle window create, destroy and resize. // Everything else is passed to the operating system. //------------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HGLRC hRC; // the rendering context int width, height; // width and height of window switch(message) { // When a window is created we need to initialize it // for openGL drawing by establishing a pixel format // and then creating a rendering context. case WM_CREATE: gHDC = GetDC(hwnd); // get current window's device context SetupPixelFormat(gHDC); // set up pixel format hRC = wglCreateContext(gHDC); // create rendering context wglMakeCurrent(gHDC, hRC); // make rendering context current return 0; break; // When a window is closed we need to delete the resources // we've used. case WM_CLOSE: wglMakeCurrent(gHDC,NULL); // deselect rendering context wglDeleteContext(hRC); // delete rendering context PostQuitMessage(0); // send quit message to queue return 0; break; // When a window is resized we need to revise our viewport // transformation and our view volume. case WM_SIZE: height = HIWORD(lParam); // retrieve window height width = LOWORD(lParam); // retrieve window width if (height == 0) height = 1; // reset viewport glViewport(0,0,width,height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); // reset aspect ratio of view volume gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f, 100.0f); // reset matrix mode to modelview glMatrixMode(GL_MODELVIEW); glLoadIdentity(); return 0; break; // let the operating system process other messages default: return DefWindowProc(hwnd, message, wParam, lParam); break; } } //------------------------------------------------------------------ // SetupPixelFormat // We need to agree with the operating system on a pixel format. // We describe what we want and the OS gives us the closest fit. //------------------------------------------------------------------- void SetupPixelFormat(HDC hDC) { int nPixelFormat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), 1, PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, PFD_TYPE_RGBA, 32, 0,0,0,0,0,0, 0, 0, 0, 0,0,0,0, 16, 0, 0, PFD_MAIN_PLANE, 0, 0,0,0}; // choose best matching pixel format nPixelFormat = ChoosePixelFormat(hDC, &pfd); // set pixel format to device context SetPixelFormat(hDC, nPixelFormat, &pfd); return; }