REM  Vector balls 4


     REM  Demonstrates use of:
     REM
     REM      GFXLIB_Clr                     (dispVars, colour)
     REM      GFXLIB_DrawBmFont3             (dispVars, bmFontAddr, stringAddr, x, y, colour)
     REM      GFXLIB_SetDispVars             (dispVars, bmpBuffAddr, bmpBuffW, bmpBuffH, viewportX, viewportY, viewportW, viewportH, paintFlag)
     REM      GFXLIB_PlotScaleColourBlend    (dispVars, bmAddr, bmW, bmH, newW, newH, x, y, colour, strength)
     REM      GFXLIB_PlotSwapRGB             (dispVars, bmAddr, bmW, bmH, x, y, swapCode)
     REM


     REM
     REM  Disable the Escape key
     REM

     
*ESC OFF


     REM
     REM  Set up a simple error handler
     REM

     
ON ERROR OSCLI "REFRESH ON" : MODE 8 : VDU 7 : REPORT : PRINT " at line ";ERL : END


     
REM
     REM  Select 64-bit floating point mode (double-precision maths)
     REM

     
*FLOAT64


     REM
     REM  Prevent the program window from being resized by the user
     REM

     
SYS "GetWindowLong", @hwnd%, -16 TO S%
     SYS "SetWindowLong", @hwnd%, -16, S% AND NOT &50000
     SYS "SetWindowPos", @hwnd%, 0, 0, 0, 0, 0, 32+7


     REM
     REM  Setup a 640x512 display mode, and turn OFF the flashing cursor
     REM

     
MODE 8
     OFF


     
REM
     REM  Install and initialise GFXLIB and install external modules
     REM

     
INSTALL @lib$ + "GFXLIB2"
     PROCInitGFXLIB

     INSTALL @lib$ + "GFXLIB_modules\PlotAlphaBlend3"        : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\DrawBmFont3"            : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\PlotScaleTintBlend"     : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\PlotShapeHalfIntensity" : PROCInitModule
     INSTALL @lib$ + "GFXLIB_modules\PlotSwapRGB"            : PROCInitModule


     GetTickCount% = FNSYS_NameToAddress( "GetTickCount" )


     REM
     REM  Install and initialise SORTLIB (which will be used to depth-sort the
     REM  'vector balls' according to their Z coordinate)
     REM

     
INSTALL @lib$+"SORTLIB"
     sort% = FN_sortinit(1,0)


     DIM bmAddrTbl%( 3 )


     REM
     REM  Load-in the sphere graphic (64x64 pixels, 24bpp) and convert to 32bpp
     REM

     
PROCLoadBMP(  @dir$ + "blueball_128x128x24.BMP", bmAddrTbl%(0), FALSE )
     PROCLoadBMP(  @dir$ + "blueball_128x128x24.BMP", bmAddrTbl%(1), FALSE )
     PROCLoadBMP(  @dir$ + "blueball_128x128x24.BMP", bmAddrTbl%(2), FALSE )
     PROCLoadBMP(  @dir$ + "blueball_128x128x24.BMP", bmAddrTbl%(3), FALSE )

     SYS GFXLIB_SetDispVars%, dispVars{}, bmAddrTbl%(0), 128, 128, 0, 0, 128, 128, TRUE
     SYS
GFXLIB_PlotSwapRGB%, dispVars{}, bmAddrTbl%(0), 128, 128, 0, 0, 0

     SYS GFXLIB_SetDispVars%, dispVars{}, bmAddrTbl%(1), 128, 128, 0, 0, 128, 128, TRUE
     SYS
GFXLIB_PlotSwapRGB%, dispVars{}, bmAddrTbl%(1), 128, 128, 0, 0, 1

     SYS GFXLIB_SetDispVars%, dispVars{}, bmAddrTbl%(2), 128, 128, 0, 0, 128, 128, TRUE
     SYS
GFXLIB_PlotSwapRGB%, dispVars{}, bmAddrTbl%(2), 128, 128, 0, 0, 2

     SYS GFXLIB_SetDispVars%, dispVars{}, bmAddrTbl%(3), 128, 128, 0, 0, 128, 128, TRUE
     SYS
GFXLIB_PlotSwapRGB%, dispVars{}, bmAddrTbl%(3), 128, 128, 0, 0, 3

     SYS GFXLIB_SetDispVars%, dispVars{}, dibs%, 640, 512, 0, 0, 640, 512, TRUE


     PROC
LoadData( @dir$ + "Arial_16pt_32bpp_white.DAT", fontData%, 0 )


     N% = 50  : REM  Number of spheres

     
