
/**
* program	: glutmech V1.1
* author	: Simon Parkinson-Bates.
* E-mail	: sapb@yallara.cs.rmit.edu.au
* Copyright Simon Parkinson-Bates.
* "source if freely avaliable to anyone to copy as long as they
*  acknowledge me in their work."
*
* Funtional features 
* ------------------
* * online menu system avaliable by pressing left mouse button
* * online cascading help system avaliable, providing information on
*	the several  key strokes and what they do.
* * animation sequence coded which makes the mech walk through an
*	environment.  Shadows will soon be added to make it look
*	more realistic.
* * menu control to view mech in wireframe or sold mode.
* * various key strokes avaliable to control idependently the mechs
*	many joints.
* * various key strokes avaliable to view mech and environment from 
*	different angles
* * various key strokes avaliable to alter positioning of the single
*	light source.
*
*
* Program features
* ----------------
* * uses double buffering
* * uses display lists
* * uses glut to manage windows, callbacks, and online menu.
* * uses glpolygonfill() to maintain colors in wireframe and solid
*	mode.
*
**/

/* start of compilation conditions */
#define BARS
#define SPHERE
#define COLOR
#define LIGHT
#define NO_NORM
#define ANIMATION
#define DRAW_BARS
#define DRAW_ENVIRO
#define MOVE_LIGHT
/* end of compilation conditions */

/* start various header files needed */
#include <stdlib.h>
#include <math.h>
#define GLUT
#define GLUT_KEY
#define GLUT_SPEC
#include <GLUT/glut.h>
/* end of header files */

/* start of display list definitions */
#define SOLID_BARS       	1
#define SOLID_ENVIRO			2
/* end of display list definitions */

/* start of motion rate variables */
#define ROTATE_RATE	10
#define TILT_RATE	10
#define LIGHT_TURN_RATE	10
#define VIEW_TURN_RATE	10
/* end of motion rate variables */

/* start of motion  variables */

/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

GLUquadricObj *qobj;

char leg = 0;

int solid_part = 0, pivot = 0, tilt = 0,
  anim = 0, turn = 0, turn1 = 0, lightturn = 0, lightturn1 = 0;

float elevation = 0.0, distance = 0.0, frame = 3.0
 /* foot1v[] = {} foot2v[] = {} */ ;

/* end of motion variables */

/* start of material definitions */
#ifdef LIGHT
GLfloat mat_specular[] =
{0.628281, 0.555802, 0.366065, 1.0};
GLfloat mat_ambient[] =
{0.24725, 0.1995, 0.0745, 1.0};
GLfloat mat_diffuse[] =
{0.75164, 0.60648, 0.22648, 1.0};
GLfloat mat_shininess[] =
{128.0 * 0.4};

/*
GLfloat mat_specular2[] =
{0.508273, 0.508273, 0.508373};
GLfloat mat_ambient2[] =
{0.19225, 0.19225, 0.19225};
GLfloat mat_diffuse2[] =
{0.50754, 0.50754, 0.50754};
GLfloat mat_shininess2[] =
{128.0 * 0.6};
*/

GLfloat mat_specular2[] =
{0.6, 0.8, 0.3};
GLfloat mat_ambient2[] =
{0.2, 0.5, 0.5};
GLfloat mat_diffuse2[] =
{0.4, 0.6, 0.8};
GLfloat mat_shininess2[] =
{128.0 * 0.8};
GLfloat mat_emiss2[] =
{0.8, 0.0, 0.0, 1.0};

GLfloat mat_emiss0[] =
{0.0, 0.0, 0.0, 1.0};

GLfloat mat_specular3[] =
{0.296648, 0.296648, 0.296648};
GLfloat mat_ambient3[] =
{0.25, 0.20725, 0.20725};
GLfloat mat_diffuse3[] =
{1, 0.829, 0.829};
GLfloat mat_shininess3[] =
{128.0 * 0.088};

GLfloat mat_specular4[] =
{0.633, 0.727811, 0.633};
GLfloat mat_ambient4[] =
{0.0215, 0.1745, 0.0215};
GLfloat mat_diffuse4[] =
{0.07568, 0.61424, 0.07568};
GLfloat mat_shininess4[] =
{128 * 0.6};

GLfloat mat_specular5[] =
{0.60, 0.60, 0.50};
GLfloat mat_ambient5[] =
{0.0, 0.0, 0.0};
GLfloat mat_diffuse5[] =
{0.5, 0.5, 0.0};
GLfloat mat_shininess5[] =
{128.0 * 0.25};

