#include "/usr/pvm3/include/pvm3.h"
#include <math.h>
#include <iostream.h>
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#define SLAVENAME "mjtargas"
#define MAXTASKS 10
#define XWINDOW 500
#define YWINDOW 500

int n, nproc, numt, i, j, who, msgtype, nhost, narch;
int mytid;               
int tids[MAXTASKS];     
int avail[MAXTASKS];   
double data [XWINDOW][YWINDOW];   
struct pvmhostinfo *hostp[MAXTASKS]; 

//---------------------------------------------------------------------------------
//Constants and Fractal Manipulation and Calculation Procedures...

double XMin=-2,XMax=2;           // Cartesian Coordinate Plane Frame of Reference
double YMin=-2,YMax=2;           // Coordinates

//--------------------------------------------------------------------------------
// GL stuff...

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

static void Reshape(int w,int h)
  { glViewport(0,0,(GLint)w,(GLint)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,XWINDOW,0,YWINDOW,-1.0,1.0);
    glMatrixMode(GL_MODELVIEW);
  }

void DrawingRoutine() //Draws the Fractal
  { n=MAXTASKS;int o;
    double result[50][XWINDOW];
    pvm_initsend(PvmDataDefault);     
    pvm_pkint(&nproc, 1, 1);          
    pvm_pkint(tids, nproc, 1);           
    pvm_pkint(&n, 1, 1);                  
    pvm_mcast(tids, nproc, 0);             
    double x,y,t;
    glBegin(GL_POINTS);
    msgtype = 5;
    int h,k;
    for(i=0 ;i<nproc;i++ )
      { pvm_recv(-1,msgtype);     
        pvm_upkint(&who,1,1);     
        for(o=0;o<50;o++)
          { pvm_upkdouble(result[o],XWINDOW,1);  
            for(h=0;h<XWINDOW;h++)
              { t=result[o][h];
                if (t!=0)
                  { if (t==Iterations) glColor3f(0.0,0.0,0.0);
                      else glColor3f(sqrt(t/(Iterations/2)),0.0,0.0);
                    glVertex3f(h+0.5,o+who*50+0.5,0.0);
                  }
              }
         }
       }
   glEnd();
 }

void ClearAndDraw() 
  { glFlush();
    glClear(GL_COLOR_BUFFER_BIT);
    DrawingRoutine();
  }

int FirstTime=1;

static void DoNothing() 
  { if (FirstTime) { ClearAndDraw(); FirstTime=0; }     
  }

void KeyboardInput(unsigned char key,int x,int y)
  { switch (key)
      { case 27: //ESC                        Quits
          pvm_exit();
          exit(0);
          break;
        default:
          break;
      }
  }

int main(int argc,char **argv)  // And Procedure Main
  { mytid = pvm_mytid();
    if( pvm_parent() == PvmNoParent ){
       puts("How many slave programs (1-MAXTASKS)?");
       scanf("%d", &nproc);
    }
    else{
       pvm_config( &nhost, &narch, hostp );
       nproc = nhost;
       if( nproc > MAXTASKS ) nproc = MAXTASKS ;
    }
    numt=pvm_spawn(SLAVENAME, (char**)0, 0, "", nproc, tids);
    if( numt < nproc ){
       printf("Trouble spawning slaves. Aborting. Error codes are:\n");
       for( i=numt ; i<nproc ; i++ ) {
          printf("TID %d %d\n",i,tids[i]); }
       for( i=0 ; i<numt ; i++ ){
          pvm_kill( tids[i] );
       }
       pvm_exit();
       exit(0);
    }
    glutInit(&argc,argv);
    glutInitDisplayMode(GLUT_RGBA);
    glutInitWindowSize(XWINDOW,YWINDOW);
    glutInitWindowPosition(0,0);
    glutCreateWindow(argv[0]);
    Init();
    glutReshapeFunc(Reshape);
    glutDisplayFunc(DoNothing);
    glutKeyboardFunc(KeyboardInput);
    glutMouseFunc(MouseInput);
    glutMainLoop();
    return 0;
  }


