Text 3D

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;  
}  

Hi !

Could you be a little more specific about where it crashes, on what line ?

Mikael