REM. Warping bitmap
     REM. Requires GFXLIB version 2.03 or higher


     
*ESC OFF


     *FLOAT 64


     ON ERROR PROCerror( REPORT$, TRUE )


     REM. Make 5 MB of RAM available for this program
     
M% = 5
     HIMEM = LOMEM + M%*&100000


     REM. Set window title
     
ProgTitle$ = "Warping bitmap"
     SYS "SetWindowText", @hwnd%, ProgTitle$


     REM. Set window dimensions
     
WinW% = 480
     WinH% = 480
     PROCfixWindowSize
     VDU 23, 22, WinW%; WinH%; 8, 16, 16, 0 : OFF


     
REM. Install and initialise GFXLIB and required modules
     
INSTALL @lib$ + "GFXLIB2.BBC"                          : PROCInitGFXLIB

     IF VAL( GFXLIBVersion$ ) < 2.03 THEN
       PROC
error( "Sorry, GFXLIB version 2.03 or higher is required to run this program.", FALSE )
     ENDIF

     INSTALL
@lib$ + "GFXLIB_modules\ClrX.BBC"              : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\PlotRotateScale2.BBC"  : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\BPlotBMRow.BBC"        : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\BPlotBMRowList.BBC"    : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\BPlotBMColumn.BBC"     : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\BPlotBMColumnList.BBC" : PROCInitModule


     GetTickCount% = FNSYS_NameToAddress( "GetTickCount" )


     REM. Load the 400x96 "GFXLIB" graphic
     
bm% = FNLoadBMP( @dir$ + "gfxlib_400x96x8.BMP", 0 )


     REM. Set up two internal 480x480 32bpp bitmap buffers
     
bm2% = FNmalloc( 4 * 480 * 480 )
     bm3% = FNmalloc( 4 * 480 * 480 )


     REM. Set up bitmap pixel rows and columns lists
     REM. (for use with GFXLIB_BPlotBMRowList and GFXLIB_BPlotBColumnList)
     
DIM rowList{(479) row%, x%, y%}
     DIM colList{(479) col%, x%, y%}

     FOR I% = 0 TO 479
       rowList{( I% )}.row% = I%
       rowList{( I% )}.y%   = I%
       colList{( I% )}.col% = I%
       colList{( I% )}.x%   = I%
     NEXT I%


     REM. Bitmap rotation angle
     
angle = 0


     REM. Frame counter (gets reset every second)
     
numFrames% = 0


     REM. Start the timer
     
SYS GetTickCount% TO time0%


     REM. Turn off automatic window refresh
     
*REFRESH OFF



     REM. +---------------+
     REM. | The main loop |
     REM. +---------------+

     
REPEAT

       
REM. Clear the main program window
       
SYS GFXLIB_Clr%, dispVars{}, 0

       REM. Set up some time-dependent values
       
T% = TIME
       
a = T% / 100
       b = T% / 500
       c = 32*SIN(T% / 1000)
       d = T% / 333

       REM. This loop could be made more efficient
       
FOR I% = 0 TO 479
         rowList{(I%)}.x% = 64 * SIN(I%/100 + a) * COS(I%/300 + b)
         colList{(I%)}.y% = 64 * COS(I%/200 + c) * SIN(I%/450 + d)
       NEXT

       
REM. Make the angle and scale of the 480x480 "GFXLIB" bitmap vary with time
       
angle = 360 * SIN(T%/1000)*COS(T%/2000)
       scale = 3 + 2*SIN(T%/500)

       REM. Render the rotated and scaled "GFXLIB" bitmap to bm2
       
SYS GFXLIB_ClrX%, dispVars{}, bm2%, 480, 480, 0
       SYS GFXLIB_SaveDispVars%, dispVars{}
       SYS GFXLIB_SetDispVars2%, dispVars{}, bm2%, 480, 480
       SYS GFXLIB_PlotRotateScale2%, dispVars{}, bm%, 400, 96, 240, 240, &100000*angle, &100000*scale
       SYS GFXLIB_RestoreDispVars%, dispVars{}

       REM. Write the horizontal pixel rows of bm2 to bm3
       
SYS GFXLIB_ClrX%, dispVars{}, bm3%, 480, 480, 0
       SYS GFXLIB_SaveDispVars%, dispVars{}
       SYS GFXLIB_SetDispVars2%, dispVars{}, bm3%, 480, 480
       SYS GFXLIB_BPlotBMRowList%, dispVars{}, bm2%, 480, 480, ^rowList{(0)}.row%, 480
       SYS GFXLIB_RestoreDispVars%, dispVars{}

       REM. Write the vertical pixel columns of bm3 to our program window
       
SYS GFXLIB_BPlotBMColumnList%, dispVars{}, bm3%, 480, 480, ^colList{(0)}.col%, 480

       REM. Update the program window
       
PROCdisplay

       REM. Increment frame number; update fps value every second
       
SYS GetTickCount% TO time1%
       IF time1%-time0% >= 1000 THEN
         SYS
"SetWindowText", @hwnd%, ProgTitle$ + " | " +STR$numFrames% + " fps"
         SYS GetTickCount% TO time0%
         numFrames% = 0
       ELSE
         
numFrames% += 1
       ENDIF

     UNTIL FALSE
     END
     
:
     :
     :
     :
     DEF PROCfixWindowSize
     LOCAL GWL_STYLE, WS_THICKFRAME, WS_MAXIMIZEBOX, ws%
     GWL_STYLE = -16
     WS_THICKFRAME = &40000
     WS_MAXIMIZEBOX = &10000
     SYS "GetWindowLong", @hwnd%, GWL_STYLE TO ws%
     SYS "SetWindowLong", @hwnd%, GWL_STYLE, ws% AND NOT (WS_THICKFRAME+WS_MAXIMIZEBOX)
     ENDPROC
     
:
     :
     :
     :
     DEF PROCerror( s$, L% )
     LOCAL hprocess%
     SYS "GetCurrentProcess" TO hprocess%
     SYS "SetPriorityClass", hprocess%, &20
     OSCLI "REFRESH ON" : ON
     COLOUR
1, &FF, &FF, &FF
     COLOUR 1
     PRINT TAB(1,1)s$;
     IF L% THEN
       PRINT
" at line "; ERL;
     ENDIF
     VDU
7
     REPEAT UNTIL INKEY(1)=0
     ENDPROC