#endif
/* end of material definitions */


void
RotateAdd(void)
{
  pivot = (pivot + ROTATE_RATE) % 360;
}

void
RotateSubtract(void)
{
  pivot = (pivot - ROTATE_RATE) % 360;
}

void
BarsTiltSubtract(void)
{
  tilt = (tilt - TILT_RATE) % 360;
}

void
BarsTiltAdd(void)
{
  tilt = (tilt + TILT_RATE) % 360;
}


/* end of body motion functions */

/* start of light source position functions */
void
TurnRight(void)
{
  turn = (turn - VIEW_TURN_RATE) % 360;
}

void
TurnLeft(void)
{
  turn = (turn + VIEW_TURN_RATE) % 360;
}

void
TurnForwards(void)
{
  turn1 = (turn1 - VIEW_TURN_RATE) % 360;
}

void
TurnBackwards(void)
{
  turn1 = (turn1 + VIEW_TURN_RATE) % 360;
}

void
LightTurnRight(void)
{
  lightturn = (lightturn + LIGHT_TURN_RATE) % 360;
}

void
LightTurnLeft(void)
{
  lightturn = (lightturn - LIGHT_TURN_RATE) % 360;
}

void
LightForwards(void)
{
  lightturn1 = (lightturn1 + LIGHT_TURN_RATE) % 360;
}

void
LightBackwards(void)
{
  lightturn1 = (lightturn1 - LIGHT_TURN_RATE) % 360;
}

/* end of light source position functions */

/* start of geometric shape functions */
void
Box2(float width, float height, float depth, char solid)
{
  char i, j = 0;
  float x = width / 2.0, y = height / 2.0, z = depth / 2.0;

  for (i = 0; i < 4; i++) {
    glRotatef(90.0, 0.0, 0.0, 1.0);
    if (j) {
      if (!solid)
        glBegin(GL_LINE_LOOP);
      else
        glBegin(GL_QUADS);
      glNormal3f(-1.0, 0.0, 0.0);
      glVertex3f(-x, y, z);
      glVertex3f(-x, -y, z);
      glVertex3f(-x, -y, -z);
      glVertex3f(-x, y, -z);
      glEnd();
      if (solid) {
        glBegin(GL_TRIANGLES);
        glNormal3f(0.0, 0.0, 1.0);
        glVertex3f(0.0, 0.0, z);
        glVertex3f(-x, y, z);
        glVertex3f(-x, -y, z);
        glNormal3f(0.0, 0.0, -1.0);
        glVertex3f(0.0, 0.0, -z);
        glVertex3f(-x, -y, -z);
        glVertex3f(-x, y, -z);
        glEnd();
      }
      j = 0;
    } else {
      if (!solid)
        glBegin(GL_LINE_LOOP);
      else
        glBegin(GL_QUADS);
      glNormal3f(-1.0, 0.0, 0.0);
      glVertex3f(-y, x, z);
      glVertex3f(-y, -x, z);
      glVertex3f(-y, -x, -z);
      glVertex3f(-y, x, -z);
      glEnd();
      if (solid) {
        glBegin(GL_TRIANGLES);
        glNormal3f(0.0, 0.0, 1.0);
        glVertex3f(0.0, 0.0, z);
        glVertex3f(-y, x, z);
        glVertex3f(-y, -x, z);
        glNormal3f(0.0, 0.0, -1.0);
        glVertex3f(0.0, 0.0, -z);
        glVertex3f(-y, -x, -z);
        glVertex3f(-y, x, -z);
        glEnd();
      }
      j = 1;
    }
  }
}

