

#include <cstdlib>
#include <GL/glut.h>

#include <iostream>
using namespace std;


GLUquadricObj *obj;
static GLfloat theta[] = {0.0,0.0,0.0};
static char spinningAxis = 'x';
static bool isAutomaticSpinning = false;

static int geomtricObjectID = 1;

void display()
{
/* display callback, clear frame buffer and z buffer,
   oriente the object and draw, swap buffers */

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();
	glRotatef(theta[0], 1.0, 0.0, 0.0);
	glRotatef(theta[1], 0.0, 1.0, 0.0);
	glRotatef(theta[2], 0.0, 0.0, 1.0);

 switch(geomtricObjectID)
 {
	case 1:
		gluCylinder(obj, 1.0, 0.5, 1.0, 12, 12); 
		break;
	case 2:
		gluSphere(obj, 1.0, 12, 12); 
		break;
	case 3:
		gluDisk(obj, 0.5, 1.0, 10, 10);
		break;
	case 4:
		gluPartialDisk( obj, 0.5, 1.0, 10, 10, 0.0, 45.0);
		break;
	case 5:
		glutWireIcosahedron();
		break;	
	case 6:
		glutWireDodecahedron();
		break;	
	case 7:
		glutWireTeapot(1.0);
		//glutSolidTeapot(1.0);
		break;
	case 8:
		glutWireTorus(0.5, 1.0, 10, 10);
		//glutSolidTorus(0.5, 1.0, 10, 10);
		break;
	case 9:
		glutWireCone(1.0, 1.0, 10, 10);
		//glutSolidCone(1.0, 1.0, 10, 10);
		break;
	default:
		glutWireTeapot(1.0);
		//glutSolidTeapot(1.0);

		break;
 }

 glutSwapBuffers();
}

void spinObject()
{
	GLint spinningAxisID = 0;

	/* Idle callback, spin cube 1 degrees about selected spinningAxis */
	if ( spinningAxis == 'x')
		spinningAxisID = 0;
	else if ( spinningAxis == 'y')
		spinningAxisID = 1;
	else if ( spinningAxis == 'z')
		spinningAxisID = 2;
	else
		{	spinningAxis == 'x';
			spinningAxisID = 0;
		}

	theta[spinningAxisID] += 1.0;
	if( theta[spinningAxisID] > 360.0 ) theta[spinningAxisID] -= 360.0;
	glutPostRedisplay();
}

void mouse(int btn, int state, int x, int y)
{

/* mouse callback, selects an spinningAxis about which to rotate */

	if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) spinningAxis = 'x';
	if(btn==GLUT_MIDDLE_BUTTON && state == GLUT_DOWN) spinningAxis = 'y';
	if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) spinningAxis = 'z';

	cout << "  Button : " << btn ;
	cout << "  spinningAxis : " << spinningAxis << endl << endl;

}

void myReshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    if (w <= h)
        glOrtho(-2.0, 2.0, -2.0 * (GLfloat) h / (GLfloat) w,
            2.0 * (GLfloat) h / (GLfloat) w, -10.0, 10.0);
    else
        glOrtho(-2.0 * (GLfloat) w / (GLfloat) h,
            2.0 * (GLfloat) w / (GLfloat) h, -2.0, 2.0, -10.0, 10.0);
    glMatrixMode(GL_MODELVIEW);
}

void key(unsigned char key, int x, int y)
{
	//Stop automatic spinning and spin the object once each time the space key is pressed
	if(key==' ') 
	{	isAutomaticSpinning = false;
		glutIdleFunc(NULL);
		spinObject();
	}

	//Toggle the automatic spinning
	if(key=='s') 
	{
		if (isAutomaticSpinning)
		{	isAutomaticSpinning = false;
			glutIdleFunc(NULL);
		}
		else
		{	isAutomaticSpinning = true;
			glutIdleFunc(spinObject);
		}
	}

	//Choose a particualr axix of spinning
	if(key=='x' || key=='y' || key=='z') 
		spinningAxis = key;

	//Choose a new geometric object o to display
	//and also Reset the orientation to (0,0,0)
	if(key>='0' && key<='9') 
	{	geomtricObjectID = GLint (key - '0'); 

		theta[0] = theta[0] = theta[0] = 0;
		switch(geomtricObjectID)
		{
			case 1:
				cout << "gluCylinder(obj, 1.0, 0.5, 1.0, 12, 12);";
				break;
			case 2:
				cout << "gluSphere(obj, 1.0, 12, 12); ";
				break;
			case 3:
				cout << "gluDisk(obj, 0.5, 1.0, 10, 10);";
				break;
			case 4:
				cout << "gluPartialDisk( obj, 0.5, 1.0, 10, 10, 0.0, 45.0);";
				break;
			case 5:
				cout << "glutWireIcosahedron();";
				break;	
			case 6:
				cout << "glutWireDodecahedron();";
				break;	
			case 7:
				cout << "glutWireTeapot(1.0);";
				break;
			case 8:
				cout << "glutWireTorus(0.5, 1.0, 10, 10);";
				break;
			case 9:
				cout << "glutWireCone(1.0, 1.0, 10, 10);";
				break;
			default:
				cout << "glutWireTeapot(1.0);";
				break;
		}

		glutPostRedisplay();
		cout << endl;
	}



	cout << "  Key pressed: " << key << endl;
	cout << "  (" << theta[0]<< ',' << theta[1] << ',' << theta[2] << ')' 
		 << " = (theta[0],theta[1],theta[2]): Current orientation of the object " << endl;
	cout << "  Rotate along spinningAxis : " << spinningAxis << endl << endl;

}

void
main(int argc, char **argv)
{
   
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(500, 500);
    glutCreateWindow("Orient the object through rotation");

	glEnable(GL_DEPTH_TEST);

/* need both double buffering and z buffer */

    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
	glutIdleFunc(NULL);
	glutMouseFunc(mouse);
	glutKeyboardFunc(key);
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glColor3f(1.0, 0.0, 1.0);

	obj = gluNewQuadric();
	//gluQuadricDrawStyle(obj, GLU_FILL);
	//gluQuadricDrawStyle(obj, GLU_POINT);
 	gluQuadricDrawStyle(obj, GLU_LINE);

    glutMainLoop();
}
