/*
 * Copyright (c) 1993-1997, Silicon Graphics, Inc.
 * ALL RIGHTS RESERVED
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that the above
 * copyright notice appear in all copies and that both the copyright notice
 * and this permission notice appear in supporting documentation, and that
 * the name of Silicon Graphics, Inc. not be used in advertising
 * or publicity pertaining to distribution of the software without specific,
 * written prior permission.
 *
 */


/*
 *  userInterface.c
 *
 *  This program governs the user interface for displaying a 3D object.
 *  Left mouse button rotates;  middle mouse button translates.
 *
 *  It began as a demo program from SGI
 *
 *    http://www.sgi.com/software/opengl/examples/redbook/source/torus.c
 *
 *  Not much of the original is still left. Just the reshape()
 *  function  and the copyright notice above.
 *
 *  Copyright (c) 2000
 *  David C. Banks
 */

#include "userInterface.h"

float idleRotAngle, idleRotx, idleRoty, idleRotz;
float idleTransx, idleTransy, idleTransz;
int   oldX, oldY;
int   RotateFlag    = 0;
int   TranslateFlag = 0;
int   ThrowFlag     = 0;


/* Get the direction the mouse drags. If the object is rotated while
being released, the rotation continues (it is thrown with spin). */
void mouse(int button, int state, int x, int y)
  {
  oldX = x;
  oldY = y;

  switch (state)
    {
    case GLUT_DOWN: 
      switch (button)
        {
	case GLUT_LEFT_BUTTON:   
	  RotateFlag    = 1; 
	  ThrowFlag     = 0; 
	  break;
	case GLUT_MIDDLE_BUTTON: 
	  TranslateFlag = 1; 
	  break;
        }
      motion(x, y);
      break;

    case GLUT_UP: 
      switch (button)
        {
	case GLUT_LEFT_BUTTON:   
	  RotateFlag    = 0; 
	  ThrowFlag     = 1; 
	  break;
	case GLUT_MIDDLE_BUTTON: 
	  TranslateFlag = 0; 
	  break;
	}
      break;
    }
  }


/* Rotate on left mouse drag; translate on middle mouse drag. */
void motion(int x, int y)
  {
  float    vx, vy, vz;
  GLfloat  matrix[16], newMatrix[16];

  vx   =   (x - oldX);
  vy   =  -(y - oldY);   // y-axis goes up rather than down 
  vz   = 0.0;

  glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
  glLoadIdentity();

  if ( RotateFlag )
    {
    idleRotAngle =  0.2*sqrt(vx*vx + vy*vy);
    idleRotx     = -1.50*vy;  
    idleRoty     =  1.50*vx;
    idleRotz     =  1.50*vz;

    glRotatef(idleRotAngle, idleRotx,  idleRoty, idleRotz);
    }
  if ( TranslateFlag )
    {
    idleTransx     = 0.01*vx;
    idleTransy     = 0.01*vy;
    idleTransz     =  vz;

    glTranslatef(idleTransx,  idleTransy, idleTransz);
    }

  glGetFloatv(GL_MODELVIEW_MATRIX, newMatrix);
  glMultMatrixf(matrix);


  oldX = x;
  oldY = y;
  }


/* Continue rotation if the left mouse throws the object. */
void idle(void)
  {
  GLfloat  matrix[16], rotMatrix[16];

  if (ThrowFlag)
    {
    glGetFloatv(GL_MODELVIEW_MATRIX, matrix);
    glLoadIdentity();
    glRotatef(idleRotAngle, idleRotx,  idleRoty, idleRotz);
    glGetFloatv(GL_MODELVIEW_MATRIX, rotMatrix);
    glMultMatrixf(matrix);
    }

  glutPostRedisplay();
  }

/* Exit when a key is pressed. */
void keyboard(unsigned char key, int x, int y)
  {
  exit(0);
  }


void userInterfaceInit(void)
  {
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutIdleFunc(idle);
  glutKeyboardFunc(keyboard);
  }