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

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

const double PI=3.141592654;
const int COLMAX=5, MAXBAR=20;
int firsttime=1,numbar=0,XMAX=600,YMAX=400;
double theta,vel,dist,range,xbar,ybar,hbar;

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

barrier bar[MAXBAR];

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

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)XMAX,0.0,(double)YMAX,-1.0,1.0);
  glMatrixMode(GL_MODELVIEW);
}

static void key_esc() {
  auxQuit();
}

static void next() {
  firsttime=0;
  cout<< "Angle : ";
  cin >> theta;
  theta = theta * PI/180.0;
  cout<< "Velocity : ";
  cin >> vel;
  cout<< "Distance : ";
  cin >> dist;
  cout<< "Range : ";
  cin >> range;
  cout<  "Barrier? (y/n) ";
  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].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++;
  }
  return hit;
}

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

      tstep = .01;
      time=0.0;
      a=32.0;
      y=.1;
      vx = (vel)*cos(theta);
      vy = (vel)*sin(theta);
      while (y > 0) {
        time += tstep;
        y = vy * time -.5 * a * time * time;
        if (barhit)
          x = xbarhit - fac*(vx*time-vxorig);
        else x = vx*time;
        if (numbar && hitthebar(x,y)) {
          barhit++;
          xbarhit = x;
          vxorig = vx*time;
 	  fac *= -1;
        }
        glColor3f(0.8,0.4,1.0);
        glVertex3f(x,y,0);
      }
      if (abs(x-dist) < range) {
	cout<<"hit! "<<x<<" ";
	double t=2.0*vy/a;
	x=vx*t;
	cout<<x<<endl; }
        else cout<<"miss!\n";
}

static void display() {
  glClear(GL_COLOR_BUFFER_BIT);
  if (firsttime) next();
  glBegin(GL_QUADS);
    glColor3f(1.0,1.0,1.0);
    glVertex3f(dist-range,0.0,0.0);
    glVertex3f(dist-range,5.0,0.0);
    glVertex3f(dist+range,5.0,0.0);
    glVertex3f(dist+range,0.0,0.0);
  glEnd();
  for (int i=0;i<numbar;i++) {
    glBegin(GL_QUADS);
      glColor3f(1.0,1.0,1.0);
      glVertex3f(bar[i].x,bar[i].y,0.0);
      glVertex3f(bar[i].x,bar[i].y+bar[i].height,0.0);
      glVertex3f(bar[i].x+bar[i].width,bar[i].y+bar[i].height,0.0);
      glVertex3f(bar[i].x+bar[i].width,bar[i].y,0.0);
    glEnd();
  }
  glBegin(GL_POINTS);
  DrawMyStuff();
  glEnd();
  glFlush();
  auxSwapBuffers();
}

int main (int argc,char **argv) {
  auxInitDisplayMode(AUX_RGBA);
  auxInitPosition(50,100,XMAX,YMAX);
  if (auxInitWindow("Missile") == GL_FALSE)
    auxQuit();
  Init();
  auxExposeFunc(Reshape);
  auxReshapeFunc(Reshape);
  auxKeyFunc(AUX_SPACE,next);
  auxMainLoop(display);
  return 0;
}
