📄 chapter4.cpp
字号:
/****************************************************************************
chapter4.cpp
This demo program displays a number of OpenGL primitive types, as well as
how changing certain parameters can alter how the primitive is drawn.
To change the primitive being displayed and the properties applied to it,
use the following controls:
Key Action
--- ------
1 Draw points
2 Draw lines
3 Draw triangles
4 Draw a triangle strip
5 Draw a triangle fan
6 Draw quads
7 Draw a polygon
a Toggle antialiasing
s Toggle stippling
p Rotate through polygon modes
Author : Dave Astle
Date : 10/23/2000
Written for OpenGL Game Programming
*****************************************************************************/
/********************************* Includes *********************************/
#define WIN32_LEAN_AND_MEAN // trim the excess fat from Windows
#include <windows.h> // standard Windows app include
#include <winuser.h> // Windows constants
#include <gl/gl.h> // standard OpenGL include
#include <gl/glu.h> // OpenGL utilties
#include <stdlib.h> // for random numbers
/*************************** Macros and Constants ***************************/
#define WND_CLASS_NAME "OpenGL Window Class"
/******************************** Data types ********************************/
// used to track which primitive we're drawing
enum primtypes_t
{
PT_POINT,
PT_LINE,
PT_TRIANGLE,
PT_TRIANGLE_STRIP,
PT_TRIANGLE_FAN,
PT_QUAD,
PT_POLYGON
};
/********************************* Globals **********************************/
// Windows variables
HDC g_hdc; // global device context
HGLRC g_hrc; // global rendering context
BOOL g_isFullscreen = TRUE; // toggles fullscreen and windowed display
BOOL g_isActive = TRUE; // false if window is minimized
HWND g_hwnd = NULL; // handle of our window
HINSTANCE g_hInstance; // application instance
// the current primitive
primtypes_t g_currentPrimitive = PT_POINT;
// used to hold data retrieved from OpenGL
GLfloat g_pointSize = 1.0;
GLfloat g_pointSizeStep;
GLfloat g_pointSizeMinMax[2];
GLfloat g_lineWidth = 1.0;
GLfloat g_lineWidthStep;
GLfloat g_lineWidthMinMax[2];
// the size of the window
GLuint g_width, g_height;
/******************************** Prototypes ********************************/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
BOOL SetupWindow(char *title, int width, int height, int bits, bool isFullscreen);
BOOL InitializeScene();
GLvoid ResizeScene(GLsizei width, GLsizei height);
BOOL DisplayScene();
BOOL KillWindow();
/****************************************************************************
WinMain()
Main Windows entry point. Creates a window, sets up OpenGL, and enters an
event loop.
*****************************************************************************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
MSG msg; // message
BOOL isDone; // flag saying when our app is complete
// create our window and set up OpenGL
SetupWindow("Primitives Demo", 800, 600, 32, TRUE);
// intialize the loop condition variable
isDone = FALSE;
// main message loop
while (!isDone)
{
// get a message if one is ready
if(PeekMessage(&msg, g_hwnd, NULL, NULL, PM_REMOVE))
{
// look for a quit message, in which case, we're done
if (msg.message == WM_QUIT)
{
isDone = TRUE;
}
else
{
// translate and dispatch to event queue
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
// render the current scene
DisplayScene();
// bring backbuffer to foreground
SwapBuffers(g_hdc);
}
// cleanup
KillWindow();
return msg.wParam;
} // end WinMain()
/****************************************************************************
WndProc
Windows message handler
*****************************************************************************/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static BOOL antialias = false; // controls antialiasing
static GLenum polyMode = GL_FILL; // controls the polygon mode
static BOOL stipple = false; // controls stippling
switch(message)
{
case WM_ACTIVATE: // watch for the window being minimized and restored
{
if (!HIWORD(wParam))
{
// program was restored or maximized
g_isActive = TRUE;
}
else
{
// program was minimized
g_isActive=FALSE;
}
return 0;
}
case WM_SYSCOMMAND: // look for screensavers and powersave mode
{
switch (wParam)
{
case SC_SCREENSAVE: // screensaver trying to start
case SC_MONITORPOWER: // monitor going to powersave mode
// returning 0 prevents either from happening
return 0;
default:
break;
}
} break;
case WM_CLOSE: // window is being closed
{
// send WM_QUIT to message queue
PostQuitMessage(0);
return 0;
}
case WM_SIZE:
{
// update perspective with new width and height
ResizeScene(LOWORD(lParam), HIWORD(lParam));
return 0;
}
case WM_CHAR:
{
switch (toupper(wParam))
{
case VK_ESCAPE:
{
// send WM_QUIT to message queue
PostQuitMessage(0);
return 0;
}
case 'A': // toggle antialiasing
{
antialias = !antialias;
// if antialiasing was just turned on, enable it
if (antialias)
{
glEnable(GL_POINT_SMOOTH);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_POLYGON_SMOOTH);
glEnable(GL_BLEND);
}
// otherwise, disable it
else
{
glDisable(GL_POINT_SMOOTH);
glDisable(GL_LINE_SMOOTH);
glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_BLEND);
}
return 0;
}
case 'S': // toggle stippling
{
stipple = !stipple;
// if stippling was just turned on, enable it
if (stipple)
{
glEnable(GL_LINE_STIPPLE);
glEnable(GL_POLYGON_STIPPLE);
}
// otherwise, disable it
else
{
glDisable(GL_LINE_STIPPLE);
glDisable(GL_POLYGON_STIPPLE);
}
return 0;
}
case 'P': // rotate polygon mode
{
// go to the next mode
polyMode++;
// wrap around if we need to
if (polyMode > GL_FILL)
polyMode = GL_POINT;
// select the new polygon mode
glPolygonMode(GL_FRONT_AND_BACK, polyMode);
}
case '+': // increase sizes
{
// increase point sizes (if we're not already at the max)
if (g_pointSize < g_pointSizeMinMax[1])
g_pointSize += g_pointSizeStep;
glPointSize(g_pointSize);
// increase line widths (if we're not already at the max)
if (g_lineWidth < g_lineWidthMinMax[1])
g_lineWidth += g_lineWidthStep;
glLineWidth(g_lineWidth);
return 0;
}
case '-': // decrease sizes
{
// decrease point sizes (if we're not already at the min)
if (g_pointSize > g_pointSizeMinMax[0])
g_pointSize -= g_pointSizeStep;
glPointSize(g_pointSize);
// decrease line widths (if we're not already at the min)
if (g_lineWidth > g_lineWidthMinMax[0])
g_lineWidth -= g_lineWidthStep;
glLineWidth(g_lineWidth);
return 0;
}
case '1': // select points
{
g_currentPrimitive = PT_POINT;
return 0;
}
case '2': // select lines
{
g_currentPrimitive = PT_LINE;
return 0;
}
case '3': // select triangles
{
g_currentPrimitive = PT_TRIANGLE;
return 0;
}
case '4': // select triangle strip
{
g_currentPrimitive = PT_TRIANGLE_STRIP;
return 0;
}
case '5': // select triangle fan
{
g_currentPrimitive = PT_TRIANGLE_FAN;
return 0;
}
case '6': // select quads
{
g_currentPrimitive = PT_QUAD;
return 0;
}
case '7': // select polygon
{
g_currentPrimitive = PT_POLYGON;
return 0; // select
}
default:
break;
};
} break;
default:
break;
}
// pass any remaining messages up to the default handler
return (DefWindowProc(hwnd, message, wParam, lParam));
} // end WndProc()
/****************************************************************************
SetupWindow()
Creates a window and the device and rendering contexts for it.
*****************************************************************************/
BOOL SetupWindow(char *title, int width, int height, int bits, bool isFullscreen)
{
// set the global flag
g_isFullscreen = isFullscreen;
// get our instance handle
g_hInstance = GetModuleHandle(NULL);
WNDCLASSEX wc; // window class
// fill out the window class structure
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // default icon
wc.hIconSm = LoadIcon(NULL, IDI_WINLOGO); // windows logo small icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // default arrow
wc.hbrBackground = NULL; //(HBRUSH) GetStockObject(BLACK_BRUSH); // black background
wc.lpszMenuName = NULL; // no menu
wc.lpszClassName = WND_CLASS_NAME;
// register the windows class
if (!RegisterClassEx(&wc))
{
MessageBox(NULL,"Unable to register the window class", "Error", MB_OK | MB_ICONEXCLAMATION);
return FALSE; // Exit And Return FALSE
}
// if we're in fullscreen mode, set the display up for it
if (g_isFullscreen)
{
// set up the device mode structure
DEVMODE screenSettings;
memset(&screenSettings,0,sizeof(screenSettings));
screenSettings.dmSize = sizeof(screenSettings);
screenSettings.dmPelsWidth = width; // screen width
screenSettings.dmPelsHeight = height; // screen height
screenSettings.dmBitsPerPel = bits; // bits per pixel
screenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
// attempt to switch to the resolution and bit depth we've selected
if (ChangeDisplaySettings(&screenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
// if we can't get fullscreen, let them choose to quit or try windowed mode
if (MessageBox(NULL, "Cannot run in the fullscreen mode at the selected resolution\n"
"on your video card. Try windowed mode instead?",
"OpenGL Game Programming",
MB_YESNO | MB_ICONEXCLAMATION) == IDYES)
{
g_isFullscreen = FALSE;
}
else
{
return FALSE;
}
}
}
DWORD dwExStyle;
DWORD dwStyle;
// if we're still in fullscreen mode, set the window style appropriately
if (g_isFullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP; // simple window with no borders or title bar
ShowCursor(FALSE); // hide the cursor for now
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
// set up the window we're rendering to so that the top left corner is at (0,0)
// and the bottom right corner is (height,width)
RECT windowRect;
windowRect.left = 0;
windowRect.right = (LONG) width;
windowRect.top = 0;
windowRect.bottom = (LONG) height;
// change the size of the rect to account for borders, etc. set by the style
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
// class registered, so now create our window
g_hwnd = CreateWindowEx(dwExStyle, // extended style
WND_CLASS_NAME, // class name
title, // app name
dwStyle | // window style
WS_CLIPCHILDREN | // required for
WS_CLIPSIBLINGS, // using OpenGL
0, 0, // x,y coordinate
windowRect.right - windowRect.left, // width
windowRect.bottom - windowRect.top, // height
NULL, // handle to parent
NULL, // handle to menu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -