///////////////////////////////////////////////////////
gltools.h
///////////////////////////////////////////////////////
#ifndef __GLTOOLS__
#define __GLTOOLS__
#include<windows.h>
#include<stdio.h>
#include"glew.h"
#include"glut.h"
#include"math.h"
#pragma comment( lib , "glew32.lib" )
GLubyte *gltLoadBMP( const char *szFileName , GLint *iWidth , GLint *iHeight , GLint *iComponents , GLenum *eFormat )
{
GLubyte *pbBmp = NULL;//返回值
tagBITMAPFILEHEADER bmpFileHeader;
tagBITMAPINFOHEADER bmpInfoHeader;
tagRGBQUAD bmpRGBQUAD;
int iRead = 0 , sDepth = 0;
FILE *rp = fopen( szFileName , "rb" );
if( NULL == rp )
{
MessageBox( NULL , L"无法打开文件!" , L"GL_Tools" , MB_OK );
return NULL;
}//if
iRead = fread( &bmpFileHeader , sizeof(tagBITMAPFILEHEADER) , 1 , rp );
iRead = fread( &bmpInfoHeader , sizeof(tagBITMAPINFOHEADER) , 1 , rp );
fseek( rp , bmpFileHeader.bfOffBits , SEEK_SET );
*iWidth = bmpInfoHeader.biWidth;
*iHeight = bmpInfoHeader.biHeight;
sDepth = bmpInfoHeader.biBitCount / 8;
if( 24 != bmpInfoHeader.biBitCount && 32 != bmpInfoHeader.biBitCount )
return NULL;
int biSizeImage = bmpInfoHeader.biHeight * ( ( bmpInfoHeader.biWidth * bmpInfoHeader.biBitCount / 8 + 3 ) / 4 ) * 4;
pbBmp = new GLubyte[ biSizeImage ];
if( NULL == pbBmp )
return NULL;
int ret = fread( pbBmp , 1 , biSizeImage , rp );
switch( sDepth )
{
case 3:
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;
break;
case 4:
*eFormat = GL_BGRA_EXT;
*iComponents = GL_RGBA8;
break;
}//switch
fclose( rp );
/*FILE *wp = fopen( "C:\\Documents and Settings\\iI0000002\\My Documents\\Visual Studio 2005\\Projects\\gl_3\\gl_3\\out.bmp" , "wb" );
fwrite( &bmpFileHeader , sizeof(tagBITMAPFILEHEADER) , 1 , wp );
fwrite( &bmpInfoHeader , sizeof(tagBITMAPINFOHEADER) , 1 , wp );
fwrite( pbBmp , bmpInfoHeader.biSizeImage , 1 , wp );
fclose( wp );*/
return pbBmp;
}
#endif
//////////////////////////////////////////////////
draw.h
//////////////////////////////////////////////////
#include"gltools.h"
#define SIZE_SPACE_X 200.0f
#define SIZE_SPACE_Y 90.0f
#define SIZE_SPACE_Z 200.0f
#define STEP_GROUND 25.0f
#define STEP_WALL 100.0f
#define STEP_SKY 5.0f
#define BUFFER_COUNT 7
#define VERTEX_DATA 0
#define TEXTURE_DATA_GROUND 1
#define TEXTURE_DATA_WALL 2
#define TEXTURE_DATA_SKY 3
#define INDEX_DATA_GROUND 4
#define INDEX_DATA_WALL 5
#define INDEX_DATA_SKY 6
GLfloat vertexSpace[ 24 ] = {
-SIZE_SPACE_X , 0 , SIZE_SPACE_Z ,
SIZE_SPACE_X , 0 , SIZE_SPACE_Z ,
SIZE_SPACE_X , 0 , -SIZE_SPACE_Z ,
-SIZE_SPACE_X , 0 , -SIZE_SPACE_Z ,
-SIZE_SPACE_X , SIZE_SPACE_Y , SIZE_SPACE_Z ,
SIZE_SPACE_X , SIZE_SPACE_Y , SIZE_SPACE_Z ,
SIZE_SPACE_X , SIZE_SPACE_Y , -SIZE_SPACE_Z ,
-SIZE_SPACE_X , SIZE_SPACE_Y , -SIZE_SPACE_Z
};
GLuint indexGround[ 4 ] = {
0 , 1 , 2 , 3 //下
};
GLfloat texCoordGround[ 8 ] = {//下
0 , 0 ,
2*SIZE_SPACE_X/STEP_GROUND , 0 ,
2*SIZE_SPACE_X/STEP_GROUND , 2*SIZE_SPACE_Z/STEP_GROUND ,
0 , 2*SIZE_SPACE_Z/STEP_GROUND
};
GLuint indexWall[ 16 ] = {
3 , 2 , 6 , 7 , //后
0 , 1 , 5 , 4 , //前
2 , 1 , 5 , 6 , //右
0 , 3 , 7 , 4 //左
};
GLfloat texCoordWall[ 16 ] = {
0 , 0 ,
2*SIZE_SPACE_X/STEP_WALL , 0 ,
0 , 0 ,
2*SIZE_SPACE_X/STEP_WALL , 0 ,
0 , 2*SIZE_SPACE_Y/STEP_WALL ,
2*SIZE_SPACE_X/STEP_WALL , 2*SIZE_SPACE_Y/STEP_WALL ,
0 , 2*SIZE_SPACE_Y/STEP_WALL ,
2*SIZE_SPACE_X/STEP_WALL , 2*SIZE_SPACE_Y/STEP_WALL
};
GLuint indexSky[ 4 ] = {
4 , 5 , 6 , 7 //上
};
GLfloat texCoordSky[ 16 ] = {//上
0 , 0 ,
0 , 0 ,
0 , 0 ,
0 , 0 ,
0 , 0 ,
1 , 0 ,
1 , 1 ,
0 , 1
};
GLuint vboSpace[ BUFFER_COUNT ] = { 0 };
#define TEXTURE_GROUND 0
#define TEXTURE_WALL 1
#define TEXTURE_SKY 2
#define TEXTURE_COUNT 3
GLuint texObj[ TEXTURE_COUNT ] = { 0 };
const char *szTexFiles[ TEXTURE_COUNT ] = {
"wood.bmp" ,
"wall2.bmp" ,
"sky2.bmp"
};
void DrawSpace()
{
glColor4f( 1 , 1 , 1 , 1 );
glPolygonMode( GL_FRONT_AND_BACK , GL_FILL );
//glBegin( GL_TRIANGLES );
// glVertex3f( 10 , 0 , 0 );
// glVertex3f( 0 , 10 , 0 );
// glVertex3f( 0 , 0 , 10 );
//glEnd();
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ VERTEX_DATA ] );
glVertexPointer( 3 , GL_FLOAT , 0 , 0 );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_GROUND ] );
glTexCoordPointer( 2 , GL_FLOAT , 0 , 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_GROUND ] );
glBindTexture( GL_TEXTURE_2D , texObj[ TEXTURE_GROUND ] );
glDrawElements( GL_QUADS , 4 , GL_UNSIGNED_INT , 0 );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_WALL ] );
glTexCoordPointer( 2 , GL_FLOAT , 0 , 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_WALL ] );
glBindTexture( GL_TEXTURE_2D , texObj[ TEXTURE_WALL ] );
glDrawElements( GL_QUADS , 16 , GL_UNSIGNED_INT , 0 );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_SKY ] );
glTexCoordPointer( 2 , GL_FLOAT , 0 , 0 );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_SKY ] );
glBindTexture( GL_TEXTURE_2D , texObj[ TEXTURE_SKY ] );
glDrawElements( GL_QUADS , 4 , GL_UNSIGNED_INT , 0 );
}
//////////////////////////////////////////////
config.h
//////////////////////////////////////////////
#include"draw.h"
/////////////////////////////
#define START_X 0.0f
#define START_Y -30.0f
#define START_Z -30.0f
#define KEY_STEP 5.0f
/////////////////////////////
GLfloat speeed[ 4 ] = { 0 };
GLint iWin;
GLint mx=0 , my=0;
GLfloat yRot = 0;
GLint iList = 0;
GLint iCount = 0;
void Timer( int value )
{
printf( "%d fps\n" , iCount );
iCount = 0;
glutTimerFunc( 1000 , Timer , 0 );
}
void Display()
{
++iCount;
GLfloat lastMatrix[16];
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glPushMatrix();
glMatrixMode( GL_MODELVIEW );
glGetFloatv( GL_MODELVIEW_MATRIX , lastMatrix );
glLoadIdentity();
glRotatef( yRot , 1 , 0 , 0 );
glMultMatrixf( lastMatrix );
DrawSpace();
glPopMatrix();
glutSwapBuffers();
}
void Reshape( int w , int h )
{
GLfloat fAspect;
if( 0 == h ) h = 1;
glViewport( 0 , 0 , w , h );
fAspect = (GLfloat)w / (GLfloat)h;
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
gluPerspective( 60 , fAspect , 1 , 800 );
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glTranslatef( 0 , START_Y , START_Z );
glutPostRedisplay();
}
void Motion( int x , int y )
{
GLfloat lastMatrix[ 16 ];
glMatrixMode( GL_MODELVIEW );
glGetFloatv( GL_MODELVIEW_MATRIX , lastMatrix );
glLoadIdentity();
yRot += (y - my) / 5;
if( yRot >= 90 )
yRot = 90;
else if( yRot <= -90 )
yRot = -90;
glRotatef( (GLfloat)(x-mx) , 0.0f , 1.0f , 0.0f );
glMultMatrixf(lastMatrix);
glutPostRedisplay();
mx = x;
my = y;
}
void Mouse( int button , int state , int x , int y )
{
if( GLUT_LEFT_BUTTON == button )
{
if( GLUT_DOWN == state )
{
mx = x;
my = y;
}//if
}//if
}
void Keyboard( unsigned char key , int x , int y )
{
GLfloat lastMatrix[16] = {0};
glMatrixMode( GL_MODELVIEW );
glGetFloatv( GL_MODELVIEW_MATRIX , lastMatrix );
glLoadIdentity();
switch( key )
{
case 'w':
glTranslatef( 0 , 0 , KEY_STEP );
break;
case 'a':
glTranslatef( KEY_STEP , 0 , 0 );
break;
case 's':
glTranslatef( 0 , 0 , -KEY_STEP );
break;
case 'd':
glTranslatef( -KEY_STEP , 0 , 0 );
break;
case 'f':
glutFullScreen();
glutSetCursor( GLUT_CURSOR_NONE );
break;
case 'q':
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
glutReshapeWindow( 800 , 600 );
glutPositionWindow( 200 , 100 );
default:
break;
}//switch
glMultMatrixf( lastMatrix );
glutPostRedisplay();
}
static GLfloat stepSlowdown[3] = { 0 };
static GLuint slowdownFlag = 0;
void SlowdownTimer( int value )
{
slowdownFlag = 1;
if( 0 == stepSlowdown[0] && 0 == stepSlowdown[1] && 0 == stepSlowdown[2] )
{
slowdownFlag = 0;
return;
}//if
GLfloat lastMatrix[16] = {0};
glMatrixMode( GL_MODELVIEW );
glGetFloatv( GL_MODELVIEW_MATRIX , lastMatrix );
glLoadIdentity();
glTranslatef( stepSlowdown[0] , stepSlowdown[1] , stepSlowdown[2] );
glMultMatrixf( lastMatrix );
glutPostRedisplay();
if( 0 < stepSlowdown[0] )
{
stepSlowdown[0] -= 0.5;
}//if
else if( 0 > stepSlowdown[0] )
{
stepSlowdown[0] += 0.5;
}
if( 0.001 > stepSlowdown[0] && -0.001 < stepSlowdown[0])
stepSlowdown[0] = 0;
if( 0 < stepSlowdown[2] )
{
stepSlowdown[2] -= 0.5;
}//if
else if( 0 > stepSlowdown[2] )
{
stepSlowdown[2] += 0.5;
}
if( 0.001 > stepSlowdown[2] && -0.001 < stepSlowdown[2])
stepSlowdown[2] = 0;
glutTimerFunc( 30 , SlowdownTimer , 0 );
}
void KeyboardUp( unsigned char key , int x , int y )
{
switch( key )
{
case 'w':
stepSlowdown[2] = KEY_STEP;
if( 0 == slowdownFlag )
{
glutTimerFunc( 1 , SlowdownTimer , 0 );
}//if
break;
case 'a':
stepSlowdown[0] = KEY_STEP;
if( 0 == slowdownFlag )
{
glutTimerFunc( 1 , SlowdownTimer , 0 );
}//if
break;
case 's':
stepSlowdown[2] = -KEY_STEP;
if( 0 == slowdownFlag )
{
glutTimerFunc( 1 , SlowdownTimer , 0 );
}//if
break;
case 'd':
stepSlowdown[0] = -KEY_STEP;
if( 0 == slowdownFlag )
{
glutTimerFunc( 1 , SlowdownTimer , 0 );
}//if
break;
case 'f':
glutFullScreen();
glutSetCursor( GLUT_CURSOR_NONE );
break;
case 'q':
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
glutReshapeWindow( 800 , 600 );
glutPositionWindow( 200 , 100 );
//glutDestroyWindow( iWin );
break;
default:
break;
}//switch
}
////////////////////////////////////////////////
main.cpp
////////////////////////////////////////////////
#include"gltools.h"
#include"config.h"
void Init()
{
glEnable( GL_DEPTH_TEST );
glClearColor( 0 , 0 , 0 , 0 );
//////////////////////////////////////
//纹理初始化
GLubyte *pBytes;
GLint iWidth , iHeight , iComponents;
GLenum eFormat;
glEnable( GL_TEXTURE_2D );
glTexEnvi( GL_TEXTURE_ENV , GL_TEXTURE_ENV_MODE , GL_REPLACE );
glGenTextures( TEXTURE_COUNT , texObj );
for( int i=0; i<TEXTURE_COUNT; ++i )
{
glBindTexture( GL_TEXTURE_2D , texObj[ i ] );
pBytes = gltLoadBMP( szTexFiles[ i ] , &iWidth , &iHeight , &iComponents , &eFormat );
glTexImage2D( GL_TEXTURE_2D , 0 , iComponents , iWidth , iHeight , 0 , eFormat , GL_UNSIGNED_BYTE , pBytes );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_REPEAT );
glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_REPEAT );
delete[] pBytes;
}//for
//////////////////////////////////////
//VBO初始化
glEnableClientState( GL_VERTEX_ARRAY );
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
glGenBuffers( BUFFER_COUNT , vboSpace );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ VERTEX_DATA ] );
glBufferData( GL_ARRAY_BUFFER , sizeof(GLfloat)*24 , vertexSpace , GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_GROUND ] );
glBufferData( GL_ARRAY_BUFFER , sizeof(GLfloat)*8 , texCoordGround , GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_WALL ] );
glBufferData( GL_ARRAY_BUFFER , sizeof(GLfloat)*16 , texCoordWall , GL_STATIC_DRAW );
glBindBuffer( GL_ARRAY_BUFFER , vboSpace[ TEXTURE_DATA_SKY ] );
glBufferData( GL_ARRAY_BUFFER , sizeof(GLfloat)*16 , texCoordSky , GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_GROUND ] );
glBufferData( GL_ELEMENT_ARRAY_BUFFER , sizeof(GLuint)*4 , indexGround , GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_WALL ] );
glBufferData( GL_ELEMENT_ARRAY_BUFFER , sizeof(GLuint)*16 , indexWall , GL_STATIC_DRAW );
glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , vboSpace[ INDEX_DATA_SKY ] );
glBufferData( GL_ELEMENT_ARRAY_BUFFER , sizeof(GLuint)*4 , indexSky , GL_STATIC_DRAW );
//////////////////////////////////////
}
void Exit()
{
glDeleteTextures( TEXTURE_COUNT , texObj );
glDeleteBuffers( BUFFER_COUNT , vboSpace );
}
int main( int argc , char** argv )
{
glutInit( &argc , argv );
glutInitDisplayMode( GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE | GLUT_MULTISAMPLE );
glutInitWindowSize( 800 , 600 );
glutInitWindowPosition( 200 , 100 );
glutCreateWindow( "Tom" );
iWin = glutGetWindow();
glewInit();
glutDisplayFunc( Display );
glutReshapeFunc( Reshape );
glutMouseFunc( Mouse );
glutMotionFunc( Motion );
glutKeyboardFunc( Keyboard );
glutKeyboardUpFunc( KeyboardUp );
//glutTimerFunc( 1000 , Timer , 0 );
Init();
glutMainLoop();
Exit();
return 0;
}