2002-09-18 22:15:49 +00:00
/*
* This Code Was Created By Jeff Molofee 2000
* A HUGE Thanks To Fredric Echols For Cleaning Up
* And Optimizing This Code , Making It More Flexible !
* If You ' ve Found This Code Useful , Please Let Me Know .
* Visit My Site At nehe . gamedev . net
* Adapted to BOINC by Eric Heien
*/
2002-10-06 00:43:54 +00:00
# include <afxwin.h>
2002-09-18 22:15:49 +00:00
# include <gl\gl.h> // Header File For The OpenGL32 Library
# include <gl\glu.h> // Header File For The GLu32 Library
# include <gl\glaux.h> // Header File For The Glaux Library
# include <stdio.h>
# include <time.h>
# include "graphics_api.h"
HDC hDC = NULL ; // Private GDI Device Context
HGLRC hRC = NULL ; // Permanent Rendering Context
HWND hWnd = NULL ; // Holds Our Window Handle
HINSTANCE hInstance ; // Holds The Instance Of The Application
int mouse_thresh = 3 ;
int initCursorPosx , initCursorPosy ;
2002-10-24 16:39:00 +00:00
GLuint base ; // Base Display List For The Font Set
GLfloat cnt1 ; // 1st Counter Used To Move Text & For Coloring
GLfloat cnt2 ; // 2nd Counter Used To Move Text & For Coloring
2002-09-18 22:15:49 +00:00
bool keys [ 256 ] ;
bool active = TRUE ; // Window Active Flag Set To TRUE By Default
bool fullscreen = TRUE ; // Fullscreen Flag Set To Fullscreen Mode By Default
BOOL done = FALSE ; // Bool Variable To Exit Loop
int counter ;
int DrawGLScene ( GLvoid ) ;
LRESULT CALLBACK WndProc ( HWND , UINT , WPARAM , LPARAM ) ; // Declaration For WndProc
DWORD WINAPI win_graphics_event_loop ( LPVOID duff ) ;
void renderBitmapString ( float x , float y , void * font , char * string ) ;
GLvoid ReSizeGLScene ( GLsizei width , GLsizei height ) // Resize And Initialize The GL Window
{
if ( height = = 0 ) { // Prevent A Divide By Zero By
height = 1 ; // Making Height Equal One
}
glViewport ( 0 , 0 , width , height ) ; // Reset The Current Viewport
glMatrixMode ( GL_PROJECTION ) ; // Select The Projection Matrix
glLoadIdentity ( ) ; // Reset The Projection Matrix
// Calculate The Aspect Ratio Of The Window
gluPerspective ( 45.0f , ( GLfloat ) width / ( GLfloat ) height , 0.1f , 100.0f ) ;
glMatrixMode ( GL_MODELVIEW ) ; // Select The Modelview Matrix
glLoadIdentity ( ) ; // Reset The Modelview Matrix
}
2002-10-24 16:39:00 +00:00
GLvoid BuildFont ( GLvoid ) // Build Our Bitmap Font
{
HFONT font ; // Windows Font ID
HFONT oldfont ; // Used For Good House Keeping
base = glGenLists ( 96 ) ; // Storage For 96 Characters
font = CreateFont ( - 24 , // 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
" Courier New " ) ; // Font Name
oldfont = ( HFONT ) SelectObject ( hDC , font ) ; // Selects The Font We Want
wglUseFontBitmaps ( hDC , 32 , 96 , base ) ; // Builds 96 Characters Starting At Character 32
SelectObject ( hDC , oldfont ) ; // Selects The Font We Want
DeleteObject ( font ) ; // Delete The Font
}
GLvoid KillFont ( GLvoid ) // Delete The Font List
{
glDeleteLists ( base , 96 ) ; // Delete All 96 Characters
}
GLvoid glPrint ( const char * fmt , . . . ) // Custom GL "Print" Routine
{
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
glPushAttrib ( GL_LIST_BIT ) ; // Pushes The Display List Bits
glListBase ( base - 32 ) ; // Sets The Base Character to 32
glCallLists ( strlen ( text ) , GL_UNSIGNED_BYTE , text ) ; // Draws The Display List Text
glPopAttrib ( ) ; // Pops The Display List Bits
2002-09-18 22:15:49 +00:00
}
int InitGL ( GLvoid ) // All Setup For OpenGL Goes Here
{
glShadeModel ( GL_SMOOTH ) ; // Enable Smooth Shading
glClearColor ( 0.0f , 0.0f , 0.0f , 0.5f ) ; // Black Background
glClearDepth ( 1.0f ) ; // Depth Buffer Setup
glEnable ( GL_DEPTH_TEST ) ; // Enables Depth Testing
glDepthFunc ( GL_LEQUAL ) ; // The Type Of Depth Testing To Do
glHint ( GL_PERSPECTIVE_CORRECTION_HINT , GL_NICEST ) ; // Really Nice Perspective Calculations
2002-10-24 16:39:00 +00:00
BuildFont ( ) ; // Build The Font
2002-09-18 22:15:49 +00:00
return TRUE ; // Initialization Went OK
}
GLvoid KillGLWindow ( GLvoid ) // Properly Kill The Window
{
if ( fullscreen ) // Are We In Fullscreen Mode?
{
//ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
//ShowCursor(TRUE); // Show Mouse Pointer
}
if ( hRC ) // Do We Have A Rendering Context?
{
if ( ! wglMakeCurrent ( NULL , NULL ) ) // Are We Able To Release The DC And RC Contexts?
{
MessageBox ( NULL , " Release Of DC And RC Failed. " , " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
}
if ( ! wglDeleteContext ( hRC ) ) // Are We Able To Delete The RC?
{
MessageBox ( NULL , " Release Rendering Context Failed. " , " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
}
hRC = NULL ; // Set RC To NULL
}
if ( hDC & & ! ReleaseDC ( hWnd , hDC ) ) // Are We Able To Release The DC
{
MessageBox ( NULL , " Release Device Context Failed. " , " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
hDC = NULL ; // Set DC To NULL
}
if ( hWnd & & ! DestroyWindow ( hWnd ) ) // Are We Able To Destroy The Window?
{
MessageBox ( NULL , " Could Not Release hWnd. " , " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
hWnd = NULL ; // Set hWnd To NULL
}
if ( ! UnregisterClass ( " OpenGL " , hInstance ) ) // Are We Able To Unregister Class
{
MessageBox ( NULL , " Could Not Unregister Class. " , " SHUTDOWN ERROR " , MB_OK | MB_ICONINFORMATION ) ;
hInstance = NULL ; // Set hInstance To NULL
}
}
/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color ( 8 / 16 / 24 / 32 ) *
* fullscreenflag - Use Fullscreen Mode ( TRUE ) Or Windowed Mode ( FALSE ) */
BOOL CreateGLWindow ( char * title , int width , int height , int bits , bool fullscreenflag )
{
GLuint PixelFormat ; // Holds The Results After Searching For A Match
WNDCLASS wc ; // Windows Class Structure
DWORD dwExStyle ; // Window Extended Style
DWORD dwStyle ; // Window Style
RECT WindowRect ; // Grabs Rectangle Upper Left / 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
HDC screenDC = NULL ; // Screen Device Context
fullscreen = fullscreenflag ; // Set The Global Fullscreen Flag
if ( fullscreen ) // Attempt Fullscreen Mode?
{
screenDC = GetDC ( NULL ) ;
WindowRect . right = GetDeviceCaps ( screenDC , HORZRES ) ;
WindowRect . bottom = GetDeviceCaps ( screenDC , VERTRES ) ;
ReleaseDC ( NULL , screenDC ) ;
}
hInstance = GetModuleHandle ( NULL ) ; // Grab An Instance For Our Window
wc . style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC ; // Redraw On Size, And Own DC For Window.
wc . lpfnWndProc = ( WNDPROC ) WndProc ; // WndProc Handles Messages
wc . cbClsExtra = 0 ; // No Extra Window Data
wc . cbWndExtra = 0 ; // No Extra Window Data
wc . hInstance = hInstance ; // Set The Instance
wc . hIcon = LoadIcon ( NULL , IDI_WINLOGO ) ; // Load The Default Icon
wc . hCursor = LoadCursor ( NULL , IDC_ARROW ) ; // Load The Arrow Pointer
wc . hbrBackground = NULL ; // No Background Required For GL
wc . lpszMenuName = NULL ; // We Don't Want A Menu
wc . lpszClassName = " OpenGL " ; // Set The Class Name
if ( ! RegisterClass ( & wc ) ) // Attempt To Register The Window Class
{
MessageBox ( NULL , " Failed To Register The Window Class. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
if ( fullscreen ) // Attempt Fullscreen Mode?
{
/*DEVMODE dmScreenSettings; // Device Mode
memset ( & dmScreenSettings , 0 , sizeof ( dmScreenSettings ) ) ; // Makes Sure Memory's Cleared
dmScreenSettings . dmSize = sizeof ( dmScreenSettings ) ; // Size Of The Devmode Structure
dmScreenSettings . dmPelsWidth = width ; // Selected Screen Width
dmScreenSettings . dmPelsHeight = height ; // Selected Screen Height
dmScreenSettings . dmBitsPerPel = bits ; // Selected Bits Per Pixel
dmScreenSettings . dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT ;
// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if ( ChangeDisplaySettings ( & dmScreenSettings , CDS_FULLSCREEN ) ! = DISP_CHANGE_SUCCESSFUL )
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if ( MessageBox ( NULL , " The Requested Fullscreen Mode Is Not Supported By \n Your Video Card. Use Windowed Mode Instead? " , " NeHe GL " , MB_YESNO | MB_ICONEXCLAMATION ) = = IDYES )
{
fullscreen = FALSE ; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox ( NULL , " Program Will Now Close. " , " ERROR " , MB_OK | MB_ICONSTOP ) ;
return FALSE ; // Return 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
// Create The Window
if ( ! ( hWnd = CreateWindowEx ( dwExStyle , // Extended Style For The Window
" OpenGL " , // Class Name
title , // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN , // Required Window Style
0 , 0 , // Window Position
WindowRect . right - WindowRect . left , // Calculate Window Width
WindowRect . bottom - WindowRect . top , // Calculate Window Height
NULL , // No Parent Window
NULL , // No Menu
hInstance , // Instance
NULL ) ) ) // Dont Pass Anything To WM_CREATE
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Window Creation Error. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
static PIXELFORMATDESCRIPTOR pfd = // pfd Tells Windows How We Want Things To Be
{
sizeof ( PIXELFORMATDESCRIPTOR ) , // Size Of This Pixel Format Descriptor
1 , // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER , // Must Support Double Buffering
PFD_TYPE_RGBA , // Request An RGBA Format
bits , // Select Our Color Depth
0 , 0 , 0 , 0 , 0 , 0 , // Color Bits Ignored
0 , // No Alpha Buffer
0 , // Shift Bit Ignored
0 , // No Accumulation Buffer
0 , 0 , 0 , 0 , // Accumulation Bits Ignored
16 , // 16Bit Z-Buffer (Depth Buffer)
0 , // No Stencil Buffer
0 , // No Auxiliary Buffer
PFD_MAIN_PLANE , // Main Drawing Layer
0 , // Reserved
0 , 0 , 0 // Layer Masks Ignored
} ;
if ( ! ( hDC = GetDC ( hWnd ) ) ) // Did We Get A Device Context?
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Can't Create A GL Device Context. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
if ( ! ( PixelFormat = ChoosePixelFormat ( hDC , & pfd ) ) ) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Can't Find A Suitable PixelFormat. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
if ( ! SetPixelFormat ( hDC , PixelFormat , & pfd ) ) // Are We Able To Set The Pixel Format?
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Can't Set The PixelFormat. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
if ( ! ( hRC = wglCreateContext ( hDC ) ) ) // Are We Able To Get A Rendering Context?
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Can't Create A GL Rendering Context. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
if ( ! wglMakeCurrent ( hDC , hRC ) ) // Try To Activate The Rendering Context
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Can't Activate The GL Rendering Context. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
ShowWindow ( hWnd , SW_SHOW ) ; // Show The Window
SetForegroundWindow ( hWnd ) ; // Slightly Higher Priority
SetFocus ( hWnd ) ; // Sets Keyboard Focus To The Window
ReSizeGLScene ( width , height ) ; // Set Up Our Perspective GL Screen
if ( ! InitGL ( ) ) // Initialize Our Newly Created GL Window
{
KillGLWindow ( ) ; // Reset The Display
MessageBox ( NULL , " Initialization Failed. " , " ERROR " , MB_OK | MB_ICONEXCLAMATION ) ;
return FALSE ; // Return FALSE
}
return TRUE ; // Success
}
LRESULT CALLBACK WndProc ( HWND hWnd , // Handle For This Window
UINT uMsg , // Message For This Window
WPARAM wParam , // Additional Message Information
LPARAM lParam ) // Additional Message Information
{
switch ( uMsg ) // Check For Windows Messages
{
case WM_ACTIVATE : // Watch For Window Activate Message
{
if ( ! HIWORD ( wParam ) ) { // Check Minimization State
active = TRUE ; // Program Is Active
} else {
active = FALSE ; // Program Is No Longer Active
}
return 0 ; // Return To The Message Loop
}
case WM_SYSCOMMAND : // Intercept System Commands
{
switch ( wParam ) { // Check System Calls
case SC_SCREENSAVE : // Screensaver Trying To Start?
if ( ! fullscreen ) {
POINT pt ;
GetCursorPos ( & pt ) ;
initCursorPosx = pt . x ;
initCursorPosy = pt . y ;
counter = 5 ;
KillGLWindow ( ) ; // Kill Our Current Window
fullscreen = ! fullscreen ;
// Recreate Our OpenGL Window
if ( ! CreateGLWindow ( " NeHe's OpenGL Framework " , 1024 , 768 , 16 , fullscreen ) )
{
return 0 ; // Quit If Window Was Not Created
}
}
case SC_MONITORPOWER : // Monitor Trying To Enter Powersave?
return 0 ; // Prevent From Happening
}
break ; // Exit
}
case WM_KEYDOWN : // Is A Key Being Held Down?
{
if ( fullscreen ) {
keys [ VK_F1 ] = true ;
}
keys [ wParam ] = TRUE ; // If So, Mark It As TRUE
return 0 ; // Jump Back
}
case WM_KEYUP : // Has A Key Been Released?
{
if ( fullscreen ) {
keys [ VK_F1 ] = true ;
}
keys [ wParam ] = FALSE ; // If So, Mark It As FALSE
return 0 ; // Jump Back
}
case WM_LBUTTONDOWN :
case WM_MBUTTONDOWN :
case WM_RBUTTONDOWN :
case WM_MOUSEMOVE :
{
if ( fullscreen ) {
counter - - ;
if ( counter < = 0 ) {
POINT pt ;
GetCursorPos ( & pt ) ;
int dx = pt . x - initCursorPosx ; if ( dx < 0 ) dx = - dx ;
int dy = pt . y - initCursorPosy ; if ( dy < 0 ) dy = - dy ;
if ( dx > mouse_thresh | | dy > mouse_thresh )
{
ShowCursor ( TRUE ) ; // Show Mouse Pointer
counter = 5 ;
keys [ VK_F1 ] = true ;
}
}
}
return 0 ;
}
case WM_CLOSE : // Did We Receive A Close Message?
{
PostQuitMessage ( 0 ) ; // Send A Quit Message
return 0 ; // Jump Back
}
case WM_SIZE : // Resize The OpenGL Window
{
ReSizeGLScene ( LOWORD ( lParam ) , HIWORD ( lParam ) ) ; // LoWord=Width, HiWord=Height
return 0 ; // Jump Back
}
}
// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc ( hWnd , uMsg , wParam , lParam ) ;
}
DWORD WINAPI win_graphics_event_loop ( LPVOID gi ) {
MSG msg ; // Windows Message Structure
clock_t next_draw_time ;
next_draw_time = clock ( ) ;
fullscreen = FALSE ; // Windowed Mode
// Create Our OpenGL Window
if ( ! CreateGLWindow ( " BOINC Application Window " , ( ( GRAPHICS_INFO * ) gi ) - > xsize ,
( ( GRAPHICS_INFO * ) gi ) - > ysize , 1 , fullscreen ) )
{
return 0 ; // Quit If Window Was Not Created
}
while ( ! done ) // Loop That Runs While done=FALSE
{
if ( PeekMessage ( & msg , NULL , 0 , 0 , PM_REMOVE ) ) // Is There A Message Waiting?
{
if ( msg . message = = WM_QUIT ) { // Have We Received A Quit Message?
done = TRUE ; // If So done=TRUE
}
else { // If Not, Deal With Window Messages
TranslateMessage ( & msg ) ; // Translate The Message
DispatchMessage ( & msg ) ; // Dispatch The Message
}
}
else // If There Are No Messages
{
if ( active ) // Program Active?
{
if ( keys [ VK_ESCAPE ] ) { // Was ESC Pressed?
done = TRUE ; // ESC Signalled A Quit
}
else if ( clock ( ) > next_draw_time ) { // Not Time To Quit, Update Screen
DrawGLScene ( ) ; // Draw The Scene
SwapBuffers ( hDC ) ; // Swap Buffers (Double Buffering). This is taking lots of CPU time
next_draw_time = clock ( ) + ( 1000 / 60 ) ;
}
}
if ( keys [ VK_F1 ] ) { // Is F1 Being Pressed?
counter = 5 ;
keys [ VK_F1 ] = FALSE ; // If So Make Key FALSE
KillGLWindow ( ) ; // Kill Our Current Window
fullscreen = ! fullscreen ; // Toggle Fullscreen / Windowed Mode
if ( ! CreateGLWindow ( " NeHe's OpenGL Framework " , 1024 , 768 , 16 , fullscreen ) )
{
return 0 ; // Quit If Window Was Not Created
}
}
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
}
}
// Shutdown
KillGLWindow ( ) ; // Kill The Window
return ( msg . wParam ) ; // Exit The Program
}
BOOL VerifyPassword ( HWND hwnd )
{ // Under NT, we return TRUE immediately. This lets the saver quit,
// and the system manages passwords. Under '95, we call VerifyScreenSavePwd.
// This checks the appropriate registry key and, if necessary,
// pops up a verify dialog
OSVERSIONINFO osv ; osv . dwOSVersionInfoSize = sizeof ( osv ) ; GetVersionEx ( & osv ) ;
if ( osv . dwPlatformId = = VER_PLATFORM_WIN32_NT ) return TRUE ;
HINSTANCE hpwdcpl = : : LoadLibrary ( " PASSWORD.CPL " ) ;
if ( hpwdcpl = = NULL ) { return TRUE ; }
typedef BOOL ( WINAPI * VERIFYSCREENSAVEPWD ) ( HWND hwnd ) ;
VERIFYSCREENSAVEPWD VerifyScreenSavePwd ;
VerifyScreenSavePwd =
( VERIFYSCREENSAVEPWD ) GetProcAddress ( hpwdcpl , " VerifyScreenSavePwd " ) ;
if ( VerifyScreenSavePwd = = NULL )
{
FreeLibrary ( hpwdcpl ) ; return TRUE ;
}
BOOL bres = VerifyScreenSavePwd ( hwnd ) ; FreeLibrary ( hpwdcpl ) ;
return bres ;
}