1.4.3. demos/sdl/sdl-1.01.03

Start felix section to demos/sdl/sdl-1.01.03-0.flx[1 /1 ]
     1: #line 3331 "./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: open C_hack;
    29: open Carray;
    30: open MixedInt;
    31: open Uint32;
    32: open Uint8;
    33: open Float;
    34: 
    35: open SDL_h;
    36: open SDL_video_h;
    37: open SDL_keyboard_h;
    38: open SDL_events_h;
    39: open SDL_keysym_h;
    40: open SDL_timer_h;
    41: open SDL_mutex_h;
    42: 
    43: // This is the Felix asynchronous event source
    44: open SDL_events;
    45: 
    46: open SDL_opengl_h;
    47: 
    48: /* screen width, height, and bit depth */
    49: val SCREEN_WIDTH  = 640;
    50: val SCREEN_HEIGHT = 480;
    51: val SCREEN_BPP = 16;
    52: 
    53: /* function to reset our viewport after a window resize */
    54: proc resizeWindow( wwidth : int, hheight :int)
    55: {
    56:   var height = hheight;
    57:   var width = wwidth;
    58: 
    59:   block_sdl_events event_lock;
    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:   /* Setup our viewport. */
    65:   glViewport( 0, 0, width, height );
    66: 
    67:   /* change to the projection matrix and set our viewing volume. */
    68:   glMatrixMode( GL_PROJECTION );
    69:   glLoadIdentity( );
    70: 
    71:   /* Set our perspective */
    72:   gluPerspective( 45.0, ratio, 0.1, 100.0 );
    73: 
    74:   /* Make sure we're chaning the model view and not the projection */
    75:   glMatrixMode( GL_MODELVIEW );
    76: 
    77:   /* Reset The View */
    78:   glLoadIdentity( );
    79:   unblock_sdl_events event_lock;
    80: }
    81: 
    82: /* general OpenGL initialization function */
    83: proc initGL()
    84: {
    85:   /* Enable smooth shading */
    86:   glShadeModel( GL_SMOOTH );
    87: 
    88:   /* Set the background black */
    89:   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    90: 
    91:   /* Depth buffer setup */
    92:   glClearDepth( 1.0 );
    93: 
    94:   /* Enables Depth Testing */
    95:   glEnable( GL_DEPTH_TEST );
    96: 
    97:   /* The Type Of Depth Test To Do */
    98:   glDepthFunc( GL_LEQUAL );
    99: 
   100:   /* Really Nice Perspective Calculations */
   101:   glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
   102: }
   103: 
   104: /* These are to calculate our fps */
   105: var T0     = 0;
   106: var Frames = 0;
   107: 
   108: var rtri = 0.0f; /* Triangle Rotation ( NEW ) */
   109: var rquad = 0.0f; /* Quad Rotation ( NEW ) */
   110: 
   111: proc rotate()
   112: {
   113:   /* Increase The Rotation Variable For The Triangle ( NEW ) */
   114:   rtri  += 0.2f;
   115:   /* Decrease The Rotation Variable For The Quad     ( NEW ) */
   116:   rquad -=0.15f;
   117: }
   118: 
   119: /* Here goes our drawing code */
   120: proc drawGLScene(drawing:1->0)
   121: {
   122:   block_sdl_events event_lock;
   123:   drawing();
   124:   unblock_sdl_events event_lock;
   125: 
   126:   /* Gather our frames per second */
   127:   Frames++;
   128:   {
   129:     var t = SDL_GetTicks();
   130:     if t - T0 >= 5000 do
   131:       val seconds = double_of (t - T0) / 1000.0;
   132:       val fps = double_of Frames / seconds;
   133:       print Frames; print " frames in "; print seconds;
   134:       print " seconds = "; print fps; print " FPS"; endl;
   135:       T0 = t;
   136:       Frames = 0;
   137:     done;
   138:   };
   139:   rotate();
   140: }
   141: 
   142: /* whether or not the window is active */
   143: var isActive = true;
   144: 
   145: if SDL_Init(SDL_INIT_AUDIO \| SDL_INIT_VIDEO) < 0 do
   146:   print "Unable to init SDL"; endl;
   147:   System::exit(1);
   148: done;
   149: 
   150: var event_lock = SDL_CreateMutex();
   151: 
   152: 
   153: proc Quit(n:int)
   154: {
   155:   SDL_Quit;
   156:   System::exit 0;
   157: }
   158: 
   159: /* Fetch the video info */
   160: var videoInfo = SDL_GetVideoInfo();
   161: 
   162: if isNULL videoInfo do
   163:   print "Video query failed"; endl;
   164:   Quit 1;
   165: done;
   166: 
   167: /* the flags to pass to SDL_SetVideoMode */
   168: var
   169:   videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
   170:   videoFlags |= cast[uint] SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
   171:   videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
   172:   videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
   173: 
   174: /* This checks to see if surfaces can be stored in memory */
   175: if  videoInfo.->hw_available != 0 do
   176:     videoFlags |= SDL_HWSURFACE;
   177: else
   178:     videoFlags |= SDL_SWSURFACE;
   179: done;
   180: 
   181: /* This checks if hardware blits can be done */
   182: if videoInfo.->blit_hw != 0 do
   183:     videoFlags |= SDL_HWACCEL;
   184: done;
   185: 
   186: /* Sets up OpenGL double buffering */
   187: ignore$ SDL_GL_SetAttribute( cast[SDL_GLattr] SDL_GL_DOUBLEBUFFER, 1 );
   188: 
   189: /* get a SDL surface */
   190: var surface = SDL_SetVideoMode
   191:   (SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags )
   192: ;
   193: 
   194: /* Verify there is a surface */
   195: if isNULL surface do
   196:   print "Video mode set failed"; endl;
   197:   Quit 1;
   198: done;
   199: 
   200: /* initialize OpenGL */
   201: initGL();
   202: 
   203: /* resize the initial window */
   204: resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
   205: 
   206: // SDL Event dispatcher
   207: proc handle_active (e:SDL_ActiveEvent)
   208: {
   209:    isActive = e.gain != 0;
   210: }
   211: 
   212: proc handle_resize(e:SDL_ResizeEvent)
   213: {
   214:   block_sdl_events event_lock;
   215:   surface = SDL_SetVideoMode(
   216:     e.w,
   217:     e.h,
   218:     16, videoFlags
   219:   );
   220:   if isNULL surface do
   221:     print "Could not get a surface after resize"; endl;
   222:   done;
   223:   resizeWindow( e.w, e.h );
   224:   unblock_sdl_events event_lock;
   225: }
   226: 
   227: /* function to handle key press events */
   228: proc handle_key( keysym : SDL_keysym)
   229: {
   230:   match keysym.sym with
   231:   | ?k when k == SDLK_ESCAPE => { Quit 0; }
   232:   | ?k when k ==  SDLK_F1 =>
   233:       {
   234:         block_sdl_events event_lock;
   235:         ignore$ SDL_WM_ToggleFullScreen( surface );
   236:         unblock_sdl_events event_lock;
   237:       }
   238:   | _ => {}
   239:   endmatch;
   240: }
   241: 
   242: /* draw the scene */
   243: proc draw(drawing: 1->0) {
   244:   if isActive call drawGLScene( drawing );
   245: }
   246: 
   247: proc keychan(x:schannel[SDL_keysym])
   248: {
   249:   whilst true do
   250:     var &k : SDL_keysym <- read x;
   251:     handle_key k;
   252:   done;
   253: }
   254: 
   255: proc activechan(x:schannel[SDL_ActiveEvent])
   256: {
   257:   whilst true do
   258:     var &k : SDL_ActiveEvent <- read x;
   259:     handle_active k;
   260:   done;
   261: }
   262: 
   263: proc resizechan(x:schannel[SDL_ResizeEvent])
   264: {
   265:   whilst true do
   266:     var &k : SDL_ResizeEvent <- read x;
   267:     handle_resize k;
   268:   done;
   269: }
   270: 
   271: proc drawchan(x:schannel[int], drawing:1->0)
   272: {
   273:   whilst true do
   274:     var &k : int <- read x;
   275:     draw drawing;
   276:   done;
   277: }
   278: 
   279: proc execute(x:schannel[int], something:1->0)
   280: {
   281:   whilst true do
   282:     var &k : int <- read x;
   283:     something();
   284:   done;
   285: }
   286: 
   287: val clock = Faio::mk_alarm_clock();
   288: proc poll_event(e: &SDL_Event)
   289: {
   290: tryagain:>
   291:   //print "Polling event"; endl;
   292:   var result = SDL_PollEvent(unref e);
   293:   if result > 0 do
   294:     //print "Got event"; endl;
   295:     return;
   296:   done;
   297:   Faio::sleep$ clock, 0.1;
   298:   goto tryagain;
   299: }
   300: 
   301: proc dispatch_event(
   302:   keyboard:schannel[SDL_keysym],
   303:   active:schannel[SDL_ActiveEvent],
   304:   resize:schannel[SDL_ResizeEvent]
   305: )
   306: {
   307:   whilst true do
   308:     //var &e : SDL_Event <- get_sdl_event event_lock;
   309:     var e : SDL_Event;
   310:     poll_event(&e);
   311:     match e.type_ with
   312:     | ?et when et == SDL_ACTIVEEVENT =>
   313:       { write (active, e.active); }
   314: 
   315:     | ?et when et == SDL_VIDEORESIZE =>
   316:       { write (resize, e.resize); }
   317: 
   318:     | ?et when et == SDL_KEYDOWN =>
   319:       { write (keyboard, e.key.keysym); }
   320: 
   321:     | ?et when et == SDL_QUIT =>
   322:       { Quit 0; }
   323: 
   324:     | _ => {}
   325:     endmatch;
   326:   done;
   327: }
   328: 
   329: /* write ticks at the desired framerate */
   330: proc framerate (x:schannel[int], framerate:double)
   331: {
   332:   whilst true do
   333:     Faio::sleep $ clock,framerate;
   334:     write (x,1);
   335:   done;
   336: }
   337: 
   338: /* LINEAR CONTROL MODEL: CANNOT DEADLOCK
   339:   ~~> async/sync connection
   340:   --> sync/sync connection
   341: 
   342:   SDL_event ~~> dispatcher
   343:                 --> resize handler
   344:                 --> active handler
   345:                 --> key handler
   346:   timer ~~> framerate --> draw
   347: */
   348: 
   349: /* make our communication channels */
   350: var keyboard = mk_schannel[SDL_keysym] ();
   351: var active = mk_schannel[SDL_ActiveEvent] ();
   352: var resize = mk_schannel[SDL_ResizeEvent] ();
   353: var clicks = mk_schannel[int] ();
   354: var rotation = mk_schannel[int] ();
   355: 
   356: /* start up the fthreads and plug them together */
   357: spawn_fthread { dispatch_event (keyboard, active, resize); };
   358: spawn_fthread { resizechan resize; };
   359: spawn_fthread { activechan active; };
   360: spawn_fthread { keychan keyboard; };
   361: 
   362: spawn_fthread { drawchan (clicks, the Drawing); };
   363: spawn_fthread { framerate (clicks, 0.05); };
   364: spawn_fthread { execute (rotation, the rotate); };
   365: spawn_fthread { framerate (rotation, 0.1); };
   366: 
   367: // main thread hangs
   368: 
   369: /* Here goes our drawing code */
   370: proc Drawing()
   371: {
   372:     /* Clear The Screen And The Depth Buffer */
   373:     glClear( GL_COLOR_BUFFER_BIT \| GL_DEPTH_BUFFER_BIT );
   374: 
   375:     /* Move Left 1.5 Units And Into The Screen 6.0 */
   376:     glLoadIdentity();
   377:     glTranslatef( -1.5f, 0.0f, -6.0f );
   378: 
   379:     /* Rotate The Triangle On The Y axis ( NEW ) */
   380:     glRotatef( rtri, 0.0f, 1.0f, 0.0f );
   381: 
   382:     glBegin( GL_TRIANGLES );             /* Drawing Using Triangles       */
   383:       glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
   384:       glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Front)       */
   385:       glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
   386:       glVertex3f( -1.0f, -1.0f,  1.0f ); /* Left Of Triangle (Front)      */
   387:       glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
   388:       glVertex3f(  1.0f, -1.0f,  1.0f ); /* Right Of Triangle (Front)     */
   389: 
   390:       glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
   391:       glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Right)       */
   392:       glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
   393:       glVertex3f(  1.0f, -1.0f,  1.0f ); /* Left Of Triangle (Right)      */
   394:       glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
   395:       glVertex3f(  1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Right)     */
   396: 
   397:       glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
   398:       glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Back)        */
   399:       glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
   400:       glVertex3f(  1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Back)       */
   401:       glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
   402:       glVertex3f( -1.0f, -1.0f, -1.0f ); /* Right Of Triangle (Back)      */
   403: 
   404:       glColor3f(   1.0f,  0.0f,  0.0f ); /* Red                           */
   405:       glVertex3f(  0.0f,  1.0f,  0.0f ); /* Top Of Triangle (Left)        */
   406:       glColor3f(   0.0f,  0.0f,  1.0f ); /* Blue                          */
   407:       glVertex3f( -1.0f, -1.0f, -1.0f ); /* Left Of Triangle (Left)       */
   408:       glColor3f(   0.0f,  1.0f,  0.0f ); /* Green                         */
   409:       glVertex3f( -1.0f, -1.0f,  1.0f ); /* Right Of Triangle (Left)      */
   410:     glEnd( );                            /* Finished Drawing The Triangle */
   411: 
   412:     /* Move Right 3 Units */
   413:     glLoadIdentity( );
   414:     glTranslatef( 1.5f, 0.0f, -6.0f );
   415: 
   416:     /* Rotate The Quad On The X axis ( NEW ) */
   417:     glRotatef( rquad, 1.0f, 0.0f, 0.0f );
   418: 
   419:     /* Set The Color To Blue One Time Only */
   420:     glColor3f( 0.5f, 0.5f, 1.0f);
   421: 
   422:     glBegin( GL_QUADS );                 /* Draw A Quad                      */
   423:       glColor3f(   0.0f,  1.0f,  0.0f ); /* Set The Color To Green           */
   424:       glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Top)      */
   425:       glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Top)       */
   426:       glVertex3f( -1.0f,  1.0f,  1.0f ); /* Bottom Left Of The Quad (Top)    */
   427:       glVertex3f(  1.0f,  1.0f,  1.0f ); /* Bottom Right Of The Quad (Top)   */
   428: 
   429:       glColor3f(   1.0f,  0.5f,  0.0f ); /* Set The Color To Orange          */
   430:       glVertex3f(  1.0f, -1.0f,  1.0f ); /* Top Right Of The Quad (Botm)     */
   431:       glVertex3f( -1.0f, -1.0f,  1.0f ); /* Top Left Of The Quad (Botm)      */
   432:       glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Botm)   */
   433:       glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Botm)  */
   434: 
   435:       glColor3f(   1.0f,  0.0f,  0.0f ); /* Set The Color To Red             */
   436:       glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Front)    */
   437:       glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Front)     */
   438:       glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Front)  */
   439:       glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Front) */
   440: 
   441:       glColor3f(   1.0f,  1.0f,  0.0f ); /* Set The Color To Yellow          */
   442:       glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Back)   */
   443:       glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Back)  */
   444:       glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Back)     */
   445:       glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Back)      */
   446: 
   447:       glColor3f(   0.0f,  0.0f,  1.0f ); /* Set The Color To Blue            */
   448:       glVertex3f( -1.0f,  1.0f,  1.0f ); /* Top Right Of The Quad (Left)     */
   449:       glVertex3f( -1.0f,  1.0f, -1.0f ); /* Top Left Of The Quad (Left)      */
   450:       glVertex3f( -1.0f, -1.0f, -1.0f ); /* Bottom Left Of The Quad (Left)   */
   451:       glVertex3f( -1.0f, -1.0f,  1.0f ); /* Bottom Right Of The Quad (Left)  */
   452: 
   453:       glColor3f(   1.0f,  0.0f,  1.0f ); /* Set The Color To Violet          */
   454:       glVertex3f(  1.0f,  1.0f, -1.0f ); /* Top Right Of The Quad (Right)    */
   455:       glVertex3f(  1.0f,  1.0f,  1.0f ); /* Top Left Of The Quad (Right)     */
   456:       glVertex3f(  1.0f, -1.0f,  1.0f ); /* Bottom Left Of The Quad (Right)  */
   457:       glVertex3f(  1.0f, -1.0f, -1.0f ); /* Bottom Right Of The Quad (Right) */
   458:     glEnd( );                            /* Done Drawing The Quad            */
   459: 
   460:     /* Draw it to the screen */
   461:     SDL_GL_SwapBuffers( );
   462: }
End felix section to demos/sdl/sdl-1.01.03-0.flx[1]