/*---------------------------- S p h e r e s . c -------------------------*/
/* This program creates a set of C-Light scene files (.img) for producing */
/* an animation of floating spheres.                                      */
/*------------------------------------------------------------------------*/

#include "stdio.h"
#include "exec/types.h"
#include "graphics/gfxbase.h"
#include "intuition/intuition.h"
#include "dos.h"
#include "vect.h"
#include "math.h"
#include "string.h"

#define DBG 0
#define NSPHERES 100
#define NLIGHTS  5
#define NFRAMES 20

#define EYE (-400.)
#define THINGS 200


/* Why the fuck these won't work as #defines I don't know. */
float XMAX = 820.;
float XMIN = (-820.);
float YMAX = 540.;
float YMIN = (-540.);
float ZMAX = 1500.;
float ZMIN = (-300.);


extern float random();

char name[120] = "\0";

struct things thing[THINGS];  /* object locations,sizes,rotations */
float direction[THINGS];   /* (+) = away from screen, (-) = towards screen. */
int n_objects;          /* number of objects already placed */
struct vector primeshift; /* primary space translation. */
struct tform tf0;       /* Primary space transform. */
struct vector eye;      /* Viewing position. */
double ObjHue[4];        /* Object and background colors. */
double ObjSat[4];
double ObjLit[4];
float rate;   /* Speed of spheres. */