void
Box(float width, float height, float depth, char solid)
{
	float x = width, y = height, z = depth;
	
	/* bottom */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(0.0, 0.0, -1.0);
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(0.0, y, 0.0);
	glVertex3f(x, y, 0.0);
	glVertex3f(x, 0.0, 0.0);
	glEnd();
	
	/* top */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(0.0, 0.0, 1.0);
	glVertex3f(0.0, 0.0, z);
	glVertex3f(0.0, y, z);
	glVertex3f(x, y, z);
	glVertex3f(x, 0.0, z);
	glEnd();
	
	/* left */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(-1.0, 0.0, 0.0);
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(0.0, y, 0.0);
	glVertex3f(0.0,y, z);
	glVertex3f(0.0, 0.0, z);
	glEnd();
	
	/* right */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(1.0, 0.0, 0.0);
	glVertex3f(x, 0.0, 0.0);
	glVertex3f(x, y, 0.0);
	glVertex3f(x, y, z);
	glVertex3f(x, 0.0, z);
	glEnd();
	
	/* front */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(0.0, 1.0, 0.0);
	glVertex3f(0.0, y, 0.0);
	glVertex3f(x, y, 0.0);
	glVertex3f(x, y, z);
	glVertex3f(0.0, y, z);
	glEnd();
	
	/* back */
	if (!solid)
		glBegin(GL_LINE_LOOP);
	else
		glBegin(GL_QUADS);
	glNormal3f(0.0, -1.0, 0.0);
	glVertex3f(0.0, 0.0, 0.0);
	glVertex3f(x, 0.0, 0.0);
	glVertex3f(x, 0.0, z);
	glVertex3f(0.0, 0.0, z);
	glEnd();
	
/*
			if (solid) {
				glBegin(GL_TRIANGLES);
				glNormal3f(0.0, 0.0, 1.0);
				glVertex3f(0.0, 0.0, z);
				glVertex3f(-x, y, z);
				glVertex3f(-x, -y, z);
				glNormal3f(0.0, 0.0, -1.0);
				glVertex3f(0.0, 0.0, -z);
				glVertex3f(-x, -y, -z);
				glVertex3f(-x, y, -z);
				glEnd();
			}
 */
}

void
Octagon(float side, float height, char solid)
{
  char j;
  float x = sin(0.785398163) * side, y = side / 2.0, z = height / 2.0, c;

  c = x + y;
  for (j = 0; j < 8; j++) {
    glTranslatef(-c, 0.0, 0.0);
    if (!solid)
      glBegin(GL_LINE_LOOP);
    else
      glBegin(GL_QUADS);
    glNormal3f(-1.0, 0.0, 0.0);
    glVertex3f(0.0, -y, z);
    glVertex3f(0.0, y, z);
    glVertex3f(0.0, y, -z);
    glVertex3f(0.0, -y, -z);
    glEnd();
    glTranslatef(c, 0.0, 0.0);
    if (solid) {
      glBegin(GL_TRIANGLES);
      glNormal3f(0.0, 0.0, 1.0);
      glVertex3f(0.0, 0.0, z);
      glVertex3f(-c, -y, z);
      glVertex3f(-c, y, z);
      glNormal3f(0.0, 0.0, -1.0);
      glVertex3f(0.0, 0.0, -z);
      glVertex3f(-c, y, -z);
      glVertex3f(-c, -y, -z);
      glEnd();
    }
    glRotatef(45.0, 0.0, 0.0, 1.0);
  }
}

/* end of geometric shape functions */
#ifdef NORM
void
Normalize(float v[3])
{
  GLfloat d = sqrt(v[1] * v[1] + v[2] * v[2] + v[3] * v[3]);

  if (d == 0.0) {
    printf("zero length vector");
    return;
  }
  v[1] /= d;
  v[2] /= d;
  v[3] /= d;
}

void
NormXprod(float v1[3], float v2[3], float v[3], float out[3])
{
  GLint i, j;
  GLfloat length;

  out[0] = v1[1] * v2[2] - v1[2] * v2[1];
  out[1] = v1[2] * v2[0] - v1[0] * v2[2];
  out[2] = v1[0] * v2[1] - v1[1] * v2[0];
  Normalize(out);
}

#endif

void
SetMaterial(GLfloat spec[], GLfloat amb[], GLfloat diff[], GLfloat shin[])
{

  glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
  glMaterialfv(GL_FRONT, GL_SHININESS, shin);
  glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
}

void
SetMaterial2(GLfloat spec[], GLfloat amb[], GLfloat diff[], GLfloat shin[], GLfloat emiss[])
{
	
	glMaterialfv(GL_FRONT, GL_SPECULAR, spec);
	glMaterialfv(GL_FRONT, GL_SHININESS, shin);
	glMaterialfv(GL_FRONT, GL_AMBIENT, amb);
	glMaterialfv(GL_FRONT, GL_DIFFUSE, diff);
	glMaterialfv(GL_FRONT, GL_EMISSION,	emiss);
}

