//---------------------------------------------------------------- // // This windows program draws a spheree, cone, and cylinder using openGL. // // My objectives is to introduce // 1. glu-objects // 2. error handling // 3. texture mapping // // //----------------------------------------------------------------- #define WIN32_LEAN_AND_MEAN // trim the excess fat from Windows #include #include #include #include #include "bmp.h" //---------------------------------------------------------------- // globals (YUCK!) //---------------------------------------------------------------- HDC gHDC; // the device context GLuint hSphere; // the handle for our sphere 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 BuildSphere(int slices, int stacks); int checkGLErrors(int errCode); unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader); //----------------------------------------------------------------- // 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); //--------------------------------- // build a sphere in a display list //--------------------------------- // initialize the list hSphere = glGenLists(1); glNewList(hSphere, GL_COMPILE); // the color is red glColor3f(1.0,0.0,0.0); // translate into the view volume // and to the right glPushMatrix(); glTranslatef(20.0f, 0.0f, -100.0f); // scale to a radius of 20 glScalef(10.0f, 10.0f, 10.0f); // build a standard sphere (i.e. radius=1, // centered at the origin) int slices = 20; // slices and stacks int stacks = 20; // control the resolution BuildSphere(slices, stacks); // restore the transform matrix glPopMatrix(); // end the list glEndList(); //------------------------------------------------------- // build a texture mapped cube //------------------------------------------------------- // first read in the bit map // the file name is hard-coded in this example // // Bitmap Information BITMAPINFOHEADER bitmapInfoHeader; // bitmap info header unsigned char* bitmapData; // the bitmap data // read texture data bitmapData = LoadBitmapFile("myTexture.bmp", &bitmapInfoHeader); // generate texture object unsigned int hTexture; glGenTextures(1,&hTexture); // you can pass an array for // texture handles if you want to // create more than 1 glBindTexture(GL_TEXTURE_2D, hTexture); // bind the texture // specify texture parameters // the following two commands tell openGL how to interpolate texture // values between the sampled values in your texture bitmap glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // the following two commands tell openGL how to extend the texture // when needed glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // now give it the texture map glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmapInfoHeader.biWidth, bitmapInfoHeader.biHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmapData); // return success or failure based // on openGL errors found return checkGLErrors(glGetError()); } //--------------------------------------------------------------------------------- // // checkGLErrors // This routine checks and reports on openGL errors. //---------------------------------------------------------------------------------- int checkGLErrors(int errCode) { // print error message as needed if (errCode != GL_NO_ERROR) { MessageBox( NULL, (const char*) gluErrorString(errCode), "OpenGL Error",MB_OK); return FAILURE; } return SUCCESS; } //---------------------------------------------------------------------------------- // // BuildSphere // This routine builds a sphere with radius 1 centered at the origin. // The "resolution" of the sphere is controlled by slices and stack //----------------------------------------------------------------------------------- void BuildSphere(int slices, int stacks) { // create the sphere GLUquadricObj* theSphere = gluNewQuadric(); double radius =1.0; gluSphere(theSphere, radius, slices, stacks); return; } //-------------------------------------------------------------- // Render // Render draws various glu-objects //--------------------------------------------------------------- void Render() { // clear the frame and depth buffers glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT); // clear the modeling transform matrix glLoadIdentity(); // draw the sphere glCallList(hSphere); // draw texture mapped triangle glEnable(GL_TEXTURE_2D); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_POLYGON); glTexCoord2f(0.0,0.0); glVertex3f(0.0f,0.0f, -30.0f); glTexCoord2f(1.0,1.0); glVertex3f(20.0f,20.0f, -30.0f); glTexCoord2f(0.0,1.0); glVertex3f(0.0f, 20.0f, -30.0f); glEnd(); glDisable(GL_TEXTURE_2D); // tell openGL to finish glFlush(); // swap the buffers SwapBuffers(gHDC); // check if everything ok checkGLErrors(glGetError()); 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; }