DIM bmAddr%( N%-1 ), bmAddr2%( N%-1 )
     DIM x%(N%-1), y%(N%-1), z%(N%-1)     : REM  Arrays to hold the sphere's position in 3D space
     
DIM x2%(N%-1), y2%(N%-1), z2%(N%-1)  : REM  Arrays to hold the sphere's position in 3D space *after* it's been rotated

     
minDist% = 100

     FOR I%=0 TO N%-1
       REPEAT
         
valid% = TRUE
         
x%=-400+RND(2*400 - 1)
         y%=-400+RND(2*400 - 1)
         z%=-400+RND(2*400 - 1)
         IF I%=0 THEN
           
x%(0) = x%
           y%(0) = y%
           z%(0) = z%
         ELSE
           FOR
J%=0 TO I%
             d% = SQR( (x%-x%(J%))^2 + (y%-y%(J%))^2 + (z%-z%(J%))^2 )
             IF d% < minDist% THEN
               
valid% = FALSE
               
J% = I%
             ENDIF
           NEXT
J%
         ENDIF
       UNTIL
valid%
       x%(I%) = x%
       y%(I%) = y%
       z%(I%) = z%
       bmAddr%( I% ) = bmAddrTbl%( RND(4)-1 )
     NEXT I%

     a#=0
     b#=0
     c#=0

     D% = dispVars{}
     P% = GFXLIB_PlotScaleTintBlend%
     Q% = GFXLIB_PlotShapeHalfIntensity%

     frames% = 0

     dispFrames% = 0

     *REFRESH OFF

     SYS GetTickCount% TO time0%

     REPEAT

       
REM
       REM  Compute the time-dependent background colour
       REM

       
bgCol% = &10000*INT(255*ABSSINRAD(TIME/4.5)) + &100*INT(255*ABSSINRAD(TIME/6.7)) + INT(255*ABSCOSRAD(TIME/6.83))


       REM
       REM  Clear the viewport
       REM

       
SYS GFXLIB_Clr%, D%, bgCol%


       REM
       REM  Rotate the 3D positions of the spheres
       REM

       
cosa# = COSa#
       cosb# = COSb#
       cosc# = COSc#
       sina# = SINa#
       sinb# = SINb#
       sinc# = SINc#

       FOR I%=0 TO N%-1

         x# = x%(I%)
         y# = y%(I%)
         z# = z%(I%)

         x1# = x#*cosa# - y#*sina#
         y1# = x#*sina# + y#*cosa#
         z1# = z#

         y2# = y1#*cosb# - z1#*sinb#
         z2# = y1#*sinb# + z1#*cosb#
         x2# = x1#

         z3# = z2#*cosc# - x2#*sinc#
         x3# = z2#*sinc# + x2#*cosc#
         y3# = y2#

         x2%(I%) = x3#
         y2%(I%) = y3#
         z2%(I%) = z3#

       NEXT I%


       REM
       REM  Sort the rotated X, Y, Z coordinate arrays according to the Z coordinate
       REM

       
bmAddr2%() = bmAddr%()

       C%=N% : CALL sort%, z2%(0), x2%(0), y2%(0), bmAddr2%(0)

       REM
       REM  Draw the actual spheres
       REM

       
FOR I%=0 TO N%-1
         d# = 1/(&3E8+z2%(I%))
         X% = &140 + &2A8 * x2%(I%) * d#
         Y% = &100 + &2A8 * y2%(I%) * d#
         Z% = &80*(&3E8-(z2%(I%)+&1F4))/&3E8
         SYS P%, D%, bmAddr2%(I%), 128, 128, Z%, Z%, X%, Y%, bgCol%, 256*(z2%(I%)+400)/800
       NEXT

       SYS
GFXLIB_DrawBmFont3%, D%, fontData%, "Frame rate: "+STR$dispFrames%+" fps", 7, 479, &000000
       SYS GFXLIB_DrawBmFont3%, D%, fontData%, "Frame rate: "+STR$dispFrames%+" fps", 8, 480, &40FF00

       REM
       REM  Bump then check the rotation angles
       REM

       
a# += 0.019151
       b# += 0.016316
       c# += 0.012194

       IF a# > 2*PI THEN a# -= 2*PI
       IF
b# > 2*PI THEN b# -= 2*PI
       IF
c# > 2*PI THEN c# -= 2*PI

       SYS
GetTickCount% TO time1%
       IF time1%-time0% >= 1000 THEN
         
dispFrames% = frames%
         frames% = 0
         SYS GetTickCount% TO time0%
       ENDIF

       PROC
display

       frames% += 1

     UNTIL FALSE