void
MakeBars(char solid)
{
	glNewList(SOLID_BARS, GL_COMPILE);
#ifdef LIGHT
	SetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
#endif
/*
	glColor3f(1.0, 1.0, 0.0);
	Box(1.0, 1.0, 3.0, solid);
	glTranslatef(0.75, 0.0, 0.0);
*/
#ifdef LIGHT
	SetMaterial2(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2, mat_emiss2);
#endif
	glColor3f(0.8, 0.6, 0.0);
	glTranslatef(0.0, -0.75, 0.0);
	glTranslatef(-1.5, 0.0, 0.0);
	Box(0.5, 3.0, 0.5, solid);
	glTranslatef(0.75, 0.0, 0.0);
	Box(0.5, 3.0, 0.5, solid);
	glTranslatef(0.75, 0.0, 0.0);
	Box(0.5, 3.0, 0.5, solid);
	glTranslatef(0.75, 0.0, 0.0);
	glColor3f(0.5, 0.0, 0.5);
	SetMaterial2(mat_specular3, mat_ambient3, mat_diffuse3, mat_shininess3, mat_emiss0);
	Box(0.5, 3.0, 0.5, solid);
	glTranslatef(0.75, 0.0, 0.0);
	Box(0.5, 3.0, 0.5, solid);
	glTranslatef(-1.5, 0.0, 0.0);
	glTranslatef(0.0, 0.75, 0.0);
	glEndList();
}


void
Enviro(char solid)
{


  glNewList(SOLID_ENVIRO, GL_COMPILE);
  SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4);
  glColor3f(0.0, 1.0, 0.0);
  glTranslatef(0.0, 2.0, 0.0);
  Box2(20.0, 0.2, 30.0, solid);
  glTranslatef(0.0, -2.0, 0.0);
  SetMaterial(mat_specular4, mat_ambient3, mat_diffuse2, mat_shininess);
  glColor3f(0.0, 0.8, 0.8);
  glTranslatef(-10.0, 0.0, 0.0);
  Box2(0.2, 30.0, 30.0, solid);
  glTranslatef(10.0, 0.0, 0.0);
  glTranslatef(0.0, 0.0, -20.0);
  Box2(20.0, 30.0, 0.2, solid);
  glTranslatef(0.0, 0.0, 20.0);
  glEndList();
}

void
Enviro2(char solid)
{
	
	int i, j;
	
	glNewList(SOLID_ENVIRO, GL_COMPILE);
	SetMaterial(mat_specular4, mat_ambient4, mat_diffuse4, mat_shininess4);
	glColor3f(0.0, 1.0, 0.0);
	glTranslatef(0.0, 3.0, 0.0);
	Box2(20.0, 0.5, 30.0, solid);
	glTranslatef(0.0, -3.0, 0.0);
	SetMaterial(mat_specular4, mat_ambient3, mat_diffuse2, mat_shininess);
	glColor3f(0.6, 0.6, 0.6);
	glTranslatef(0.0, 0.0, -10.0);
	for (j = 0; j < 6; j++) {
		for (i = 0; i < 2; i++) {
			if (i)
				glScalef(-1.0, 1.0, 1.0);
			glTranslatef(10.0, 4.0, 0.0);
			Box2(4.0, 8.0, 2.0, solid);
			glTranslatef(0.0, -1.0, -3.0);
			Box2(4.0, 6.0, 2.0, solid);
			glTranslatef(-10.0, -3.0, 3.0);
		}
		glScalef(-1.0, 1.0, 1.0);
		glTranslatef(0.0, 0.0, 5.0);
	}
	glEndList();
}

void
Toggle(void)
{
  if (solid_part)
    solid_part = 0;
  else
    solid_part = 1;
}

void
disable(void)
{
  glDisable(GL_LIGHTING);
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_NORMALIZE);
  glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void
lighting(void)
{

  GLfloat position[] =
  {0.0, 0.0, 5.0, 1.0};

#ifdef MOVE_LIGHT
  glRotatef((GLfloat) lightturn1, 1.0, 0.0, 0.0);
  glRotatef((GLfloat) lightturn, 0.0, 1.0, 0.0);
  glRotatef(0.0, 1.0, 0.0, 0.0);
#endif
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_NORMALIZE);
  glDepthFunc(GL_LESS);
  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

  glLightfv(GL_LIGHT0, GL_POSITION, position);
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 80.0);

  glTranslatef(0.0, 0.0, 2.0);
  glDisable(GL_LIGHTING);
  Box(0.1, 0.1, 0.1, 0);
  glEnable(GL_LIGHTING);
}

