Exemplo n.º 1
0
void _3dfx_BlitScale( grs_bitmap *source_bmp, grs_bitmap *dest_bmp,
                      int x0, int y0, int x1, int y1,
                      fix u0, fix v0, fix u1, fix v1, int orient )
{
   if ( _3dfx_available )
   {
      if ( source_bmp->bm_flags & BM_FLAG_RLE )
      {
         fix u, v, du, dv;
         int x, y;
         ubyte * sbits;
         unsigned long * dbits;
         unsigned long * fb;

         du = (u1-u0) / (x1-x0);
         dv = (v1-v0) / (y1-y0);

         v = v0;

         grLfbBegin();

         grLfbBypassMode( GR_LFBBYPASS_ENABLE );

         fb = ( unsigned long * ) grLfbGetWritePtr( GR_BUFFER_BACKBUFFER );
         grLfbWriteMode( GR_LFBWRITEMODE_8888 );

         guColorCombineFunction( GR_COLORCOMBINE_DECAL_TEXTURE );

         for ( y = y0; y <= y1; y++, v += dv )
         {
            extern ubyte scale_rle_data[];

            decode_row( source_bmp, f2i( v ) );

            sbits = scale_rle_data + f2i( u0 );
            dbits = fb + _3DFX_FB_WIDTH * y + x0;

            u = u0;

            for ( x = x0; x <= x1; x++ )
            {
               int pindex = sbits[ u >> 16 ];

               if ( pindex != 255 )
                  *dbits = _3dfx_PaletteToARGB( pindex );

               dbits++;
               u += du;
            }
         }
         grLfbBypassMode( GR_LFBBYPASS_DISABLE );

         grLfbEnd();
      }
      else
      {
Exemplo n.º 2
0
void
main( int argc, char **argv ) {
  float
    minColor = 15.f,
    maxColor = 240.f;

  GrVertex
    localVerts[NVERTS],
    texVerts[NVERTS];

  int
    nFrames = 0;
  
  float
    alpha = 192.0f,
    y_angle = 0.0f;

  FxBool
    lines = FXFALSE,
    blend = FXFALSE,
    texturing = FXFALSE,
    antialias = FXTRUE,
    bilinear = FXTRUE,
    render = FXTRUE,
    backbuffer = FXTRUE,
    background = FXTRUE;

  GrCullMode_t
    cullMode = GR_CULL_DISABLE;

  float
    wWidth, wHeight;

  GrScreenResolution_t
    screenRes;

  GrMipMapId_t
    triDecal,
    bgDecal;

  Gu3dfInfo
    bgInfo, triInfo;

  FxU16
    *scrnImage;

  GrColorCombineFnc_t
    ccFnc = GR_COLORCOMBINE_ITRGB;

  int
    numFrames = -1,
    frameCount = 0;



  char
    *bgFileName = NULL,
    *triFileName = NULL;
  wWidth = 640.0f;
  wHeight = 480.0f;

  screenRes = GR_RESOLUTION_640x480;

  --argc; ++argv;

  while (argc) {
    if (strstr(*argv, "320x200")) {
      wWidth = 320.0f; wHeight = 200.0f;
      screenRes = GR_RESOLUTION_320x200;
      --argc; ++argv;
    } else if (strstr(*argv, "320x240")) {
      wWidth = 320.0f; wHeight = 240.0f;
      screenRes = GR_RESOLUTION_320x240;
      --argc; ++argv;
    } else if (strstr(*argv, "400x256")) {
      wWidth = 400.0f; wHeight = 256.0f;
      screenRes = GR_RESOLUTION_400x256;
      --argc; ++argv;
    } else if (strstr(*argv, "512x384")) {
      wWidth = 512.0f; wHeight = 384.0f;
      screenRes = GR_RESOLUTION_512x384;
      --argc; ++argv;
    } else if (strstr(*argv, "640x480")) {
      wWidth = 640.0f; wHeight = 480.0f;
      screenRes = GR_RESOLUTION_640x480;
      --argc; ++argv;
    } else if (strstr(*argv, "800x600")) {
      wWidth = 800.0f; wHeight = 600.0f;
      screenRes = GR_RESOLUTION_800x600;
      --argc; ++argv;
    } else if (strstr(*argv, "856x480")) {
      wWidth = 856.0f; wHeight = 480.0f;
      screenRes = GR_RESOLUTION_856x480;
      --argc; ++argv;
    } else if (strstr(*argv, "960x720")) {
      wWidth = 960.0f; wHeight = 720.0f;
      screenRes = GR_RESOLUTION_960x720;
      --argc; ++argv;
    } else if (strstr(*argv, "640x200")) {
      wWidth = 640.f; wHeight = 200.f;
      screenRes = GR_RESOLUTION_640x200;
      --argc; ++argv;
    } else if (strstr(*argv, "640x350")) {
      wWidth = 640.f; wHeight = 350.f;
      screenRes = GR_RESOLUTION_640x350;
      --argc; ++argv;
    } else if (strstr(*argv, "640x400")) {
      wWidth = 640.f; wHeight = 400.f;
      screenRes = GR_RESOLUTION_640x400;
      --argc; ++argv;
    } else if (strstr(*argv, "bgFile")) {
      bgFileName = argv[1];
      argc-= 2; argv += 2;
    } else if (strstr(*argv, "triFile")) {
      triFileName = argv[1];
      argc-= 2; argv += 2;
    } else if (strstr(*argv, "alpha")) {
      alpha = (float)atof(argv[1]);
      argc -= 2; argv += 2;
    } else if (strstr(*argv, "-n")) {
      numFrames = atoi(argv[1]);
      argc -= 2; argv += 2;
    } else {
      fprintf(
              stderr,
              "Useage:  test27 [-bgFile bgfile.3ds] [-triFile triFile.3ds] [ScreenRes (i.e. 640x480 .. 960x720] [-alpha alphavalue] [-n numFrames]\n");
      exit(-1);
    }
  }

  scrnImage = malloc((int)wWidth * (int)wHeight * sizeof(FxU16));

  puts( "\nTEST27:" );
  puts( "Antialiased Polygon Test\n" );
  puts("press H for help\n");
  if(numFrames == -1)
  {
    puts("Press a key to continue");
    getch();
  }
  grGlideInit();

  if ( !grSstQueryHardware( &hwconfig ) )
  {
    fprintf( stderr, "main: grSstQueryHardware failed!\n" );
    grGlideShutdown();
    exit( -1 );
  }

  /* Select SST 0 */
  grSstSelect( 0 );

  /* Open up the hardware */
  if ( !grSstOpen( screenRes,
                   GR_REFRESH_60Hz,
                   GR_COLORFORMAT_ABGR,
                   GR_ORIGIN_LOWER_LEFT,
                   GR_SMOOTHING_ENABLE,
                   2 ) )
  {
    fprintf( stderr, "main: grSstOpen failed!\n" );
    grGlideShutdown();
    exit( -1 );
  }

  localVerts[0].x = -0.666f;
  localVerts[0].y = -1.0f;
  localVerts[0].z = 0.0f;
  localVerts[0].tmuvtx[0].sow = 85.f;
  localVerts[0].tmuvtx[0].tow = 255.f;
  localVerts[0].oow = 1.f;  
  localVerts[0].r = maxColor;
  localVerts[0].g = minColor;
  localVerts[0].b = minColor;
  localVerts[0].a = 255.f;

  localVerts[1].x = -1.0f;
  localVerts[1].y = -0.666f;
  localVerts[1].z = 0.0f;
  localVerts[1].tmuvtx[0].sow = 0.f;
  localVerts[1].tmuvtx[0].tow = 170.f;
  localVerts[1].oow = 1.f;  
  localVerts[1].r = minColor;
  localVerts[1].g = maxColor;
  localVerts[1].b = minColor;
  localVerts[1].a = 255.f;

  localVerts[2].x = -1.f;
  localVerts[2].y = 0.333f;
  localVerts[2].z = 0.0f;
  localVerts[2].tmuvtx[0].sow = 0.f;
  localVerts[2].tmuvtx[0].tow = 85.f;
  localVerts[2].oow = 1.f;  
  localVerts[2].r = minColor;
  localVerts[2].g = minColor;
  localVerts[2].b = maxColor;
  localVerts[2].a = 255.f;


  localVerts[3].x = -0.666f;
  localVerts[3].y = 1.f;
  localVerts[3].z = 0.0f;
  localVerts[3].tmuvtx[0].sow = 85.f;
  localVerts[3].tmuvtx[0].tow = 0.f;
  localVerts[3].oow = 1.f;  
  localVerts[3].r = maxColor;
  localVerts[3].g = minColor;
  localVerts[3].b = maxColor;
  localVerts[3].a = 255.f;

  localVerts[4].x = 0.333f;
  localVerts[4].y = 1.f;
  localVerts[4].z = 0.0f;
  localVerts[4].tmuvtx[0].sow = 170.f;
  localVerts[4].tmuvtx[0].tow = 0.f;
  localVerts[4].oow = 1.f;  
  localVerts[4].r = minColor;
  localVerts[4].g = maxColor;
  localVerts[4].b = maxColor;
  localVerts[4].a = 255.f;

  localVerts[5].x = 1.f;
  localVerts[5].y = 0.333f;
  localVerts[5].z = 0.0f;
  localVerts[5].tmuvtx[0].sow = 255.f;
  localVerts[5].tmuvtx[0].tow = 85.f;
  localVerts[5].oow = 1.f;  
  localVerts[5].r = maxColor;
  localVerts[5].g = maxColor;
  localVerts[5].b = minColor;
  localVerts[5].a = 255.f;

  localVerts[6].x = 1.f;
  localVerts[6].y = -0.666f;
  localVerts[6].z = 0.0f;
  localVerts[6].tmuvtx[0].sow = 255.f;
  localVerts[6].tmuvtx[0].tow = 170.f;
  localVerts[6].oow = 1.f;  
  localVerts[6].r = maxColor;
  localVerts[6].g = maxColor;
  localVerts[6].b = maxColor;
  localVerts[6].a = 255.f;

  localVerts[7].x = 0.333f;
  localVerts[7].y = -1.f;
  localVerts[7].z = 0.0f;
  localVerts[7].tmuvtx[0].sow = 170.f;
  localVerts[7].tmuvtx[0].tow = 255.f;
  localVerts[7].oow = 1.f;  
  localVerts[7].r = minColor;
  localVerts[7].g = minColor;
  localVerts[7].b = minColor;
  localVerts[7].a = 255.f;

  texVerts[0].x = 0.f;
  texVerts[0].y = 0.f;
  texVerts[0].a = 255.f;
  texVerts[0].oow = 1.f;
  texVerts[0].tmuvtx[0].sow = 0.f * texVerts[0].oow;
  texVerts[0].tmuvtx[0].tow = 255.f * texVerts[0].oow;

  texVerts[1].x = wWidth;
  texVerts[1].y = 0.f;
  texVerts[1].a = 255.f;
  texVerts[1].oow = 1.f;
  texVerts[1].tmuvtx[0].sow = 255.f * texVerts[1].oow;
  texVerts[1].tmuvtx[0].tow = 255.f * texVerts[1].oow;

  texVerts[2].x = wWidth;
  texVerts[2].y = wHeight;
  texVerts[2].a = 255.f;
  texVerts[2].oow = 1.f;
  texVerts[2].tmuvtx[0].sow = 255.f * texVerts[2].oow;
  texVerts[2].tmuvtx[0].tow = 0.f * texVerts[2].oow;
  
  texVerts[3].x = 0.f;
  texVerts[3].y = wHeight;
  texVerts[3].a = 255.f;
  texVerts[3].oow = 1.f;
  texVerts[3].tmuvtx[0].sow = 0.f * texVerts[3].oow;
  texVerts[3].tmuvtx[0].tow = 0.f * texVerts[3].oow;
  
  if (bgFileName == NULL)
    bgFileName = "miro.3df";
  if (triFileName == NULL)
    triFileName = "matt1.3df";

  if ( gu3dfGetInfo( bgFileName, &bgInfo ) )  {
     bgInfo.data = malloc( bgInfo.mem_required );

     if ( bgInfo.data == 0 ) {
       fprintf( stderr, "out of memory for texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }

     if ( !gu3dfLoad( bgFileName, &bgInfo ) ) {
       fprintf( stderr, "could not load texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }

     bgDecal = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
                                  bgInfo.header.width, bgInfo.header.height,
                                  bgInfo.header.format,
                                  GR_MIPMAP_NEAREST,
                                  bgInfo.header.small_lod, bgInfo.header.large_lod,
                                  bgInfo.header.aspect_ratio,
                                  GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                  GR_TEXTUREFILTER_BILINEAR, GR_TEXTUREFILTER_BILINEAR,
                                  0.0F,
                                  FXFALSE );
     if ( bgDecal == GR_NULL_MIPMAP_HANDLE ) {
       fprintf( stderr, "could not allocate memory for texture file %s\n", bgFileName );
       grGlideShutdown();
       exit( -1 );
     }
     guTexDownloadMipMap( bgDecal, bgInfo.data, &bgInfo.table.nccTable );
     free( bgInfo.data );
  } else {
    fprintf( stderr, "could not get info on %s\n", bgFileName );
    grGlideShutdown();
    exit( -1 );
  }
  
  if ( gu3dfGetInfo( triFileName, &triInfo ) )  {
    triInfo.data = malloc( triInfo.mem_required );
    
    if ( triInfo.data == 0 ) {
      fprintf( stderr, "out of memory for texture file  %s\n", triFileName );
      grGlideShutdown();
      exit( -1 );
    }
    
    if ( !gu3dfLoad( triFileName, &triInfo ) ) {
      fprintf( stderr, "could not load texture file %s\n", triFileName );
      grGlideShutdown();
      exit( -1 );
    }

    triDecal = guTexAllocateMemory( 0, GR_MIPMAPLEVELMASK_BOTH,
                                    triInfo.header.width,  
                                    triInfo.header.height, 
                                    triInfo.header.format,
                                    GR_MIPMAP_NEAREST,
                                    triInfo.header.small_lod,
                                    triInfo.header.large_lod, 
                                    triInfo.header.aspect_ratio,
                                    GR_TEXTURECLAMP_WRAP,
                                    GR_TEXTURECLAMP_WRAP, 
                                    GR_TEXTUREFILTER_BILINEAR,
                                    GR_TEXTUREFILTER_BILINEAR, 
                                    0.0F,
                                    FXFALSE );
    if ( triDecal == GR_NULL_MIPMAP_HANDLE ) {
       fprintf( stderr, "could not allocate memory for %s\n", triFileName );
       grGlideShutdown();
       exit( -1 );
     }
     guTexDownloadMipMap( triDecal, triInfo.data, &triInfo.table.nccTable );
     free( triInfo.data );
  } else {
    fprintf( stderr, "could not get info on %s\n", triFileName );
    grGlideShutdown();
    exit( -1 );
  }

  grTexCombineFunction(GR_TMU0, GR_TEXTURECOMBINE_DECAL);
  grRenderBuffer(backbuffer == FXTRUE ? GR_BUFFER_BACKBUFFER : GR_BUFFER_FRONTBUFFER);
  guAlphaSource( GR_ALPHASOURCE_ITERATED_ALPHA );
  grAlphaBlendFunction( GR_BLEND_SRC_ALPHA, GR_BLEND_ONE_MINUS_SRC_ALPHA, GR_BLEND_ONE, GR_BLEND_ZERO );
  grAlphaTestFunction( GR_CMP_ALWAYS );
  
  while ( 1 ) {
    Matrix rotm;
    GrVertex xformedVerts[NVERTS];
    int i;
    int ilist[NVERTS];

    ++nFrames;

    for (i = 0; i < NVERTS; i++)
      ilist[i] = i;

    MatMakeYRot( rotm, DEG2RAD( y_angle ) );
    
    for( i = 0; i < NVERTS; i++ ) {
      PointMatMult( &xformedVerts[i], &localVerts[i], rotm );
      xformedVerts[i].x = xformedVerts[i].x / ( xformedVerts[i].z + 2.0f );
      xformedVerts[i].y = xformedVerts[i].y / ( xformedVerts[i].z + 2.0f );
      xformedVerts[i].x *= wHeight / 2.0f;
      xformedVerts[i].y *= wHeight / 2.0f;
      xformedVerts[i].x += wHeight / 2.0f;
      xformedVerts[i].y += wHeight / 2.0f;
      xformedVerts[i].oow = 1.f / ((xformedVerts[i].z + 2) * wHeight);
      xformedVerts[i].tmuvtx[0].sow *= xformedVerts[i].oow;
      xformedVerts[i].tmuvtx[0].tow *= xformedVerts[i].oow;
      SNAP_COORD( xformedVerts[i].x );
      SNAP_COORD( xformedVerts[i].y );
    }
    
    guColorCombineFunction( ccFnc );
    
    grLfbBypassMode(GR_LFBBYPASS_ENABLE);

    if (render == FXTRUE) {
      grBufferClear( 0xffffffff, 0, GR_WDEPTHVALUE_FARTHEST );

   
      if (background == FXTRUE) {
        GrState
          oldState;

        grGlideGetState(&oldState);

        grAlphaBlendFunction(
                             GR_BLEND_ONE, GR_BLEND_ZERO,
                             GR_BLEND_ONE, GR_BLEND_ZERO);

        grColorCombine(
                       GR_COMBINE_FUNCTION_SCALE_OTHER,
                       GR_COMBINE_FACTOR_ONE,
                       GR_COMBINE_LOCAL_NONE,
                       GR_COMBINE_OTHER_TEXTURE, FXFALSE
                       );

        guTexSource(bgDecal);
        
        grDrawTriangle(&texVerts[0], &texVerts[1], &texVerts[2]);
        grDrawTriangle(&texVerts[2], &texVerts[3], &texVerts[0]);

        grGlideSetState(&oldState);

      }

      if (texturing == FXTRUE)
        guTexSource(bgDecal);

      if (texturing)
        guTexSource(triDecal);

      if (lines == FXTRUE) {
        for (i = 0; i < NVERTS - 1; i++)
          if (antialias == FXTRUE) 
            grAADrawLine(&xformedVerts[i], &xformedVerts[i+1]);
          else
            grDrawLine(&xformedVerts[i], &xformedVerts[i+1]);
        grAADrawLine(&xformedVerts[NVERTS-1], &xformedVerts[0]);
      } else {
        if (antialias == FXTRUE) {
          grAADrawPolygon(NVERTS, ilist, xformedVerts);
        } else {
          grDrawPolygon(NVERTS, ilist, xformedVerts);
        }
      }


      if (backbuffer) {
        grBufferSwap( 1 );
      }
    }
    
    if (kbhit()) {
      char c = getch();
      
      switch (c) {
      case 'a':
      case 'A':
        if (antialias == FXFALSE) {
          printf("Turning ON Antialiasing\n");
          antialias = FXTRUE;
        } else {
          printf("Turning OFF Antialiasing\n");
          antialias = FXFALSE;
        }
        break;
      case 'B':
      case 'b':
        if (bilinear == FXFALSE) {
          bilinear = FXTRUE;
          printf("Turning ON BiLinear blending\n");
          guTexChangeAttributes(
                                triDecal, bgInfo.header.width,
                                bgInfo.header.height, 
                                bgInfo.header.format, GR_MIPMAP_NEAREST,
                                bgInfo.header.small_lod,
                                bgInfo.header.large_lod, 
                                bgInfo.header.aspect_ratio,
                                GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                GR_TEXTUREFILTER_BILINEAR,
                                GR_TEXTUREFILTER_BILINEAR);
        } else {
          bilinear = FXFALSE;
          printf("Turning OFF BiLinear blending\n");
          guTexChangeAttributes(
                                triDecal, bgInfo.header.width,
                                bgInfo.header.height, 
                                bgInfo.header.format, GR_MIPMAP_NEAREST,
                                bgInfo.header.small_lod,
                                bgInfo.header.large_lod,
                                bgInfo.header.aspect_ratio, 
                                GR_TEXTURECLAMP_WRAP, GR_TEXTURECLAMP_WRAP,
                                GR_TEXTUREFILTER_POINT_SAMPLED,
                                GR_TEXTUREFILTER_POINT_SAMPLED);
        }
        break;

      case 'c':
      case 'C':
        if (blend == FXTRUE) {
          blend = FXFALSE;
          for (i = 0; i < NVERTS; i++)
            localVerts[i].a = 255.f;
        } else {
          blend = FXTRUE;
          for (i = 0; i < NVERTS; i++)
            localVerts[i].a = alpha;
        }
        break;

      case 'd':
      case 'D':
        printf("vtxa = (%.2f, %.2f), vtxb = (%.2f, %.2f), vtxc = (%.2f, %.2f)\n",
               xformedVerts[0].x, xformedVerts[0].y,
               xformedVerts[1].x, xformedVerts[1].y,
               xformedVerts[2].x, xformedVerts[2].y
               );
        break;

      case 'f':
      case 'F':
        if (backbuffer == FXTRUE) {
          backbuffer = FXFALSE;
          grRenderBuffer(GR_BUFFER_FRONTBUFFER);
        } else {
          backbuffer = FXTRUE;
          grRenderBuffer(GR_BUFFER_BACKBUFFER);
        }
        break;

      case 'g':
      case 'G':
        grLfbBegin();

        grLfbWriteMode(GR_LFBWRITEMODE_565);
        grLfbOrigin(GR_ORIGIN_UPPER_LEFT);
        grLfbGetReadPtr(GR_BUFFER_FRONTBUFFER);
        printf("Press a key to get front buffer\n");
        while (!kbhit());
        c = getch();
        guFbReadRegion(0,0,(int)wWidth,(int)wHeight,scrnImage,(int)wWidth * sizeof(FxU16));
        printf("Press a key to put image in back buffer and swap\n");
        while (!kbhit());
        getch();

        grLfbGetWritePtr(GR_BUFFER_BACKBUFFER);
        guFbWriteRegion(0,0,(int)wWidth,(int)wHeight,scrnImage,(int)wWidth * sizeof(FxU16));
        grBufferSwap(1);

        printf("Press a key to continue...\n");
        while (!kbhit());
        getch();

        grLfbEnd();

        break;

      case 'h':
      case 'H':
      case '?':
        grSstPassthruMode(GR_PASSTHRU_SHOW_VGA);
        printf("Keymap:\n");
        printf("        A or a:         toggle Antialiasing\n");
        printf("        B or b:         toggle Bilinear\n");
        printf("        F or f:         toggle Front buffer \n");
        printf("        H, h, or ?:     Help\n");
        printf("        I or i:         toggle background Image\n");
        printf("        P or p:         Pause rendering\n");
        printf("        Q or q:         Quit\n");
        printf("        S or s:         toggle hidden Surface removal (backface culling)\n");
        printf("        T or t:         toggle Texturing\n");
        printf("Press a key to continue...\n");
        getch();
        grSstPassthruMode(GR_PASSTHRU_SHOW_SST1);
        break;

      case 'i':
      case 'I':
        if (background == FXTRUE) {
          background = FXFALSE;
          printf("Turning off background\n");
        } else {
          printf("Turning on background\n");
          background = FXTRUE;
        }
        break;
      case 'l':
      case 'L':
        if (lines == FXTRUE) {
          lines = FXFALSE;
          printf("Turning OFF lines\n");
        } else {
          lines = FXTRUE;
          printf("Turning ON lines\n");
        }
        break;
      case 'm':
      case 'M':
        ccFnc = GR_COLORCOMBINE_TEXTURE_TIMES_ITRGB;
        break;

      case 'p':
      case 'P':
        if (render == FXTRUE)
          render = FXFALSE;
        else
          render = FXTRUE;
        break;
        
      case 'q':
      case 'Q':
        grGlideShutdown();
        exit(0);
        break;

      case 'S':
      case 's':
        if (cullMode == GR_CULL_DISABLE) {
          cullMode = GR_CULL_NEGATIVE;
          printf("Turning ON backface culling (hidden Surface removal)\n");
        } else  {
          cullMode = GR_CULL_DISABLE;
          printf("Turning OFF backface culling (hidden Surface removal)\n");
        }
        grCullMode(cullMode);
        break;
      case 'T':
      case 't':
        if (texturing == FXFALSE) {
          printf("Turning ON texturing\n");
          ccFnc = GR_COLORCOMBINE_DECAL_TEXTURE;
          texturing = FXTRUE;
        } else {
          printf("Turning OFF texturing\n");
          ccFnc = GR_COLORCOMBINE_ITRGB;
          texturing = FXFALSE;
        }
        break;
        
      }
    }
    
    if (render) {
      y_angle += 2.f;
      if( y_angle > 360.0f )
        y_angle -= 360.0f;
    }
    frameCount++;
    if(frameCount < 0)
      frameCount = 0;
    if(frameCount == numFrames)
      break;
  }
  grGlideShutdown();
}