/* vbunny_spider.c : example file for 6.837 F97 PS3A */
#include <stdio.h>
#include <pwd.h>
#include <sys/types.h>
#include <unistd.h>
#include <time.h>
#include "arg_parse.h"

#define  HALFPI (PI/2)

/* common to all programs */
int  debug, helponly;


void
emit_help( void )
{
  extern char helpmsg[];  /* defined below */
  fprintf (stderr, helpmsg);
}

/* output legal inventor file header, with */
/* timestamp, creator id, and command line */
void
emit_header( int argc,  char *argv[], FILE* f)
{
struct passwd *pwent = NULL;
time_t cl;

  /* output inventor header */
  fprintf (f,"#Inventor V2.1 ascii\n");
  /* output date/timestamp */
  cl = time(NULL);
  fprintf (f,"# %s", asctime (localtime(&cl)));
  /* output creator uid */
  pwent = getpwuid(getuid());
  fprintf (f,"# Created by %s using\n#", pwent->pw_name );
  /* echo command line */
  while (argc--)
    fprintf (f, " %s", *argv++ ); 
  fprintf (f,"\n");
}

/* YOU SHOULD NOT NEED TO EDIT ANYTHING ABOVE */
/* THIS LINE, BUT YOU MAY DO SO IF YOU WISH. */

/* extended help message */
char helpmsg[] = "\
Usage: vbunny_spider [options] ('-' prints all options; -help prints this msg)\n\
Generates a spider.\n\
-legs tells number of legs (8 is default)\n\
-body tells size of body compared to legs (1 is default)\n\
-speed sets the speed of leg animation (2 is default)\n\
-eyes sets the number of eyes.  0 means no eyes.\n\
-eyespeed sets the speed of eye rotation (0.4 is default)\n\
-stalkheight sets the height of the eyestalks\n\
-trans is how transparent the body is (max 1)\n\
-dist sets the distance walked. 0 means no translation";

/* parameters specific to object you are defining */
float thickness = 0.025, depth = 0.25, width = 0.8;
float redcomp = 0.4, greencomp = 0.5, bluecomp = 0.6;

void writeLeg(FILE* f) {
  fprintf(f,"Switch {\n");
  fprintf(f,"   DEF myleg Separator {\n");
  fprintf(f,"     Material {diffuseColor 0.7 0 0} # Dark Red\n");
  fprintf(f,"     Coordinate3 {\n");
  fprintf(f,"            point [ 0   0.2   0.2,\n"); //0
  fprintf(f,"                    0   0.2   -0.2,\n"); //1
  fprintf(f,"                    0   -0.2   -0.2,\n"); //2
  fprintf(f,"                    0   -0.2   0.2,\n"); //3
  fprintf(f,"                    0.2   0.1   0.1,\n"); //4
  fprintf(f,"                    0.2   0.1   -0.1,\n"); //5
  fprintf(f,"                    0.2   -0.1   -0.1,\n"); //6
  fprintf(f,"                    0.2   -0.1   0.1,\n"); //7
  fprintf(f,"                    2   0   0]\n");       //8
  fprintf(f,"            } # Coordinate 3\n");
  fprintf(f,"      DEF myseg Separator {\n");
  fprintf(f,"        IndexedFaceSet { coordIndex [0,1,2,3,-1,\n");
  fprintf(f,"                                     0,4,5,1,-1,\n");
  fprintf(f,"                                     1,5,6,2,-1,\n");
  fprintf(f,"                                     2,6,7,3,-1,\n");
  fprintf(f,"                                     3,7,4,0,-1,\n");
  fprintf(f,"                                     4,8,5,-1,\n");
  fprintf(f,"                                     5,8,6,-1,\n");
  fprintf(f,"                                     6,8,7,-1,\n");
  fprintf(f,"                                     7,8,4,-1]\n");
  fprintf(f,"                       } #indexed face\n");
  fprintf(f,"      } # my Seg\n");
  fprintf(f,"   Translation {translation 2 0 0}\n");
  fprintf(f,"   Sphere {radius 0.1}\n");
  fprintf(f,"   Translation {translation -2 0 0}\n");
  fprintf(f,"   Translation {translation 2 -2 0}\n");
  fprintf(f,"   Rotation {rotation 0 0 1 %f}\n",HALFPI);
  fprintf(f,"   USE myseg\n");
  fprintf(f,"   } # Separator myleg\n");
  fprintf(f,"} #Switch\n");
}

