outdated: 28.Bezier Patches / Fullscreen Fix

Bézier curve经常应用于计算机图形学邻域。

三次Bézier curve演示:

p为点的坐标。

一次Bézier curve:

二次Bézier curve:

三次Bézier curve:

每次对每个点进行处理。未处理时:

下面为代码。同样修改部分位于双行星号内。

  1 /******************************************************************************************************************************************/
  2 /******************************************************************************************************************************************/
  3 #include <windows.h>
  4 #include <math.h>
  5 #include <stdio.h>
  6 #include <gl/glew.h>
  7 #include <GL\glut.h>
  8 #include <GL/GLUAX.H>
  9 #pragma comment(lib, "legacy_stdio_definitions.lib")
 10 
 11 /*
 12 *  Every OpenGL program is linked to a Rendering Context.
 13 *  A Rendering Context is what links OpenGL calls to the Device Context.
 14 *  In order for your program to draw to a Window you need to create a Device Context.
 15 *  The DC connects the Window to the GDI (Graphics Device Interface).
 16 */
 17 
 18 HGLRC     hRC = NULL;         // Permanent rendering context
 19 HDC       hDC = NULL;         // Private GDI device context
 20 HWND      hWnd = NULL;        // Holds our window handle
 21 HINSTANCE hInstance;          // Holds the instance of the application
 22 
 23 /*
 24 *  It's important to make this global so that each procedure knows if
 25 *  the program is running in fullscreen mode or not.
 26 */
 27 
 28 bool keys[256];         // Array used for the keyboard routine
 29 bool active = TRUE;     // Window active flag set to TRUE by default
 30 bool fullscreen = TRUE; // Fullscreen flag set to fullscreen mode by default
 31 
 32 typedef struct point_3d {               // 3-dimensional
 33     double x, y, z;
 34 } POINT_3D;
 35 
 36 typedef struct bpatch {
 37     POINT_3D anchors[4][4];             // 4X4 grid of anchors ponits
 38     GLuint dlBPatch;                    // Display list for Bezier patch
 39     GLuint texture;                     // Texture for the patch
 40 } BEZIER_PATCH;
 41 
 42 DEVMODE DMsaved;                        // Saves the previous screen settings
 43 
 44 GLfloat rotx = 0.0f;
 45 GLfloat rotz = 0.0f;
 46 BEZIER_PATCH mybezier;
 47 bool showCPoints = true;                 // Toggles displaying the control point grid
 48 
 49 int divs = 7;                           // Number of intrapolations (controls poly resolution)
 50 
 51 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration for WndProc
 52 
 53 // Adds 2 points
 54 POINT_3D pointAdd(POINT_3D p, POINT_3D q)
 55 {
 56     p.x += q.x; p.y += q.y; p.z += q.z;
 57     return p;
 58 }
 59 
 60 // Multiplies A point and a constant
 61 POINT_3D pointTimes(double c, POINT_3D p)
 62 {
 63     p.x *= c; p.y *= c; p.z *= c;
 64     return p;
 65 }
 66 
 67 // Function for quick point creation
 68 POINT_3D makePoint(double a, double b, double c)
 69 {
 70     POINT_3D p;
 71     p.x = a; p.y = b; p.z = c;
 72     return p;
 73 }
 74 // Calculates 3rd degree polynomial based on array of 4 points
 75 // and a single variable (u) which is generally between 0 and 1
 76 POINT_3D Bernstein(float u, POINT_3D* p)
 77 {
 78     POINT_3D a, b, c, d, r;
 79 
 80     a = pointTimes(pow(u, 3), p[0]);
 81     b = pointTimes(3 * pow(u, 2) * (1 - u), p[1]);
 82     c = pointTimes(3 * u * pow((1 - u), 2), p[2]);
 83     d = pointTimes(pow((1 - u), 3), p[3]);
 84 
 85     r = pointAdd(pointAdd(a, b), pointAdd(c, d));
 86     return r;
 87 }
 88 
 89 // Generates a display list based on the data in the patch and the number of divisions
 90 GLuint genBezier(BEZIER_PATCH patch, int divs)
 91 {
 92     float px, py, pyold;
 93     GLuint drawlist = glGenLists(1);
 94     POINT_3D temp[4];
 95     POINT_3D* last = (POINT_3D*)malloc(sizeof(POINT_3D) * (divs + 1));
 96 
 97     if (patch.dlBPatch != NULL) {               // Get rid of any old display lists
 98         glDeleteLists(patch.dlBPatch, 1);
 99     }
100     temp[0] = patch.anchors[0][3];              // The first derived curve
101     temp[1] = patch.anchors[1][3];
102     temp[2] = patch.anchors[2][3];
103     temp[3] = patch.anchors[3][3];
104 
105     for (int v = 0; v <= divs; ++v) {           // Create the first line of points
106         px = ((float)v) / ((float)divs);
107         // Use the 4 points from the derived curve to calculate the points along that curve
108         last[v] = Bernstein(px, temp);
109     }
110     glNewList(drawlist, GL_COMPILE);
111     glBindTexture(GL_TEXTURE_2D, patch.texture);
112 
113     for (int u = 1; u <= divs; ++u) {
114         py = ((float)u) / ((float)divs);
115         pyold = ((float)u - 1.0f) / ((float)divs);
116         temp[0] = Bernstein(py, patch.anchors[0]);        // Calculate new Bezier
117         temp[1] = Bernstein(py, patch.anchors[1]);
118         temp[2] = Bernstein(py, patch.anchors[2]);
119         temp[3] = Bernstein(py, patch.anchors[3]);
120         
121         int a = 0;
122         glBegin(GL_TRIANGLE_STRIP);
123         for (int v = 0; v <= divs; ++v) {
124             px = ((float)v) / ((float)divs);
125             glTexCoord2f(pyold + a++, px + a++);
126             glVertex3d(last[v].x, last[v].y, last[v].z);      // Old point
127 
128             last[v] = Bernstein(px, temp);
129             glTexCoord2f(py + a++, px + a++);
130             glVertex3d(last[v].x, last[v].y, last[v].z);      // New point
131         }
132         glEnd();
133     }
134     glEndList();
135 
136     free(last);
137     return drawlist;
138 }
139 
140 void initBezier(void)
141 {
142     mybezier.anchors[0][0] = makePoint(-0.75f, -0.75f, -0.5f);     // Set the Bezier vertices
143     mybezier.anchors[0][1] = makePoint(-0.25f, -0.75f, 0.0f);
144     mybezier.anchors[0][2] = makePoint(0.25f, -0.75f, 0.0f);
145     mybezier.anchors[0][3] = makePoint(0.75f, -0.75f, -0.5f);
146     mybezier.anchors[1][0] = makePoint(-0.75f, -0.25f, -0.75f);
147     mybezier.anchors[1][1] = makePoint(-0.25f, -0.25f, 0.5f);
148     mybezier.anchors[1][2] = makePoint(0.25f, -0.25f, 0.5f);
149     mybezier.anchors[1][3] = makePoint(0.75f, -0.25f, -0.75f);
150     mybezier.anchors[2][0] = makePoint(-0.75f, 0.25f, 0.0f);
151     mybezier.anchors[2][1] = makePoint(-0.25f, 0.25f, -0.5f);
152     mybezier.anchors[2][2] = makePoint(0.25f, 0.25f, -0.5f);
153     mybezier.anchors[2][3] = makePoint(0.75f, 0.25f, 0.0f);
154     mybezier.anchors[3][0] = makePoint(-0.75f, 0.75f, -0.5f);
155     mybezier.anchors[3][1] = makePoint(-0.25f, 0.75f, -1.0f);
156     mybezier.anchors[3][2] = makePoint(0.25f, 0.75f, -1.0f);
157     mybezier.anchors[3][3] = makePoint(0.75f, 0.75f, -0.5f);
158     
159     mybezier.dlBPatch = NULL;
160 }
161 
162 bool LoadGLTexture(GLuint* texPntr, char* name)
163 {
164     bool success = false;
165     AUX_RGBImageRec* TextureImage = NULL;
166 
167     glGenTextures(1, texPntr);
168 
169     FILE* test = NULL;
170     TextureImage = NULL;
171 
172     test = fopen(name, "r");
173     if (test != NULL) {
174         fclose(test);
175         TextureImage = auxDIBImageLoad(name);
176     }
177 
178     if (TextureImage != NULL) {
179         success = true;
180 
181         glBindTexture(GL_TEXTURE_2D, *texPntr);
182         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY, 0,
183             GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data);
184         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
185         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
186     }
187     if (TextureImage->data) {
188         free(TextureImage->data);
189     }
190     return success;
191 }
192 /******************************************************************************************************************************************/
193 /******************************************************************************************************************************************/
194 GLvoid ReSizeGLScene(GLsizei width, GLsizei height)   // Resize and initialize the GL window
195 {
196     if (height == 0) {                                // Prevent a divide by zero by
197         height = 1;                                   // Making height equal one
198     }
199     
200     glViewport(0, 0, width, height);                  // Reset the current viewport
201 
202     /*
203      *  The following lines set the screen up for a perspective view. 
204      *  Meaning things in the distance get smaller. This creates a realistic looking scene. 
205      *  The perspective is calculated with a 45 degree viewing angle based on 
206      *  the windows width and height. The 0.1f, 100.0f is the starting point and 
207      *  ending point for how deep we can draw into the screen.
208      *
209      *  The projection matrix is responsible for adding perspective to our scene.
210      *  glLoadIdentity() restores the selected matrix to it's original state.
211      *  The modelview matrix is where our object information is stored.
212      *   Lastly we reset the modelview matrix.
213      */
214 
215     glMatrixMode(GL_PROJECTION);                      // Select the projection matrix
216     glLoadIdentity();                                 // Reset the projection matrix
217     
218                                                       // Calculate the aspect ratio of the window
219     gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
220 //    glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f);  // Create orhto 640X480 view (0, 0, at the top)
221 
222     glMatrixMode(GL_MODELVIEW);                       // Seclet the modelview matrix
223     glLoadIdentity();                                 // Reset the modelview matrix
224 }
225 /******************************************************************************************************************************************/
226 /******************************************************************************************************************************************/
227 
228 int InitGL(GLvoid)                                    // All setup for OpenGL goes here
229 {
230     glEnable(GL_TEXTURE_2D);
231     glShadeModel(GL_SMOOTH);
232     glClearColor(0.05f, 0.05f, 0.05f, 0.5f);          // Background
233     glClearDepth(1.0f);                               // Depth buffer setup
234     glEnable(GL_DEPTH_TEST);
235     glDepthFunc(GL_LEQUAL);
236     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
237     
238     initBezier();
239     LoadGLTexture(&(mybezier.texture), "image.bmp");
240     mybezier.dlBPatch = genBezier(mybezier, divs);
241 
242     return TRUE;
243 }
244 
245 /*
246  *  For now all we will do is clear the screen to the color we previously decided on,
247  *  clear the depth buffer and reset the scene. We wont draw anything yet.
248  */
249 bool DrawGLScene(GLvoid)                                  // Here's where we do all the drawing
250 {
251     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
252     
253     glLoadIdentity();
254     glTranslatef(0.0f, 0.0f, -4.0f);
255     glRotatef(-75.0f, 1.0f, 0.0f, 0.0f);
256     glRotatef(rotx, 1.0f, 0.0f, 0.0f);
257     glRotatef(rotz, 0.0f, 0.0f, 1.0f);
258 
259     glCallList(mybezier.dlBPatch);
260 
261     if (showCPoints) {                       // If drawing the grid is toggled on
262         glDisable(GL_TEXTURE_2D);
263         glColor3f(1.0f, 0.0f, 0.0f);
264         for (int i = 0; i < 4; ++i) {        // Draw the horizontal lines
265             glBegin(GL_LINE_STRIP);
266             for (int j = 0; j < 4; ++j)
267                 glVertex3d(mybezier.anchors[i][j].x, mybezier.anchors[i][j].y, mybezier.anchors[i][j].z);
268             glEnd();
269         }
270         for (int i = 0; i < 4; ++i) {        // Draw the vertical lines
271             glBegin(GL_LINE_STRIP);
272             for (int j = 0; j < 4; ++j)
273                 glVertex3d(mybezier.anchors[j][i].x, mybezier.anchors[j][i].y, mybezier.anchors[j][i].z);
274             glEnd();
275         }
276         glColor3f(1.0f, 1.0f, 1.0f);
277         glEnable(GL_TEXTURE_2D);
278     }
279     return true;
280 }
281 
282 /*
283  *  The job of KillGLWindow() is to release the Rendering Context, 
284  *  the Device Context and finally the Window Handle. 
285  */
286 
287 GLvoid KillGLWindow(GLvoid)                             // Properly kill the window
288 {
289     if (fullscreen) {                                   // Are we in fullscreen mode
290         if (!ChangeDisplaySettings(NULL, CDS_TEST)) {   // If the shortcut doesn't work
291             ChangeDisplaySettings(NULL, CDS_RESET);     // Do it anyway (to get the values out of the registry)
292             ChangeDisplaySettings(&DMsaved, CDS_RESET); //
293         }
294         else {
295             ChangeDisplaySettings(NULL, 0);                  // If so switch back to the desktop
296         }
297 //******************************************************************************************************************************************/
298 //******************************************************************************************************************************************/
299         /*
300          *  We use ChangeDisplaySettings(NULL,0) to return us to our original desktop.
301          *  After we've switched back to the desktop we make the cursor visible again.
302          */
303         ShowCursor(TRUE);                                // Show mouse pointer
304     }
305 
306     if (hRC) {                                           // Do we have a rendering context
307         if (!wglMakeCurrent(NULL, NULL)) {                // Are we able to release the DC and RC contexts
308             MessageBox(NULL, "Release of DC and RC failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
309         }
310 
311         if (!wglDeleteContext(hRC)) {                     // Are we able to delete the RC
312             MessageBox(NULL, "Release rendering context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
313             hRC = NULL;                                  // Set RC to NULL
314         }
315 
316         if (hDC && !ReleaseDC(hWnd, hDC)) {              // Are we able to release the DC
317             MessageBox(NULL, "Release device context failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
318             hDC = NULL;                                  // Set DC to NULL
319         }
320         if (hWnd && !DestroyWindow(hWnd)) {              // Are we able to destroy the window
321             MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
322             hWnd = NULL;                                 // Set hWnd to NULL
323         }
324 
325         if (!UnregisterClass("OpenGL", hInstance)) {     // Are we able to unregister class
326             MessageBox(NULL, "Could not register class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
327             hInstance = NULL;                            // Set hInstance to NULL
328         }
329     }
330 }
331 /*
332  * The next section of code creates our OpenGL Window.
333  */
334 
335 BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
336 {
337     /*
338      * Find  a pixel format that matches the one we want
339      */
340     GLuint PixelFormat;                                  // Holds the result after serching for a match
341     
342     /*
343      * Before you create a window, you MUST register a Class for the window
344      */
345     WNDCLASS wc;                                         // Windows class structure
346 
347     /*
348      *  dwExStyle and dwStyle will store the Extended and normal Window Style Information.
349     */
350     DWORD dwExStyle;                                     // Window extend style
351     DWORD dwStyle;                                       // Window style
352 
353 
354     RECT WindowRect;                                     // Grabs rectangle upper left/lower right values
355     WindowRect.left = (long)0;                           // Set left value to 0
356     WindowRect.right = (long)width;                      // Set right value to requested width
357     WindowRect.top = (long)0;                            // Set top value to 0
358     WindowRect.bottom = (long)height;                    // Set bottom value to requested height
359 
360     fullscreen = fullscreenflag;                         // Set the global fullscreen flag
361 
362     /*
363      *  The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. 
364      *  CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. 
365      *  WndProc is the procedure that watches for messages in our program. 
366      *  No extra Window data is used so we zero the two fields. Then we set the instance. 
367      *  Next we set hIcon to NULL meaning we don't want an ICON in the Window, 
368      *  and for a mouse pointer we use the standard arrow. The background color doesn't matter 
369      *  (we set that in GL). We don't want a menu in this Window so we set it to NULL, 
370      *  and the class name can be any name you want. I'll use "OpenGL" for simplicity.
371      */
372     hInstance = GetModuleHandle(NULL);                   // Grab an instance for our window
373     wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;       // Redraw on move, and own DC for window
374     wc.lpfnWndProc = (WNDPROC)WndProc;                   // WndProc handles message
375     wc.cbClsExtra = 0;                                   // No extra window date
376     wc.cbWndExtra = 0;                                   // No extra window date
377     wc.hInstance = hInstance;                            // set the instance
378     wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);              // Load the default icon
379     wc.hCursor = LoadCursor(NULL, IDC_ARROW);            // Load the arrow pointer
380     wc.hbrBackground = NULL;                             // No background requried for GL
381     wc.lpszMenuName = NULL;                              // We don't want a menu
382     wc.lpszClassName = "OpenGL";                         // set the class name
383 //******************************************************************************************************************************************/
384 //******************************************************************************************************************************************/
385     EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DMsaved);  // Save the current display state
386 //******************************************************************************************************************************************/
387 //******************************************************************************************************************************************/
388 
389     if (!RegisterClass(&wc)) {                           // Attempt to register the window class
390         MessageBox(NULL, "Failed to register the window class.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
391         return FALSE;                                    // Exit and return false
392     }
393 
394     if (fullscreen) {                                    // attempt fullsreen model
395         
396         /*
397         T*  here are a few very important things you should keep in mind when switching to full screen mode.
398          *  Make sure the width and height that you use in fullscreen mode is the same as 
399          *  the width and height you plan to use for your window, and most importantly,
400          *  set fullscreen mode BEFORE you create your window.
401          */
402         DEVMODE dmScreenSettings;                        // Device mode
403         memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); // Make sure memory's cleared
404         dmScreenSettings.dmSize = sizeof(dmScreenSettings);     // Size of devmode structure
405         dmScreenSettings.dmPelsWidth = width;            // Select window width
406         dmScreenSettings.dmPelsHeight = height;          // Select window height
407         dmScreenSettings.dmBitsPerPel = bits;            // Select bits per pixel
408         dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
409         
410         /*
411          *  In the line below ChangeDisplaySettings tries to switch to a mode that matches 
412          *  what we stored in dmScreenSettings. I use the parameter CDS_FULLSCREEN when switching modes, 
413          *  because it's supposed to remove the start bar at the bottom of the screen, 
414          *  plus it doesn't move or resize the windows on your desktop when you switch to 
415          *  fullscreen mode and back.
416          */
417         //Try to set selected mode and get results. Note: CDS_FULLSCREEN gets rid of start bar
418         if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
419             //If the mode fails, offer two options. Quit or run in a window
420             if (MessageBox(NULL, "The requested fullscreen mode is not supported by\n your video card. Use"
421                 "windowed mode instead?", "GL", MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
422             {
423                 fullscreen = FALSE;                       // Select windowed mode (fullscreen=FLASE)
424             }
425             else {
426                 // Pop up a message box letting user know the programe is closing.
427                 MessageBox(NULL, "Program will now close.", "ERROR", MB_OK | MB_ICONSTOP);
428                 return FALSE;                             // Exit and return FALSE
429             }
430         }
431     }
432 
433     if (fullscreen) {                                     // Are we still in fullscreen mode
434         
435         /*
436          *  If we are still in fullscreen mode we'll set the extended style to WS_EX_APPWINDOW, 
437          *  which force a top level window down to the taskbar once our window is visible. 
438          *  For the window style we'll create a WS_POPUP window. 
439          *  This type of window has no border around it, making it perfect for fullscreen mode.
440 
441          *  Finally, we disable the mouse pointer. If your program is not interactive, 
442          *  it's usually nice to disable the mouse pointer when in fullscreen mode. It's up to you though.
443          */
444         dwExStyle = WS_EX_APPWINDOW;                      // Window extended style
445         dwStyle = WS_POPUP;                               // Window style
446         ShowCursor(FALSE);                                // Hide mosue pointer 
447     }
448     else {
449 
450         /*
451          *  If we're using a window instead of fullscreen mode, 
452          *  we'll add WS_EX_WINDOWEDGE to the extended style. This gives the window a more 3D look. 
453          *  For style we'll use WS_OVERLAPPEDWINDOW instead of WS_POPUP. 
454          *  WS_OVERLAPPEDWINDOW creates a window with a title bar, sizing border, 
455          *  window menu, and minimize / maximize buttons.
456          */
457         dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;   // Window extended style
458         dwStyle = WS_OVERLAPPEDWINDOW;                    // Window style
459     }
460 
461     /*
462      *  By using the AdjustWindowRectEx command none of our OpenGL scene will be covered up by the borders, 
463      *  instead, the window will be made larger to account for the pixels needed to draw the window border. 
464      *  In fullscreen mode, this command has no effect.
465      */
466     AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);  // Adjust window to true resqusted
467     
468     /*
469      *  WS_CLIPSIBLINGS and WS_CLIPCHILDREN are both REQUIRED for OpenGL to work properly. 
470      *  These styles prevent other windows from drawing over or into our OpenGL Window.
471      */
472     if (!(hWnd = CreateWindowEx(dwExStyle,                // Extended style for the window
473         "OpenGL",                                         // Class name
474         title,                                            // Window title
475         WS_CLIPSIBLINGS |                                 // Requried window style
476         WS_CLIPCHILDREN |                                 // Requried window style
477         dwStyle,                                          // Select window style
478         0, 0,                                             // Window position
479         WindowRect.right - WindowRect.left,               // Calculate adjusted window width
480         WindowRect.bottom - WindowRect.top,               // Calculate adjusted window height
481         NULL,                                             // No parent window
482         NULL,                                             // No menu
483         hInstance,                                        // Instance
484         NULL)))                                           // Don't pass anything to WM_CREATE
485     {
486         KillGLWindow();                                   //Reset the display
487         MessageBox(NULL, "Window creation error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
488         return FALSE;                                     // Retrurn FALSE;
489     }
490 
491     /*
492      *  aside from the stencil buffer and the (slow) accumulation buffer
493      */
494     static PIXELFORMATDESCRIPTOR pfd =                    // pfd tells windows how we want things to be 
495     {
496         sizeof(PIXELFORMATDESCRIPTOR),                    // Size of this pixel format descriptor
497         1,                                                // Version number
498         PFD_DRAW_TO_WINDOW |                              // Format must support window
499         PFD_SUPPORT_OPENGL |                              // Format must support OpenGL
500         PFD_DOUBLEBUFFER,                                 // Must support double buffer
501         PFD_TYPE_RGBA,                                    // Request an RGBA format
502         bits,                                             // Select our color depth
503         0, 0, 0, 0, 0, 0,                                 // Color bits ignored
504         0,                                                // No alpha buffer
505         0,                                                // shift bit ignored
506         0,                                                // No accumulation buffer
507         0, 0, 0, 0,                                       // Accumulation bits ignored
508         16,                                               // 16Bits Z_Buffer (depth buffer)
509         0,                                                // No stencil buffer
510         0,                                                // No auxiliary buffer
511         PFD_MAIN_PLANE,                                   // Main drawing layer
512         0,                                                // Reserved
513         0, 0, 0                                           // Layer makes ignored
514     };
515 
516     if (!(hDC = GetDC(hWnd))) {                           // Did we get a device context
517         KillGLWindow();                                   // Reset the display
518         MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
519         return FALSE;                                     // Return FALSE
520     }
521 
522     if (!(PixelFormat = ChoosePixelFormat(hDC, &pfd))) {  // Did window find a matching pixel format
523         KillGLWindow();                                   // Reset the display
524         MessageBox(NULL, "Can't find a suitable pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
525         return FALSE;                                     // Return FALSE;
526     }
527 
528     if (!SetPixelFormat(hDC, PixelFormat, &pfd)) {        // Are we able to set the pixel format
529         KillGLWindow();                                   // Reset the display
530         MessageBox(NULL, "Can't set the pixelformat.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
531         return FALSE;                                     // Return FALSE;
532     }
533 
534     if (!(hRC = wglCreateContext(hDC))) {                 // Are we able to rendering context
535         KillGLWindow();                                   // Reset the display
536         MessageBox(NULL, "Can't create a GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
537         return FALSE;                                     // Return FASLE;
538     }
539 
540     if (!wglMakeCurrent(hDC, hRC)) {                      // Try to activate the rendering context
541         KillGLWindow();                                   // Reset the display
542         MessageBox(NULL, "Can't activate the GL rendering context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
543         return FALSE;                                     // Return FALSE    
544     }
545 
546     /*
547      *  ReSizeGLScene passing the screen width and height to set up our perspective OpenGL screen.
548      */
549     ShowWindow(hWnd, SW_SHOW);                            // Show the window
550     SetForegroundWindow(hWnd);                            // slightly higher priority
551     SetFocus(hWnd);                                       // Sets keyboard focus to the window
552     ReSizeGLScene(width, height);                         // Set up our perspective GL screen
553 
554 /*
555  *  we can set up lighting, textures, and anything else that needs to be setup in InitGL().
556  */
557     if (!InitGL()) {                                      // Initialize our newly created GL window
558         KillGLWindow();                                   // Reset the display
559         MessageBox(NULL, "Initialize Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
560         return FALSE;                                     // Return FALSE
561     }
562     return TRUE;
563 }
564 
565 LRESULT CALLBACK WndProc(HWND hWnd,                       // Handle for this window
566     UINT uMsg,                                            // Message for this window
567     WPARAM wParam,                                        // Additional message information
568     LPARAM lParam)                                        // Additional message information
569 {
570     switch (uMsg) {                                       // Check for window message
571     case WM_ACTIVATE: {                               // Check minimization state
572         if (!HIWORD(wParam)) {
573             active = TRUE;                            // Program is active
574         }
575         else {
576             active = FALSE;                           // Program is no longer active
577         }
578         return 0;                                     // Return to the message loop
579     }
580     case WM_SYSCOMMAND: {                             // Intercept system commands
581         switch (wParam) {                             // Check system calls
582         case SC_SCREENSAVE:                       // Screensaver trying to start
583         case SC_MONITORPOWER:                     // Monitor trying to enter powersave
584             return 0;                                 // Prevent form happening
585         }
586         break;                                        // Exit
587     }
588     case WM_CLOSE: {                                  // Did we receive a close message
589         PostQuitMessage(0);                           // Send a quit message
590         return 0;
591     }
592     case WM_KEYDOWN: {                                // Is a key being held down
593         keys[wParam] = TRUE;                          // if so, mark it as TRUE
594         return 0;                                     // Jump back
595     }
596     case WM_KEYUP: {                                  // Has a key been released
597         keys[wParam] = FALSE;                         // if so, mark it as FALSE
598         return 0;                                     // Jump back
599     }
600     case WM_SIZE: {                                   // Resize the OpenGL window
601         ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));   // LoWord = width HiWord = height
602         return 0;                                     // Jump back
603     }
604     }
605     return DefWindowProc(hWnd, uMsg, wParam, lParam);     // Pass all unhandled message to DefWindwProc
606 }
607 
608 int WINAPI WinMain(HINSTANCE hInstance,                   // Instance
609     HINSTANCE hPrevInstance,                              // Previous instance
610     LPSTR lpCmdLine,                                      // Command line parameters
611     int nCmdShow)                                         // Window show state
612 {
613     MSG msg;                                              // Window message structure
614     BOOL done = FALSE;                                    // Bool variable to exit loop
615                                                           // Ask the user which screen mode they prefer
616     if (MessageBox(NULL, "Would you like to run in fullscreen mode?",
617         "Start fullscreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
618     {
619         fullscreen = FALSE;                               // Window mode
620     }
621     // Create our OpenGL window
622     if (!CreateGLWindow("3D Shapes", 800, 600, 32, fullscreen)) {  // (Modified)
623         return 0;                                         // Quit if window was not create
624     }
625     while (!done) {                                       // Loop that runs until donw = TRUE
626         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {   // Is there a message wating
627             if (msg.message == WM_QUIT) {                 // Havw we received a quit message
628                 done = TRUE;                              // if so done  = TRUE
629             }
630             else {                                        // If not, deal with window message
631                 TranslateMessage(&msg);                   // Translate message
632                 DispatchMessage(&msg);                    // Dispatch message
633             }
634         }
635         else {
636             // Draw the scene. Watch for ESC key and quit message from DrawGLScene()
637             if (active) {                                 // Program active
638                 if (keys[VK_ESCAPE]) {                    // Was ESC pressed
639                     done = TRUE;                          // ESC signalled a quit
640                 }
641                 else {                                    // Not time to quit, update screen
642                     DrawGLScene();                        // Draw scene
643                     SwapBuffers(hDC);                     // Swap buffers (double buffering)
644 //******************************************************************************************************************************************/
645 //******************************************************************************************************************************************/
646                 }
647             }
648             if (keys['W']) rotx -= 0.1f;
649             if (keys['S']) rotx += 0.1f;
650             if (keys['A']) rotz -= 0.1f;
651             if (keys['D']) rotz += 0.1f;
652             if (keys[VK_LEFT]) rotz -= 0.1f;
653             if (keys[VK_RIGHT]) rotz += 0.1f;
654             if (keys[VK_UP]) {
655                 divs++;
656                 mybezier.dlBPatch = genBezier(mybezier, divs);
657                 keys[VK_UP] = false;
658             }
659             if (keys[VK_DOWN] && divs > 1) {
660                 divs--;
661                 mybezier.dlBPatch = genBezier(mybezier, divs);
662                 keys[VK_DOWN] = false;
663             }
664             if (keys[VK_SPACE]) {
665                 showCPoints = !showCPoints;
666                 keys[VK_SPACE] = false;
667             }
668 //******************************************************************************************************************************************/
669 //******************************************************************************************************************************************/
670 
671             /*
672             *  It allows us to press the F1 key to switch from fullscreen mode to
673             *  windowed mode or windowed mode to fullscreen mode.
674             */
675             if (keys[VK_F1]) {                            // Is F1 being pressed
676                 keys[VK_F1] = FALSE;                      // If so make key FASLE
677                 KillGLWindow();                           // Kill our current window
678                 fullscreen = !fullscreen;                 // Toggle fullscreen / window mode
679                 //Recreate our OpenGL window(modified)
680                 if (!CreateGLWindow("3D Shapes", 640, 480, 16, fullscreen)) {
681                     return 0;                             // Quit if window was not create
682                 }
683             }
684         }
685     }
686     // Shutdown
687     KillGLWindow();                                       // Kill the window
688     return (msg.wParam);                                  // Exit the program
689 }
Bézier_curve.cpp

Thanks for Nehe's tutorials, this is his home.

posted @ 2016-08-09 20:43  clairvoyant  阅读(228)  评论(0编辑  收藏  举报