/* Jin Ding -- Period 2 -- 3/13/98 */
/* halftor.cpp */

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

#define MAX 100
#define HMAX MAX/2.0

double altitude[MAX][MAX],
  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 hump
  cent=1.5;   // offset from center

void setAltitude() {
int x,y;
double dist;

  for (x=0;x<MAX;x++)
    for (y=0;y<MAX;y++) {
      dist=cent*MAX/10.0 - sqrt((x-HMAX)*(x-HMAX) + (y-HMAX)*(y-HMAX));
      altitude[x][y]=(int)sqrt((alt*alt)-(dist*dist));
    /* altitude ranges from 0 to alt */
    }
}

void pickColor(double value) {
  green=0.67-value/(3.0*alt/2.0);
  red=1.0-value/(4.0*alt/2.0);
  blue=0.0;
}

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 moveUp() { y += 10; }

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

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

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

static void altNeg() { 
  if (alt > 1.0) {
  alt -= 1.0; 
  setAltitude(); }
}
		
static void altPos() { alt += 1.0; setAltitude(); }

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

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

void DrawMyStuff() {
int x,y;
double dist;

  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-HMAX,altitude[x][y],y-HMAX);
      pickColor(altitude[x+1][y]);
      glColor3f(red,green,blue);
      glVertex3f(x+1-HMAX,altitude[x+1][y],y-HMAX);
      pickColor(altitude[x][y+1]);
      glColor3f(red,green,blue);
      glVertex3f(x-HMAX,altitude[x][y+1],y+1-HMAX);
      pickColor(altitude[x+1][y+1]);
      glColor3f(red,green,blue);
      glVertex3f(x+1-HMAX,altitude[x+1][y+1],y+1-HMAX);
      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(-50.0,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("Half Torus") == GL_FALSE)
    auxQuit();
  Init();
  auxKeyFunc(AUX_LEFT,moveAway);
  auxKeyFunc(AUX_RIGHT,moveCloser);
  auxKeyFunc(AUX_UP,moveUp);
  auxKeyFunc(AUX_DOWN,moveDown);
  auxKeyFunc(AUX_i,altNeg);
  auxKeyFunc(AUX_k,altPos);
  auxKeyFunc(AUX_e,rippleIn);
  auxKeyFunc(AUX_d,rippleOut);
  cout<<"  left : moveAway        right : moveCloser\n"
      <<"    up : moveUp           down : moveDown\n"
      <<"     i : altNeg              k : altPos\n"
      <<"     e : rippleIn            d : rippleOut\n";
  auxExposeFunc(Reshape);
  auxReshapeFunc(Reshape);
  auxMainLoop(display);
}