void
DrawBars(void)
{
  int i;

  glScalef(0.5, 0.5, 0.5);
  glPushMatrix();
  glTranslatef(0.0, -0.75, 0.0);
  glRotatef((GLfloat) tilt, 1.0, 0.0, 0.0);

  glRotatef(90.0, 1.0, 0.0, 0.0);

  glRotatef(-90.0, 1.0, 0.0, 0.0);

  glTranslatef(0.0, 0.75, 0.0);
  glPushMatrix();
  glRotatef((GLfloat) pivot, 0.0, 1.0, 0.0);
  glPushMatrix();
#ifdef BARS
  glCallList(SOLID_BARS);
#endif
  glPopMatrix();
  glPushMatrix();
  glTranslatef(0.5, 0.5, 0.0);

  glPopMatrix();
  for (i = 0; i < 2; i++) {
    glPushMatrix();
    if (i)
      glScalef(-1.0, 1.0, 1.0);
    glTranslatef(1.5, 0.0, 0.0);

    glTranslatef(0.9, 0.0, 0.0);

    glTranslatef(0.0, -1.4, 0.0);

    glTranslatef(0.0, -2.9, 0.0);

    glTranslatef(0.0, -0.9, -0.2);

    glPopMatrix();
  }
  glPopMatrix();

  glPopMatrix();


}

