/* * This code was created by Jeff Molofee '99 * (ported to Linux/SDL by Ti Leggett '01) * * If you've found this code useful, please let me know. * * Visit Jeff at http://nehe.gamedev.net/ * * or for port-specific comments, questions, bugreports etc. * email to leggett@eecs.tulane.edu */ #include #include #include #include #include #include #include "glQuaternion.h" using namespace std; /* screen width, height, and bit depth */ #define SCREEN_WIDTH 640 #define SCREEN_HEIGHT 480 #define SCREEN_BPP 16 #define PI 3.14159265358797932384626433832795 /* Set up some booleans */ #define TRUE 1 #define FALSE 0 /* This is our SDL surface */ SDL_Surface *surface; SDL_Window *mw; /* Whether or not lighting is on */ int light = FALSE; GLfloat xrot; /* X Rotation */ GLfloat yrot; /* Y Rotation */ GLfloat xspeed; /* X Rotation Speed */ GLfloat yspeed; /* Y Rotation Speed */ GLfloat z = -5.0f; /* Depth Into The Screen */ glQuaternion q4; //This quaternion will hold the current angle configuration /* Ambient Light Values ( NEW ) */ GLfloat LightAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f }; /* Diffuse Light Values ( NEW ) */ GLfloat LightDiffuse[] = { 0.0f, 0.0f, 0.0f, 1.0f }; /* Light Position ( NEW ) */ GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f, 1.0f }; //the 1 is just a flag that says that position given is the 3-d coordinates of the light GLuint filter; /* Which Filter To Use */ GLuint texture[4]; /* Storage for 3 textures */ /* function to release/destroy our resources and restoring the old desktop */ void Quit( int returnCode ) { /* clean up the window */ SDL_Quit( ); /* and exit appropriately */ exit( returnCode ); } /* function to load in bitmap as a GL texture */ int LoadGLTextures( ) { /* Status indicator */ int Status = FALSE; /* Create storage space for the texture */ SDL_Surface *TextureImage[2]; /* Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit */ if ( ( TextureImage[0] = SDL_LoadBMP( "data/crate.bmp" ) ) ) { /* Set the status to true */ Status = TRUE; /* Create The Texture */ glGenTextures( 4, &texture[0] ); /* Load in texture 1 */ /* Typical Texture Generation Using Data From The Bitmap */ glBindTexture( GL_TEXTURE_2D, texture[0] ); /* Generate The Texture */ glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage[0]->w, TextureImage[0]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, TextureImage[0]->pixels ); /* Nearest Filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); /* Load in texture 2 */ /* Typical Texture Generation Using Data From The Bitmap */ glBindTexture( GL_TEXTURE_2D, texture[1] ); /* Linear Filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); /* Generate The Texture */ glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage[0]->w, TextureImage[0]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, TextureImage[0]->pixels ); /* Load in texture 3 */ /* Typical Texture Generation Using Data From The Bitmap */ glBindTexture( GL_TEXTURE_2D, texture[2] ); /* Mipmapped Filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); /* Generate The MipMapped Texture ( NEW ) */ glTexParameteri(GL_TEXTURE_2D,GL_GENERATE_MIPMAP,GL_TRUE); } TextureImage[1] = SDL_LoadBMP( "data/p1.bmp" ); glBindTexture( GL_TEXTURE_2D, texture[3] ); /* Generate The Texture */ glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage[1]->w, TextureImage[1]->h, 0, GL_BGR, GL_UNSIGNED_BYTE, TextureImage[1]->pixels ); /* Nearest Filtering */ glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); /* Free up any memory we may have used */ if ( TextureImage[0] ) { SDL_FreeSurface( TextureImage[0] ); SDL_FreeSurface( TextureImage[1] ); } return Status; } /* function to reset our viewport after a window resize */ int resizeWindow( int width, int height ) { /* Height / width ration */ GLfloat ratio; /* Protect against a divide by zero */ if ( height == 0 ) height = 1; ratio = ( GLfloat )width / ( GLfloat )height; /* Setup our viewport. */ glViewport( 0, 0, ( GLint )width, ( GLint )height ); /* change to the projection matrix and set our viewing volume. */ glMatrixMode( GL_PROJECTION ); glLoadIdentity( ); /* Set our perspective */ glFrustum (-tan(45.0/360*PI)*0.1*ratio,tan(45.0/360*PI)*0.1*ratio,-tan(45.0/360*PI)*0.1,tan(45.0/360*PI)*0.1,0.1,100); /* Make sure we're chaning the model view and not the projection */ glMatrixMode( GL_MODELVIEW ); /* Reset The View */ glLoadIdentity( ); return( TRUE ); } /* function to handle key press events */ void handleKeyPress( SDL_Keysym *keysym ) { switch ( keysym->sym ) { case SDLK_ESCAPE: /* ESC key was pressed */ Quit( 0 ); break; case SDLK_f: /* 'f' key was pressed * this pages through the different filters */ filter = ( ++filter ) % 3; break; case SDLK_l: /* 'l' key was pressed * this toggles the light */ light = !light; if ( !light ) glDisable( GL_LIGHTING ); else glEnable( GL_LIGHTING ); break; case SDLK_PAGEUP: /* PageUp key was pressed * this zooms into the scene */ z -= 0.02f; break; case SDLK_PAGEDOWN: /* PageDown key was pressed * this zooms out of the scene */ z += 0.02f; break; case SDLK_UP: /* Up arrow key was pressed * this affects the x rotation */ // xspeed -= 0.01f; xrot = -0.1; yrot = 0; break; case SDLK_DOWN: /* Down arrow key was pressed * this affects the x rotation */ // xspeed += 0.01f; xrot = 0.1; yrot = 0; break; case SDLK_RIGHT: /* Right arrow key was pressed * this affects the y rotation */ // yspeed += 0.01f; yrot = 0.1; xrot = 0; break; case SDLK_LEFT: /* Left arrow key was pressed * this affects the y rotation */ // yspeed -= 0.01f; yrot-= 0.1; xrot = 0; break; default: break; } return; } /* general OpenGL initialization function */ int initGL( GLvoid ) { /* Load in the texture */ if ( !LoadGLTextures( ) ) return FALSE; /* Enable Texture Mapping ( NEW ) */ glEnable( GL_TEXTURE_2D ); /* Enable smooth shading */ glShadeModel( GL_SMOOTH ); /* Set the background black */ glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); /* Depth buffer setup */ glClearDepth( 1.0f ); /* Enables Depth Testing */ glEnable( GL_DEPTH_TEST ); /* The Type Of Depth Test To Do */ glDepthFunc( GL_LEQUAL ); /* Really Nice Perspective Calculations */ glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST ); /* Setup The Ambient Light */ glLightfv( GL_LIGHT1, GL_AMBIENT, LightAmbient ); /* Setup The Diffuse Light */ glLightfv( GL_LIGHT1, GL_DIFFUSE, LightDiffuse ); /* Position The Light */ glLightfv( GL_LIGHT1, GL_POSITION, LightPosition ); /* Enable Light One */ glEnable( GL_LIGHT1 ); q4.CreateFromAxisAngle(0,0,0,0); //Initializes the quaternion to no rotation return( TRUE ); } /* Here goes our drawing code */ int drawGLScene( GLvoid ) { /* These are to calculate our fps */ static GLint T0 = 0; static GLint Frames = 0; /* Clear The Screen And The Depth Buffer */ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); /* Reset the view */ glLoadIdentity( ); glBindTexture( GL_TEXTURE_2D, texture[3] ); glColor3f (1,1,1); /* Start Drawing Quads */ glBegin( GL_QUADS ); /* Front Face */ /* Normal Pointing Towards Viewer */ /* Point 1 (Front) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 60.0f, 60.0f, -100.0f ); /* Point 2 (Front) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -60.0f, 60.0f, -100.0f ); /* Point 3 (Front) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -60.0f, -60.0f, -100.0f ); /* Point 4 (Front) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 60.0f, -60.0f, -100.0f ); glEnd (); /* Translate Into/Out Of The Screen By z */ glTranslatef( 0.0f, 0.0f, z ); glQuaternion q1, q2, q3; q1.CreateFromAxisAngle (1,0,0,xrot); //rotate xrot degrees around x-axis q2.CreateFromAxisAngle (0,1,0,yrot); //rotate yrot degrees around the y-axis GLfloat pm[16]; q4 = q1*q2*q4; q4.Normalize(); //make the absolute value one q4.CreateMatrix (pm); glMultMatrixf (pm); // glRotatef( xrot, 1.0f, 0.0f, 0.0f); /* Rotate On The X Axis By xrot */ // glRotatef( yrot, 0.0f, 1.0f, 0.0f); /* Rotate On The Y Axis By yrot */ /* Select A Texture Based On filter */ glBindTexture( GL_TEXTURE_2D, texture[filter] ); glColor3f (1,1,1); /* Start Drawing Quads */ glBegin( GL_QUADS ); /* Front Face */ /* Normal Pointing Towards Viewer */ glNormal3f( 0.0f, 0.0f, 1.0f ); /* Point 1 (Front) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f ); /* Point 2 (Front) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 1.0f ); /* Point 3 (Front) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); /* Point 4 (Front) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, 1.0f ); /* Back Face */ /* Normal Pointing Away From Viewer */ glNormal3f( 0.0f, 0.0f, -1.0f); /* Point 1 (Back) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.0f ); /* Point 2 (Back) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, -1.0f ); /* Point 3 (Back) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, -1.0f ); /* Point 4 (Back) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, -1.0f ); /* Top Face */ /* Normal Pointing Up */ glNormal3f( 0.0f, 1.0f, 0.0f ); /* Point 1 (Top) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, -1.0f ); /* Point 2 (Top) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, 1.0f, 1.0f ); /* Point 3 (Top) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); /* Point 4 (Top) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, -1.0f ); /* Bottom Face */ /* Normal Pointing Down */ glNormal3f( 0.0f, -1.0f, 0.0f ); /* Point 1 (Bottom) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, -1.0f, -1.0f ); /* Point 2 (Bottom) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, -1.0f, -1.0f ); /* Point 3 (Bottom) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 1.0f ); /* Point 4 (Bottom) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f ); /* Right face */ /* Normal Pointing Right */ glNormal3f( 1.0f, 0.0f, 0.0f); /* Point 1 (Right) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, -1.0f ); /* Point 2 (Right) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, -1.0f ); /* Point 3 (Right) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f, 1.0f, 1.0f ); /* Point 4 (Right) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, 1.0f ); /* Left Face*/ /* Normal Pointing Left */ glNormal3f( -1.0f, 0.0f, 0.0f ); /* Point 1 (Left) */ glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.0f ); /* Point 2 (Left) */ glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, 1.0f ); /* Point 3 (Left) */ glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, 1.0f ); /* Point 4 (Left) */ glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f, 1.0f, -1.0f ); glEnd(); /* Draw it to the screen */ SDL_GL_SwapWindow(mw); /* Gather our frames per second */ Frames++; { GLint t = SDL_GetTicks(); if (t - T0 >= 5000) { GLfloat seconds = (t - T0) / 1000.0; GLfloat fps = Frames / seconds; printf("%d frames in %g seconds = %g FPS\n", Frames, seconds, fps); T0 = t; Frames = 0; } } #ifdef _COMMENTAP_ xrot += xspeed; /* Add xspeed To xrot */ yrot += yspeed; /* Add yspeed To yrot */ #endif return( TRUE ); } int main( int argc, char **argv ) { /* Flags to pass to SDL_SetVideoMode */ int videoFlags; /* main loop variable */ int done = FALSE; /* used to collect events */ SDL_Event event; /* this holds some info about our display */ /* whether or not the window is active */ int isActive = TRUE; /* initialize SDL */ if ( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { fprintf( stderr, "Video initialization failed: %s\n", SDL_GetError( ) ); Quit( 1 ); } /* Fetch the video info */ SDL_Init(SDL_INIT_VIDEO); SDL_GL_SetAttribute (SDL_GL_CONTEXT_MAJOR_VERSION,2); SDL_GL_SetAttribute (SDL_GL_CONTEXT_MINOR_VERSION,1); GLenum my_vertex_shader; my_vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB); /* get a SDL surface */ mw = SDL_CreateWindow ("Box",SDL_WINDOWPOS_UNDEFINED,SDL_WINDOWPOS_UNDEFINED,SCREEN_WIDTH,SCREEN_HEIGHT,SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN); SDL_GL_CreateContext (mw); SDL_GL_SetSwapInterval (1); /* Verify there is a surface */ /* initialize OpenGL */ initGL( ); /* resize the initial window */ resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT ); /* wait for events */ while ( !done ) { /* handle the events in the queue */ while ( SDL_PollEvent( &event ) ) { switch( event.type ) { case SDL_KEYDOWN: /* handle key presses */ handleKeyPress( &event.key.keysym ); break; case SDL_QUIT: /* handle quit requests */ done = 1; break; default: break; } } /* draw the scene */ if ( isActive ) drawGLScene( ); } /* clean ourselves up and exit */ Quit( 0 ); /* Should never get here */ return( 0 ); }