/*  Jin Ding -- pd 3 -- 5/13/98  */
/*  Mmissile.cpp */

#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <glaux.h>
#include "/usr/pvm3/include/pvm3.h"

#define SLAVENAME "Smissile"
#define PI 3.141592654
#define MAXBAR 5
#define MAXVEL 400
#define YMAX 180
#define NUMTASKS YMAX/10

int firsttime=1,numbar=0;
double dist,range;
double bar[MAXBAR*4];
int tids[NUMTASKS];                   /* slave task ids */
struct pvmhostinfo hostp[NUMTASKS]; /* pointers to host information */

void InitBar() {
  for (int i=0;i<MAXBAR;i++) 
    for (int j=0;j<4;j++)
      bar[i*4+j]=0.0; 
}

static void Init (void) {
  glClearColor(0.0,0.0,0.0,1.0);
  glShadeModel(GL_FLAT);
}

static void Reshape (int width,int height) {
  glViewport(0,0,(GLint)width,(GLint)height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0.0,(double)MAXVEL,0.0,(double)PI/2.0,-1.0,1.0);
  glMatrixMode(GL_MODELVIEW);
}

void DrawMyStuff () {
double theta,vel;
int msgtype,tasknum,thetanum;
//2*MAXVEL*20*3 +1 for the null character
double result[MAXVEL*120];

  msgtype=0;
  for (tasknum=0;tasknum<NUMTASKS;tasknum++) {
    pvm_initsend(PvmDataDefault);
    pvm_pkdouble(&dist,1,1);
    pvm_pkdouble(&range,1,1);
    pvm_pkint(&tasknum,1,1);
    pvm_pkdouble(bar,MAXBAR*4,1);
    pvm_pkint(&numbar,1,1);
    pvm_send(tids[tasknum],msgtype);
  }
  msgtype=5;
  for (tasknum=0;tasknum<NUMTASKS;tasknum++) {
    pvm_recv(-1,msgtype);
    pvm_upkint(&thetanum,1,1);
    pvm_upkdouble(result,MAXVEL*120,1);
    cout<<thetanum<<" "<<tids[thetanum]<<endl;
    for (int j=0;j<20;j++) {
      theta = (double)(thetanum*20+j)/4.0*PI/180.0;
      for (int i=0;i<6*MAXVEL;i+=3) {
        int index=j*6*MAXVEL+i;
        glColor3f(result[index],result[index+1],result[index+2]);
        glVertex3f((double)i/6.0,theta,0);
      }
    }
  }
}

void next() {
  firsttime=0;
  InitBar();
  cout<< "Distance : "; cin >> dist;
  cout<< "Range : "; cin >> range;
  numbar = 100;
  while (numbar > MAXBAR) {
    cout<< "Number of Barriers? (max " << MAXBAR << ") ";
    cin >> numbar;
  }
  for (int i=0;i<numbar;i++) {
    cout<< "Barrier #" << i+1 << endl;
    cout<< "X : "; cin >> bar[i*4];
    cout<< "Y : "; cin >> bar[i*4+2];
    cout<< "Width : "; cin >> bar[i*4+1];
    cout<< "Height : "; cin >> bar[i*4+3];
  };
}

static void display() {
int numt,i,mytid;

  /* enroll in pvm */
  mytid = pvm_mytid();

/* start up slave tasks */
  numt=pvm_spawn(SLAVENAME, (char**)0, 0, "", NUMTASKS, tids);
  if( numt < NUMTASKS ){
     printf("Trouble spawning slaves. Aborting. Error codes are:\n");
     for( i=numt ; i<NUMTASKS ; i++ ) {
        printf("TID %d %d\n",i,tids[i]); }
     for( i=0 ; i<numt ; i++ ){
        pvm_kill( tids[i] );
     }
     pvm_exit();
     exit(0);
  }

  glClear(GL_COLOR_BUFFER_BIT);
  if (firsttime) next();
  glBegin(GL_POINTS);
  DrawMyStuff();
  glEnd();
  glFlush();
  auxSwapBuffers();

  /* Program Finished - exit PVM before stopping */
  pvm_exit();
}

int main(int argc,char **argv) {
  auxInitDisplayMode(AUX_RGBA);
  auxInitPosition(50,100,MAXVEL,YMAX);
  if (auxInitWindow("Missile") == GL_FALSE)
    auxQuit();
  Init();

  auxExposeFunc(Reshape);
  auxReshapeFunc(Reshape);
  auxKeyFunc(AUX_SPACE,next);
  auxMainLoop(display);

}
