1.4.4. demos/sdl/sdl-1.01.04

Start felix section to demos/sdl/sdl-1.01.04-0.flx[1 /1 ]
     1: #line 3796 "./lpsrc/flx_sdl.pak"
     2: // REQUIRES OpenGL and GLU
     3: /*
     4:  * This code was created by Jeff Molofee '99
     5:  * (ported to Linux/SDL by Ti Leggett '01)
     6:  *
     7:  * If you've found this code useful, please let me know.
     8:  *
     9:  * Visit Jeff at http://nehe.gamedev.net/
    10:  *
    11:  * or for port-specific comments, questions, bugreports etc.
    12:  * email to leggett@eecs.tulane.edu
    13:  */
    14: 
    15: #import <flx.flxh>
    16: include "SDL/SDL";
    17: include "SDL/SDL_keyboard";
    18: include "SDL/SDL_keysym";
    19: include "SDL/SDL_video";
    20: include "SDL/SDL_events";
    21: include "SDL/SDL_timer";
    22: include "SDL/SDL_mutex";
    23: include "SDL/SDL_opengl";
    24: 
    25: include "flx_faio";
    26: include "flx_faio_sdl";
    27: 
    28: 
    29: open C_hack;
    30: open Carray;
    31: open MixedInt;
    32: open Uint32;
    33: open Uint8;
    34: open Float;
    35: 
    36: open SDL_h;
    37: open SDL_video_h;
    38: open SDL_keyboard_h;
    39: open SDL_events_h;
    40: open SDL_keysym_h;
    41: open SDL_timer_h;
    42: open SDL_mutex_h;
    43: 
    44: // This is the Felix asynchronous event source
    45: open SDL_events;
    46: 
    47: open SDL_opengl_h;
    48: 
    49: /* screen width, height, and bit depth */
    50: val SCREEN_WIDTH  = 640;
    51: val SCREEN_HEIGHT = 480;
    52: val SCREEN_BPP = 16;
    53: 
    54: /* function to reset our viewport after a window resize */
    55: proc resizeWindow( wwidth : int, hheight :int)
    56: {
    57:   var height = hheight;
    58:   var width = wwidth;
    59: 
    60:   /* Protect against a divide by zero */
    61:   if height == 0 do height = 1; done;
    62:   var ratio = double_of width / double_of height;
    63: 
    64:   block_sdl_events event_lock;
    65:   /* Setup our viewport. */
    66:   glViewport( 0, 0, width, height );
    67: 
    68:   /* change to the projection matrix and set our viewing volume. */
    69:   glMatrixMode( GL_PROJECTION );
    70:   glLoadIdentity( );
    71: 
    72:   /* Set our perspective */
    73:   gluPerspective( 45.0, ratio, 0.1, 100.0 );
    74: 
    75:   /* Make sure we're chaning the model view and not the projection */
    76:   glMatrixMode( GL_MODELVIEW );
    77: 
    78:   /* Reset The View */
    79:   glLoadIdentity( );
    80:   unblock_sdl_events event_lock;
    81: }
    82: 
    83: /* function to load in bitmap as a GL texture */
    84: proc LoadGLTextures( )
    85: {
    86:   /* Create storage space for the texture */
    87:   var TextureImage = SDL_LoadBMP(enconst c"media/textures/sdl206.bmp");
    88:   if isNULL TextureImage do
    89:     print "Can't load texture file media/textures/sdl206.bmp";
    90:     Quit 1;
    91:   done;
    92: 
    93:   /* Create The Texture */
    94:     glGenTextures( 1, texture );
    95: 
    96:   /* Typical Texture Generation Using Data From The Bitmap */
    97:   glBindTexture( GL_TEXTURE_2D, texture.[0] );
    98: 
    99:     /* Generate The Texture */
   100:   glTexImage2D( GL_TEXTURE_2D, 0, 3, TextureImage.->w,
   101:     TextureImage.->h, 0, GL_RGB,
   102:     GL_UNSIGNED_BYTE, TextureImage.->pixels
   103:   );
   104: 
   105:   /* Linear Filtering */
   106:   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
   107:     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
   108: 
   109:   /* Free up any memory we may have used */
   110:     SDL_FreeSurface( TextureImage );
   111: }
   112: 
   113: /* general OpenGL initialization function */
   114: proc initGL()
   115: {
   116:   /* Enable Texture Mapping ( NEW ) */
   117:   glEnable( GL_TEXTURE_2D );
   118: 
   119:   /* Enable smooth shading */
   120:   glShadeModel( GL_SMOOTH );
   121: 
   122:   /* Set the background black */
   123:   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
   124: 
   125:   /* Depth buffer setup */
   126:   glClearDepth( 1.0 );
   127: 
   128:   /* Enables Depth Testing */
   129:   glEnable( GL_DEPTH_TEST );
   130: 
   131:   /* The Type Of Depth Test To Do */
   132:   glDepthFunc( GL_LEQUAL );
   133: 
   134:   /* Really Nice Perspective Calculations */
   135:   glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
   136: }
   137: 
   138: /* These are to calculate our fps */
   139: var T0     = 0;
   140: var Frames = 0;
   141: 
   142: var xrot = 0.0f; /* X Rotation ( NEW ) */
   143: var yrot = 0.0f; /* Y Rotation ( NEW ) */
   144: var zrot = 0.0f; /* Z Rotation ( NEW ) */
   145: 
   146: proc rotate()
   147: {
   148:   xrot += 0.3f; /* X Axis Rotation */
   149:   yrot += 0.2f; /* Y Axis Rotation */
   150:   zrot += 0.4f; /* Z Axis Rotation */
   151: }
   152: 
   153: var f_texture : uint ^ 2; /* Storage For One Texture ( NEW ) */
   154: var texture : carray[uint] = carray f_texture;
   155: 
   156: 
   157: /* Here goes our drawing code */
   158: proc drawGLScene(drawing:1->0)
   159: {
   160:   block_sdl_events event_lock;
   161:   drawing();
   162:   unblock_sdl_events event_lock;
   163: 
   164:   /* Gather our frames per second */
   165:   Frames++;
   166:   {
   167:     var t = SDL_GetTicks();
   168:     if t - T0 >= 5000 do
   169:       val seconds = double_of (t - T0) / 1000.0;
   170:       val fps = double_of Frames / seconds;
   171:       print Frames; print " frames in "; print seconds;
   172:       print " seconds = "; print fps; print " FPS"; endl;
   173:       T0 = t;
   174:       Frames = 0;
   175:     done;
   176:   };
   177:   rotate();
   178: }
   179: 
   180: /* whether or not the window is active */
   181: var isActive = true;
   182: 
   183: if SDL_Init(SDL_INIT_AUDIO \| SDL_INIT_VIDEO) < 0 do
   184:   print "Unable to init SDL"; endl;
   185:   System::exit(1);
   186: done;
   187: 
   188: var event_lock = SDL_CreateMutex();
   189: 
   190: 
   191: proc Quit(n:int)
   192: {
   193:   SDL_Quit;
   194:   System::exit 0;
   195: }
   196: 
   197: /* Fetch the video info */
   198: var videoInfo = SDL_GetVideoInfo();
   199: 
   200: if isNULL videoInfo do
   201:   print "Video query failed"; endl;
   202:   Quit 1;
   203: done;
   204: 
   205: /* the flags to pass to SDL_SetVideoMode */
   206: var
   207:   videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
   208:   videoFlags |= cast[uint] SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
   209:   videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
   210:   videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
   211: 
   212: /* This checks to see if surfaces can be stored in memory */
   213: if  videoInfo.->hw_available != 0 do
   214:     videoFlags |= SDL_HWSURFACE;
   215: else
   216:     videoFlags |= SDL_SWSURFACE;
   217: done;
   218: 
   219: /* This checks if hardware blits can be done */
   220: if videoInfo.->blit_hw != 0 do
   221:     videoFlags |= SDL_HWACCEL;
   222: done;
   223: 
   224: /* Sets up OpenGL double buffering */
   225: ignore$ SDL_GL_SetAttribute( cast[SDL_GLattr] SDL_GL_DOUBLEBUFFER, 1 );
   226: 
   227: /* get a SDL surface */
   228: var surface = SDL_SetVideoMode
   229:   (SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags )
   230: ;
   231: 
   232: /* Verify there is a surface */
   233: if isNULL surface do
   234:   print "Video mode set failed"; endl;
   235:   Quit 1;
   236: done;
   237: 
   238: /* initialize OpenGL */
   239: initGL();
   240: LoadGLTextures();
   241: 
   242: /* resize the initial window */
   243: resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
   244: 
   245: // SDL Event dispatcher
   246: proc handle_active (e:SDL_ActiveEvent)
   247: {
   248:    isActive = e.gain != 0;
   249: }
   250: 
   251: proc handle_resize(e:SDL_ResizeEvent)
   252: {
   253:   block_sdl_events event_lock;
   254:   surface = SDL_SetVideoMode(
   255:     e.w,
   256:     e.h,
   257:     16, videoFlags
   258:   );
   259:   if isNULL surface do
   260:     print "Could not get a surface after resize"; endl;
   261:   done;
   262:   resizeWindow( e.w, e.h );
   263:   unblock_sdl_events event_lock;
   264: }
   265: 
   266: /* function to handle key press events */
   267: proc handle_key( keysym : SDL_keysym)
   268: {
   269:   match keysym.sym with
   270:   | ?k when k == SDLK_ESCAPE => { Quit 0; }
   271:   | ?k when k ==  SDLK_F1 =>
   272:         {
   273:         block_sdl_events event_lock;
   274:         ignore$ SDL_WM_ToggleFullScreen( surface );
   275:         unblock_sdl_events event_lock;
   276:       }
   277:   | _ => {}
   278:   endmatch;
   279: }
   280: 
   281: /* draw the scene */
   282: proc draw(drawing: 1->0) {
   283:   if isActive call drawGLScene( drawing );
   284: }
   285: 
   286: proc keychan(x:schannel[SDL_keysym])
   287: {
   288:   whilst true do
   289:     var &k : SDL_keysym <- read x;
   290:     handle_key k;
   291:   done;
   292: }
   293: 
   294: proc activechan(x:schannel[SDL_ActiveEvent])
   295: {
   296:   whilst true do
   297:     var &k : SDL_ActiveEvent <- read x;
   298:     handle_active k;
   299:   done;
   300: }
   301: 
   302: proc resizechan(x:schannel[SDL_ResizeEvent])
   303: {
   304:   whilst true do
   305:     var &k : SDL_ResizeEvent <- read x;
   306:     handle_resize k;
   307:   done;
   308: }
   309: 
   310: proc drawchan(x:schannel[int], drawing:1->0)
   311: {
   312:   whilst true do
   313:     var &k : int <- read x;
   314:     draw drawing;
   315:   done;
   316: }
   317: 
   318: proc execute(x:schannel[int], something:1->0)
   319: {
   320:   whilst true do
   321:     var &k : int <- read x;
   322:     something();
   323:   done;
   324: }
   325: 
   326: val clock = Faio::mk_alarm_clock();
   327: proc poll_event(e: &SDL_Event)
   328: {
   329: tryagain:>
   330:   //print "Polling event"; endl;
   331:   var result = SDL_PollEvent(unref e);
   332:   if result > 0 do
   333:     //print "Got event"; endl;
   334:     return;
   335:   done;
   336:   Faio::sleep$ clock, 0.1;
   337:   goto tryagain;
   338: }
   339: 
   340: 
   341: proc dispatch_event(
   342:   keyboard:schannel[SDL_keysym],
   343:   active:schannel[SDL_ActiveEvent],
   344:   resize:schannel[SDL_ResizeEvent]
   345: )
   346: {
   347:   whilst true do
   348:     //var &e : SDL_Event <- get_sdl_event event_lock;
   349:     var e : SDL_Event;
   350:     poll_event(&e);
   351:     match e.type_ with
   352:     | ?et when et == SDL_ACTIVEEVENT =>
   353:       { write (active, e.active); }
   354: 
   355:     | ?et when et == SDL_VIDEORESIZE =>
   356:       { write (resize, e.resize); }
   357: 
   358:     | ?et when et == SDL_KEYDOWN =>
   359:       { write (keyboard, e.key.keysym); }
   360: 
   361:     | ?et when et == SDL_QUIT =>
   362:       { Quit 0; }
   363: 
   364:     | _ => {}
   365:     endmatch;
   366:   done;
   367: }
   368: 
   369: /* write ticks at the desired framerate */
   370: proc framerate (x:schannel[int], framerate:double)
   371: {
   372:   whilst true do
   373:     Faio::sleep $ clock,framerate;
   374:     write (x,1);
   375:   done;
   376: }
   377: 
   378: /* LINEAR CONTROL MODEL: CANNOT DEADLOCK
   379:   ~~> async/sync connection
   380:   --> sync/sync connection
   381: 
   382:   SDL_event ~~> dispatcher
   383:                 --> resize handler
   384:                 --> active handler
   385:                 --> key handler
   386:   timer ~~> framerate --> draw
   387: */
   388: 
   389: /* make our communication channels */
   390: var keyboard = mk_schannel[SDL_keysym] ();
   391: var active = mk_schannel[SDL_ActiveEvent] ();
   392: var resize = mk_schannel[SDL_ResizeEvent] ();
   393: var clicks = mk_schannel[int] ();
   394: var rotation = mk_schannel[int] ();
   395: 
   396: /* start up the fthreads and plug them together */
   397: spawn_fthread { dispatch_event (keyboard, active, resize); };
   398: spawn_fthread { resizechan resize; };
   399: spawn_fthread { activechan active; };
   400: spawn_fthread { keychan keyboard; };
   401: 
   402: spawn_fthread { drawchan (clicks, the Drawing); };
   403: spawn_fthread { framerate (clicks, 0.1); };
   404: spawn_fthread { execute (rotation, the rotate); };
   405: spawn_fthread { framerate (rotation, 0.1); };
   406: 
   407: 
   408: // main thread hangs
   409: 
   410: /* Here goes our drawing code */
   411: proc Drawing()
   412: {
   413:     /* Clear The Screen And The Depth Buffer */
   414:     glClear( GL_COLOR_BUFFER_BIT \| GL_DEPTH_BUFFER_BIT );
   415: 
   416:     /* Move Into The Screen 5 Units */
   417:     glLoadIdentity( );
   418:     glTranslatef( 0.0f, 0.0f, -5.0f );
   419: 
   420:     glRotatef( xrot, 1.0f, 0.0f, 0.0f); /* Rotate On The X Axis */
   421:     glRotatef( yrot, 0.0f, 1.0f, 0.0f); /* Rotate On The Y Axis */
   422:     glRotatef( zrot, 0.0f, 0.0f, 1.0f); /* Rotate On The Z Axis */
   423: 
   424:     /* Select Our Texture */
   425:     glBindTexture( GL_TEXTURE_2D, texture.[0] );
   426: 
   427:     /* NOTE:
   428:      *   The x coordinates of the glTexCoord2f function need to inverted
   429:      * for SDL because of the way SDL_LoadBmp loads the data. So where
   430:      * in the tutorial it has glTexCoord2f( 1.0f, 0.0f ); it should
   431:      * now read glTexCoord2f( 0.0f, 0.0f );
   432:      */
   433:     glBegin(GL_QUADS);
   434:       /* Front Face */
   435:       /* Bottom Left Of The Texture and Quad */
   436:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, -1.0f, 1.0f );
   437:       /* Bottom Right Of The Texture and Quad */
   438:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f(  1.0f, -1.0f, 1.0f );
   439:       /* Top Right Of The Texture and Quad */
   440:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f(  1.0f,  1.0f, 1.0f );
   441:       /* Top Left Of The Texture and Quad */
   442:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f,  1.0f, 1.0f );
   443: 
   444:       /* Back Face */
   445:       /* Bottom Right Of The Texture and Quad */
   446:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.0f );
   447:       /* Top Right Of The Texture and Quad */
   448:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f,  1.0f, -1.0f );
   449:       /* Top Left Of The Texture and Quad */
   450:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f(  1.0f,  1.0f, -1.0f );
   451:       /* Bottom Left Of The Texture and Quad */
   452:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f(  1.0f, -1.0f, -1.0f );
   453: 
   454:       /* Top Face */
   455:       /* Top Left Of The Texture and Quad */
   456:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f,  1.0f, -1.0f );
   457:       /* Bottom Left Of The Texture and Quad */
   458:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f,  1.0f,  1.0f );
   459:       /* Bottom Right Of The Texture and Quad */
   460:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f(  1.0f,  1.0f,  1.0f );
   461:       /* Top Right Of The Texture and Quad */
   462:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f(  1.0f,  1.0f, -1.0f );
   463: 
   464:       /* Bottom Face */
   465:       /* Top Right Of The Texture and Quad */
   466:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f, -1.0f, -1.0f );
   467:       /* Top Left Of The Texture and Quad */
   468:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f(  1.0f, -1.0f, -1.0f );
   469:       /* Bottom Left Of The Texture and Quad */
   470:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f(  1.0f, -1.0f,  1.0f );
   471:       /* Bottom Right Of The Texture and Quad */
   472:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f,  1.0f );
   473: 
   474:       /* Right face */
   475:       /* Bottom Right Of The Texture and Quad */
   476:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f( 1.0f, -1.0f, -1.0f );
   477:       /* Top Right Of The Texture and Quad */
   478:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f( 1.0f,  1.0f, -1.0f );
   479:       /* Top Left Of The Texture and Quad */
   480:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f( 1.0f,  1.0f,  1.0f );
   481:       /* Bottom Left Of The Texture and Quad */
   482:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f( 1.0f, -1.0f,  1.0f );
   483: 
   484:       /* Left Face */
   485:       /* Bottom Left Of The Texture and Quad */
   486:       glTexCoord2f( 1.0f, 0.0f ); glVertex3f( -1.0f, -1.0f, -1.0f );
   487:       /* Bottom Right Of The Texture and Quad */
   488:       glTexCoord2f( 0.0f, 0.0f ); glVertex3f( -1.0f, -1.0f,  1.0f );
   489:       /* Top Right Of The Texture and Quad */
   490:       glTexCoord2f( 0.0f, 1.0f ); glVertex3f( -1.0f,  1.0f,  1.0f );
   491:       /* Top Left Of The Texture and Quad */
   492:       glTexCoord2f( 1.0f, 1.0f ); glVertex3f( -1.0f,  1.0f, -1.0f );
   493:     glEnd( );
   494: 
   495:     /* Draw it to the screen */
   496:     SDL_GL_SwapBuffers( );
   497: }
End felix section to demos/sdl/sdl-1.01.04-0.flx[1]