main()
{
   int error, i, errflag, it;
   FILE *fp;
   int frame, object;


   /*--- Set random number seed. */

   random(1777731);

   /*--- Set rate to match a full cycle of travel in NFRAMES. */

   rate = 2. * (ZMAX - ZMIN)/NFRAMES;

   /*--- Locate spheres randomly in space. */

   object = 1;  /* Zero is reserved for a light. */
   for(it=0; it<NSPHERES; it++)
   {
      thing[object].type = 1;  /* BALL */
      thing[object].xloc = (XMAX - XMIN) * random(0) + XMIN;
#if DBG
      printf("\n XMAX - XMIN: %f  random(0): %f  (XMAX-XMIN)*rnd(0): %f",
         (XMAX - XMIN), random(0), (XMAX - XMIN) * random(0));
#endif
      thing[object].yloc = (YMAX - YMIN) * random(0) + YMIN;
      thing[object].zloc = (ZMAX - ZMIN) * random(0) + ZMIN;
#if DBG
      printf("\n xloc: %f  yloc: %f  zloc: %f", thing[object].xloc,
         thing[object].yloc, thing[object].zloc);
#endif
      if(random(0) < .5)
      {
         direction[object] = 1.;
      } else
      {
         direction[object] = (-1.);
      }
#if DBG
      printf("\n direction: %f", direction[object]);
#endif
      thing[object].xsize = 1.;
      thing[object].ysize = 1.;
      thing[object].zsize = 1.;
      thing[object].xrot = 0.;
      thing[object].yrot = 0.;
      thing[object].zrot = 0.;
      thing[object].color = 1;
      thing[object].other = 0;
      object++;
   }

   /*--- Locate lights randomly in space. */

   for(it=0; it<NLIGHTS; it++)
   {
      thing[object].type = 3;  /* LIGHT */
      thing[object].xloc = (XMAX - XMIN) * random(0) + XMIN;
      thing[object].yloc = (YMAX - YMIN) * random(0) + YMIN;
      thing[object].zloc = (ZMAX - ZMIN) * random(0) + ZMIN;
#if DBG
      printf("\n xloc: %f  yloc: %f  zloc: %f", thing[object].xloc,
         thing[object].yloc, thing[object].zloc);
#endif
      if(random(0) < .5)
      {
         direction[object] = 1.;
      } else
      {
         direction[object] = (-1.);
      }
#if DBG
      printf("\n direction: %f", direction[object]);
#endif
      thing[object].xsize = 1.;
      thing[object].ysize = 1.;
      thing[object].zsize = 1.;
      thing[object].xrot = 0.;
      thing[object].yrot = 0.;
      thing[object].zrot = 0.;
      thing[object].color = 1;
      thing[object].other = 0;
      object++;
   }


   /*--- Loop through all frames. */

   for(frame=0; frame<NFRAMES; frame++)
   {
      /*--- Set name of output file. */

      if(frame < 10)
      {
         sprintf(name,"Spheres%1d.img",frame);
      } else
      {
         sprintf(name,"Spheres%2d.img",frame);
      }

      /*--- Open output file. */

      fp = NULL;
      fp = fopen(name,"w");
      if(fp == NULL)
      {
         printf("\n Error opening file %s for writing.", name);
         exit(0);
      }

      /*--- Assign values to variables. */

      n_objects = NSPHERES + NLIGHTS + 1;

                        /* Defaults listed below. */
      tf0.Ax = 0.;      /* 0. */
      tf0.Ay = 0.;      /* 0. */
      tf0.Az = 0.;      /* 0. */

      tf0.Sx = 2.;      /* 2. */
      tf0.Sy = 1.;      /* 1. */
      tf0.Sz = 1.;      /* 1. */

      primeshift.x = 0.;      /* 0. */
      primeshift.y = 0.;      /* 0. */
      primeshift.z = 0.;      /* 0. */

      eye.x = 0.;         /* 0. */
      eye.y = 0.;         /* 0. */
      eye.z = EYE;      /* -1000. */

      ObjHue[0] = 244.;   /* 244. */  /* Blue */
      ObjSat[0] = 1.;     /* 1. */
      ObjLit[0] = .33;    /* .33 */
      ObjHue[1] = 60.;    /* 60. */  /* Yellow? */
      ObjSat[1] = 1.;     /* 1. */
      ObjLit[1] = .5;     /* .5 */
      ObjHue[2] = 0.;     /* 0. */  /* Red */
      ObjSat[2] = 1.;     /* 1. */
      ObjLit[2] = .5;     /* .5 */
      ObjHue[3] = 112.;   /* 112. */  /* Green? */
      ObjSat[3] = 1.;     /* 1. */
      ObjLit[3] = .37;    /* .37 */

      /*--- Define a light near observer so there is always some light on */
      /*--- the front of the spheres. */

      object = 0;
      thing[object].type = 3;  /* LIGHT */
      thing[object].xloc = 0.;
      thing[object].yloc = 0.;
      thing[object].zloc = ZMIN - 30.;
      thing[object].xsize = 1.;
      thing[object].ysize = 1.;
      thing[object].zsize = 1.;
      thing[object].xrot = 0.;
      thing[object].yrot = 0.;
      thing[object].zrot = 0.;
      thing[object].color = 1;
      thing[object].other = 0;
      object++;

      /*--- Move spheres in space. */

      for(it=0; it<NSPHERES; it++)
      {
         thing[object].zloc = thing[object].zloc + direction[object] * rate;
         if(thing[object].zloc < ZMIN)
         {
            direction[object] = (-direction[object]);  /* change direction. */
            /* Do a perfect reflection in space-time. */
            thing[object].zloc = ZMIN + (ZMIN - thing[object].zloc);
         }
         if(thing[object].zloc > ZMAX)
         {
            direction[object] = (-direction[object]);  /* change direction. */
            /* Do a perfect reflection in space-time. */
            thing[object].zloc = ZMAX - (thing[object].zloc - ZMAX);
         }
         object++;
      }

      /*--- Move lights in space. */

      for(it=0; it<NLIGHTS; it++)
      {
         thing[object].zloc = thing[object].zloc + direction[object] * rate;
         if(thing[object].zloc < ZMIN)
         {
            direction[object] = (-direction[object]);  /* change direction. */
            /* Do a perfect reflection in space-time. */
            thing[object].zloc = ZMIN + (ZMIN - thing[object].zloc);
         }
         if(thing[object].zloc > ZMAX)
         {
            direction[object] = (-direction[object]);  /* change direction. */
            /* Do a perfect reflection in space-time. */
            thing[object].zloc = ZMAX - (thing[object].zloc - ZMAX);
         }
         object++;
      }

      /*--- Write data to file. */

      errflag = 0;
      /*--- Write header to identify as a CUBE data file. */
      error = fprintf(fp,"@CUBE@\n");
      if(error == 0)errflag = 1;
      error = fprintf(fp,"%d\n",n_objects);
      if(error == 0)errflag = 1;
      error = fprintf(fp,"%f %f %f\n",tf0.Ax,
         tf0.Ay,tf0.Az);
      if(error == 0)errflag = 1;
      error = fprintf(fp,"%f %f %f\n",tf0.Sx,
         tf0.Sy,tf0.Sz);
      if(error == 0)errflag = 1;
      error = fprintf(fp,"%f %f %f\n",primeshift.x,
         primeshift.y, primeshift.z);
      if(error == 0)errflag = 1;
      error = fprintf(fp,"%f %f %f\n",eye.x,
         eye.y, eye.z);
      if(error == 0)errflag = 1;
      for(i=0; i<4; i++)
      {
         error = fprintf(fp,"%f %f %f\n",ObjHue[i],
            ObjSat[i], ObjLit[i]);
         if(error == 0)errflag = 1;
      }
      for(i=0; i<n_objects; i++)
      {
         error = fprintf(fp, "%d %f %f %f\n",thing[i].type,
            thing[i].xloc, thing[i].yloc, thing[i].zloc);
         if(error == 0)errflag = 1;
         error = fprintf(fp, "%f %f %f\n", thing[i].xsize,
           thing[i].ysize, thing[i].zsize);
        if(error == 0)errflag = 1;
        error = fprintf(fp, "%f %f %f\n", thing[i].xrot,
           thing[i].yrot, thing[i].zrot);
        if(error == 0)errflag = 1;
        error = fprintf(fp, "%d %d\n", thing[i].color,
           thing[i].other);
        if(error == 0)errflag = 1;
        if(errflag == 1)
        {
           printf("\n Error writing to file.\n");
        }
     }

     /*--- Close output file. */

      fclose(fp);
   }

   printf("\n All Done!\n");

   return(0);
}