void writeEye(FILE *f,float eyespeed,float sh) {
  fprintf(f,"Switch {\n");
  fprintf(f,"   DEF mystalk Separator {\n");
  fprintf(f,"    Translation {translation 0 %f 0}\n",sh/2);
  fprintf(f,"    Material {diffuseColor 0 0 0.5} # Dark Blue\n");
  fprintf(f,"    Cylinder {radius 0.15\n             height %f} # \n",sh);
  fprintf(f,"    Translation {translation 0 %f 0}\n",sh/2);
  fprintf(f,"    Material {diffuseColor 1 1 1} # White\n");
  fprintf(f,"    Sphere {radius 0.4}\n");
  fprintf(f,"    Material {diffuseColor 0.1 0.1 0.1} # Dark Dark Gray\n");
  if(eyespeed!=0) {
    fprintf(f,"    Rotor { rotation 0 1 0 0.1\n");
    fprintf(f,"            speed %f}\n",eyespeed+2*eyespeed*(float)rand()/32000);
  }
  fprintf(f,"    Rotation {rotation 0 1 0 %f}\n",(float)rand()/15000);
  fprintf(f,"    Translation {translation -0.35 0 0}\n");
  fprintf(f,"    Sphere {radius 0.15}\n");
  fprintf(f,"    } # mystalk\n");
  fprintf(f,"} #Switch\n");
}

void writeBody(FILE* f,int maxlegs,float bodySize,float speed,int maxEyes,int dist,float trans,char* defName) {
  int legnum,eyenum;
  float rot;
  float s;
  
  srand(time(NULL));

  s=3+3+bodySize;  //biggest dimension is width
  s=1/s;

  if(defName==NULL)
     fprintf(f,"DEF vbunny_spider Separator {\n");
    else
      fprintf(f,"DEF %s Separator {\n",defName);

  //body must fit in 1x1x1 cube, so scale everthing...
  fprintf(f,"   Scale {scaleFactor %f %f %f}\n",s,s,s);
  //align so Z is up axis...
  fprintf(f,"   Rotation {rotation 1 0 0 %f}\n",HALFPI);

  fprintf(f,"   Shuttle {\n");
  fprintf(f,"     translation0 0 0 %f\n",(float)0);
  fprintf(f,"     translation1 0 0 %f\n",(float)dist*1.5);
  fprintf(f,"     speed %f\n}",(float)0.5*speed/dist);
      
  fprintf(f,"Separator {\n");
  fprintf(f,"  Material {emissiveColor 0 0.1 0\n");
  fprintf(f,"          diffuseColor 0 1 0\n");
  fprintf(f,"          transparency %f} # see through?\n",trans);
  fprintf(f,"  Scale { scaleFactor 1 0.5 1} # flat spheres\n");
  fprintf(f,"  Sphere { radius %f}\n",(float)bodySize*1.05);
  fprintf(f,"  Translation { translation 0 %f 0}\n",bodySize);
  fprintf(f,"  Sphere { radius %f}\n",(float)bodySize/2);
  fprintf(f,"} # Separator for Torso\n");
  
  fprintf(f,"Separator {\n");
  fprintf(f,"  Translation { translation 0 %f 0}\n",bodySize*0.55);
  rot=PI/((float)maxEyes+1);
  fprintf(f,"   Rotation {rotation 0 0 1 %f}\n",HALFPI);
  for(eyenum=0;eyenum<maxEyes;eyenum++) {
    fprintf(f,"   Rotation {rotation 0 0 1 %f}\n",-rot);
    fprintf(f,"   USE mystalk\n");
  }
  fprintf(f,"} # Separator for Eyes\n");

  for(legnum=0;legnum<maxlegs;legnum++) {
    rot=(float)legnum*2.0*PI/(float)maxlegs;
    fprintf(f,"Separator {\n");
    fprintf(f,"   Rotation {rotation 0 1 0 %f}\n",rot);
    fprintf(f,"   Translation {translation %f 0 0}\n",bodySize);
    //fprintf(f,"   Rotation {rotation 0 0 1 %f}\n",HALFPI/4);
    fprintf(f,"   Pendulum {\n");
    fprintf(f,"     rotation 0 0 1 %f\n",HALFPI/4);
    if(rand()>16000) {
      fprintf(f,"     rotation0 0 0 1 %f\n",HALFPI/8);
      fprintf(f,"     rotation1 0 0 1 %f\n",(HALFPI/4)+(HALFPI/6));
    } else {
      fprintf(f,"     rotation0 0 0 1 %f\n",HALFPI/6+HALFPI/4);
      fprintf(f,"     rotation1 0 0 1 %f\n",(HALFPI/8));
    }
    fprintf(f,"     speed %f\n",speed);
    fprintf(f,"   } # Pendulum\n");
    fprintf(f,"   USE myleg\n");
    fprintf(f,"} # Separator for leg %d\n",legnum+1);
  }
 fprintf(f,"} # Separator for spider\n");

}



