/*********************************************************************
 *   File:     MorphingWithIdleFunc.cpp
 *   Author:   Dr. Dalton R. Hunkins     
 *   Date:     September 2008
 *
 *
 *  Purpose of Exmaple
 *  This example illustrates using an Idle
 *  function in creating an animation. The reason
 *  we use  an glut idle function versus counted 
 *  iteration is the iteration will run to completion 
 *  before any user events can be handled. On the 
 *  other hand, an idle runs while the event queue
 *  is empty and is interrupted wheneven an event
 *  must be handled.
 *
 *
 * User Interaction particular to this example:
 *   Menu:
 *    Right Mouse Button tiggered providing choices
 *       to pause and resume animation 
 *       to display full screen or window
 *       to set speed of the animation (amount of change per frame)
**********************************************************************/

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#include <cmath>

#define MENU_ITEM_PAUSE   902
#define MENU_ITEM_RESUME  903
#define MENU_ITEM_FULL    904
#define MENU_ITEM_WINDOW  905

#define MENU_ITEM_SLOWER      906
#define MENU_ITEM_SLOW        907
#define MENU_ITEM_NORMAL      908
#define MENU_ITEM_FAST        909  
#define MENU_ITEM_FASTER      910

int count              = 0;
int numberOfPartitions = 1000;
int millisecondDelay   = 50;
int countDirection     = 1;

void star() {
	 glClear(GL_COLOR_BUFFER_BIT);
	
     double PI = 3.14159;
     				
     double radius1 = -0.75 * (count/ (double) numberOfPartitions) + 1.0;
     double radius2 =  0.75 * (count/ (double) numberOfPartitions) + 0.25;
     
     float colorValue1 = -1.0*(count/ (float) numberOfPartitions) + 1.0;
     float colorValue2 = 1.0*(count/ (float) numberOfPartitions);

     glBegin(GL_TRIANGLE_FAN);
        glColor3f(0.7, 0.7, 0.7);
	    glVertex3d(0.0, 0.0, 0.0);
	    
	    glColor3f(colorValue1, colorValue2, colorValue2);
	    glVertex3d(radius1 * cos(0.0   * PI / 180.0), 
                     radius1 * sin(0.0   * PI / 180.0), 0.0);
                     
        glColor3f(colorValue1, colorValue1, colorValue2);             
	    glVertex3d(radius2 * cos(30.0  * PI / 180.0), 
                     radius2 * sin(30.0  * PI / 180.0), 0.0);
                     
        glColor3f(colorValue2, colorValue1, colorValue2);
	    glVertex3d(radius1 * cos(60.0  * PI / 180.0), 
                     radius1 * sin(60.0  * PI / 180.0), 0.0);
                     
        glColor3f(colorValue2, colorValue1, colorValue1);                             
	    glVertex3d(radius2 * cos(90.0  * PI / 180.0), 
                     radius2 * sin(90.0  * PI / 180.0), 0.0);
                     
        glColor3f(colorValue2, colorValue2, colorValue1);                             
	    glVertex3d(radius1 * cos(120.0 * PI / 180.0), 
                     radius1 * sin(120.0 * PI / 180.0), 0.0);
                     
        glColor3f(colorValue1, colorValue2, colorValue1);                                                  
	    glVertex3d(radius2 * cos(150.0 * PI / 180.0), 
                     radius2 * sin(150.0 * PI / 180.0), 0.0);
                                          
	    glColor3f(colorValue1, colorValue2, colorValue2);
	    glVertex3d(radius1 * cos(180.0 * PI / 180.0), 
                     radius1 * sin(180.0 * PI / 180.0), 0.0);
                     
        glColor3f(colorValue1, colorValue1, colorValue2);             
	    glVertex3d(radius2 * cos(210.0 * PI / 180.0), 
                     radius2 * sin(210.0 * PI / 180.0), 0.0);
                                        
        glColor3f(colorValue2, colorValue1, colorValue2);
	    glVertex3d(radius1 * cos(240.0 * PI / 180.0), 
                     radius1 * sin(240.0 * PI / 180.0), 0.0);
                     
        glColor3f(colorValue2, colorValue1, colorValue1);                             
	    glVertex3d(radius2 * cos(270.0 * PI / 180.0), 
                     radius2 * sin(270.0 * PI / 180.0), 0.0);
                     
        glColor3f(colorValue2, colorValue2, colorValue1);                             
	    glVertex3d(radius1 * cos(300.0 * PI / 180.0), 
                     radius1 * sin(300.0 * PI / 180.0), 0.0);
                     
        glColor3f(colorValue1, colorValue2, colorValue1);                                                  
	    glVertex3d(radius2 * cos(330.0 * PI / 180.0), 
                     radius2 * sin(330.0 * PI / 180.0), 0.0);
                     
	    glColor3f(colorValue1, colorValue2, colorValue2);
	    glVertex3d(radius1 * cos(360.0 * PI / 180.0), 
                     radius1 * sin(360.0 * PI / 180.0), 0.0);
	  glEnd();
   glutSwapBuffers();
}

void init() {
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluOrtho2D(-1.0, 1.0, -1.0, 1.0);
  	  
   glClearColor(0.0, 0.0, 0.0, 1.0);
}	  
   
void animation() {
  glutPostRedisplay();
  count += countDirection;
  if (count > numberOfPartitions) {
     count = numberOfPartitions;
     countDirection *= -1;
  }
  else if (count < 0) {
     count = 0; 
     countDirection *= -1;
  }   
}

void menuHandler(int selection) {
   switch (selection) {
      // Pausing and Resuming Animation
      case MENU_ITEM_PAUSE :
        glutIdleFunc(NULL);
        break;
      case MENU_ITEM_RESUME :
        glutIdleFunc(animation);
        break;

      // Changing the Display Area
      case MENU_ITEM_FULL :
        glutFullScreen();
        break;
      case MENU_ITEM_WINDOW :
          glutPositionWindow(50, 50);
          glutReshapeWindow(500, 500);
          break;

      // Setting the Animation Speed
      case MENU_ITEM_SLOWER :
          numberOfPartitions = 1800;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_SLOW :
          numberOfPartitions = 1400;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_NORMAL :
          numberOfPartitions = 1000;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_FAST :
          numberOfPartitions = 600;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_FASTER :
          numberOfPartitions = 200;
          count = 0;
          glutPostRedisplay();
          break; 
   }
}         
   	          
void createMenu() {
    glutCreateMenu(menuHandler);
    glutAddMenuEntry("Pause Animation",  MENU_ITEM_PAUSE);
    glutAddMenuEntry("Resume Animation", MENU_ITEM_RESUME);
    glutAddMenuEntry("Full Screen",      MENU_ITEM_FULL);
    glutAddMenuEntry("Window",           MENU_ITEM_WINDOW);
    glutAddMenuEntry("Slower Speed",     MENU_ITEM_SLOWER);
    glutAddMenuEntry("Slow Speed",       MENU_ITEM_SLOW);
    glutAddMenuEntry("Normal Speed",     MENU_ITEM_NORMAL);
    glutAddMenuEntry("Fast Speed",       MENU_ITEM_FAST);
    glutAddMenuEntry("Faster Speed",     MENU_ITEM_FASTER);
    glutAttachMenu(GLUT_RIGHT_BUTTON);                                 	
}

int main (int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowPosition(10, 10);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Morphing");

    createMenu();
   
    init();
            	    
    glutDisplayFunc(star);

    glutIdleFunc(animation);

    glutMainLoop();
    return 0;
}