home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible / OpenGL_Superbible_Waite_Group_Press_1996.iso / book / chapt10 / shaft / shaft.c < prev    next >
C/C++ Source or Header  |  1996-07-05  |  20KB  |  737 lines

  1. // Shaft.c
  2. // Draws just the shaft of a bolt
  3.  
  4. #include <windows.h>            // Window defines
  5. #include <gl\gl.h>              // OpenGL
  6. #include <gl\glu.h>             // GLU library
  7. #include <math.h>                // Define for trig funcs.
  8. #include "resource.h"           // About box resource identifiers.
  9.  
  10.  
  11. HPALETTE hPalette = NULL;
  12.  
  13. // Application name and instance storeage
  14. static LPCTSTR lpszAppName = "Bolt Shaft";
  15. static HINSTANCE hInstance;
  16.  
  17. // Rotation amounts
  18. static GLfloat xRot = 0.0f;
  19. static GLfloat yRot = 0.0f;
  20.  
  21. // Declaration for Window procedure
  22. LRESULT CALLBACK WndProc(   HWND    hWnd,
  23.                             UINT    message,
  24.                             WPARAM  wParam,
  25.                             LPARAM  lParam);
  26.  
  27. // Dialog procedure for about box
  28. BOOL APIENTRY AboutDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam);
  29.  
  30. // Set Pixel Format function - forward declaration
  31. void SetDCPixelFormat(HDC hDC);
  32.  
  33.  
  34.  
  35. // Reduces a normal vector specified as a set of three coordinates,
  36. // to a unit normal vector of length one.
  37. void ReduceToUnit(float vector[3])
  38.     {
  39.     float length;
  40.     
  41.     // Calculate the length of the vector        
  42.     length = (float)sqrt((vector[0]*vector[0]) + 
  43.                         (vector[1]*vector[1]) +
  44.                         (vector[2]*vector[2]));
  45.  
  46.     // Keep the program from blowing up by providing an exceptable
  47.     // value for vectors that may calculated too close to zero.
  48.     if(length == 0.0f)
  49.         length = 1.0f;
  50.  
  51.     // Dividing each element by the length will result in a
  52.     // unit normal vector.
  53.     vector[0] /= length;
  54.     vector[1] /= length;
  55.     vector[2] /= length;
  56.     }
  57.  
  58.  
  59. // Points p1, p2, & p3 specified in counter clock-wise order
  60. void calcNormal(float v[3][3], float out[3])
  61.     {
  62.     float v1[3],v2[3];
  63.     static const int x = 0;
  64.     static const int y = 1;
  65.     static const int z = 2;
  66.  
  67.     // Calculate two vectors from the three points
  68.     v1[x] = v[0][x] - v[1][x];
  69.     v1[y] = v[0][y] - v[1][y];
  70.     v1[z] = v[0][z] - v[1][z];
  71.  
  72.     v2[x] = v[1][x] - v[2][x];
  73.     v2[y] = v[1][y] - v[2][y];
  74.     v2[z] = v[1][z] - v[2][z];
  75.  
  76.     // Take the cross product of the two vectors to get
  77.     // the normal vector which will be stored in out
  78.     out[x] = v1[y]*v2[z] - v1[z]*v2[y];
  79.     out[y] = v1[z]*v2[x] - v1[x]*v2[z];
  80.     out[z] = v1[x]*v2[y] - v1[y]*v2[x];
  81.  
  82.     // Normalize the vector (shorten length to one)
  83.     ReduceToUnit(out);
  84.     }
  85.  
  86.  
  87.  
  88. // Change viewing volume and viewport.  Called when window is resized
  89. void ChangeSize(GLsizei w, GLsizei h)
  90.     {
  91.     GLfloat nRange = 100.0f;
  92.  
  93.     // Prevent a divide by zero
  94.     if(h == 0)
  95.         h = 1;
  96.  
  97.  
  98.     // Set Viewport to window dimensions
  99.     glViewport(0, 0, w, h);
  100.  
  101.     // Reset coordinate system
  102.     glMatrixMode(GL_PROJECTION);
  103.     glLoadIdentity();
  104.  
  105.     // Establish clipping volume (left, right, bottom, top, near, far)
  106.     if (w <= h) 
  107.         glOrtho (-nRange, nRange, -nRange*h/w, nRange*h/w, -nRange*2.0f, nRange*2.0f);
  108.     else 
  109.         glOrtho (-nRange*w/h, nRange*w/h, -nRange, nRange, -nRange*2.0f, nRange*2.0f);
  110.  
  111.     glMatrixMode(GL_MODELVIEW);
  112.     glLoadIdentity();
  113.     }
  114.  
  115.  
  116.  
  117. // This function does any needed initialization on the rendering
  118. // context.  Here it sets up and initializes the lighting for
  119. // the scene.
  120. void SetupRC()
  121.     {
  122.     // Light values and coordinates
  123.     GLfloat  ambientLight[] = {0.4f, 0.4f, 0.4f, 1.0f };
  124.     GLfloat  diffuseLight[] = {0.7f, 0.7f, 0.7f, 1.0f };
  125.     GLfloat  specular[] = { 0.9f, 0.9f, 0.9f, 1.0f};
  126.     GLfloat     lightPos[] = { -50.0f, 200.0f, 200.0f, 1.0f };
  127.     GLfloat  specref[] =  { 0.6f, 0.6f, 0.6f, 1.0f };
  128.  
  129.  
  130.     glEnable(GL_DEPTH_TEST);    // Hidden surface removal
  131.     glEnable(GL_CULL_FACE);        // Do not calculate inside of solid object
  132.     
  133.     // Enable lighting
  134.     glEnable(GL_LIGHTING);
  135.  
  136.     // Setup light 0
  137.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambientLight);
  138.     glLightfv(GL_LIGHT0,GL_AMBIENT,ambientLight);
  139.     glLightfv(GL_LIGHT0,GL_DIFFUSE,diffuseLight);
  140.     glLightfv(GL_LIGHT0,GL_SPECULAR,specular);
  141.  
  142.     // Position and turn on the light
  143.     glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
  144.     glEnable(GL_LIGHT0);
  145.  
  146.     // Enable color tracking
  147.     glEnable(GL_COLOR_MATERIAL);
  148.     
  149.     // Set Material properties to follow glColor values
  150.     glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
  151.  
  152.     // All materials hereafter have full specular reflectivity
  153.     // with a moderate shine
  154.     glMaterialfv(GL_FRONT, GL_SPECULAR,specref);
  155.     glMateriali(GL_FRONT,GL_SHININESS,64);
  156.  
  157.     // Black background
  158.     glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
  159.     }
  160.  
  161.  
  162. // Creates the shaft of the bolt as a cylinder with one end
  163. // closed.
  164. void RenderShaft(void)
  165.     {
  166.     float x,y,angle;            // Used to calculate cylinder wall
  167.     float height = 75.0f;        // Height of the cylinder
  168.     float diameter = 20.0f;        // Diameter of the cylinder
  169.     float normal[3],corners[4][3];    // Storeage for vertices calculations
  170.     float step = (3.1415f/50.0f);    // Approximate the cylinder wall with
  171.                                     // 100 flat segments.
  172.  
  173.     
  174.     // Set material color for head of screw
  175.     glColor3f(0.0f, 0.0f, 0.7f);
  176.  
  177.     // counter clock-wise polygons face out (the default for triangles)
  178.     glFrontFace(GL_CCW);            
  179.  
  180.  
  181.     // First assemble the wall as 100 quadrilaterals formed by
  182.     // placing adjoining triangles together
  183.     glBegin(GL_TRIANGLES);
  184.  
  185.     // Go around and draw the sides
  186.     for(angle = 0.0f; angle < (2.0f*3.1415f); angle += step)
  187.         {
  188.         // Calculate x and y position of the next vertex
  189.         x = diameter*(float)sin(angle);
  190.         y = diameter*(float)cos(angle);
  191.     
  192.         // Get the coordinate for this point and extrude the 
  193.         // length of the cylinder.
  194.         corners[0][0] = x;
  195.         corners[0][1] = y;
  196.         corners[0][2] = -height;
  197.  
  198.         corners[1][0] = x;
  199.         corners[1][1] = y;
  200.         corners[1][2] = 0.0f;
  201.  
  202.         // Get the next point and do the same
  203.         x = diameter*(float)sin(angle+step);
  204.         y = diameter*(float)cos(angle+step);
  205.  
  206.         // If finished, use know starting point to close the surface
  207.         if(angle+step < 3.1415*2.0) // Not Finished
  208.             {
  209.             corners[2][0] = x;
  210.             corners[2][1] = y;
  211.             corners[2][2] = 0.0f;
  212.  
  213.             corners[3][0] = x;
  214.             corners[3][1] = y;
  215.             corners[3][2] = -height;
  216.             }
  217.         else
  218.             {
  219.             // Finished, use the staring point
  220.             corners[2][0] = 0.0f;
  221.             corners[2][1] = diameter;
  222.             corners[2][2] = 0.0f;
  223.  
  224.             corners[3][0] = 0.0f;
  225.             corners[3][1] = diameter;
  226.             corners[3][2] = -height;
  227.             }
  228.  
  229.         // Instead of using real normal to actual flat section
  230.         // Use what the normal would be if the surface was really
  231.         // curved. Since the cylinder goes up the Z axis, the normal 
  232.         // points from the Z axis out directly through each vertex. 
  233.         // Therefore we can use the vertex as the normal, as long as
  234.         // we reduce it to unit length first.
  235.         
  236.         // First Triangle ////////////////////////////////////////
  237.         // Fill the normal vector with the coordinate points
  238.         normal[0] = corners[0][0];
  239.         normal[1] = corners[0][1];
  240.         normal[2] = corners[0][2];
  241.         
  242.         // Reduce to length of one and specify for this point
  243.         ReduceToUnit(normal);
  244.         glNormal3fv(normal);
  245.         glVertex3fv(corners[0]);
  246.  
  247.         // Get vertex, caluclate unit normal and go
  248.         normal[0] = corners[1][0];
  249.         normal[1] = corners[1][1];
  250.         normal[2] = corners[1][2];
  251.         ReduceToUnit(normal);
  252.         glNormal3fv(normal);
  253.         glVertex3fv(corners[1]);
  254.  
  255.         // Get vertex, caluclate unit normal and go
  256.         normal[0] = corners[2][0];
  257.         normal[1] = corners[2][1];
  258.         normal[2] = corners[2][2];
  259.         ReduceToUnit(normal);
  260.         glNormal3fv(normal);
  261.         glVertex3fv(corners[2]);
  262.  
  263.  
  264.         // Second Triangle ////////////////////////////////////////
  265.  
  266.         // Get vertex, caluclate unit normal and go
  267.         normal[0] = corners[2][0];
  268.         normal[1] = corners[2][1];
  269.         normal[2] = corners[2][2];
  270.         ReduceToUnit(normal);
  271.         glNormal3fv(normal);
  272.         glVertex3fv(corners[2]);
  273.  
  274.         // Get vertex, caluclate unit normal and go
  275.         normal[0] = corners[3][0];
  276.         normal[1] = corners[3][1];
  277.         normal[2] = corners[3][2];
  278.         ReduceToUnit(normal);
  279.         glNormal3fv(normal);
  280.         glVertex3fv(corners[3]);
  281.  
  282.         // Get vertex, caluclate unit normal and go
  283.         normal[0] = corners[0][0];
  284.         normal[1] = corners[0][1];
  285.         normal[2] = corners[0][2];
  286.         ReduceToUnit(normal);
  287.         glNormal3fv(normal);
  288.         glVertex3fv(corners[0]);
  289.         }
  290.  
  291.     glEnd();    // Done with cylinder sides
  292.  
  293.     // Begin a new triangle fan to cover the bottom
  294.     glBegin(GL_TRIANGLE_FAN);
  295.  
  296.     // Normal points down the Z axis
  297.     glNormal3f(0.0f, 0.0f, -1.0f);
  298.     
  299.     // Center of fan is at the origin
  300.     glVertex3f(0.0f, 0.0f, -height);
  301.     
  302.     // Spin around matching step size of cylinder wall
  303.     for(angle = 0.0f; angle < (2.0f*3.1415f); angle += step)
  304.         {
  305.         // Calculate x and y position of the next vertex
  306.         x = diameter*(float)sin(angle);
  307.         y = diameter*(float)cos(angle);
  308.  
  309.         // Specify the next vertex for the triangle fan
  310.         glVertex3f(x, y, -height);
  311.         }
  312.  
  313.     // Close the fan
  314.     glVertex3f(0.0f, diameter, -height);
  315.     glEnd();
  316.     }
  317.  
  318.  
  319.  
  320. // Called to draw scene
  321. void RenderScene(void)
  322.     {
  323.     // Clear the window with current clearing color
  324.     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  325.  
  326.     // Save the matrix state
  327.     glMatrixMode(GL_MODELVIEW);
  328.     glPushMatrix();
  329.     
  330.     // Rotate about x and y axes
  331.     glRotatef(xRot, 1.0f, 0.0f, 0.0f);
  332.     glRotatef(yRot, 0.0f, 1.0f, 0.0f);
  333.  
  334.     // Render just shaft of the nut
  335.     RenderShaft();
  336.  
  337.     glPopMatrix();
  338.  
  339.     // Flush drawing commands
  340.     glFlush();
  341.     }
  342.  
  343.  
  344. // Select the pixel format for a given device context
  345. void SetDCPixelFormat(HDC hDC)
  346.     {
  347.     int nPixelFormat;
  348.  
  349.     static PIXELFORMATDESCRIPTOR pfd = {
  350.         sizeof(PIXELFORMATDESCRIPTOR),  // Size of this structure
  351.         1,                                                              // Version of this structure    
  352.         PFD_DRAW_TO_WINDOW |                    // Draw to Window (not to bitmap)
  353.         PFD_SUPPORT_OPENGL |                    // Support OpenGL calls in window
  354.         PFD_DOUBLEBUFFER,                       // Double buffered
  355.         PFD_TYPE_RGBA,                          // RGBA Color mode
  356.         24,                                     // Want 24bit color 
  357.         0,0,0,0,0,0,                            // Not used to select mode
  358.         0,0,                                    // Not used to select mode
  359.         0,0,0,0,0,                              // Not used to select mode
  360.         32,                                     // Size of depth buffer
  361.         0,                                      // Not used to select mode
  362.         0,                                      // Not used to select mode
  363.         PFD_MAIN_PLANE,                         // Draw in main plane
  364.         0,                                      // Not used to select mode
  365.         0,0,0 };                                // Not used to select mode
  366.  
  367.     // Choose a pixel format that best matches that described in pfd
  368.     nPixelFormat = ChoosePixelFormat(hDC, &pfd);
  369.  
  370.     // Set the pixel format for the device context
  371.     SetPixelFormat(hDC, nPixelFormat, &pfd);
  372.     }
  373.  
  374.  
  375.  
  376. // If necessary, creates a 3-3-2 palette for the device context listed.
  377. HPALETTE GetOpenGLPalette(HDC hDC)
  378.     {
  379.     HPALETTE hRetPal = NULL;    // Handle to palette to be created
  380.     PIXELFORMATDESCRIPTOR pfd;    // Pixel Format Descriptor
  381.     LOGPALETTE *pPal;            // Pointer to memory for logical palette
  382.     int nPixelFormat;            // Pixel format index
  383.     int nColors;                // Number of entries in palette
  384.     int i;                        // Counting variable
  385.     BYTE RedRange,GreenRange,BlueRange;
  386.                                 // Range for each color entry (7,7,and 3)
  387.  
  388.  
  389.     // Get the pixel format index and retrieve the pixel format description
  390.     nPixelFormat = GetPixelFormat(hDC);
  391.     DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  392.  
  393.     // Does this pixel format require a palette?  If not, do not create a
  394.     // palette and just return NULL
  395.     if(!(pfd.dwFlags & PFD_NEED_PALETTE))
  396.         return NULL;
  397.  
  398.     // Number of entries in palette.  8 bits yeilds 256 entries
  399.     nColors = 1 << pfd.cColorBits;    
  400.  
  401.     // Allocate space for a logical palette structure plus all the palette entries
  402.     pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY));
  403.  
  404.     // Fill in palette header 
  405.     pPal->palVersion = 0x300;        // Windows 3.0
  406.     pPal->palNumEntries = nColors; // table size
  407.  
  408.     // Build mask of all 1's.  This creates a number represented by having
  409.     // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
  410.     // pfd.cBlueBits.  
  411.     RedRange = (1 << pfd.cRedBits) -1;
  412.     GreenRange = (1 << pfd.cGreenBits) - 1;
  413.     BlueRange = (1 << pfd.cBlueBits) -1;
  414.  
  415.     // Loop through all the palette entries
  416.     for(i = 0; i < nColors; i++)
  417.         {
  418.         // Fill in the 8-bit equivalents for each component
  419.         pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
  420.         pPal->palPalEntry[i].peRed = (unsigned char)(
  421.             (double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
  422.  
  423.         pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
  424.         pPal->palPalEntry[i].peGreen = (unsigned char)(
  425.             (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);
  426.  
  427.         pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
  428.         pPal->palPalEntry[i].peBlue = (unsigned char)(
  429.             (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);
  430.  
  431.         pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
  432.         }
  433.         
  434.  
  435.     // Create the palette
  436.     hRetPal = CreatePalette(pPal);
  437.  
  438.     // Go ahead and select and realize the palette for this device context
  439.     SelectPalette(hDC,hRetPal,FALSE);
  440.     RealizePalette(hDC);
  441.  
  442.     // Free the memory used for the logical palette structure
  443.     free(pPal);
  444.  
  445.     // Return the handle to the new palette
  446.     return hRetPal;
  447.     }
  448.  
  449.  
  450. // Entry point of all Windows programs
  451. int APIENTRY WinMain(   HINSTANCE       hInst,
  452.                         HINSTANCE       hPrevInstance,
  453.                         LPSTR           lpCmdLine,
  454.                         int                     nCmdShow)
  455.     {
  456.     MSG                     msg;            // Windows message structure
  457.     WNDCLASS        wc;                     // Windows class structure
  458.     HWND            hWnd;           // Storeage for window handle
  459.  
  460.     hInstance = hInst;
  461.  
  462.     // Register Window style
  463.     wc.style                        = CS_HREDRAW | CS_VREDRAW;
  464.     wc.lpfnWndProc          = (WNDPROC) WndProc;
  465.     wc.cbClsExtra           = 0;
  466.     wc.cbWndExtra           = 0;
  467.     wc.hInstance            = hInstance;
  468.     wc.hIcon                        = NULL;
  469.     wc.hCursor                      = LoadCursor(NULL, IDC_ARROW);
  470.     
  471.     // No need for background brush for OpenGL window
  472.     wc.hbrBackground        = NULL;         
  473.     
  474.     wc.lpszMenuName         = MAKEINTRESOURCE(IDR_MENU);
  475.     wc.lpszClassName        = lpszAppName;
  476.  
  477.     // Register the window class
  478.     if(RegisterClass(&wc) == 0)
  479.         return FALSE;
  480.  
  481.  
  482.     // Create the main application window
  483.     hWnd = CreateWindow(
  484.                 lpszAppName,
  485.                 lpszAppName,
  486.                 
  487.                 // OpenGL requires WS_CLIPCHILDREN and WS_CLIPSIBLINGS
  488.                 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
  489.     
  490.                 // Window position and size
  491.                 50, 50,
  492.                 400, 400,
  493.                 NULL,
  494.                 NULL,
  495.                 hInstance,
  496.                 NULL);
  497.  
  498.     // If window was not created, quit
  499.     if(hWnd == NULL)
  500.         return FALSE;
  501.  
  502.  
  503.     // Display the window
  504.     ShowWindow(hWnd,SW_SHOW);
  505.     UpdateWindow(hWnd);
  506.  
  507.     // Process application messages until the application closes
  508.     while( GetMessage(&msg, NULL, 0, 0))
  509.         {
  510.         TranslateMessage(&msg);
  511.         DispatchMessage(&msg);
  512.         }
  513.  
  514.     return msg.wParam;
  515.     }
  516.  
  517.  
  518.  
  519.  
  520. // Window procedure, handles all messages for this program
  521. LRESULT CALLBACK WndProc(       HWND    hWnd,
  522.                             UINT    message,
  523.                             WPARAM  wParam,
  524.                             LPARAM  lParam)
  525.     {
  526.     static HGLRC hRC;               // Permenant Rendering context
  527.     static HDC hDC;                 // Private GDI Device context
  528.  
  529.     switch (message)
  530.         {
  531.         // Window creation, setup for OpenGL
  532.         case WM_CREATE:
  533.             // Store the device context
  534.             hDC = GetDC(hWnd);              
  535.  
  536.             // Select the pixel format
  537.             SetDCPixelFormat(hDC);          
  538.  
  539.             hPalette = GetOpenGLPalette(hDC);
  540.  
  541.             // Create the rendering context and make it current
  542.             hRC = wglCreateContext(hDC);
  543.             wglMakeCurrent(hDC, hRC);
  544.             SetupRC();
  545.  
  546.             break;
  547.  
  548.         // Window is being destroyed, cleanup
  549.         case WM_DESTROY:
  550.             // Deselect the current rendering context and delete it
  551.             wglMakeCurrent(hDC,NULL);
  552.             wglDeleteContext(hRC);
  553.  
  554.             if(hPalette != NULL)
  555.                 DeleteObject(hPalette);
  556.  
  557.             // Tell the application to terminate after the window
  558.             // is gone.
  559.             PostQuitMessage(0);
  560.             break;
  561.  
  562.         // Window is resized.
  563.         case WM_SIZE:
  564.             // Call our function which modifies the clipping
  565.             // volume and viewport
  566.             ChangeSize(LOWORD(lParam), HIWORD(lParam));
  567.             break;
  568.  
  569.  
  570.         // The painting function.  This message sent by Windows 
  571.         // whenever the screen needs updating.
  572.         case WM_PAINT:
  573.             {
  574.             // Call OpenGL drawing code
  575.             RenderScene();
  576.  
  577.             SwapBuffers(hDC);
  578.  
  579.             // Validate the newly painted client area
  580.             ValidateRect(hWnd,NULL);
  581.             }
  582.             break;
  583.  
  584.         // Windows is telling the application that it may modify
  585.         // the system palette.  This message in essance asks the 
  586.         // application for a new palette.
  587.         case WM_QUERYNEWPALETTE:
  588.             // If the palette was created.
  589.             if(hPalette)
  590.                 {
  591.                 int nRet;
  592.  
  593.                 // Selects the palette into the current device context
  594.                 SelectPalette(hDC, hPalette, FALSE);
  595.  
  596.                 // Map entries from the currently selected palette to
  597.                 // the system palette.  The return value is the number 
  598.                 // of palette entries modified.
  599.                 nRet = RealizePalette(hDC);
  600.  
  601.                 // Repaint, forces remap of palette in current window
  602.                 InvalidateRect(hWnd,NULL,FALSE);
  603.  
  604.                 return nRet;
  605.                 }
  606.             break;
  607.  
  608.     
  609.         // This window may set the palette, even though it is not the 
  610.         // currently active window.
  611.         case WM_PALETTECHANGED:
  612.             // Don't do anything if the palette does not exist, or if
  613.             // this is the window that changed the palette.
  614.             if((hPalette != NULL) && ((HWND)wParam != hWnd))
  615.                 {
  616.                 // Select the palette into the device context
  617.                 SelectPalette(hDC,hPalette,FALSE);
  618.  
  619.                 // Map entries to system palette
  620.                 RealizePalette(hDC);
  621.                 
  622.                 // Remap the current colors to the newly realized palette
  623.                 UpdateColors(hDC);
  624.                 return 0;
  625.                 }
  626.             break;
  627.  
  628.         // Key press, check for arrow keys to do cube rotation.
  629.         case WM_KEYDOWN:
  630.             {
  631.             if(wParam == VK_UP)
  632.                 xRot-= 5.0f;
  633.  
  634.             if(wParam == VK_DOWN)
  635.                 xRot += 5.0f;
  636.  
  637.             if(wParam == VK_LEFT)
  638.                 yRot -= 5.0f;
  639.  
  640.             if(wParam == VK_RIGHT)
  641.                 yRot += 5.0f;
  642.  
  643.             xRot = (float)((const int)xRot % 360);
  644.             yRot = (float)((const int)yRot % 360);
  645.  
  646.             InvalidateRect(hWnd,NULL,FALSE);
  647.             }
  648.             break;
  649.  
  650.         // A menu command
  651.         case WM_COMMAND:
  652.             {
  653.             switch(LOWORD(wParam))
  654.                 {
  655.                 // Exit the program
  656.                 case ID_FILE_EXIT:
  657.                     DestroyWindow(hWnd);
  658.                     break;
  659.  
  660.                 // Display the about box
  661.                 case ID_HELP_ABOUT:
  662.                     DialogBox (hInstance,
  663.                         MAKEINTRESOURCE(IDD_DIALOG_ABOUT),
  664.                         hWnd,
  665.                         AboutDlgProc);
  666.                     break;
  667.                 }
  668.             }
  669.             break;
  670.  
  671.  
  672.     default:   // Passes it on if unproccessed
  673.         return (DefWindowProc(hWnd, message, wParam, lParam));
  674.  
  675.     }
  676.  
  677.     return (0L);
  678.     }
  679.  
  680.  
  681.  
  682.  
  683. // Dialog procedure.
  684. BOOL APIENTRY AboutDlgProc (HWND hDlg, UINT message, UINT wParam, LONG lParam)
  685.     {
  686.     
  687.     switch (message)
  688.     {
  689.         // Initialize the dialog box
  690.         case WM_INITDIALOG:
  691.             {
  692.             int i;
  693.             GLenum glError;
  694.  
  695.             // glGetString demo
  696.             SetDlgItemText(hDlg,IDC_OPENGL_VENDOR,glGetString(GL_VENDOR));
  697.             SetDlgItemText(hDlg,IDC_OPENGL_RENDERER,glGetString(GL_RENDERER));
  698.             SetDlgItemText(hDlg,IDC_OPENGL_VERSION,glGetString(GL_VERSION));
  699.             SetDlgItemText(hDlg,IDC_OPENGL_EXTENSIONS,glGetString(GL_EXTENSIONS));
  700.  
  701.             // gluGetString demo
  702.             SetDlgItemText(hDlg,IDC_GLU_VERSION,gluGetString(GLU_VERSION));
  703.             SetDlgItemText(hDlg,IDC_GLU_EXTENSIONS,gluGetString(GLU_EXTENSIONS));
  704.  
  705.  
  706.             // Display any recent error messages
  707.             i = 0;
  708.             do {
  709.                 glError = glGetError();
  710.                 SetDlgItemText(hDlg,IDC_ERROR1+i,gluErrorString(glError));
  711.                 i++;
  712.                 }
  713.             while(i < 6 && glError != GL_NO_ERROR);
  714.  
  715.  
  716.             return (TRUE);
  717.             }
  718.             break;
  719.  
  720.         // Process command messages
  721.         case WM_COMMAND:      
  722.             {
  723.             // Validate and Make the changes
  724.             if(LOWORD(wParam) == IDOK)
  725.                 EndDialog(hDlg,TRUE);
  726.             }
  727.             break;
  728.  
  729.         // Closed from sysbox
  730.         case WM_CLOSE:
  731.             EndDialog(hDlg,TRUE);
  732.             break;
  733.         }
  734.  
  735.     return FALSE;
  736.     }
  737.