int main(
  int argc,
  char *argv[])
{

  FILE *f;
  int  numberOfLegs=8;  //the number of legs the spider has
  float  bodySize=1,eyeSpeed=0.4;
  float speed=2,stalkheight=2,trans=0;
  int   dist=5,numberOfEyes=2;
  char *defname = NULL;

  /* parse command line arguments */
  extern int arg_parse(int ac, char **av, ...);
  if (arg_parse(argc, argv,
    "-help",              ARG_FLAG(&helponly),
                          "output an extensive help message and quit",
    "-debug",             ARG_FLAG(&debug),
                          "set debug flag",
    "-legs %d",         &numberOfLegs,
				          "set number of legs",
    "-body %f",      &bodySize,
				          "set size of body compared to legs",
    "-speed %f",          &speed,
				       "sets the leg speed.",
    "-eyespeed %f",          &eyeSpeed,
				          "sets the eyespeed.",
   "-dist %d",          &dist,
				          "sets the distance walked. 0=no walk  Should be less than 10",
   "-eyes %d",          &numberOfEyes,
				          "sets the number of Eyes.. >=0",
    "-stalkheight %f",    &stalkheight, "the height of the eye stalks",
    "-trans %f",    &trans, "How transparent the body is (amx 1)",
    "-defname %S",        &defname,
                          "inventor definition name",
    0) < 0) exit(1);

  /* give help if requested */
  if ( helponly ) { emit_help(); exit(0); }

  if(defname!=NULL)
    f=fopen(defname,"wb+");
  else
    f=stdout/*fopen("vbunny_spider\0","wb+")*/;

  emit_header( argc, argv, f );
  

  //check params...

  if(numberOfLegs<0)
    numberOfLegs=8;
  if(bodySize<0)
    bodySize=0;
  if(numberOfEyes<0)
    numberOfEyes=2;
  if(dist>10)
    dist=10;
  if(stalkheight<0)
    stalkheight=2;
  if(trans>1 || trans<0)
    trans=0;

  writeLeg(f);   /*write the leg into the iv file*/
  writeEye(f,eyeSpeed,stalkheight);   /*write the eye stalk into the iv file*/
  writeBody(f,numberOfLegs,bodySize,speed,numberOfEyes,dist,trans,defname);



  /* for now, we just echo all program state */
  fprintf (stderr, "\tdebug is %d\n", debug);  
  fprintf (stderr, "\tlegs is %d\n", numberOfLegs);
  fprintf (stderr, "\tbody is %f\n", bodySize);
  fprintf (stderr, "\tspeed is %f\n", speed);
  fprintf (stderr, "\tnumber of eyes is %d\n", numberOfEyes);
  fprintf (stderr, "\teyespeed is %f\n", eyeSpeed);
  fprintf (stderr, "\tstalkheight is %f\n", stalkheight);
  fprintf (stderr, "\tdistance walked is %d\n", dist);
 fprintf (stderr, "\ttrans is %f\n", trans);
 if (defname == NULL) defname = "null";
  fprintf (stderr, "\tdefname is '%s'\n", defname);

  fclose(f);

  /* return OK status */
  return 0;
}




