Before anyone accuses of careless cut & paste, I wrote all of this from scratch while currently reading the OpenGL Superbible, Nehe tutorials and Game Tutorials LLC. The problem isnt that I dotn understand the code. The problem is that the compiler doesnt understand me (how great would that be?). Anyways, excuse my arrogance.
Here is my code:
gl_win32_core.h
Code: Select all
//This file contains all of the core Win32/OpenGL function prototypes, system includes and global variables required for setting up a basic
//windowed rendering environment for OpenGL application using Win32.
#ifndef _GL_WIN32_CORE_H_
#define _GL_WIN32_CORE_H_
//Library includes
//#pragma comment(lib, "opengl32.lib")
//#pragma comment(lib, "glu32.lib")
//System includes
#include <windows.h> // Must have for Windows platform builds
#include <tchar.h> // Requires to convert each character in each string argument into a 2 byte character. Win32 treats all string characters as UNICODE.
#include <gl\gl.h> // Microsoft OpenGL headers (version 1.1 by themselves)
#include <gl\glu.h> // OpenGL Utilities
//OpenGL hRC specific
GLfloat windowWidth;
GLfloat windowHeight;
//Win32 specific global variables
static LPCTSTR lpszAppName = L"Swogle";
static HWND g_hWnd; //Window handle
static RECT g_rRect; //Window rendering dimensions
static HDC g_hDC; //GDI hardware device context
static HGLRC g_hRC; //Hardware renedeing contect for OpenGL
static HINSTANCE g_hInstance; //App instance (id)
///////////////////////////////////
//Core Win32 function prototypes
///////////////////////////////////
//WinMain
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
//WindowProc
LRESULT CALLBACK WndProc(HWND hwnd, UINT nMsg, WPARAM wParam, LPARAM lParam);
//Prog main loop
WPARAM MainLoop();
//Resiter and create new window
HWND CreateMyWindow(LPSTR strWindowName, int nWidth, int nHeight);
/////////////////////////////////////
//Core OpenGL function prototypes
////////////////////////////////////
//Set display format
void SetDCPixelFormat();
//Change window size
void ChangeSize(GLsizei w, GLsizei h);
//This draws everything to the screen
void RenderScene();
//Free all memeory associated with the program
void DeInit();
#endif
Code: Select all
//This file contains all of the core Win32/OpenGL function implementations required for setting up a basic
//windowed rendering environment for OpenGL application using Win32.
#include "gl_win32_core.h"
//=======================================================================================================================================================
//=======================================================================================================================================================
//Core Win32 function implementations
//=======================================================================================================================================================
//=======================================================================================================================================================
/////////////////////////////////////
//WinMain function implementation
////////////////////////////////////
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//HWND hWnd; //Local window handle
//Create new window
g_hWnd = CreateMyWindow("SWOGLE 1.0", 800, 600);
//If window handle is invalid, quit the program
if(g_hWnd == NULL)
{
return TRUE;
}
g_hInstance = hInstance;
//Initialize the program here
//Run message loop and return the result
return MainLoop();
}
//////////////////////////////////////////////
//CreateMyWindow() function implementation
//////////////////////////////////////////////
HWND CreateMyWindow(LPCTSTR strWindowName, int nWidth, int nHeight)
{
HWND hWnd; //Local window handle
WNDCLASS wc; //Window class that will be registered
//clear the memory first
memset(&wc, 0, sizeof(wc));
//Set all of the attributes up for the window class & register it
wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC; //CS_OWNDC: Tells Windows to create a device context just for this window
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = g_hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL; //No need for background brush when using OpenGL
wc.lpszMenuName = NULL; //No menus either
wc.lpszClassName = lpszAppName;
//Now, register the windows class with Windows
RegisterClass(&wc);
//Create the main application window
hWnd = CreateWindow(
lpszAppName,
strWindowName,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, //WS_CLIPCHILDREN & WS_CLIPSIBLINGS are used to prevent
CW_USEDEFAULT, //the OpenGL rendering context from rendering into other
CW_USEDEFAULT, //windows. An OpenGL rendering context must be associated
nWidth, //with only one active window at a time.
nHeight,
NULL,
NULL,
g_hInstance,
NULL
);
//If there is no window handle...
if(!hWnd)
{
return NULL;
}
// Show the window
ShowWindow(hWnd, SW_SHOWNORMAL);
// Draw the window
UpdateWindow(hWnd);
//Sets Keyboard Focus To The Window
SetFocus(hWnd);
return hWnd;
}
/////////////////////////////////////////
//WindowProc() function implementation
////////////////////////////////////////
LRESULT CALLBACK WndProc(HWND hWnd,UINT nMsg, WPARAM wParam, LPARAM lParam)
{
switch(nMsg)
{
//Setup the window for OpenGL here
case WM_CREATE:
{
//Store device context
g_hDC = GetDC(hWnd);
//Select the pixel format
SetDCPixelFormat();
//Create the rendering context and make it current
g_hRC = wglCreateContext(g_hDC);
wglMakeCurrent(g_hDC, g_hRC);
//Create a timer that calls specific functions 30 times a second
SetTimer(hWnd, 30, 1, NULL);
return 0;
}
//When the window is destroyed, clean up after OpenGL
case WM_DESTROY:
{
//Kill timer
KillTimer(hWnd, 101);
//Delete any OpenGL-allocated memory here
//Deselect current rendering context and delete it
wglMakeCurrent(g_hDC, NULL);
wglDeleteContext(g_hRC);
//Terminate program after window is destroyed
PostQuitMessage(0);
return 0;
}
//Change window size appropriately (keeping all clipping bounds for the viewport and rendering volume in order)
case WM_SIZE:
{
ChangeSize(LOWORD(lParam), HIWORD(lParam));
return 0;
}
//Call the timer function here. The MoveSquare() function goes here, and after it is called, the window is
//invalidated so that it will be drawn again. This happens 30 times a second.
case WM_TIMER:
{
//Anim code goes here
//Invalidate the rect
InvalidateRect(hWnd, NULL, FALSE);
return 0;
}
//The WM_PAINT message is sent by Windows everytime the screen needs to be updated. And that's what we do here
case WM_PAINT:
{
//Render current scene
RenderScene();
//Swap buffers
SwapBuffers(g_hDC);
//Validate the newly painted client area
ValidateRect(hWnd, NULL);
return 0;
}
default:
{
return DefWindowProc(hWnd, nMsg, wParam, lParam);
}
}
return 0;
}
///////////////////////////////////////
//MainLoop() function implementation
//////////////////////////////////////
WPARAM MainLoop()
{
MSG msg;
while(1)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) //Peek to see if there are any messages in the que...
{
if (!GetMessage(&msg, NULL, 0, 0)) //Same as above, except the message get's removed from the message queue
{
return msg.wParam; //If there is no message to get, return wParam, which returns a 0 upon normal program termination
}
//do the rest
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
//call game logic code here
}
}
//Window cleanup code goes here...
DeInit();
//Return the exit code for the application.
return msg.wParam;
}
//=======================================================================================================================================================
//=======================================================================================================================================================
//Core OpenGL function implementations
//=======================================================================================================================================================
//=======================================================================================================================================================
//////////////////////////////////////////////////////////////////////////
//Hardware device context pixel format setting function implementation
/////////////////////////////////////////////////////////////////////////
void SetDCPixelFormat()
{
int nPixelFormat;
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0,0,0,0,0,0,
0,0,
0,0,0,0,0,
16,
0,
0,
0,
0,
0,0,0
};
//Choose a best matched pixel format fitting the above description
nPixelFormat = ChoosePixelFormat(g_hDC, &pfd);
//Set the pixel format for the HDC
SetPixelFormat(g_hDC, nPixelFormat, &pfd);
}
///////////////////////////////////////////
//RenderScene() function implementation
//////////////////////////////////////////
void RenderScene()
{
//Set the background clearing color to gray
glClearColor(0.25f, 0.25f, 0.25f, 1.0f);
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT);
}
///////////////////////////////////////
//ChangeSize function implementation
//////////////////////////////////////
void ChangeSize(GLsizei w, GLsizei h)
{
GLfloat aspectRatio; //Aspect artio for drawing the window
//Avoid dividing by zero
if(h == 0)
{
h = 1;
}
//Set viewport to window dimenstions (0, 0 is the clipping region; w, h are the width and height of the viewport in pixels
glViewport(0, 0, w, h);
//Reset coordinate system
glMatrixMode(GL_PROJECTION);//Define projection matrix
glLoadIdentity();//Load identity matrix for GL_PROJECTION (reset matrix)
aspectRatio = (GLfloat)w / (GLfloat)h;
if(w <= h)
{
windowWidth = 100;
windowHeight = 100 / aspectRatio;
glOrtho(-100.0, 100.0, -windowHeight, windowHeight, 1.0, -1.0);
}
else
{
windowWidth = 100 * aspectRatio;
windowHeight = 100;
glOrtho(-windowWidth, windowWidth, -100.0, 100.0, 1.0, -1.0);
}
glMatrixMode(GL_MODELVIEW);//Set the matrix mode to effect all of the current geometry that is drawn
glLoadIdentity();//Reset the matrix
}
/////////////////////////////////////////////////
//Free all memeory associated with the program
////////////////////////////////////////////////
void DeInit()
{
//Add all cleanup code associated with the window here
//Unregister the window class
UnregisterClass(lpszAppName, g_hInstance);
}
The error is this:
Code: Select all
1>Compiling...
1>gl_win32_core.cpp
1>Linking...
1>gl_win32_core.obj : error LNK2019: unresolved external symbol "struct HWND__ * __cdecl CreateMyWindow(char *,int,int)" (?CreateMyWindow@@YAPAUHWND__@@PADHH@Z) referenced in function _WinMain@16
1>C:\Users\Vladeta\Desktop\game development\opengl_progs\progs\gl_win32_template\Debug\gl_win32_template.exe : fatal error LNK1120: 1 unresolved externals
My guess is that the cuplrit is my idea of making all of the window and hardware contexts, as well as the application instance, global.
However, seeing as they are declared as static, they should not loose their assigned value. If I declare them as extern, I still get the same error.
Any help is much appreciated.