标签:
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 }
Thanks for Nehe‘s tutorials, this is his home.
outdated: 28.Bezier Patches / Fullscreen Fix
标签:
原文地址:http://www.cnblogs.com/clairvoyant/p/5754558.html