Introductory Examples
¢ The code below has been divided into 3 main components as described below.
Ø The main function, winmain.cpp
Contains the code necessary to deal with Microsoft Windows routines and to create the Window (the window that is created by glut if not using Win32).
Ø The class, ClassCode.h
Contains the prototypes for OpenGL code.
Ø The implementation, ClassCode.cpp
Contains the function definitions for the OpenGL code prototypes in the above header file.
¢ The rationale for the separation is that it aids in debugging, code writing, and code modification (a goal of all modern languages)
¢ This may seem like a lot of code but most of it does not have to be modified by the user - the operations do not change.
¢ Note that some languages, like Visual Basic, hide the "behind the scenes" code from the user. Others, like Visual C++, do not.
¢ Even if it is exposed, that does not mean that it is necessary to understand all of it.
¢ You need to understand only those portions that should be changed depending on the problem. That part will be explained throughout the course.
winmain.cpp
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include "ClassCode.h"
bool exiting = false;
long windowWidth = 800;
long windowHeight = 600;
long windowBits = 32;
bool fullscreen = false;
HDC hDC;
ClassCode *g_glRender = NULL;
void SetupPixelFormat(HDC hDC)
{
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
// size
1,
// version
PFD_SUPPORT_OPENGL |
// OpenGL window
PFD_DRAW_TO_WINDOW |
// render to window
PFD_DOUBLEBUFFER,
// support double-buffering
PFD_TYPE_RGBA,
// color type
32,
// prefered color depth
0, 0, 0, 0, 0, 0,
// color bits (ignored)
0,
// no alpha buffer
0,
// alpha bits (ignored)
0,
// no accumulation buffer
0, 0, 0, 0,
// accum bits (ignored)
16,
// depth buffer
0,
// no stencil buffer
0,
// no auxiliary buffers
PFD_MAIN_PLANE,
// main layer
0,
// reserved
0, 0, 0,
// no layer, visible, damage masks
};
pixelFormat = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, pixelFormat, &pfd);
}
LRESULT CALLBACK MainWindowProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
static HDC hDC;
static HGLRC hRC;
int height, width;
// dispatch messages
switch (uMsg)
{
case WM_CREATE:
// window creation
hDC = GetDC(hWnd);
SetupPixelFormat(hDC);
//SetupPalette();
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
break;
case WM_DESTROY:
// window destroy
case WM_QUIT:
case WM_CLOSE:
// windows is closing
// deselect rendering context and delete it
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hRC);
// send WM_QUIT to message queue
PostQuitMessage(0);
break;
case WM_SIZE:
height = HIWORD(lParam);
// retrieve width and height
width = LOWORD(lParam);
g_glRender->SetupProjection(width, height);
break;
case WM_ACTIVATEAPP:
// activate app
break;
case WM_PAINT:
// paint
PAINTSTRUCT ps;
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
// left mouse button
break;
case WM_RBUTTONDOWN:
// right mouse button
break;
case WM_MOUSEMOVE:
// mouse movement
break;
case WM_LBUTTONUP:
// left button release
break;
case WM_RBUTTONUP:
// right button release
break;
case WM_KEYUP:
break;
case WM_KEYDOWN:
int fwKeys;
LPARAM keyData;
fwKeys = (int)wParam;
// virtual-key code
keyData = lParam;
// key data
switch(fwKeys)
{
case VK_ESCAPE:
PostQuitMessage(0);
break;
default:
break;
}
break;
default:
break;
}
return
DefWindowProc(hWnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE
hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
WNDCLASSEX windowClass;
// window class
HWND
hwnd;
// window handle
MSG
msg;
// message
DWORD
dwExStyle;
// Window Extended Style
DWORD
dwStyle;
// Window Style
RECT
windowRect;
g_glRender = new ClassCode;
windowRect.left=(long)0;
// Set Left Value To 0
windowRect.right=(long)windowWidth;
// Set Right Value To Requested Width
windowRect.top=(long)0;
// Set Top Value To 0
windowRect.bottom=(long)windowHeight;
// Set Bottom Value To Requested Height
// fill out the window class structure
windowClass.cbSize
= sizeof(WNDCLASSEX);
windowClass.style
= CS_HREDRAW | CS_VREDRAW;
windowClass.lpfnWndProc
= MainWindowProc;
windowClass.cbClsExtra
= 0;
windowClass.cbWndExtra
= 0;
windowClass.hInstance
= hInstance;
windowClass.hIcon
= LoadIcon(NULL, IDI_APPLICATION);
// default icon
windowClass.hCursor
= LoadCursor(NULL, IDC_ARROW);
// default arrow
windowClass.hbrBackground
= NULL;
// don't need background
windowClass.lpszMenuName
= NULL;
// no menu
windowClass.lpszClassName
= "GLClass";
windowClass.hIconSm
= LoadIcon(NULL, IDI_WINLOGO);
// windows logo small icon
// register the windows class
if (!RegisterClassEx(&windowClass))
return 0;
if (fullscreen)
// fullscreen?
{
DEVMODE dmScreenSettings;
// device mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize = sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = windowWidth;
// screen width
dmScreenSettings.dmPelsHeight = windowHeight;
// screen height
dmScreenSettings.dmBitsPerPel = windowBits;
// bits per pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
//
if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) !=
DISP_CHANGE_SUCCESSFUL)
{
// setting display mode failed, switch to windowed
MessageBox(NULL, "Display mode failed", NULL, MB_OK);
fullscreen = FALSE;
}
}
if (fullscreen)
// Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW;
// Window Extended Style
dwStyle=WS_POPUP;
// Windows Style
ShowCursor(FALSE);
// Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
// Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW;
// Windows Style
}
AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle);
// Adjust Window To True Requested Size
// class registered, so now create our window
hwnd = CreateWindowEx(NULL,
// extended style
"GLClass",
// class name
"BOGLGP - Chapter 2 - OpenGL Application",
// app name
dwStyle | WS_CLIPCHILDREN |
WS_CLIPSIBLINGS,
0, 0,
// x,y coordinate
windowRect.right - windowRect.left,
windowRect.bottom - windowRect.top, // width, height
NULL,
// handle to parent
NULL,
// handle to menu
hInstance,
// application instance
NULL);
// no extra params
hDC = GetDC(hwnd);
// check if window creation failed (hwnd would equal NULL)
if (!hwnd)
return 0;
ShowWindow(hwnd, SW_SHOW);
// display the window
UpdateWindow(hwnd);
// update the window
g_glRender->Init();
while (!exiting)
{
g_glRender->Prepare(0.0f);
g_glRender->Render();
SwapBuffers(hDC);
while (PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage (&msg, NULL, 0, 0))
{
exiting = true;
break;
}
TranslateMessage (&msg);
DispatchMessage (&msg);
}
}
delete g_glRender;
if (fullscreen)
{
ChangeDisplaySettings(NULL,0);
// If So Switch Back To The Desktop
ShowCursor(TRUE);
// Show Mouse Pointer
}
return (int)msg.wParam;
}
#ifndef
__GL_COMPONENT
#define
__GL_COMPONENT
#define
PI 3.14159
#define
TWO_PI PI*2.0
#define
HALF_PI PI/2.0
class
CGfxOpenGL
{
private:
int m_windowWidth;
int m_windowHeight;
float m_angle;
public:
CGfxOpenGL();
virtual ~CGfxOpenGL();
bool Init();
bool Shutdown();
void SetupProjection(int
width, int height);
void Prepare(float
dt);
void Render();
};
#endif
#pragma comment(lib,"glu32.lib")
#pragma comment(lib,"opengl32.lib")
#ifdef _WINDOWS
#include <windows.h>
#endif
#include <gl/gl.h>
#include <gl/glu.h>
#include <math.h>
#include "ClassCode.h"
// disable implicit float-double casting
#pragma warning(disable:4305)
ClassCode::ClassCode()
{
}
ClassCode::~ClassCode()
{
}
bool ClassCode::Init()
{
// clear to black background
glClearColor(0.0, 0.0, 0.0, 0.0);
m_angle = 0.0f;
return true;
}
bool ClassCode::Shutdown()
{
return true;
}
void ClassCode::SetupProjection(int width, int height)
{
if (height == 0)
// don't want a divide by zero
{
height = 1;
}
glViewport(0, 0, width, height);
// reset the viewport to new dimensions
glMatrixMode(GL_PROJECTION);
// set projection matrix current matrix
glLoadIdentity();
// reset projection matrix
// calculate aspect ratio of window
gluPerspective(52.0f,(GLfloat)width/(GLfloat)height,1.0f,1000.0f);
glMatrixMode(GL_MODELVIEW);
// set modelview matrix
glLoadIdentity();
// reset modelview matrix
m_windowWidth = width;
m_windowHeight = height;
}
void ClassCode::Prepare(float dt)
{
m_angle += 0.1f;
}
void ClassCode::Render()
{
// clear screen and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
// move back 5 units and rotate about all 3 axes
glTranslatef(0.0, 0.0, -5.0f);
glRotatef(m_angle, 1.0f, 0.0f, 0.0f);
glRotatef(m_angle, 0.0f, 1.0f, 0.0f);
glRotatef(m_angle, 0.0f, 0.0f, 1.0f);
// lime greenish color
glColor3f(0.7f, 1.0f, 0.3f);
// draw the triangle such that the rotation point is in the center
glBegin(GL_TRIANGLES);
glVertex3f(1.0f, -1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 0.0f);
glVertex3f(0.0f, 1.0f, 0.0f);
glEnd();
}