/*
======================================================================
shells.c

Ernie Wright  02 Jun 05

This version has been modified to fit your TV.
====================================================================== */

/*
 * shells.c - Creates a shell using Pickover's generation method (see IEEE
 *     CG&A November 1989).  One light source.  This thing tends to bring ray
 *     tracers to their knees (lots of overlapping primitives, many quite
 *     tiny) - it's meant as a study of a realistic yet pathological database.
 *
 *     There are various additional characteristics which can be diddled with
 *     for different shell shapes (most pretty unrealistic, but there you go).
 *     See Pickover's article for more information.  Do "shells -?" to see the
 *     additional parameters which can be varied (listed at the end).
 *
 * Author:  Eric Haines
 *
 * Modified:  Antonio Costa, INESC
 *     Changed lib_get_opts to shells_get_opts
 *     Corrected bug with light source definition
 *     Changed several vars from COORD4 to COORD3
 *
 * Size factor determines the number of objects output.
 *      Total objects = 180*(2**SF) spheres
 *
 *      Size factor     # spheres    # squares
 *           1              360           1
 *           2              720           1
 *           3             1440           1
 *           4             2880           1
 *           5             5760           1
 */

#include <stdio.h>
#include <math.h>
#include "lwmod.h"
#include "def.h"
#include "lib.h"


static int size_factor;
static int output_format = 0;
static char *spdName = "Shells";

static  double  fgamma = 1.0 ;  /* 0.01 to 3 */
static  double  alpha = 0.0 ;   /* > 1 - 1.1 is good */
static  double  beta = -2.0 ;   /* ~ -2 */
static  double  a = 0.15 ;      /* exponent constant */
static  double  k = 1.0 ;       /* relative size */


void spdShells( int sf )
{
   double  r,angle ;
   long    i, steps ;
   COORD3  back_color, obj_color ;
   COORD3  from, at, up ;
   COORD4  light ;
   COORD4  sphere;


    size_factor = sf;

    /* output background color - UNC sky blue */
    /* NOTE: Do this BEFORE lib_output_viewpoint(), for display_init() */
    SET_COORD3( back_color, 0.078, 0.361, 0.753 ) ;
    lib_output_background_color( back_color ) ;

    /* output viewpoint */
    SET_COORD3( from, -6.0, -60.0, 35.0 ) ;
    SET_COORD3( at, 0.0, 8.0, -15.0 ) ;
    SET_COORD3( up, 0.0, 0.0, 1.0 ) ;
    lib_output_viewpoint( from, at, up, 45.0, 1.0, 0.5, 512, 512 ) ;

    /* output light sources */
    SET_COORD4( light, -100.0, -100.0, 100.0, 1.0 ) ;
    lib_output_light( light ) ;

    /* set up sphere color */
    SET_COORD3( obj_color, 1.0, 0.8, 0.4 ) ;
    lib_output_color( spdName, 1, obj_color, 0.0, 0.8, 0.2, 0.5, 10.0, 0.0, 1.0 ) ;

    steps = (long)(180.0 * pow( 2.0, (double)size_factor )) ;
    lwMonitorBegin( spdName, "Creating shells.", steps );
    for ( i = -steps*2/3; i <= steps/3 ; ++i ) {
      if ( lwMonitorStep( 1 ))
         return;
      angle = 3.0 * 6.0 * PI * (double)i / (double)steps ;
      r = k * exp( a * angle ) ;
      sphere[X] = r * sin( angle ) ;
      sphere[Y] = r * cos( angle ) ;
      if ( alpha > 0.0 ) {
         /* alternate formula: z = alpha * angle */
         sphere[Z] = alpha * angle ;
      } else {
         sphere[Z] = beta * r ;
      }
      sphere[W] = r / fgamma ;
      lib_output_sphere( sphere, output_format ) ;
    }
    lwMonitorDone();
}
