2012-02-05 21:02:28 -06:00
/*
* This Code Was Created By Jeff Molofee 2000
* A HUGE Thanks To Fredric Echols For Cleaning Up
* And Optimizing The Base Code , Making It More Flexible !
* If You ' ve Found This Code Useful , Please Let Me Know .
* Visit My Site At nehe . gamedev . net
*/
# include <windows.h> // Header File For Windows
# include <gl\gl.h> // Header File For The OpenGL32 Library
# include <gl\glu.h> // Header File For The GLu32 Library
# include <gl\glext.h>
# include "SOIL.h"
# include "libvitaboy.hpp"
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
bool keys [ 256 ] ; // Array Used For The Keyboard Routine
bool active = TRUE ; // Window Active Flag Set To TRUE By Default
bool fullscreen = TRUE ; // Fullscreen Flag Set To Fullscreen Mode By Default
float zoom = - 4 ;
float xrot = 0 ;
float yrot = 0 ;
float zrot = 90 ;
GLuint texture [ 1 ] ; // Storage For One Texture ( NEW )
Mesh_t Mesh ;
LRESULT CALLBACK WndProc ( HWND , UINT , WPARAM , LPARAM ) ; // Declaration For WndProc
int LoadGLTextures ( ) // Load Bitmaps And Convert To Textures
{
/* load an image file directly as a new OpenGL texture */
texture [ 0 ] = SOIL_load_OGL_texture ( " texture.jpg " , SOIL_LOAD_AUTO , SOIL_CREATE_NEW_ID , SOIL_FLAG_INVERT_Y ) ;
if ( texture [ 0 ] = = 0 )
return false ;
// Typical Texture Generation Using Data From The Bitmap
glBindTexture ( GL_TEXTURE_2D , texture [ 0 ] ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
2012-02-05 22:00:17 -06:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT ) ;
2012-02-05 21:02:28 -06:00
return true ; // Return Success
}
void 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
}
int InitGL ( void ) // All Setup For OpenGL Goes Here
{
if ( ! LoadGLTextures ( ) ) // Jump To Texture Loading Routine ( NEW )
{
return FALSE ; // If Texture Didn't Load Return FALSE
}
glEnable ( GL_TEXTURE_2D ) ; // Enable Texture Mapping ( NEW )
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
return TRUE ; // Initialization Went OK
}
int DrawGLScene ( void ) // Here's Where We Do All The Drawing
{
2012-02-05 21:17:48 -06:00
if ( keys [ ' A ' ] ) { if ( zoom < = - 1.0f ) zoom + = 0.05f ; }
if ( keys [ ' S ' ] ) { if ( zoom > = - 10.0f ) zoom - = 0.05f ; }
if ( keys [ VK_UP ] ) { if ( ( xrot - = 1.0f ) < = - 360 ) xrot + = 360 ; }
if ( keys [ VK_DOWN ] ) { if ( ( xrot + = 1.0f ) > = 360 ) xrot - = 360 ; }
2012-02-05 21:02:28 -06:00
if ( keys [ VK_LEFT ] ) { if ( ( yrot - = 1.0f ) < = - 360 ) yrot + = 360 ; }
2012-02-05 21:17:48 -06:00
if ( keys [ VK_RIGHT ] ) { if ( ( yrot + = 1.0f ) > = 360 ) yrot - = 360 ; }
if ( keys [ ' X ' ] ) { if ( ( zrot - = 1.0f ) < = - 360 ) zrot + = 360 ; }
if ( keys [ ' Z ' ] ) { if ( ( zrot + = 1.0f ) > = 360 ) zrot - = 360 ; }
2012-02-05 21:02:28 -06:00
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ; // Clear The Screen And The Depth Buffer
glLoadIdentity ( ) ; // Reset The Current Modelview Matrix
glTranslatef ( 0.0f , 0.0f , zoom ) ; // Move Into The Screen
glRotatef ( xrot , 1.0f , 0.0f , 0.0f ) ;
glRotatef ( yrot , 0.0f , 1.0f , 0.0f ) ;
glRotatef ( zrot , 0.0f , 0.0f , 1.0f ) ;
glBindTexture ( GL_TEXTURE_2D , texture [ 0 ] ) ;
glEnableClientState ( GL_VERTEX_ARRAY ) ;
glEnableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
glVertexPointer ( 3 , GL_FLOAT , offsetof ( Vertex_t , y ) - offsetof ( Vertex_t , x ) - sizeof ( float ) , Mesh . UnclothedVertexData ) ;
glTexCoordPointer ( 2 , GL_FLOAT , offsetof ( TextureVertex_t , v ) - offsetof ( TextureVertex_t , u ) - sizeof ( float ) , Mesh . TextureVertexData ) ;
glDrawElements ( GL_TRIANGLES , Mesh . FaceCount * 3 , GL_UNSIGNED_INT , Mesh . FaceData ) ;
glDisableClientState ( GL_VERTEX_ARRAY ) ;
glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
return TRUE ; // Keep Going
}
void KillGLWindow ( void ) // 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
fullscreen = fullscreenflag ; // Set The Global Fullscreen Flag
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
{
// LoWord Can Be WA_INACTIVE, WA_ACTIVE, WA_CLICKACTIVE,
// The High-Order Word Specifies The Minimized State Of The Window Being Activated Or Deactivated.
// A NonZero Value Indicates The Window Is Minimized.
if ( ( LOWORD ( wParam ) ! = WA_INACTIVE ) & & ! ( ( BOOL ) HIWORD ( wParam ) ) )
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?
case SC_MONITORPOWER : // Monitor Trying To Enter Powersave?
return 0 ; // Prevent From Happening
}
break ; // Exit
}
case WM_CLOSE : // Did We Receive A Close Message?
{
PostQuitMessage ( 0 ) ; // Send A Quit Message
return 0 ; // Jump Back
}
case WM_KEYDOWN : // Is A Key Being Held Down?
{
keys [ wParam ] = TRUE ; // If So, Mark It As TRUE
return 0 ; // Jump Back
}
case WM_KEYUP : // Has A Key Been Released?
{
keys [ wParam ] = FALSE ; // If So, Mark It As FALSE
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 ) ;
}
int WINAPI WinMain ( HINSTANCE hInstance , // Instance
HINSTANCE hPrevInstance , // Previous Instance
LPSTR lpCmdLine , // Command Line Parameters
int nCmdShow ) // Window Show State
{
MSG msg ; // Windows Message Structure
BOOL done = FALSE ; // Bool Variable To Exit Loop
// Ask The User Which Screen Mode They Prefer
if ( MessageBox ( NULL , " Would You Like To Run In Fullscreen Mode? " , " Start FullScreen? " , MB_YESNO | MB_ICONQUESTION ) = = IDNO )
{
fullscreen = FALSE ; // Windowed Mode
}
HANDLE hFile ;
unsigned FileSize ;
uint8_t * InData ;
DWORD bytestransferred ;
hFile = CreateFile ( " mesh.mesh " , GENERIC_READ , FILE_SHARE_READ , NULL , OPEN_EXISTING , FILE_FLAG_SEQUENTIAL_SCAN , NULL ) ;
if ( hFile = = INVALID_HANDLE_VALUE ) {
if ( GetLastError ( ) = = ERROR_FILE_NOT_FOUND ) {
MessageBox ( NULL , " The specified mesh does not exist. " , " Error " , MB_OK ) ;
return - 1 ;
}
MessageBox ( NULL , " The mesh could not be opened for reading. " , " Error " , MB_OK ) ;
return - 1 ;
}
FileSize = GetFileSize ( hFile , NULL ) ;
InData = ( uint8_t * ) malloc ( FileSize ) ;
if ( InData = = NULL ) {
MessageBox ( NULL , " Memory for the mesh could not be allocated. " , " Error " , MB_OK ) ;
return - 1 ;
}
if ( ! ReadFile ( hFile , InData , FileSize , & bytestransferred , NULL ) | | bytestransferred ! = FileSize ) {
MessageBox ( NULL , " The mesh could not be read. " , " Error " , MB_OK ) ;
return - 1 ;
}
CloseHandle ( hFile ) ;
VBFile . set ( InData , FileSize ) ;
ReadMesh ( Mesh ) ;
// Create Our OpenGL Window
if ( ! CreateGLWindow ( " libvitaboy - Renderer " , 640 , 480 , 16 , 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
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ( ( active & & ! DrawGLScene ( ) ) | | keys [ VK_ESCAPE ] ) // Active? Was There A Quit Received?
{
done = TRUE ; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers ( hDC ) ; // Swap Buffers (Double Buffering)
}
if ( keys [ VK_F1 ] ) // Is F1 Being Pressed?
{
keys [ VK_F1 ] = FALSE ; // If So Make Key FALSE
KillGLWindow ( ) ; // Kill Our Current Window
fullscreen = ! fullscreen ; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if ( ! CreateGLWindow ( " NeHe's Solid Object Tutorial " , 640 , 480 , 16 , fullscreen ) )
{
return 0 ; // Quit If Window Was Not Created
}
}
}
}
// Shutdown
KillGLWindow ( ) ; // Kill The Window
return ( msg . wParam ) ; // Exit The Program
}