/*********************************************************************
 *   File:     MorphingWithTimerFunc.cpp
 *   Author:   Dr. Dalton R. Hunkins     
 *   Date:     September 2008
 *
 *
 *  Purpose of Exmaple
 *  This example illustrates using an Timer
 *  function in creating an animation. We use
 *  an glut timer function versus an idle 
 *  function to remove platform dependency. 
 *  In particular, the speed in which the 
 *  animation runs when using an idle function
 *  varies with the speed of the platform and 
 *  its graphics card. Making the speed of the 
 *  animation uniform between platforms is 
 *  desirable, which we accomplish with a glut 
 *  timer function.  We define a timer function 
 *  with a delay and, in turn, establish a 
 *  frame rate for the animation, as we see here.
 *
 *
 *   User Interaction particular to this example:
 *    Menu:
 *      Right Mouse Button tiggered providing choices
 *        to display full screen or window
 *        to set speed of the animation (number of delay in milliseconds
**********************************************************************/

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

#include <cmath>

#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  = 50;
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;
   }   
   glutTimerFunc(millisecondDelay, animation, 0);
}

void menuHandler(int selection) {
   switch (selection) {
   // 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 :
          millisecondDelay = 500;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_SLOW :
          millisecondDelay = 100;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_NORMAL :
          millisecondDelay = 50;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_FAST :
          millisecondDelay = 10;
          count = 0;
          glutPostRedisplay();
          break; 
      case MENU_ITEM_FASTER :
          millisecondDelay = 0;
          count = 0;
          glutPostRedisplay();
          break; 
   }
}         
   	          
void createMenu() {
    glutCreateMenu(menuHandler);
    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);

    glutTimerFunc(0, animation, 0);

    glutMainLoop();
    return 0;
}