Example 3
Rendering a Grid using a variation of Triangles and Quads
#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
"TriangleQuads",
// 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.0);
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 ClassCode
{
private:
int m_windowWidth;
int m_windowHeight;
public:
ClassCode();
virtual ~ClassCode();
bool Init();
bool Shutdown();
void SetupProjection(int width, int height);
void Prepare(float dt);
void Render();
void DrawPoints();
void DrawTriangles();
void DrawTriangleStrip();
void DrawTriangleFan();
void DrawQuads();
void DrawQuadStrip();
};
#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()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
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)
{
}
void ClassCode::Render()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// clear screen and depth buffer
glLoadIdentity();
gluLookAt(0.0, 10.0, 0.1, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// top left
glPushMatrix();
glTranslatef(-6.0f, 0.0f, -4.0f);
DrawPoints();
glPopMatrix();
// top middle
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glTranslatef(-2.0f, 0.0f, -4.0f);
DrawTriangles();
glPopMatrix();
// top right
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glTranslatef(2.0f, 0.0f, -4.0f);
DrawQuads();
glPopMatrix();
// bottom left
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glTranslatef(-6.0f, 0.0f, 0.5f);
DrawTriangleStrip();
glPopMatrix();
// bottom middle
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glTranslatef(-2.0f, 0.0f, 0.5f);
DrawTriangleFan();
glPopMatrix();
// bottom right
glPushMatrix();
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glTranslatef(2.0f, 0.0f, 0.5f);
DrawQuadStrip();
glPopMatrix();
}
// draw grid of points showing dataset we are working with
void ClassCode::DrawPoints()
{
glPointSize(4.0);
glBegin(GL_POINTS);
for (int x = 0; x < 4; x++)
for (int z = 0; z < 4; z++)
glVertex3f(x, 0, z);
glEnd();
}
// draw grid as individual triangles
void ClassCode::DrawTriangles()
{
glBegin(GL_TRIANGLES);
for (int x = 0; x < 3; x++)
{
for (int z = 0; z < 3; z++)
{
glVertex3f(x, 0.0, z);
glVertex3f((x+1.0), 0.0, z);
glVertex3f(x, 0.0, (z+1.0));
}
}
glEnd();
}
// draw grid as triangle fan
void ClassCode::DrawTriangleFan()
{
glBegin(GL_TRIANGLE_FAN);
// center vertex of fan
glVertex3f(0.0, 0.0, 0.0);
// bottom side
for (int x = 4; x > 0; x--)
glVertex3f(x-1, 0.0, 3.0);
// right side
for (int z = 4; z > 0; z--)
glVertex3f(3.0, 0.0, z-1);
glEnd();
}
// draw grid as triangle strips
void ClassCode::DrawTriangleStrip()
{
// 3 rows of triangle strips
for (int x = 0; x < 3; x++)
{
glBegin(GL_TRIANGLE_STRIP);
for (int z = 0; z < 3; z++)
{
glVertex3f(x, 0.0, z);
glVertex3f((x+1.0), 0.0, z);
glVertex3f(x, 0.0, (z+1.0));
glVertex3f((x+1.0), 0.0, (z+1.0));
}
glEnd();
}
}
// draw grid as individual quads
void ClassCode::DrawQuads()
{
glBegin(GL_QUADS);
for (int x = 0; x < 3; x++)
{
for (int z = 0; z < 3; z++)
{
glVertex3f(x, 0.0, z);
glVertex3f((x+1.0), 0.0, z);
glVertex3f((x+1.0), 0.0, (z+1.0));
glVertex3f(x, 0.0, (z+1.0));
}
}
glEnd();
}
// draw grid as quad strips
void ClassCode::DrawQuadStrip()
{
for (int x = 0; x < 3; x++)
{
glBegin(GL_QUAD_STRIP);
for (int z = 0; z < 4; z++)
{
glVertex3f(x, 0.0, z);
glVertex3f((x+1.0), 0.0, z);
}
glEnd();
}
}