/* Jin Ding -- Pd 2 -- 4/21/98 */
/* missile.cpp */

#include <stdio.h>
#include <iostream.h>
#include <math.h>
#include <glaux.h>

const double PI=3.141592654;
const int MAXBAR=20;
int MAXVEL=400,YMAX=360,firsttime=1,numbar=0,prevBar=MAXBAR;
double dist,range;

typedef struct {
  double x,y,height,width;
} barrier;

barrier bar[MAXBAR];

float abs (float x) {
  return sqrt(x*x);
}

void InitBar() {
  for (int i=0;i<MAXBAR;i++) {
    bar[i].x=0.0;
    bar[i].y=0.0;
    bar[i].height=0.0;
    bar[i].width=0.0;
  }
  prevBar=MAXBAR;
}

static void Init (void) {
  glClearColor(0.2,0.2,0.2,1.0);
  glShadeModel(GL_SMOOTH);
}

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

static void key_esc() {
  auxQuit();
}

static void next() {
  firsttime=0;
  InitBar();
  cout<< "Distance : "; cin >> dist;
  cout<< "Range : "; cin >> range;
  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].x;
    cout<< "Y : "; cin >> bar[i].y;
    cout<< "Width : "; cin >> bar[i].width;
    cout<< "Height : "; cin >> bar[i].height;
  };
}

int hitthebar (double x,double y) {
int i=0,hit=0;

  while ((i < numbar) && (!hit)) {
    hit = ((x < (bar[i].x + bar[i].width)) && (x > bar[i].x) && (y < (bar[i].y + bar[i].height)) && (y > bar[i].y));
    i++;
  }
  if (hit && ((i-1) == prevBar)) hit = 0;
  if (hit) prevBar=i-1;
  return hit;
}

void DrawMyStuff () {
double a,x,y,time,tstep,theta,vel,vy,vx,xbarhit,vxorig;
int index,barhit=0,fac=1;

    a=32.0;
    tstep = .05;
    for (theta=0.0;theta<2.0*PI;theta+=PI/360.0) 
      for (vel=0.0;vel<2.0*MAXVEL;vel++) {
        time=0.0;
        y=.1;
        vx = (vel/2.0)*cos(theta/4.0);
        vy = (vel/2.0)*sin(theta/4.0);
        while (y > 0) {
          time += tstep;
          y = vy * time -.5 * a * time * time;
          if (barhit)
            x = xbarhit + fac*(abs(vx*time-vxorig));
          else x = vx*time;
          if (numbar && hitthebar(x,y)) {
              barhit++;
              xbarhit = x;
              vxorig = vx*time;
              fac *= -1;
          }
        }
//        if (abs(x-dist) < range) {
          double factor = 1.2 - (((int)abs(x-dist))%(int)range)/range;
          glColor3f(factor*1.2,.4*factor*factor,.1*factor*factor);
          glVertex3f(vel/2.0,theta*180.0/PI,0);
//        }
      }
}

static void display() {
  glClear(GL_COLOR_BUFFER_BIT);
  if (firsttime) next();
  glBegin(GL_POINTS);
  DrawMyStuff();
  glEnd();
  glFlush();
  auxSwapBuffers();
}

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);
  return 0;
}
