#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "glaux.h"
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

double xspin=0,yspin=0,zspin=0,xd=0,yd=0,zd=0,speed=0,walkdip=1.5;
int count=0;

const xmax=40; const xlbound=-99*2; const xhbound=0;
const zmax=40; const zlbound=0;   const zhbound=99*2;

const scale=5;

double elev[xmax][zmax];


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

static void Reshape(int w,int h)
  { glViewport(0,0,(GLint)w,(GLint)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0,(GLfloat)w/(GLfloat)h,1,500);
    glMatrixMode(GL_MODELVIEW);
    gluLookAt(0,5,0,100,1,0,0,1,0);
  }

int round(double n)
  { if (n-(int)n<0.5) return (int)n; else return (int)n+1; }


void Updateyd()
  { if ((xd<=xhbound)&&(xd>=xlbound)&&(zd>=zlbound)&&(zd<=zhbound))
      yd=elev[round(-xd)/scale][round(zd)/scale]+walkdip;
    else yd=walkdip;
  }

static void KPLeftArrow()
  { yspin-=5; 
  }

static void KPRightArrow()
  { yspin+=5;
  }

static void KPUpArrow()
  { if (xspin>(-85)) xspin-=5;
  }

static void KPDownArrow() 
  { if (xspin<85) xspin+=5;
  }

static void MoveForward()    
  { xd+=sin(yspin*M_PI/180)*speed; 
    zd+=cos(yspin*M_PI/180)*speed;
  }

static void KP1Button() { speed=0; }
static void KP2Button() { speed=1; }
static void KP3Button() { speed=2; }
static void KP4Button() { speed=3; }
static void KP5Button() { speed=4; }
static void KP6Button() { speed=5; }
static void KP7Button() { speed=6; }
static void KP8Button() { speed=7; }
static void KP9Button() { speed=8; }
static void KP0Button() { speed=9; }
static void KPBackSpace() { speed*=(-1); }

void DrawingRoutine()
  { int x,z;
    glColor3f(0.0,1.0,0.0);
    glPolygonMode(GL_FRONT,GL_LINE);
    glPolygonMode(GL_BACK,GL_LINE);
    glBegin(GL_LINES);
      for(z=0;z<zmax;z++)
        { for(x=0;x<xmax;x++)
            { glVertex3f(x*scale,elev[x][z],z*scale); 
            }
        }
        for(x=0;x<xmax;x++)
          { for(z=0;z<zmax;z++)
              { glVertex3f(x*scale,elev[x][z],z*scale);
              }
          }
    glEnd();
  }

void Updatewalkdip()
  { if (speed==0) walkdip=0; 
     else 
       switch (count)
         { case 0: { walkdip=0; break; }
           case 1: { walkdip=-0.1*speed; break; }
           case 2: { walkdip=-0.2*speed; break; }
           case 3: { walkdip=-0.1*speed; break; }
           case 4: { walkdip=0;    break; }
           case 5: { walkdip=0.1*speed; break; }
           case 6: { walkdip=0.2*speed; break; }
           case 7: { walkdip=0.1*speed; break; }
         }
  }

static void display()
  { glClear(GL_COLOR_BUFFER_BIT);
    count=(count+1)%8;
    Updatewalkdip();
    Updateyd();
    glPushMatrix();
    glRotatef(xspin,1,0,0);
    glRotatef(yspin,0,1,0);
    glRotatef(zspin,0,0,1);
    glTranslatef(xd,-yd,-zd);
    DrawingRoutine();
    glPopMatrix();
    glFlush();
    glXSwapBuffers(auxXDisplay(), auxXWindow());
  }

static void NoKP()
  { MoveForward();
    display();
  }

int main(int argc,char **argv)
  { int x,z;
    for(x=0;x<xmax;x++)
      { for(z=0;z<zmax;z++)
          { 
	    if ((x>xmax-xmax/4)&&(z>zmax-zmax/4)) elev[x][z]=50; 
            else 
               elev[x][z]=(-3*sqrt(x*z));
          }
      }
    

    auxInitDisplayMode(AUX_DOUBLE | AUX_RGBA);
    auxInitPosition(0,0,800,400);
    if (auxInitWindow("SC3.cc")==GL_FALSE) auxQuit();
    Init();
    auxIdleFunc(NoKP);
    auxExposeFunc(Reshape);
    auxReshapeFunc(Reshape);
    auxKeyFunc(AUX_UP,KPUpArrow);
    auxKeyFunc(AUX_DOWN,KPDownArrow);
    auxKeyFunc(AUX_LEFT,KPLeftArrow);
    auxKeyFunc(AUX_RIGHT,KPRightArrow);
    auxKeyFunc('1',KP1Button);
    auxKeyFunc('2',KP2Button);
    auxKeyFunc('3',KP3Button);
    auxKeyFunc('4',KP4Button);
    auxKeyFunc('5',KP5Button);
    auxKeyFunc('6',KP6Button);
    auxKeyFunc('7',KP7Button);
    auxKeyFunc('8',KP8Button);
    auxKeyFunc('9',KP9Button);
    auxKeyFunc('0',KP0Button);
    auxKeyFunc('b',KPBackSpace);
    auxMainLoop(display);
    return 0;
 }