void
display(void)
{
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glEnable(GL_DEPTH_TEST);

  glPushMatrix();
  glRotatef((GLfloat) turn, 0.0, 1.0, 0.0);
  glRotatef((GLfloat) turn1, 1.0, 0.0, 0.0);
#ifdef LIGHT
  if (solid_part) {
    glPushMatrix();
    lighting();
    glPopMatrix();
  } else
    disable();
#endif
#ifdef DRAW_BARS
  glPushMatrix();
  glTranslatef(0.0, elevation, 0.0);
  DrawBars();
  glPopMatrix();
#endif
#ifdef DRAW_ENVIRO
  glPushMatrix();
  if (distance >= 20.136)
    distance = 0.0;
  glTranslatef(0.0, -5.0, -distance);
  glCallList(SOLID_ENVIRO);
  glTranslatef(0.0, 0.0, 10.0);
  glCallList(SOLID_ENVIRO);
  glPopMatrix();
#endif
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void
myinit(void)
{
  char i = 1;

  qobj = gluNewQuadric();
#ifdef LIGHT
  SetMaterial(mat_specular2, mat_ambient2, mat_diffuse2, mat_shininess2);
#endif
  glEnable(GL_DEPTH_TEST);
  MakeBars(i);

  Enviro(i);

}

void
myReshape(int w, int h)
{
  glViewport(0, 0, w, h);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  glTranslatef(0.0, 1.2, -5.5);  /* viewing transform  */
}

#ifdef ANIMATION
void
animation_walk(void)
{
  float angle;
  static int step;
	int i,j;

  if (step == 0 || step == 2) {
    /* for(frame=3.0; frame<=21.0; frame=frame+3.0){ */
    if (frame >= 0.0 && frame <= 21.0) {
      if (frame == 0.0)
        frame = 3.0;
      angle = (180 / M_PI) * (acos(((cos((M_PI / 180) * frame) * 2.043) + 1.1625) / 3.2059));
      if (frame > 0) {
        elevation = -(3.2055 - (cos((M_PI / 180) * angle) * 3.2055));
      } else
        elevation = 0.0;

      if (frame == 21)
        step++;
      if (frame < 21)
        frame = frame + 3.0;
    }
  }
  if (step == 1 || step == 3) {
    /* for(x=21.0; x>=0.0; x=x-3.0){ */
    if (frame <= 21.0 && frame >= 0.0) {
      angle = (180 / M_PI) * (acos(((cos((M_PI / 180) * frame) * 2.043) + 1.1625) / 3.2029));
      if (frame > 0)
        elevation = -(3.2055 - (cos((M_PI / 180) * angle) * 3.2055));
      else
        elevation = 0.0;

      if (frame == 0.0)
        step++;
      if (frame > 0)
        frame = frame - 3.0;
    }
  }
  if (step == 4)
    step = 0;
  distance += 0.1678;
	j = 0;
	for (i = 0; i < 9000000; i++)
		j = j + 1;
  glutPostRedisplay();
}

void
animation(void)
{
  animation_walk();
}

#endif

#ifdef GLUT
#ifdef GLUT_KEY
/* ARGSUSED1 */
void
keyboard(unsigned char key, int x, int y)
{

  int i = 0;

  switch (key) {

    /* start of bars control functions */
  case 'd':{
      RotateAdd();
      i++;
    }
    break;
  case 'g':{
      RotateSubtract();
      i++;
    }
    break;
  case 'r':{
      BarsTiltAdd();
      i++;
    }
    break;
  case 'f':{
      BarsTiltSubtract();
      i++;
    }
    break;
    /* end of bars control functions */


    /* start of light source position functions */
  case 'p':{
      LightTurnRight();
      i++;
    }
    break;
  case 'i':{
      LightTurnLeft();
      i++;
    }
    break;
  case 'o':{
      LightForwards();
      i++;
    }
    break;
  case '9':{
      LightBackwards();
      i++;
    }
    break;
    /* end of light source position functions */
  }
  if (i)
    glutPostRedisplay();
}

#endif

#ifdef GLUT_SPEC
/* ARGSUSED1 */
void
special(int key, int x, int y)
{

  int i = 0;

  switch (key) {
    /* start of view position functions */
  case GLUT_KEY_RIGHT:{
      TurnRight();
      i++;
    }
    break;
  case GLUT_KEY_LEFT:{
      TurnLeft();
      i++;
    }
    break;
  case GLUT_KEY_DOWN:{
      TurnForwards();
      i++;
    }
    break;
  case GLUT_KEY_UP:{
      TurnBackwards();
      i++;
    }
    break;
    /* end of view postions functions */
    /* start of miseclleneous functions */

    /* end of miscelleneous functions */
  }
  if (i)
    glutPostRedisplay();
}

#endif
#endif
void
menu_select(int mode)
{
  switch (mode) {
#ifdef ANIMATION
  case 1:
    glutIdleFunc(animation);
    break;
#endif
  case 2:
    glutIdleFunc(NULL);
    break;
  case 3:
    Toggle();
    glutPostRedisplay();
    break;
  case 4:
    exit(EXIT_SUCCESS);
  }
}

/* ARGSUSED */
void
null_select(int mode)
{
}

void
glutMenu(void)
{

  int glut_menu[4];

  glut_menu[2] = glutCreateMenu(null_select);
  glutAddMenuEntry("right         : right arrow", 0);
  glutAddMenuEntry("left          : left arrow", 0);
  glutAddMenuEntry("down          : up arrow", 0);
  glutAddMenuEntry("up            : down arrow", 0);

  glut_menu[3] = glutCreateMenu(null_select);
  glutAddMenuEntry("right         : p", 0);
  glutAddMenuEntry("left          : i", 0);
  glutAddMenuEntry("up            : 9", 0);
  glutAddMenuEntry("down          : o", 0);

  glut_menu[1] = glutCreateMenu(null_select);
  glutAddMenuEntry("turn left    : d", 0);
  glutAddMenuEntry("turn right   : g", 0);
  glutAddMenuEntry("up           : r", 0);
  glutAddMenuEntry("down         : f", 0);

  glut_menu[0] = glutCreateMenu(NULL);
  glutAddSubMenu("move the bars?", glut_menu[1]);
  glutAddSubMenu("rotate the scene..", glut_menu[2]);
#ifdef MOVE_LIGHT
  glutAddSubMenu("rotate the light source..", glut_menu[3]);
#endif

  glutCreateMenu(menu_select);
#ifdef ANIMATION
  glutAddMenuEntry("Start Walk", 1);
  glutAddMenuEntry("Stop Walk", 2);
#endif
  glutAddMenuEntry("Toggle Wireframe", 3);
  glutAddSubMenu("How do I ..", glut_menu[0]);
  glutAddMenuEntry("Quit", 4);
  glutAttachMenu(GLUT_LEFT_BUTTON);
  glutAttachMenu(GLUT_RIGHT_BUTTON);
}

int
main(int argc, char **argv)
{
#ifdef GLUT
  /* start of glut windowing and control functions */
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
  glutInitWindowSize(800, 600);
  glutCreateWindow("OverView");
  myinit();
  glutDisplayFunc(display);
  glutReshapeFunc(myReshape);
#ifdef GLUT_KEY
  glutKeyboardFunc(keyboard);
#endif
#ifdef GLUT_SPEC
  glutSpecialFunc(special);
#endif
  glutMenu();
  glutMainLoop();
  /* end of glut windowing and control functions */
#endif
  return 0;             /* ANSI C requires main to return int. */
}
