/* 
Jeffrey Grafton <jgrafton at tjhsst dot edu>
11/2/2002

This program is released under the GNU General Public License.
A copy of this license is available online at
http://www.gnu.org/copyleft/gpl.html.
*/


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

#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 600

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

GLfloat light_position[] = {5.0, 5.0, 5.0, 1.0};
GLfloat light_eyes[] = {0.0, 0.0, 0.0, 1.0};
GLfloat white_light[] = {0.1, 0.1, 0.0, 1.0};
GLfloat spin_val = 0.0;
GLfloat mat_specular[] = {0.5, 0.5, 0.5, 1.0};
GLfloat mat_shininess[]= {50.0};
GLdouble head_spin = 0.0;
GLdouble arm_spin = 60.0;
GLdouble body_spin = 0.0;
GLdouble view_spin = 0.0;
GLdouble leg_spin = 90.0;

void init(void)
{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_COLOR_MATERIAL);
	
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	
	glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
	glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);
}

void display(void)
{
	/*GLfloat emission[] = {0.5, 0.5, 0.0, 1.0};
	GLfloat black[] = {0.0, 0.0, 0.0, 1.0};
	*/
	GLUquadric *quadric = gluNewQuadric();
	gluQuadricDrawStyle(quadric, GLU_FILL); 
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
	glLoadIdentity();
	gluLookAt(view_position[0], view_position[1], view_position[2], 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

	glLightfv(GL_LIGHT0, GL_POSITION, light_position);
	glLightfv(GL_LIGHT0, GL_AMBIENT, white_light);
	
	glRotated(view_spin, 0.0, 1.0, 0.0);
	
	glPushMatrix();
		glColor3d(0.5, 0.5, 0.5);
		glPushMatrix();
			glRotated(body_spin, 0.0, 1.0, 0.0);
			glPushMatrix();
				glScaled(1.2, 1.7, 1.0);
				glutSolidSphere(0.5, 50, 50);
			glPopMatrix();
		
			glPushMatrix();
				glRotated(head_spin, 0.0, 1.0, 0.0);
				glPushMatrix();
					glRotated(90.0, 0.0, 1.0, 0.0);
					glTranslated(0.0, 1.0, 0.0);
					glPushMatrix();
						glScaled(1.8, 1.0, 1.2);
						gluCylinder(quadric, 0.3, 0.0, 0.7, 20, 20);
					glPopMatrix();
				glPopMatrix();
				glPushMatrix();
					glRotated(270.0, 0.0, 1.0, 0.0);
					glTranslated(0.0, 1.0, 0.0);
					glPushMatrix();
						glScaled(1.8, 1.0, 1.2);
						gluCylinder(quadric, 0.3, 0.0, 0.7, 20, 20);
					glPopMatrix();
				glPopMatrix();
				glPushMatrix();
					glTranslated(0.0, 1.0, 0.0);
					glRotated(90, 1.0, 0.0, 0.0);
					gluCylinder(quadric, 0.3, 0.3, 0.5, 20, 20);
				glPopMatrix();
				glPushMatrix();
					glColor3d(1.0, 1.0, 0.0);
					glTranslated(0.2, 1.0, 0.4);
					glutSolidCube(0.05);
					
					glTranslated(-0.4, 0.0, 0.0);
					glutSolidCube(0.05);
				glPopMatrix();
			glPopMatrix();
		
			glColor3d(0.5, 0.5, 0.5);
			glPushMatrix();	
				glTranslated(0.35, 0.5, 0.0);
				glRotated(90.0, 0.0, 1.0, 0.0);
				glRotated(arm_spin, 1.0, 0.0, 0.0);
				gluCylinder(quadric, 0.1, 0.1, 0.9, 20, 20);
			glPopMatrix();
			glPushMatrix();
				glTranslated(-0.35, 0.5, 0.0);
				glRotated(90.0, 0.0, 1.0, 0.0);
				glRotated(180.0 - arm_spin, 1.0, 0.0, 0.0);
				gluCylinder(quadric, 0.1, 0.1, 0.9, 20, 20);
			glPopMatrix();
		glPopMatrix();

		glPushMatrix();
			glTranslated(0.0, -0.8, 0.0);
			glPushMatrix();
				glScaled(2.0, 1.0, 1.5);
				glutSolidSphere(0.3, 50, 50);
			glPopMatrix();
			glPushMatrix();
				glTranslated(0.45, 0.0, 0.0);
				glRotated(leg_spin, 1.0, 0.0, 0.0);
				gluCylinder(quadric, 0.15, 0.1, 0.9, 20, 20);
			glPopMatrix();
			glPushMatrix();
				glTranslated(-0.45, 0.0, 0.0);
				glRotated(180-leg_spin, 1.0, 0.0, 0.0);
				gluCylinder(quadric, 0.15, 0.1, 0.9, 20, 20);
				glPushMatrix();
					glTranslated(0.0, 0.0, 0.9);
					glRotated(fabs(90-leg_spin)/(leg_spin > 90 ? 7.0 : 1.0), 1.0, 0.0, 0.0);
					gluCylinder(quadric, 0.1, 0.05, 0.8, 20, 20);
				glPopMatrix();
			glPopMatrix();
		glPopMatrix();
	glPopMatrix();
	
	glutSwapBuffers();
}

void reshape(int w, int h)
{
	glViewport(0, 0, (GLsizei)w, (GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
	glMatrixMode(GL_MODELVIEW);
}

void keyboard (unsigned char key, int x, int y)
{
	if(key == 'o')
		view_spin += 5.0;
	if(key == 'p')
		view_spin -= 5.0;
	if(key == 'k')
		head_spin += 5.0;
	if(key == 'l')
		head_spin -= 5.0;
	if(key == 'q' && arm_spin > -30.0)
		arm_spin -= 5.0;
	if(key == 'a' && arm_spin < 60.0)
		arm_spin += 5.0;
	if(key == 'n')
		body_spin += 5.0;
	if(key == 'm')
		body_spin -= 5.0;
	if(key == '[')
		view_position[2] -= 1.0;
	if(key == ']')
		view_position[2] += 1.0;
	if(key == 'w' && leg_spin > 45.0)
		leg_spin -= 5.0;
	if(key == 's' && leg_spin < 135.0)
		leg_spin += 5.0;
 	glutPostRedisplay();
}

int
main (int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
	glutCreateWindow(argv[0]);
	init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutKeyboardFunc(keyboard);
	glutMainLoop();
	return 0;
}

