//---------------------------------------------------------------- // // This windows program draws a rotating red cube using openGL. // // My objectives are to introduce // 1. depth buffering // 2. hierarchical coordinates // 3. display lists // //----------------------------------------------------------------- #define WIN32_LEAN_AND_MEAN #include #include #include #include //---------------------------------------------------------------- // globals (YUCK!) //---------------------------------------------------------------- HDC gHDC; // the device context GLuint hCube; // the handle for our cube const int SUCCESS = 0; const int FAILURE = 1; //---------------------------------------------------------------- // function prototypes //---------------------------------------------------------------- LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam); void SetupPixelFormat(HDC hDC); int Init(); void Render(); void BuildCube(void); void BuildRectangle(void); //----------------------------------------------------------------- // 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; bool done = false; // initialize openGL parameters if (Init()==FAILURE) { MessageBox(NULL,"\tUnable to initialize OpenGL.","Error",NULL); done = true; } // go into a message loop MSG msg; // structure for storing messages 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 //--------------------------------------------------------------- int Init() { // the background is black glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // enable depth buffering glEnable(GL_DEPTH_TEST); // create a cube in a display list hCube = glGenLists(1); // get a handle for our display list if (hCube == 0) { // 0 is not a valid handle return FAILURE; } glNewList(hCube, GL_COMPILE); // start the display list glScalef(0.5f,0.5f,0.5f); // scale the cube by 1/2 BuildCube(); // build the cube glEndList(); // end the display list return SUCCESS; } //-------------------------------------------------------------- // BuildCube // This routine builds a 1x1x1 cube centered at the origin. //--------------------------------------------------------------- void BuildCube(void) { // front glColor3f(1.0f, 0.0f, 0.0f); // set the color to red glPushMatrix(); // save the modelview matrix glTranslatef(-0.5,-0.5,0.5); // position it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix // back glColor3f(1.0f, 1.0f, 0.0f); // set the color to yellow glPushMatrix(); // save the modelview matrix glTranslatef(-0.5,-0.5,-0.5); // position it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix // top glColor3f(0.0f, 1.0f, 0.0f); // set the color to green glPushMatrix(); // save the modelview matrix glTranslatef(-0.5,0.5,0.5); // position it glRotatef(-90.0f,1.0f,0.0f,0.0f);// rotate it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix // bottom glColor3f(0.0f, 1.0f, 1.0f); // set the color to blue/green glPushMatrix(); // save the modelview matrix glTranslatef(-0.5,-0.5,0.5); // position it glRotatef(-90.0f,1.0f,0.0f,0.0f);// rotate it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix // left glColor3f(0.0f, 0.0f, 1.0f); // set the color to blue glPushMatrix(); // save the modelview matrix glTranslatef(-0.5,-0.5,0.5); // position it glRotatef(90.0f,0.0f,1.0f,0.0f);// rotate it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix // right glColor3f(1.0f, 0.0f, 1.0f); // set the color to purple glPushMatrix(); // save the modelview matrix glTranslatef(0.5,-0.5,0.5); // position it glRotatef(90.0f,0.0f,1.0f,0.0f);// rotate it BuildRectangle(); // build the face glPopMatrix(); // restore the modelview matrix return; } //-------------------------------------------------------------- // BuildRectangle // This routine builds a 1x1 rectangle in the z=0 plane // with its bottom left corner at the origin //-------------------------------------------------------------- void BuildRectangle() { glBegin(GL_POLYGON); glVertex3f(0.0f,0.0f,0.0f); glVertex3f(1.0f,0.0f,0.0f); glVertex3f(1.0f,1.0f,0.0f); glVertex3f(0.0f,1.0f,0.0f); glEnd(); return; } //-------------------------------------------------------------- // Render // Render draws a rotating cube //--------------------------------------------------------------- void Render() { // we're going to rotate a cube by angle static float angle = 0; // clear the modelview matrix glLoadIdentity(); // clear the frame buffer glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // translate the cube into the view volume glTranslatef(0.0f, 0.0f, -2.0f); // rotate the cube by angle glRotatef(angle, 0.0f, 1.0f, 0.0f); angle += 0.1f; // draw the cube glCallList(hCube); // 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; }