Here’s a rehash of Nehe’s Lesson 14. Even though I consider his tut’s to be some of the best out on the WWW… For some strange reason, this particular lesson crashed two low spec PC’s I had tried it on.
I changed the lighting and it stopped crashing. I also changed the 3d Text rotations to only two Axis, which may have been another possible cause of the crashes.
If anybody knows any other reason why this lesson sometimes crashes, Let us know.
But, this remake does’nt seem to crash, at least on my PC…It seems to be “very” stable.
Compile it, and let me know.
Hope this board does’nt trash the code:
/***************************************************************************
*
* EZY 3D Text
* Outline Font
* VER 0.0000001
*
* A rehash of Nehe's Lesson 14
* A Twist on Blaine Hodge's Window Opening
* As Well As Different Lighting, ect..
*
*
* Compile as a Win32 .cpp and not a console App.
* In Dev C++, compile with the following parameters in linker whitespace:
* -lopengl32 -lglu32 -lkernel32 -luser32 -lgdi32 -lwinspool -lcomdlg32
* -ladvapi32 -lshell32 -lole32 -loleaut32 -luuid -lodbc32 -lodbccp32
*
****************************************************************************/
/************************
* Includes
* Includes and defines
************************/
#include <windows.h>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <gl/gl.h>
#include <GL/glu.h>
/**************************************
* Prototype Function Declarations
*
**************************************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int iCmdShow);
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
int EnableOpenGL(HWND hWnd, HDC *hDC, HGLRC *hRC);
int Init(void) ;
int Build3DFont(HDC);
int DrawScene(void) ;
int UpdateScene(void) ;
void glPrint3D(const char *fmt, ...) ;
int DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC);
/**************************************************
* Declare various variables as static to namespace
**************************************************/
static int Width;
static int Height;
static bool quit = FALSE;
static bool fullscreen = TRUE ;
static bool keys[256];
GLYPHMETRICSFLOAT gmf[256];
GLuint base; // Base Display List For The Font Set
GLfloat rot; // Used To Rotate The Text
/************************************************************
* 1.Main Windows Function Declaration and Definition
*
* Create instance for window, register window class,
* Main loop with scene animation.
************************************************************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int iCmdShow)
{ //Opening Brace For WinMain
// At Start of App, Offer Two Options, Fullscreen or Windowed.
if (MessageBox(NULL," Use Fullscreen in 1024x768 instead of Windowed ?","EZY 3D Text",MB_YESNO|MB_ICONINFORMATION)==IDYES)
{
Width= 1024;
Height= 768;
}
else
{
// windowed Chosen
fullscreen = FALSE;
Width= 640;
Height= 480;
}
//WinMain´s Variable Declarations
WNDCLASS wc;
HWND hWnd;
HDC hDC;
HGLRC hRC;
MSG msg;
iCmdShow ;
//Variables For Screen
DWORD dWinStyle; //Var to hold Window Style
dWinStyle ; // Windows Style
RECT WindowRect; // Grabs Rectangle Upper Left and Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)Width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)Height; // Set Bottom Value To Requested Height
// Set Up Window Class
wc.style = CS_OWNDC;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "GLExample";
//Register The &wc Window Class
if (!RegisterClass(&wc)) // Failed Attempt At Registering Window Class
{
MessageBox(NULL,"Failed Attempt at Registering Window Class.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Exit And Return FALSE
}
// Grab the Video Mode and change resolution
if (fullscreen)
{
DEVMODE dmScreenSettings;
memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
dmScreenSettings.dmSize=sizeof(dmScreenSettings);
dmScreenSettings.dmPelsWidth = Width;
dmScreenSettings.dmPelsHeight =Height;
dmScreenSettings.dmBitsPerPel = 16;
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// Pop Up A Message Box To Inform User Resolution Failed
MessageBox(NULL,"Failed Resolution Attempt.
Choose A Lower Resolution. ","ERROR",MB_OK|MB_ICONSTOP);
return FALSE;
}
}
if(!fullscreen)
{
//Windowed Mode chosen
iCmdShow = SW_SHOW ;
dWinStyle = WS_POPUPWINDOW | WS_CAPTION| WS_VISIBLE ;
}
else
{
// in fullscreen mode
iCmdShow = SW_SHOWMAXIMIZED;
ShowCursor(FALSE);
dWinStyle = WS_POPUP ;
}
AdjustWindowRectEx(&WindowRect, dWinStyle, FALSE, 0);
// Create Main Window
hWnd = CreateWindow
(
"GLExample",
"EZY 3D Text", // Window caption
WS_CLIPSIBLINGS| // Must be set for OpenGL to work
WS_CLIPCHILDREN| // WS_CLIPCHILDREN and WS_CLIPSIBLINGS
dWinStyle, // Popup window variable
0, // Initial x position
0, // Initial y position
WindowRect.right-WindowRect.left, // Calculate Adjusted Window Width
WindowRect.bottom-WindowRect.top, // Calculate Adjusted Window Height
NULL, // Parent window handle
NULL, // Window menu handle
hInstance, // Program instance handle
NULL // Creation parameters
);
// Open , show and update window
ShowWindow(hWnd,iCmdShow);
SetForegroundWindow(hWnd);
SetFocus(hWnd);
UpdateWindow (hWnd);
// Call Pixelformat descriptor
// and make RC concurrent with DC
EnableOpenGL( hWnd, &hDC, &hRC );
//Call Init() Function for viewport,
//Projection and Modelview Mtrix settings
Init() ;
// Call Our Build 3D Fonts Function
Build3DFont(hDC) ;
//............................................
//Program Main repetitive Loop Starts Here
//............................................
while ( !quit )
{
// check for messages
if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
// handle or dispatch messages
if ( msg.message == WM_QUIT )
{
quit = TRUE;
}
else
{
TranslateMessage( &msg );
//Invoke Win CallBack Function
DispatchMessage( &msg );
}
}
else
{
// Call the DrawScene Function
DrawScene() ;
//Make Scene Visible
SwapBuffers( hDC );
//Call UpdateScene Function
UpdateScene() ;
} //Closes Lst Else
} // Closes While Loop
// Call Disable OpenGL Function if
//an Error or and escape sequence is used
DisableOpenGL( hWnd, hDC, hRC );
/*Destroy the Window*/
if (!DestroyWindow(hWnd)) // Window Destroyed?
{
MessageBox(NULL,"Failed Attempt At Destroying Window.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}
/*Unregister the Class*/
if (!UnregisterClass("GLExample",hInstance)) // Was Class Unregistered?
{
MessageBox(NULL,"Failed Attempt At Unregistering Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
glDeleteLists(base, 256);
return msg.wParam;
} // Closing Brace For WinMain
/*************************************************
* 2.Window Callback Function (Body)Definition
* Messages, user keyboard
* Event Driven
**************************************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_SYSCOMMAND:
switch(lParam)
{
case SC_SCREENSAVE: //Screen saver starting?
case SC_MONITORPOWER: //PowerSave Mode?
return 0;
}
break;
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
case WM_KEYDOWN:
{
keys[wParam] = TRUE ;
return 0;
}
case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE ;// If So, Mark It As FALSE
return 0; // Jump Back
}
break;
default:
break;
}
return DefWindowProc( hWnd, message, wParam, lParam );
}
/**************************************************************************
* 3. Enable OpenGL Function
* Pixel format description, device context and it´s Ogl render context,
***************************************************************************/
int EnableOpenGL (HWND hWnd, HDC *hDC, HGLRC *hRC)
{
PIXELFORMATDESCRIPTOR pfd;
int iFormat;
/* get the device context (DC) */
*hDC = GetDC (hWnd);
/* set the pixel format for the DC */
ZeroMemory (&pfd, sizeof (pfd));
pfd.nSize = sizeof (pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
pfd.cDepthBits = 16;
pfd.iLayerType = PFD_MAIN_PLANE;
if ( (iFormat = ChoosePixelFormat(*hDC, &pfd)) == 0 )
{
MessageBox(NULL, "ChoosePixelFormat failed", "Error", MB_OK);
return FALSE;
}
if (SetPixelFormat(*hDC, iFormat, &pfd) == FALSE)
{
MessageBox(NULL, "SetPixelFormat failed", "Error", MB_OK);
return FALSE;
}
/* create and enable the render context (RC) */
*hRC = wglCreateContext( *hDC );
/* make render context current with current device context*/
wglMakeCurrent( *hDC, *hRC );
return 0;
}
/*******************************
* 4. Init Function
* Set Viewport and various
*******************************/
int Init(void)
{
//Set depth testing, buffers and Viewport
glViewport (0, 0, Width, Height); //Screen Drawing Area
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); //Clear The Background To Black
glClearDepth(1.0); //Clear Depth Buffer
glDepthFunc(GL_LEQUAL); //The Depth Test To Do
glEnable(GL_BLEND);
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
// Increase default lighting from 0.2f to 0.5
GLfloat global_ambient[] = { 0.5f, 0.5f, 0.5f, 1.0f };
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, global_ambient);
// Set light's diffuse and specular emission properties
GLfloat lightSpecular[4] = { 0.3f, 0.3f, 0.3f, 0.3f } ; // Light 0 specular properties
GLfloat lightDiffuse[4] = { 0.5f, 0.5f, 0.5f, 0.5f } ; // Light 0 diffuse properties
glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiffuse);
glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpecular);
// Enable Lighting for 3D objects
glEnable(GL_LIGHT0);
glEnable(GL_LIGHTING);
//Projection Matrix for viewing volumes
glMatrixMode (GL_PROJECTION);
glPushMatrix ();
glLoadIdentity ();
// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,1000.0f);
// Modelview Matrix for Objects
glMatrixMode (GL_MODELVIEW);
//Reset modelview matrix
glLoadIdentity();
return TRUE ;
}
/*****************************
* 5. Build 3D Font Function
*****************************/
int Build3DFont(HDC hDC) // Build Our Bitmap Font
{
HFONT font; // Windows Font ID
base = glGenLists(256); // Storage For 256 Characters
font = CreateFont( -12, // Height Of Font
0, // Width Of Font
0, // Angle Of Escapement
0, // Orientation Angle
FW_BOLD, // Font Weight
FALSE, // Italic
FALSE, // Underline
FALSE, // Strikeout
ANSI_CHARSET, // Character Set Identifier
OUT_TT_PRECIS, // Output Precision
CLIP_DEFAULT_PRECIS, // Clipping Precision
ANTIALIASED_QUALITY, // Output Quality
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
"Comic Sans MS"); // Font Name
SelectObject(hDC, font); // Selects The Font We Created
wglUseFontOutlines( hDC, // Select The Current DC
0, // Starting Character
255, // Number Of Display Lists To Build
base, // Starting Display Lists
0.0f, // Deviation From The True Outlines
0.2f, // Font Thickness In The Z Direction
WGL_FONT_POLYGONS, // Use Polygons, Not Lines
gmf); // Address Of Buffer To Recieve Data
return TRUE ;
}
/*************************************
* 6. Draw Scene Function
* OpenGL Drawing Code Goes Here
*************************************/
int DrawScene(void)
{
//Clear previous frame color and depth enable drawing of next frame
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/*Clear existing internal tansformations by loading identity matrix for entire scene*/
glLoadIdentity ();
glPushMatrix ();
//place light 0 in front of cube object by 1 unit
GLfloat lightPosL0[4] = {0.0f, 0.0f, -9.0f, 1.0f};
glPopMatrix ();
GLfloat blue[4] = { 0.0f, 0.0f, 1.0f, 1.0f } ;
glMaterialfv(GL_FRONT, GL_SPECULAR, blue );
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue );
glMaterialf(GL_FRONT, GL_SHININESS, 500.0);
glPushMatrix ();
glTranslatef(0.0f,0.0f,-10.0f); // Move Ten Units Into The Screen
glRotatef(rot,1.0f,0.0f,0.0f); // Rotate On The X Axis
glRotatef(rot*1.4f,0.0f,0.0f,1.0f); // Rotate On The Z Axis
// Print GL 3D Text To The Screen
glPrint3D("EZY 3D TEXT");
glPopMatrix ();
return TRUE ;
}
/********************************
* 7. Update Scene Function
* Update animations, Keyboard
********************************/
int UpdateScene(void)
{
// Increase The Rotation Variable
rot+=0.5f;
/*Keyboard Section*/
// escape key sequence
if(keys[VK_ESCAPE])
{
quit = TRUE; // set bool var quit, to true and exit
}
return TRUE ;
}
/********************************************
* 8. GL Print 3D Font Function
********************************************/
void glPrint3D(const char *fmt, ...) // Custom GL "Print" Routine
{
float length=0; // Used To Find The Length Of The Text
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
return ; // Do Nothing
va_start(ap, fmt); // Parses The String For Variables
vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
for (unsigned int loop=0;loop<(strlen(text));loop++) // Loop To Find Text Length
{
length+=gmf[text[loop]].gmfCellIncX; // Increase Length By Each Characters Width
}
glTranslatef(-length/2,0.0f,0.0f); // Center Our Text On The Screen
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(base); // Sets The Base Character to 0
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text
glPopAttrib(); // Pops The Display List Bits
}
/**************************************************
* 9. Disable OpenGL Function
*
***************************************************/
int DisableOpenGL(HWND hWnd, HDC hDC, HGLRC hRC)
{
wglMakeCurrent( NULL, NULL );
wglDeleteContext( hRC );
ReleaseDC( hWnd, hDC );
// Restore default desktop mode with mouse pointer
if (fullscreen) ChangeDisplaySettings(NULL,0);
return TRUE;
}