           Subject: The Programmer`s Circle & Sphere Routine Library
                By: James Collett (Professor)
       A Member Of: VIRTUAL INFINITY
              Date: May 1994
           Address: Park View Farm, Carlton, Nr Nuneaton, Warks, CV13 ODA
          Internet: s6005146@brookes.ac.uk
      Mono Account: bcc


    Copyright
    =========
        This  library may be freely COPIED and DISTRIBUTED *providing*  the 
    following three conditions are met ...

      1) All files must stay together:

      CIRC&SPH.BCC\INTRO.TXT    - This info file
      CIRC&SPH.BCC\CIRCLES\*.*  - Contains four source files & an info file
      CIRC&SPH.BCC\SPHDEMO\*.* - Contains four binary files & an info file
      CIRC&SPH.BCC\SPH_CODE\*.* - Contains six source files & an info file
      CIRC&SPH.BCC\WAVES\*.*    - Contains two source files

      2) My name, Professor of VIRTUAL INFINITY, must stay with the library

      3) NO financial profit must be made

        The library may be freely MODIFIED and IMPLEMENTED *providing*  the 
    following three conditions are met ...

      1) Copies of all the original files must be kept and distributed with 
      any modified source files

      2) Credit must be given to me on any new routines or implementations, 
      for example "sphere`s based on code by Professor of VIRTUAL INFINITY"

      3) NO financial profit must be made


    Intro To The Library
    ====================
        If  you  have  seen some of my previous GFA  screens  (for  example 
    the disters,  infinite sprites,  star-fields,  rotating globe) you  may 
    have noticed I,  like many demo coders, use trigonometry a fair bit.  I 
    thought it was about time I revealed a secret or two about the  circle! 
    This library is aimed at programmers,  NOT mathematicians,  and I  have 
    tried  to  leave  as much maths as possible out of  the  source  codes. 
    Therefore  I`m  going to discuss the maths a little bit in  this  file, 
    along with give a few instructions on using the library.


    About The Library
    =================
        All the routines in this library have been written in GFA 3.5e  and 
    implemented  in ST low resolution (320 * 200).   The source files  have 
    deliberately been left in ASCII format to allow them to be converted to 
    other  languages,  [which is permitted providing the conditions  listed 
    above are met].

        With  the  exception of CIRC&SPH.BCC\WAVES\*.*,  each  source  file 
    contains a brief,  internal description of what the routine does.  Each 
    folder which contains sources,  also contains an info file which  lists 
    the descriptions for all the sources within that folder -- for  example 
    the  info  file in CIRC&SPH.BCC\CIRCLES\ contains listings of  all  the 
    descriptions for all the sources within CIRC&SPH.BCC\CIRCLES\.


    Using The Library
    =================
        Finally  the bit you`re interested in!   The actual source  library 
    consists  of  three  folders,  which should be read &  studied  in  the 
    following recommended order:

    CIRC&SPH.BCC\WAVES\*.*    - Trig. functions used to make arcs & circles
    CIRC&SPH.BCC\CIRCLES\*.*  - Selection of circle routines
    CIRC&SPH.BCC\SPH_CODE\*.* - Example implementation of the sphere

        The fourth folder included,  CIRC&SPH.BCC\SPHDEMO\, contains a few 
    executable (binary) files which I wrote earlier this year.


    Wave & Circle Technical Notes
    =============================
        Perhaps  surprisingly,  or  perhaps obviously,  there are  lots  of 
    routines and algorithms around for drawing circles, everybody has their 
    own  idea of what makes a particular 'circle routine' good or  bad.   I 
    use  two  basic  methods to draw circles,  which I  called  the  "angle 
    method"  and  the "axis method" (discussed  shortly).   Both  of  these 
    methods have good points & bad points;  both are suitable for different 
    jobs;   and   I  actually  incorporate  both  methods  in   my   sphere 
    implementation (discussed later).

        "Angle Method":
        ~~~~~~~~~~~~~~~
        A  circle contains 360 degrees - everyone knows that from  using  a 
    protractor  or magnetic compass!   Although degrees is a good scale  to 
    use from a 'human' point of view,  it`s unfortunately not a good  scale 
    from  a  'computer language' point of  view!   (High  level)  languages 
    provide two functions called COS and SIN, which respectively return the 
    horizontal (X axis) and vertical (Y axis) co-ordinate components, given 
    the 'position' around the scale (e.g.  1/4 way around the circle or 2/3 
    way round the circle).  These two functions don`t use the degrees scale 
    [from 0 to 359],  but instead use a strange scale called RADIANS [which 
    goes  from 0 to 2*PI,  where PI is a magic constant ~=  3.14159].   For 
    example ...
                                X = COS(radian)
                                Y = SIN(radian)

        To draw a complete circle, all that needs to be done is to loop the 
    angle  {which  mathematicians  actually call  'theta'  -  they`re  even 
    stranger than programmers!} from 0 to 2*PI at a step of 2*PI/100,  say. 
    Then  at  each  'theta  position' (angle  position  around  the  scale) 
    calculate  the X and Y co-ordinates using the two functions and plot  a 
    point at those co-ordinates!  And that is basically it!  Basically ...

        The  two  functions assume the absolute origin  <X=0, Y=0>  is  the 
    centre  of the circle.   If you wish to set the origin to anywhere  you 
    have to add this to 'shift' the circle.   For example to set the origin 
    to <100,100> and 'shift' the circle across 100 and down 100 ...

                              X = 100+COS(theta)
                              Y = 100+SIN(theta)

        The two functions also assume the X and Y RADIUSES are 1,  which is 
    *tiny*  in  terms  of a computer  screen.   To  change  the  respective 
    radiuses (circle size) simply multiply the two functions by the  radius 
    factor.  And  that  really  is it!   From all this  an  "angle  method" 
    algorithm can be written ...

           x_abs=160                     ! Absolute horizontal origin
           y_abs=100                     ! Absolute vertical origin
           x_rad=100                     ! X radius
           y_rad=50                      ! Y radius
           step=0.01                     ! Theta increment step

           FOR theta=0 TO 2*PI STEP step
             x=COS(theta)*x_rad
             y=SIN(theta)*y_rad
             PLOT(x_abs+x,y_abs+y)
           NEXT theta

        This  algorithm  loops  the angle theta from 0 to 2*PI  at  a  pre-
    defined step of 0.01.   At each 'theta position' (angle position around 
    the  scale) it calculates the X and Y co-ordinate components using  the 
    two functions and pre-defined radiuses.   The algorithm then plots each 
    point using an assumed function called PLOT.   Notice that the  'shift' 
    to  the  required origin <160,  100> has been moved to  the  line  that 
    actually plots the point.

        "Axis Method":
        ~~~~~~~~~~~~~~
        As already discussed,  (high level) languages provide two functions 
    called COS and SIN,  which respectively return the horizontal (X  axis) 
    and  vertical  (Y axis) co-ordinate components,  given  the  'position' 
    around  the circle in RADIANS [a scale from 0 to 2*PI,  where PI  is  a 
    magic constant ~=3.14159].  (High level) languages also provide another 
    two  functions  called  ACOS  and  ASIN (in  GFA  -  may  vary  between 
    languages).   These  do  the inverse to the first  two  functions,  and 
    respectively  return  the  angle  in  radians  given  the   co-ordinate 
    component for a circle with a RADIUS of 1.  For example ...

                                theta = ACOS(X)
                                theta = ASIN(Y)

       As already discussed with the "angle method", the X & Y co-ordinates 
    can  be determined given the angle (theta).   These  inverse  functions 
    allow theta & Y to be determined given X;  and also allow theta & X  to 
    be determined given Y ...
                               theta = ASIN(Y)
                                   X = COS(theta)

                              =>   X = COS(ASIN(Y))

        In other words,  given a horizontal (Y axis) line through a circle, 
    the  vertical  (X  axis)  position of the point on  that  line  can  be 
    determined  easily!   To draw a complete circle,  all that needs to  be 
    done is to loop Y component from the circle`s top horizontal line  (-ve 
    Y radius) to the bottom horizontal line (+ve Y radius).   Then at  each 
    horizontal  line  (Y  component) calculate  the  vertical  position  (X 
    component)  using  the inverse functions and plot a point at  that  co-
    ordinate!  And that is basically it!  Basically ...

        As  I hope you`ve already realised,  there are two points  on  each 
    horizontal line: one +ve and one -ve, relative to the absolute X origin 
    at  the centre of the circle!   The important thing to notice  is  that 
    both  points are equi-distant from the absolute,  although one +ve  and 
    the other -ve.  Each horizontal line contains the following two points, 
    where x_abs is the wished vertical origin or the amount to 'shift'  the 
    circle across by ...
                           X1 = x_abs + COS(ASIN(Y))
                           X2 = x_abs - COS(ASIN(Y))

        The  SIN  and COS functions return components for a circle  with  a 
    radius  of 1,  which then have to be multiplied by the  wished  factor. 
    Similarly the ASIN and ACOS functions assume the components passed  are 
    for  a circle with a radius of 1,  and therefore have to  be  initially 
    divided by the wished radius factor ...
    
                     X1 = x_abs + COS(ASIN(Y/y_rad))*x_rad
                     X2 = x_abs - COS(ASIN(Y/y_rad))*x_rad

        And  that really is it!   From all this an "axis method"  algorithm 
    can be written ...

           x_abs=160                    ! Absolute horizontal origin
           y_abs=100                    ! Absolute vertical origin
           x_rad=100                    ! X radius
           y_rad=50                     ! Y radius

           y=-y_rad
           WHILE y<=+y_rad
             theta=ASIN(y/y_rad)
             x=COS(theta)*x_rad
             PLOT(x_abs-x,y_abs+y)
             PLOT(x_abs+x,y_abs+y)
             INC y
           WEND

        This algorithm loops Y from the circle`s top horizontal line (-ve Y 
    radius) to the bottom horizontal line (+ve Y radius).   Then at each  Y 
    it calculates the X using the inverse functions and plots points  using 
    an  assumed  function called PLOT.   Notice that the  'shifts'  to  the 
    required origin <160,  100> have been moved to the lines that  actually 
    plot the points.

        In Summary:
        ~~~~~~~~~~~
        The  "angle method" determines the X and Y co-ordinate  components, 
    given the angle (theta) in radians ...

                             X = COS(theta)*x_rad
                             Y = SIN(theta)*y_rad

        The  "axis  method"  determines the angle (in radians)  and  two  X 
    components, given the Y component ...

                          theta = ASIN(Y/y_rad)
                             X1 = +COS(theta)*x_rad
                             X2 = -COS(theta)*x_rad


    Sphere Technical Notes
    ======================
        Before  you  study the sphere sources,  I recommend you  study  the 
    circle sources.   Before you read these notes, I recommend you read the 
    circle notes (above) and either understand the maths or accept the code 
    in the summary (directly above).

        Once you know how the circle "angle method" and "axis method" work, 
    the  sphere sources should hopefully speak for themselves.   {In  other 
    words,  you`ll probably have to read the following notes to  understand 
    what the sources are going on about!}

        "Scaffold" Concept:
        ~~~~~~~~~~~~~~~~~~~
        The  most  important  diagram to keep in mind  is  not  the  actual 
    sphere, but the invisible "scaffolding" on which the sphere is built.

        In the case of a sphere about the Y axis,  the scaffold consists of 
    the Y axis itself and a number of parallel XZ planes about the Y axis:

                         -ve Y
                  ---------|---------
                 ----------|----------
                -----------|-----------   Side view of sphere showing
               ------------|------------    XZ planes about Y axis.
              -------------|-------------
             --------------O--------------         Y|
              -------------|-------------           |
               ------------|------------            |
                -----------|-----------             |
                 ----------|----------              +-------
                  ---------|---------                      X
                         +ve Y

        The central plane,  which I call the 'absolute  plane',  intersects 
    the absolute origin <X=0, Y=0, Z=0>, indicated with 'O' on the diagram. 
    There are a number of parallel, equi-distant planes above the absolute; 
    and a number of parallel, equi-distant planes below the absolute plane.

        In the case of a sphere about the X axis,  the scaffold consists of 
    the X axis itself and a number of parallel YZ planes about the X  axis. 
    The 'absolute plane' intersects the absolute origin <0,0,0>.  There are 
    a number of parallel,  equi-distant planes LEFT of the absolute;  and a 
    number of parallel, equi-distant planes right of the absolute plane.

        For  the purposes of these notes,  I shall only explain the Y  axis 
    model (refer to diagram above) and leave you to "convert" everything to 
    the X axis model.

        Building A Sphere, In Theory:
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        If a circle (or 'ring') were to be drawn on each XZ plane, all with 
    constant X and Z radiuses, then a cylinder would be observed.

        If  a 'ring' were to be drawn on each plane,  but instead of  using 
    constant radiuses the radiuses incremented & decremented as illustrated 
    in the diagram,  then a sphere would be observed!   The radius of  each 
    'ring'  can  be  calculated from the position on the  Y  axis  and  the 
    inverse  functions  (ASIN),  i.e.  the  radius of each  'ring'  can  be 
    calculated  using  the "axis method".   Each 'ring' can then  be  drawn 
    using either of the methods, though the "angle method" is preferable if 
    the sphere is to be rotated at a later stage.

        Building A Sphere, In Practice:
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        From this an algorithm can be written to draw a sphere about the  Y 
    axis ...

      x_abs=160                    ! Absolute horizontal origin
      y_abs=100                    ! Absolute vertical origin
      x_maxrad=60                  ! X radius at "absolute ring"
      z_maxrad=15                  ! Z radius at "absolute ring"
      y_half=6                     ! Number of rings above|below absolute
      y_dist=10                    ! Y distance between rings
      xz_step=0.03                 ! Theta increment step
      
      y_total=y_half*2+1           ! [Total number of rings]
      y_maxrad=y_half*y_dist       ! [Y radius]

      FOR xz_theta=0 TO 2*PI STEP xz_step
        y_count=-y_half
        WHILE y_count<=+y_half
          y_or=y_abs+y_count*y_dist

          y_costheta=COS(ASIN(y_count/y_half))
          x_rad=y_costheta*x_maxrad
          z_rad=y_costheta*z_maxrad

          x=COS(xz_theta)*x_rad
          z=SIN(xz_theta)*z_rad
          PLOT(x_abs+x,y_or+z)

          INC y_count
        WEND
      NEXT xz_theta

        Before I run through what the actual loops do,  let me just explain 
    some of the pre-defined constants.   Y_half should be set to the number 
    of  parallel,  equi-distant  plane 'rings' above and  below  the  plane 
    'ring'  which intersects the absolute origin <0,0,0>:  for  example  in 
    this algorithm there are 6 rings above the absolute and 6 rings  below. 
    The total number of rings [y_total] is calculated as y_half*2 + 1:  for 
    example 13 in this case.

        Y_dist should be set to the (pixel) distance between  rings.   From 
    this the Y radius [y_maxrad] can be calculated:  60 in this  case,  the 
    same as the X radius.  Notice that the two constants in square brackets 
    are  not  used  by the algorithm,  they are simply  included  for  user 
    reference.

        The algorithm loops the angle theta through 2*PI radians at a  pre-
    defined step of 0.03.   At each 'theta position' (angle position around 
    the scale) it loops Y from the sphere`s top plane (-ve Y radius) to the 
    bottom plane (+ve Y radius).  Then at each Y, at each theta, it firstly 
    calculates the X & Z radiuses (using the inverse  functions);  secondly 
    calculates  the  X & Z components (using the  radiuses  &  theta);  and 
    thirdly  plots a point using an assumed function called  PLOT.   Notice 
    that  each  'ring' needs a 'local' Y origin,  y_or,  but  can  use  the 
    absolute X origin, x_abs.

        Rotation & Animation ('@'), Intro & Theory:
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        All the sources which rotate contain a number of lines marked  with 
    '@'  and  otherwise  undocumented.   These lines  don`t  actually  have 
    anything to do with the sphere itself!   They`re included to perform  a 
    bit of "magic" (explained shortly) and smooth the sphere animation out, 
    as it flickers and is "jerky" without them.

        [If you wish to erase or 'rem out' the seven '@' lines in the  main 
    programs you may,  providing you keep copies of the originals for  your 
    own  use and for the distribution conditions - though removing the  '@' 
    lines will make the animation far from flicker free.   Note the  eighth 
    '@' line in the PAGEFLIP procedure can be left unaltered.]

        This isn`t the time or place to discuss in detail what these  lines 
    do,  as  they`re not directly relevant to the sphere,  but  here`s  the 
    rough idea.   The computer actually has two screens: a 'view screen' or 
    read screen (physical screen);  and an 'update screen' or write  screen 
    (logical screen).   When the system is started (i.e. when you power the 
    computer up),  both these screens use the same bitmap (pixel list),  so 
    that when a pixel is updated the change can instantly be viewed:

                    'View screen' ----->  +-----------------+
                                          | "System" bitmap |
                  'Update screen' ----->  +-----------------+

        It  is  possible  to set it up so the  two  screens  use  different 
    bitmaps.   This can be done by creating a second bitmap, and moving one 
    of the screens to the bitmap:
                                        +-----------------+
                  'View screen' ----->  |  Second bitmap  |
                                        +-----------------+
                                         +-----------------+
                 'Update screen' ----->  | "System" bitmap |
                                         +-----------------+

        In  this case the second bitmap will be viewed,  but all  write  or 
    update  operations will take place in the "system" bitmap and won`t  be 
    seen.

        Rotation & Animation ('@'), Practice:
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        The  first  four '@' lines of the sources which  animate  create  a 
    second bitmap;  label it with a variable SCR1%;  and label the "system" 
    bitmap with a variable SCR2%:
                                        +----- SCR1% -----+
                                        |  Second bitmap  |
                                        +-----------------+
                   'View screen' ----->  +----- SCR2% -----+
                                         | "System" bitmap |
                 'Update screen' ----->  +-----------------+

        The first time round the loop,  the fifth '@' line calls  procedure 
    PAGEFLIP,  which sets SCR1% to 'update' and SCR2% to 'view'.  The sixth 
    '@' line then swaps the two variable labels around, (the purpose of all 
    this will become clear in a moment):
                                          +----- SCR2% -----+
                  'Update screen' ----->  |  Second bitmap  |
                                          +-----------------+
                                         +----- SCR1% -----+
                   'View screen' ----->  | "System" bitmap |
                                         +-----------------+     State One
                                                                 
        The "system" bitmap being 'viewed' is,  of course, initially blank. 
    Meanwhile  the  first animation frame is secretly drawn on  the  second 
    bitmap.  The second time round the loop PAGEFLIP does exactly as it did 
    before,  it sets SCR1% to 'update' and SCR2% to 'view'.   The sixth '@' 
    line then swaps the two variable labels around:

                                        +----- SCR1% -----+
                  'View screen' ----->  |  Second bitmap  |
                                        +-----------------+
                                         +----- SCR2% -----+
                 'Update screen' ----->  | "System" bitmap |
                                         +-----------------+     State Two
                                                                 
        The  second bitmap being 'viewed' shows the first animation  frame. 
    Meanwhile the second animation frame is secretly drawn on the  "system" 
    bitmap.   The third time round the loop PAGEFLIP swaps the screens  and 
    the sixth line swaps the labels, so the 'view screen' is SCR1% which is 
    the  "system"  bitmap;  and the 'update screen' is SCR2% which  is  the 
    second bitmap (see State One).

        Now,  the "system" bitmap being 'viewed' shows the second animation 
    frame;  meanwhile the third frame is drawn on the second bitmap.   Each 
    time around the loop the program toggles between the two states.  While 
    each frame is being 'viewed', so the next frame is secretly drawn. This 
    means  all the updating processing is hidden and the result is  flicker 
    free animation.

        This continues until a key press is detected,  when the seventh '@' 
    line calls PAGEFLIP to reset to the default system setting:

                    'View screen' ----->  +-----------------+
                                          | "System" bitmap |
                  'Update screen' ----->  +-----------------+

        If  you  use  this  animation  technique,  which  is  called  'page 
    flipping',  it  is *VITALLY IMPORTANT* you reset to the default  system 
    setting  before  terminating  your program.   If  you  don`t  GEM  will 
    certainly get confused if your language doesn`t get confused first!!

        If  you didn`t understand any of this section about  animation  and 
    the  lines marked with '@',  then just see them as a bit of "magic"  to 
    smooth the sphere animation out,  as it flickers and is "jerky" without 
    them.   If you want any further information about animation or anything 
    discussed in this file,  please don`t hesitate to contact me.   May  be 
    one  day I`ll get round to writing a proper tutorial on  animation  and 
    page flipping, though may be not ...


    ***********************************************************************
    * Coming Soon To An ATARI Near You:                                   *
    * =================================                                   *
    *     Well,  they  say  you  need  an i486  minimum  to  do  -really- *
    * impressive things such as texture mapping.   I disagree.  Watch out *
    * for the GFA, advanced sphere library, including:                    *
    *                                                                  *
    *                Raytracing hi-color spheres on the ST                *
    *                                                                     *
    *              Raytracing hi-color spheres on the FALCON              *
    *                                                                     *
    *            "Wrapping" images around cylinders & spheres             *
    *                                                                     *
    *    Impossible??  Just wait and see!   The advanced sphere  library  *
    * will hopefully be released July 1994.                               *
    *                            ~ ~ ~ ~ ~                                *
    ***********************************************************************


    And Finally:
    ============
        Although there is no financial charge for the library,  support  is 
    appreciated.  You can support in two ways:

    1) by distributing the library to everyone you know, ensuring all files 
       remain together and unaltered,

    2) feedback:  all comments,  queries,  error / incompatibility reports, 
       ideas,  suggestions,  etc are welcome - both positive and  negative. 
       My postal and E-mail addresses are previously listed.


    ---END---
