Original Post
Okay, I'm really struggling here. I'm trying to code OO style in .Net. I have a header file ("glutInput.h") with a class definition containing methods and so on. I then have a C++ file ("glutInput.cpp") containing all the implementation for the methods. When I link them together I have '#include "glutInput.h"' in both my Main.cpp file ( containing the main() entry point ) and my "glutInput.cpp" file. This is how I would normally do it. I get a list of errors. Firstly, even though I have an #ifdef / #endif macro wrapping the header file, it acts as if I have defined a variable in both objects ( it seems to ignore preprocessor macros ). Secondly, all the methods are reported to have not been implemented, even though they have been in "glutInput.cpp". So what am I doing wrong? Main.cpp: glutInput.h: glutInput.cpp:
/*--------------------------------------------------------
Header files required.
--------------------------------------------------------*/
// Windows
#include <windows.h>
// OpenGL
#include <GL/gl.h>
#include <GL/glaux.h>
#include <GL/glu.h>
#include "glut.h"
// C Header files
#include <cmath>
#include <stdio.h>
// Project files
#include "glutInput.h"
/*--------------------------------------------------------
Get rid of the console window.
--------------------------------------------------------*/
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")
/*--------------------------------------------------------
Pi / 180 -> Used to convert degrees to radians.
g_fSpd -> Controls the speed of movement.
--------------------------------------------------------*/
#define piover180 0.017453292519943295769236907684886f
#define g_fSpd 0.03f
/*--------------------------------------------------------
Structures.
--------------------------------------------------------*/
// Vertex Structure
struct tagVERTEX
{
float x, y, z;
float u, v, w;
};
typedef tagVERTEX VERTEX;
typedef tagVERTEX *LPVERTEX;
// Triangle structure
struct tagTRIANGLE
{
VERTEX m_vertex[3];
};
typedef tagTRIANGLE TRIANGLE;
typedef tagTRIANGLE *LPTRIANGLE;
// Sector structure.
struct tagSECTOR
{
int m_nTriangles;
LPTRIANGLE m_lpTriangles;
} g_SSector;
typedef tagSECTOR SECTOR;
typedef tagSECTOR *LPSECTOR;
/*--------------------------------------------------------
Globals used in the running of the program.
--------------------------------------------------------*/
// Is window active?
bool active = true;
// Texture Storage
UINT texture[3];
int filter = 0;
// Position
VERTEX g_Position;
/*--------------------------------------------------------
Callback function primitives for GLUT event handling.
--------------------------------------------------------*/
bool glInitFunc();
void glDisplayFunc();
void glIdleFunc();
void glReshapeFunc( int, int );
/*--------------------------------------------------------
File handling.
--------------------------------------------------------*/
void worldInitFunc();
inline void readLine( FILE*, const char* );
/*--------------------------------------------------------
Other function primitives.
--------------------------------------------------------*/
void glPrint( void*, char* );
bool LoadTextures();
/*--------------------------------------------------------
main()
The main entry point for the program.
--------------------------------------------------------*/
int main( int argc, char** argv )
{
bool bGameMode = ( MessageBox(NULL, "Do you want to enter game mode?", "?Question",
MB_ICONQUESTION | MB_YESNO ) == IDYES );
// Pass in program arguments to GLUT.
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGB );
// Run in full screen...
glutGameModeString( "1024x768:32" );
if ( bGameMode && glutGameModeGet( GLUT_GAME_MODE_POSSIBLE ) )
{
glutEnterGameMode();
}
// ...or in windowed mode.
else
{
glutInitWindowSize( 1024, 768 );
glutCreateWindow( argv[0] );
}
// Call our Init functions.
if( !glInitFunc() )
{
MessageBox( NULL, "Failed to initialise OpenGL", "Error", MB_ICONERROR );
exit( 0 );
}
worldInitFunc();
// Set up the GLUT event handlers.
glutDisplayFunc( glDisplayFunc );
glutIdleFunc ( glIdleFunc );
glutReshapeFunc( glReshapeFunc );
glutKeyboardFunc( glkKeyboardFunc );
glutKeyboardUpFunc( glkKeyboardUpFunc );
glutSpecialFunc( glkSpecialFunc );
glutSpecialUpFunc( glkSpecialUpFunc );
glutPassiveMotionFunc( glmPassiveMotionFunc );
// Start the GLUT main loop running.
glutMainLoop();
// When GLUT finishes running, exit the program
return 0;
}
/*--------------------------------------------------------
glInitFunc()
Sets up OpenGL.
--------------------------------------------------------*/
bool glInitFunc()
{
// Hide the cursor
glutSetCursor( GLUT_CURSOR_NONE );
// Load the texture in
if( !LoadTextures() )
{
return false;
}
// Enable Texture Mapping
glEnable( GL_TEXTURE_2D );
// Use smooth shading model
glShadeModel( GL_SMOOTH );
// Set the background colour to black
glClearColor( 0.5f, 0.5f, 0.5f, 1.0f );
// Set up the depth buffer
glClearDepth( 1.0f );
glEnable( GL_DEPTH_TEST );
// Use the best perspective calculations
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
// Set up fog
glFogi( GL_FOG_MODE, GL_LINEAR );
float fogColor[4]= {0.5f, 0.5f, 0.5f, 1.0f};
glFogfv( GL_FOG_COLOR, fogColor );
glFogf( GL_FOG_DENSITY, 0.35f );
glHint( GL_FOG_HINT, GL_NICEST );
glFogf( GL_FOG_START, 0.0f );
glFogf( GL_FOG_END, 5.0f );
glEnable(GL_FOG);
return true;
}
/*--------------------------------------------------------
glDisplayFunc()
Renders the OpenGL scene each frame.
--------------------------------------------------------*/
void glDisplayFunc()
{
// Clear the screen and depth buffer and reset the
// view matrix.
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
float x, y, z, u, v;
float xtrans = -g_Position.x;
float ztrans = -g_Position.z;
float sceneroty = g_Position.v;
int nTriangles;
glRotatef( g_Position.u, 1.0f, 0.0f, 0.0f );
glRotatef( sceneroty, 0.0f, 1.0f, 0.0f );
glTranslatef( xtrans, -0.5f, ztrans );
glBindTexture( GL_TEXTURE_2D, texture[filter] );
nTriangles = g_SSector.m_nTriangles;
// Draw each triangle
glBegin( GL_TRIANGLES );
for( int i = 0; i < nTriangles; ++i )
{
glNormal3f( 0.0f, 0.0f, 1.0f );
x = g_SSector.m_lpTriangles.m_vertex[0].x;
y = g_SSector.m_lpTriangles.m_vertex[0].y;
z = g_SSector.m_lpTriangles.m_vertex[0].z;
u = g_SSector.m_lpTriangles.m_vertex[0].u;
v = g_SSector.m_lpTriangles.m_vertex[0].v;
glTexCoord2f( u, v ); glVertex3f( x, y, z );
glNormal3f( 0.0f, 0.0f, 1.0f );
x = g_SSector.m_lpTriangles.m_vertex[1].x;
y = g_SSector.m_lpTriangles.m_vertex[1].y;
z = g_SSector.m_lpTriangles.m_vertex[1].z;
u = g_SSector.m_lpTriangles.m_vertex[1].u;
v = g_SSector.m_lpTriangles.m_vertex[1].v;
glTexCoord2f( u, v ); glVertex3f( x, y, z );
glNormal3f( 0.0f, 0.0f, 1.0f );
x = g_SSector.m_lpTriangles.m_vertex[2].x;
y = g_SSector.m_lpTriangles.m_vertex[2].y;
z = g_SSector.m_lpTriangles.m_vertex[2].z;
u = g_SSector.m_lpTriangles.m_vertex[2].u;
v = g_SSector.m_lpTriangles.m_vertex[2].v;
glTexCoord2f( u, v ); glVertex3f( x, y, z );
}
glEnd();
// Swap the screen buffers
glutSwapBuffers();
}
/*--------------------------------------------------------
glIdleFunc()
Carries out backround tasks.
--------------------------------------------------------*/
void glIdleFunc()
{
// WASD control
if( KEYHELD( 'w' ) )
{
g_Position.x += ( float )sin( g_Position.v * piover180 ) * g_fSpd;
g_Position.z -= ( float )cos( g_Position.v * piover180 ) * g_fSpd;
}
if( KEYHELD( 'a' ) )
{
g_Position.x -= ( float )cos( g_Position.v * piover180 ) * g_fSpd;
g_Position.z -= ( float )sin( g_Position.v * piover180 ) * g_fSpd;
}
if( KEYHELD( 's' ) )
{
g_Position.x -= ( float )sin( g_Position.v * piover180 ) * g_fSpd;
g_Position.z += ( float )cos( g_Position.v * piover180 ) * g_fSpd;
}
if( KEYHELD( 'd' ) )
{
g_Position.x += ( float )cos( g_Position.v * piover180 ) * g_fSpd;
g_Position.z += ( float )sin( g_Position.v * piover180 ) * g_fSpd;
}
// Mouselook
g_Position.u += DY();
g_Position.v += DX();
// Filter control.
if( KEY( 'f' ) )
{
filter = ( filter + 1 ) % 3;
}
// Exit if ALT-F4 is pressed.
if( ALT() && SPKEY( GLUT_KEY_F4 ) )
{
exit( 0 );
}
// Update display
glutPostRedisplay();
}
/*--------------------------------------------------------
glReshapeFunc()
Gets called if the window is resized. Can be used
to keep the scene in proportion.
--------------------------------------------------------*/
void glReshapeFunc( int width, int height )
{
// Avoid divide by zero error
if( 0 == height )
{
height = 1;
}
// Reset the current viewport
glViewport( 0, 0, width, height );
// Reset the projection matrix
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
// Calculate the Aspect Ratio of the window
gluPerspective( 45.0f, ( float )width / ( float )height, 0.1f, 100.0f );
// Reset the modelview matrix
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
}
/*--------------------------------------------------------
LoadBMP()
Loads a bitmap into memory.
--------------------------------------------------------*/
AUX_RGBImageRec* LoadBMP( char* filename )
{
FILE* file = NULL;
// Check specified file exists
if( !filename )
{
return NULL;
}
// Open the file
file = fopen( filename, "r" );
// Check file exists
if( !file )
{
return NULL;
}
// Load the bitmap
fclose( file );
return auxDIBImageLoad( filename );
}
/*--------------------------------------------------------
LoadTextures()
Loads textures into memory.
--------------------------------------------------------*/
bool LoadTextures()
{
// Switch to return.
bool status = false;
// Holds the texture data.
AUX_RGBImageRec* TextureImage;
// Load the bitmap.
if( TextureImage = LoadBMP( "./Runtime/Tim.bmp" ) )
{
status = true;
// Create the textures
glGenTextures( 3, &texture[0] );
// Create nearest filtered texture.
glBindTexture( GL_TEXTURE_2D, texture[2] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY,
0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data );
// Create linear filtered texture.
glBindTexture( GL_TEXTURE_2D, texture[1] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage->sizeX, TextureImage->sizeY,
0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data );
// Create mipmapped texture.
glBindTexture( GL_TEXTURE_2D, texture[0] );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
gluBuild2DMipmaps( GL_TEXTURE_2D, 3, TextureImage->sizeX, TextureImage->sizeY,
GL_RGB, GL_UNSIGNED_BYTE, TextureImage->data );
}
// Free up texture memory.
if( TextureImage )
{
if( TextureImage->data )
{
free( TextureImage->data );
}
free( TextureImage );
}
return status;
}
/*--------------------------------------------------------
readLine()
Reads a line from a text file into memory.
--------------------------------------------------------*/
inline void readLine( FILE* f, char* string )
{
do
{
fgets( string, 255, f );
}
while ( ( '/' == string[0] ) || ( '\n' == string[0] ) );
}
/*--------------------------------------------------------
worldInitFunc()
Loads the world data into memory.
--------------------------------------------------------*/
void worldInitFunc()
{
FILE *file;
int cTriangles;
char sLine[255];
// Load the world data file
file = fopen( "./Runtime/world.lvl", "rt" );
// Get the number of polygons
readLine( file, sLine );
sscanf( sLine, "NUMPOLLIES %d\n", &cTriangles );
g_SSector.m_lpTriangles = new TRIANGLE[cTriangles];
g_SSector.m_nTriangles = cTriangles;
// Read in all the triangle data.
for( int i = 0; i < cTriangles; ++i )
{
for( int j = 0; j < 3; ++j )
{
readLine( file, sLine );
sscanf( sLine, "%f %f %f %f %f",
&g_SSector.m_lpTriangles.m_vertex[j].x,
&g_SSector.m_lpTriangles.m_vertex[j].y,
&g_SSector.m_lpTriangles.m_vertex[j].z,
&g_SSector.m_lpTriangles.m_vertex[j].u,
&g_SSector.m_lpTriangles.m_vertex[j].v );
}
}
// Close the file
fclose( file );
}
/*--------------------------------------------------------
glPrint()
Prints text to the screen.
--------------------------------------------------------*/
void glPrint( void* font, const char* string )
{
char* p = ( char* ) string;
while( '\0' != *p )
{
glutBitmapCharacter( font, *p++ );
}
}
/*--------------------------------------------------------
glutInput.h
Holds all data structures and macros used for input
detection.
--------------------------------------------------------*/
// Include only one
#ifndef GLUT_INPUT_INCLUDED
#define GLUT_INPUT_INCLUDED
/*--------------------------------------------------------
The keymap data structure.
--------------------------------------------------------*/
struct tagKEYS
{
// Keymaps
bool m_abDown[256];
bool m_abHeld[256];
bool m_abSpecial[108];
bool m_abSpheld[108];
bool m_bAlt, m_bCtrl, m_bShift;
// Mouse state
int m_iX, m_iY, m_iDx, m_iDy;
// Callback function primitives
static void glkKeyboard( unsigned char, int, int );
static void glkKeyboardUp( unsigned char, int, int );
static void glkSpecial( int, int, int );
static void glkSpecialUp( int, int, int );
static void glkGetActive();
static void glmPassiveMotion( int, int );
// Macro primitives
inline bool glkKey( unsigned char );
inline bool glkSpKey( unsigned char );
inline bool glkKeyHeld( unsigned char );
inline bool glkSpKeyHeld( unsigned char );
inline bool glkAlt();
inline bool glkCtrl();
inline bool glkShift();
inline int glmDx();
inline int glmDy();
} g_SKeymap;
// Couple of standard type definitions
typedef tagKEYS KEYS;
typedef tagKEYS *LPKEYS;
// Define some Macros
#define glkKeyboardFunc tagKEYS::glkKeyboard
#define glkKeyboardUpFunc tagKEYS::glkKeyboardUp
#define glkSpecialFunc tagKEYS::glkSpecial
#define glkSpecialUpFunc tagKEYS::glkSpecialUp
#define glmPassiveMotionFunc tagKEYS::glmPassiveMotion
#define KEY g_SKeymap.glkKey
#define KEYHELD g_SKeymap.glkKeyHeld
#define SPKEY g_SKeymap.glkSpKey
#define SPKEYHELD g_SKeymap.glkSpKeyHeld
#define ALT g_SKeymap.glkAlt
#define CTRL g_SKeymap.glkCtrl
#define SHIFT g_SKeymap.glkShift
#define DX g_SKeymap.glmDx
#define DY g_SKeymap.glmDy
// End include only once
#endif
/*--------------------------------------------------------
glutInput.cpp
Implementations of the macros and callback
functions.
--------------------------------------------------------*/
/*--------------------------------------------------------
Required header files.
--------------------------------------------------------*/
#include "glut.h"
#include "glutInput.h"
/*--------------------------------------------------------
Macros to be used to aid input detection code.
--------------------------------------------------------*/
// Key pressed, not held down.
// ( Only returns true in the frame that key is pressed )
bool tagKEYS::glkKey( unsigned char k )
{
if ( ( m_abDown[k] ) && !( m_abHeld[k] ) )
{
m_abHeld[k] = true;
return true;
}
return false;
}
// Key held down.
bool tagKEYS::glkKeyHeld( unsigned char k )
{
return ( m_abDown[k] );
}
// Special key down.
bool tagKEYS::glkSpKey( unsigned char k )
{
if ( ( m_abSpecial[k] ) && !( m_abSpheld[k] ) )
{
m_abSpheld[k] = true;
return true;
}
return false;
}
// Special key held.
bool tagKEYS::glkSpKeyHeld( unsigned char k )
{
return ( m_abSpecial[k] );
}
// ALT, CTRL and SHIFT
bool tagKEYS::glkAlt()
{
return ( m_bAlt );
}
bool tagKEYS::glkCtrl()
{
return ( m_bCtrl );
}
bool tagKEYS::glkShift()
{
return ( m_bShift );
}
// Change in X and Y
int tagKEYS::glmDx()
{
int temp = m_iDx;
m_iDx = 0;
return temp;
}
int tagKEYS::glmDy()
{
int temp = m_iDy;
m_iDy = 0;
return temp;
}
/*--------------------------------------------------------
The following functions are passed into the glut as
event handlers. They handle all the input detection
for the program.
//------------------------------------------------------//
GetActive()
Gets the state of Alt, Ctrl and Shift keys.
--------------------------------------------------------*/
void tagKEYS::glkGetActive()
{
if( glutGetModifiers() & GLUT_ACTIVE_ALT )
{
g_SKeymap.m_bAlt = true;
}
else
{
g_SKeymap.m_bAlt = false;
}
if( glutGetModifiers() & GLUT_ACTIVE_CTRL )
{
g_SKeymap.m_bCtrl = true;
}
else
{
g_SKeymap.m_bCtrl = false;
}
if( glutGetModifiers() & GLUT_ACTIVE_SHIFT )
{
g_SKeymap.m_bShift = true;
}
else
{
g_SKeymap.m_bShift = false;
}
}
/*--------------------------------------------------------
Keyboard()
Sets a key in the key matrix to true when a key is
pressed.
--------------------------------------------------------*/
void glkKeyboardFunc( unsigned char k, int x, int y )
{
// Indicate that key is down.
g_SKeymap.m_abDown[k] = true;
// Check for other keys.
glkGetActive();
}
/*--------------------------------------------------------
KeyboardUp()
Sets a key in the key matrix to false when a key is
released.
--------------------------------------------------------*/
void glkKeyboardUpFunc( unsigned char k, int x, int y )
{
// Indicate that key is up.
g_SKeymap.m_abDown[k] = false;
g_SKeymap.m_abHeld[k] = false;
// Check for other keys.
glkGetActive();
}
/*--------------------------------------------------------
Special()
Sets a key in the key matrix to true when a key is
pressed. Also exits the program if Alt-F4 is being
held.
--------------------------------------------------------*/
void glkSpecialFunc( int k, int x, int y )
{
// Indicate which special key is down.
g_SKeymap.m_abSpecial[k] = true;
// Check for other keys.
glkGetActive();
}
/*--------------------------------------------------------
SpecialUp()
Sets a key in the key matrix to false when a key is
released.
--------------------------------------------------------*/
void glkSpecialUpFunc( int k, int x, int y )
{
// Indicate which special key is up.
g_SKeymap.m_abSpecial[k] = false;
g_SKeymap.m_abSpheld[k] = false;
// Check for other keys.
glkGetActive();
}
/*--------------------------------------------------------
PassiveMotion()
Keeps track of the change in mouse motion.
--------------------------------------------------------*/
void glmPassiveMotionFunc( int x, int y )
{
// Update the change in mouse position.
g_SKeymap.m_iDx = x - g_SKeymap.m_iX;
g_SKeymap.m_iDy = y - g_SKeymap.m_iY;
// looping mouse
if( x >= glutGet( GLUT_WINDOW_WIDTH ) - 10 )
{
x = 11;
glutWarpPointer( x, y );
}
if( x <= 10 )
{
x = glutGet( GLUT_WINDOW_WIDTH ) - 11;
glutWarpPointer( x, y );
}
if( y >= glutGet( GLUT_WINDOW_HEIGHT ) - 10 )
{
y = 11;
glutWarpPointer( x, y );
}
if( y <= 10 )
{
y = glutGet( GLUT_WINDOW_HEIGHT ) - 11;
glutWarpPointer( x, y );
}
// Update new coordinates.
g_SKeymap.m_iX = x;
g_SKeymap.m_iY = y;
}