/* Jin Ding -- Period 2 -- 3/12/98 */
/* ripple.cpp */

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

const MAX=100;
double altitude[MAX][MAX],
  spin=-55.0, // viewing angle
  y=MAX/1.5,  // viewing height
  z=0.0,      // viewing distance
  red=1.0, green=1.0, blue=1.0,
  alt=10.0,   // height of sine wave
  cent=1.5,   // offset from center
  period=5.0;    // period of sine wave

void setAltitude() {
int x,y;

  for (x=0;x<MAX;x++)
    for (y=0;y<MAX;y++) 
      altitude[x][y]=(int)(alt)*sin((cent*MAX/10.0 - sqrt((x-MAX/2.0)*(x-MAX/2.0) + (y-MAX/2.0)*(y-MAX/2.0)))/(period*MAX/100.0))+sqrt(alt*alt);
    /* altitude ranges from 0 to 2*alt */
}

void pickColor(double value) {
  green=0.67-value/(3.0*sqrt(alt*alt));
  red=1.0-value/(4.0*sqrt(alt*alt));
  blue=0.0;
  if ((alt < 1.0) && (alt > -1.0)) { 
    red=.4;
    green=.2;
  } 
}

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

static void Reshape(int width, int height) {
  glViewport(0,0,(GLsizei)width,(GLsizei)height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(60.0,(GLfloat)width/(GLfloat)height,1.0,MAX*2.0);
  glMatrixMode(GL_MODELVIEW);
}

static void key_esc() { auxQuit(); }

static void spinClock() { spin -= 5; }

static void spinCounter() { spin += 5; }

static void moveUp() { y += 10; }

static void moveDown() { y -= 10; }

static void moveAway() { z += 5; }

static void moveCloser() { z -= 5; }

static void flipPos() { 
  alt += 1.0; 
  setAltitude(); 
}
		
static void flipNeg() { 
  alt -= 1.0; 
  setAltitude(); 
}

static void flip() { alt *= -1.0; setAltitude(); }

static void rippleIn() { cent -= .25; setAltitude(); }

static void rippleOut() { cent += .25; setAltitude(); }

static void thinWave() { period -= .5; setAltitude(); }

static void thickWave() { period += .5; setAltitude(); }

void DrawMyStuff() {
int x,y;

  for (x=0;x<MAX-1;x++)
    for (y=0;y<MAX-1;y++) {
      glBegin(GL_QUAD_STRIP);
      pickColor(altitude[x][y]);
      glColor3f(red,green,blue);
      glVertex3f(x-MAX/2.0,altitude[x][y],y-MAX/2.0);
      pickColor(altitude[x+1][y]);
      glColor3f(red,green,blue);
      glVertex3f(x+1-MAX/2.0,altitude[x+1][y],y-MAX/2.0);
      pickColor(altitude[x][y+1]);
      glColor3f(red,green,blue);
      glVertex3f(x-MAX/2.0,altitude[x][y+1],y+1-MAX/2.0);
      pickColor(altitude[x+1][y+1]);
      glColor3f(red,green,blue);
      glVertex3f(x+1-MAX/2.0,altitude[x+1][y+1],y+1-MAX/2.0);
      glEnd();
    }
}

static void display() {
  glClear(GL_COLOR_BUFFER_BIT);
  glPushMatrix();
    glLoadIdentity();
    gluLookAt(0.0,y,2.2*MAX,0.0,0.0,0.0,0.0,1.0,0.0);
    glTranslatef(0.0,0.0,MAX-z);
    glRotatef(spin,0.0,1.0,0.0);
    DrawMyStuff();
  glPopMatrix();
  glFlush();
  auxSwapBuffers();
}

void main() {
  setAltitude();
  auxInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  auxInitPosition(50,50,550,550);
  if (auxInitWindow("Ripple") == GL_FALSE)
    auxQuit();
  Init();
  auxKeyFunc(AUX_LEFT,spinCounter);
  auxKeyFunc(AUX_RIGHT,spinClock);
  auxKeyFunc(AUX_UP,moveCloser);
  auxKeyFunc(AUX_DOWN,moveAway);
  auxKeyFunc(AUX_RETURN,moveUp);
  auxKeyFunc(AUX_SPACE,moveDown);
  auxKeyFunc(AUX_0,flipPos);
  auxKeyFunc(AUX_9,flipNeg);
  auxKeyFunc(AUX_1,flip);
  auxKeyFunc(AUX_e,rippleIn);
  auxKeyFunc(AUX_d,rippleOut);
  auxKeyFunc(AUX_i,thinWave);
  auxKeyFunc(AUX_k,thickWave);
  cout<<"  left : spinCounter      right : spinClock\n"
      <<"    up : moveCloser        down : moveAway\n"
      <<"return : moveUp           space : moveDown\n"
      <<"     0 : flipPos              9 : flipNeg\n"
      <<"     1 : flip\n" 
      <<"     e : rippleIn             d : rippleOut\n"
      <<"     i : thinWave             k : thickWave\n";
  auxExposeFunc(Reshape);
  auxReshapeFunc(Reshape);
  auxMainLoop(display);
}

