Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

sdl_gl_test.c

Go to the documentation of this file.
00001 /*
00002  * SDL OpenGL Tutorial.
00003  * (c) Michael Vance, 2000
00004  * briareos@lokigames.com
00005  *
00006  * Distributed under terms of the LGPL. 
00007  */
00008 
00009 #include <SDL/SDL.h>
00010 #include <GL/gl.h>
00011 #include <GL/glu.h>
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 
00016 static GLboolean should_rotate = GL_TRUE;
00017 
00018 static void quit_tutorial( int code )
00019 {
00020     /*
00021      * Quit SDL so we can release the fullscreen
00022      * mode and restore the previous video settings,
00023      * etc.
00024      */
00025     SDL_Quit( );
00026 
00027     /* Exit program. */
00028     exit( code );
00029 }
00030 
00031 static void handle_key_down( SDL_keysym* keysym )
00032 {
00033 
00034     /* 
00035      * We're only interested if 'Esc' has
00036      * been presssed.
00037      *
00038      * EXERCISE: 
00039      * Handle the arrow keys and have that change the
00040      * viewing position/angle.
00041      */
00042     switch( keysym->sym ) {
00043         case SDLK_ESCAPE:
00044             quit_tutorial( 0 );
00045             break;
00046         case SDLK_SPACE:
00047             should_rotate = !should_rotate;
00048             break;
00049         default:
00050             break;
00051     }
00052 
00053 }
00054 
00055 static void process_events( void )
00056 {
00057     /* Our SDL event placeholder. */
00058     SDL_Event event;
00059 
00060     /* Grab all the events off the queue. */
00061     while( SDL_PollEvent( &event ) ) {
00062 
00063         switch( event.type ) {
00064             case SDL_KEYDOWN:
00065                 /* Handle key presses. */
00066                 handle_key_down( &event.key.keysym );
00067                 break;
00068             case SDL_QUIT:
00069                 /* Handle quit requests (like Ctrl-c). */
00070                 quit_tutorial( 0 );
00071                 break;
00072         }
00073 
00074     }
00075 
00076 }
00077 
00078 static void draw_screen( void )
00079 {
00080     /* Our angle of rotation. */
00081     static float angle = 0.0f;
00082 
00083     /*
00084      * EXERCISE:
00085      * Replace this awful mess with vertex
00086      * arrays and a call to glDrawElements.
00087      *
00088      * EXERCISE:
00089      * After completing the above, change
00090      * it to use compiled vertex arrays.
00091      *
00092      * EXERCISE:
00093      * Verify my windings are correct here ;).
00094      */
00095     static GLfloat v0[] = { -1.0f, -1.0f,  1.0f };
00096     static GLfloat v1[] = {  1.0f, -1.0f,  1.0f };
00097     static GLfloat v2[] = {  1.0f,  1.0f,  1.0f };
00098     static GLfloat v3[] = { -1.0f,  1.0f,  1.0f };
00099     static GLfloat v4[] = { -1.0f, -1.0f, -1.0f };
00100     static GLfloat v5[] = {  1.0f, -1.0f, -1.0f };
00101     static GLfloat v6[] = {  1.0f,  1.0f, -1.0f };
00102     static GLfloat v7[] = { -1.0f,  1.0f, -1.0f };
00103     static GLubyte red[]    = { 255,   0,   0, 255 };
00104     static GLubyte green[]  = {   0, 255,   0, 255 };
00105     static GLubyte blue[]   = {   0,   0, 255, 255 };
00106     static GLubyte white[]  = { 255, 255, 255, 255 };
00107     static GLubyte yellow[] = {   0, 255, 255, 255 };
00108     static GLubyte black[]  = {   0,   0,   0, 255 };
00109     static GLubyte orange[] = { 255, 255,   0, 255 };
00110     static GLubyte purple[] = { 255,   0, 255,   0 };
00111 
00112     /* Clear the color and depth buffers. */
00113     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00114 
00115     /* We don't want to modify the projection matrix. */
00116     glMatrixMode( GL_MODELVIEW );
00117     glLoadIdentity( );
00118 
00119     /* Move down the z-axis. */
00120     glTranslatef( 0.0, 0.0, -5.0 );
00121 
00122     /* Rotate. */
00123     glRotatef( angle, 0.0, 1.0, 0.0 );
00124 
00125     if( should_rotate ) {
00126 
00127         if( ++angle > 360.0f ) {
00128             angle = 0.0f;
00129         }
00130 
00131     }
00132 
00133     /* Send our triangle data to the pipeline. */
00134     glBegin( GL_TRIANGLES );
00135 
00136     glColor4ubv( red );
00137     glVertex3fv( v0 );
00138     glColor4ubv( green );
00139     glVertex3fv( v1 );
00140     glColor4ubv( blue );
00141     glVertex3fv( v2 );
00142 
00143     glColor4ubv( red );
00144     glVertex3fv( v0 );
00145     glColor4ubv( blue );
00146     glVertex3fv( v2 );
00147     glColor4ubv( white );
00148     glVertex3fv( v3 );
00149 
00150     glColor4ubv( green );
00151     glVertex3fv( v1 );
00152     glColor4ubv( black );
00153     glVertex3fv( v5 );
00154     glColor4ubv( orange );
00155     glVertex3fv( v6 );
00156 
00157     glColor4ubv( green );
00158     glVertex3fv( v1 );
00159     glColor4ubv( orange );
00160     glVertex3fv( v6 );
00161     glColor4ubv( blue );
00162     glVertex3fv( v2 );
00163 
00164     glColor4ubv( black );
00165     glVertex3fv( v5 );
00166     glColor4ubv( yellow );
00167     glVertex3fv( v4 );
00168     glColor4ubv( purple );
00169     glVertex3fv( v7 );
00170 
00171     glColor4ubv( black );
00172     glVertex3fv( v5 );
00173     glColor4ubv( purple );
00174     glVertex3fv( v7 );
00175     glColor4ubv( orange );
00176     glVertex3fv( v6 );
00177 
00178     glColor4ubv( yellow );
00179     glVertex3fv( v4 );
00180     glColor4ubv( red );
00181     glVertex3fv( v0 );
00182     glColor4ubv( white );
00183     glVertex3fv( v3 );
00184 
00185     glColor4ubv( yellow );
00186     glVertex3fv( v4 );
00187     glColor4ubv( white );
00188     glVertex3fv( v3 );
00189     glColor4ubv( purple );
00190     glVertex3fv( v7 );
00191 
00192     glColor4ubv( white );
00193     glVertex3fv( v3 );
00194     glColor4ubv( blue );
00195     glVertex3fv( v2 );
00196     glColor4ubv( orange );
00197     glVertex3fv( v6 );
00198 
00199     glColor4ubv( white );
00200     glVertex3fv( v3 );
00201     glColor4ubv( orange );
00202     glVertex3fv( v6 );
00203     glColor4ubv( purple );
00204     glVertex3fv( v7 );
00205 
00206     glColor4ubv( green );
00207     glVertex3fv( v1 );
00208     glColor4ubv( red );
00209     glVertex3fv( v0 );
00210     glColor4ubv( yellow );
00211     glVertex3fv( v4 );
00212 
00213     glColor4ubv( green );
00214     glVertex3fv( v1 );
00215     glColor4ubv( yellow );
00216     glVertex3fv( v4 );
00217     glColor4ubv( black );
00218     glVertex3fv( v5 );
00219 
00220     glEnd( );
00221 
00222     /*
00223      * EXERCISE:
00224      * Draw text telling the user that 'Spc'
00225      * pauses the rotation and 'Esc' quits.
00226      * Do it using vetors and textured quads.
00227      */
00228 
00229     /*
00230      * Swap the buffers. This this tells the driver to
00231      * render the next frame from the contents of the
00232      * back-buffer, and to set all rendering operations
00233      * to occur on what was the front-buffer.
00234      *
00235      * Double buffering prevents nasty visual tearing
00236      * from the application drawing on areas of the
00237      * screen that are being updated at the same time.
00238      */
00239     SDL_GL_SwapBuffers( );
00240 }
00241 
00242 static void setup_opengl( int width, int height )
00243 {
00244     float ratio = (float) width / (float) height;
00245 
00246     /* Our shading model--Gouraud (smooth). */
00247     glShadeModel( GL_SMOOTH );
00248 
00249     /* Culling. */
00250     glCullFace( GL_BACK );
00251     glFrontFace( GL_CCW );
00252     glEnable( GL_CULL_FACE );
00253 
00254     /* Set the clear color. */
00255     glClearColor( 0, 0, 0, 0 );
00256 
00257     /* Setup our viewport. */
00258     glViewport( 0, 0, width, height );
00259 
00260     /*
00261      * Change to the projection matrix and set
00262      * our viewing volume.
00263      */
00264     glMatrixMode( GL_PROJECTION );
00265     glLoadIdentity( );
00266     /*
00267      * EXERCISE:
00268      * Replace this with a call to glFrustum.
00269      */
00270     gluPerspective( 60.0, ratio, 1.0, 1024.0 );
00271 }
00272 
00273 int main( int argc, char* argv[] )
00274 {
00275     /* Information about the current video settings. */
00276     const SDL_VideoInfo* info = NULL;
00277     /* Dimensions of our window. */
00278     int width = 0;
00279     int height = 0;
00280     /* Color depth in bits of our window. */
00281     int bpp = 0;
00282     /* Flags we will pass into SDL_SetVideoMode. */
00283     int flags = 0;
00284 
00285     /* First, initialize SDL's video subsystem. */
00286     if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) {
00287         /* Failed, exit. */
00288         fprintf( stderr, "Video initialization failed: %s\n",
00289                 SDL_GetError( ) );
00290         quit_tutorial( 1 );
00291     }
00292 
00293     /* Let's get some video information. */
00294     info = SDL_GetVideoInfo( );
00295 
00296     if( !info ) {
00297         /* This should probably never happen. */
00298         fprintf( stderr, "Video query failed: %s\n",
00299                 SDL_GetError( ) );
00300         quit_tutorial( 1 );
00301     }
00302 
00303     /*
00304      * Set our width/height to 640/480 (you would
00305      * of course let the user decide this in a normal
00306      * app). We get the bpp we will request from
00307      * the display. On X11, VidMode can't change
00308      * resolution, so this is probably being overly
00309      * safe. Under Win32, ChangeDisplaySettings
00310      * can change the bpp.
00311      */
00312     width = 640;
00313     height = 480;
00314     bpp = info->vfmt->BitsPerPixel;
00315 
00316     /*
00317      * Now, we want to setup our requested
00318      * window attributes for our OpenGL window.
00319      * We want *at least* 5 bits of red, green
00320      * and blue. We also want at least a 16-bit
00321      * depth buffer.
00322      *
00323      * The last thing we do is request a double
00324      * buffered window. '1' turns on double
00325      * buffering, '0' turns it off.
00326      *
00327      * Note that we do not use SDL_DOUBLEBUF in
00328      * the flags to SDL_SetVideoMode. That does
00329      * not affect the GL attribute state, only
00330      * the standard 2D blitting setup.
00331      */
00332     SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 );
00333     SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 );
00334     SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 );
00335     SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
00336     SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
00337 
00338     /*
00339      * We want to request that SDL provide us
00340      * with an OpenGL window, in a fullscreen
00341      * video mode.
00342      *
00343      * EXERCISE:
00344      * Make starting windowed an option, and
00345      * handle the resize events properly with
00346      * glViewport.
00347      */
00348     flags = SDL_OPENGL | SDL_FULLSCREEN;
00349 
00350     /*
00351      * Set the video mode
00352      */
00353     if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) {
00354         /* 
00355          * This could happen for a variety of reasons,
00356          * including DISPLAY not being set, the specified
00357          * resolution not being available, etc.
00358          */
00359         fprintf( stderr, "Video mode set failed: %s\n",
00360                 SDL_GetError( ) );
00361         quit_tutorial( 1 );
00362     }
00363 
00364     /*
00365      * At this point, we should have a properly setup
00366      * double-buffered window for use with OpenGL.
00367      */
00368     setup_opengl( width, height );
00369 
00370     /*
00371      * Now we want to begin our normal app process--
00372      * an event loop with a lot of redrawing.
00373      */
00374     while( 1 ) {
00375         /* Process incoming events. */
00376         process_events( );
00377         /* Draw the screen. */
00378         draw_screen( );
00379     }
00380 
00381     /*
00382      * EXERCISE:
00383      * Record timings using SDL_GetTicks() and
00384      * and print out frames per second at program
00385      * end.
00386      */
00387 
00388     /* Never reached. */
00389     return 0;
00390 }

Anoid NG © Michael Westergaard, Martin Stig Stissing, Ronni Michael Laursen, and Kristian Bisgaard Lassen