/*
	Example - simple rotations around the X-axis
	
	Assumptions are simple -- body is modeled as a set of small squares, and heat flows
	between squares based on the relative heats of the two squares and a diffusion
	function that includes a constant that models the heat conductivity of the bodies.
	
	The diffusion function mimics the error-diffusion approach of some standard halftoning
	techniques
*/
#include "glut.h"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

float vp = 20.0;

void myinit(void);
void square(void);
void axis(float,char);
void axes(float);
void display(void);
void reshape(int, int);

void myinit(void)
{
	glEnable (GL_DEPTH_TEST);
	glClearColor(0.5, 0.5, 0.5, 1.0); // gray background
}

void square (void)
{
	typedef GLfloat point [3];

	point v[8] = {
		{12.0, -1.0, -1.0},
		{12.0, -1.0,  1.0},
		{12.0,  1.0,  1.0},
		{12.0,  1.0, -1.0} };

	glBegin (GL_QUADS);
		glVertex3fv(v[0]);
		glVertex3fv(v[1]);
		glVertex3fv(v[2]);
		glVertex3fv(v[3]);
	glEnd();
}

void axis(float scale, char whichAxis)
{
// draw one axis, the Z-axis, as the template for all axes
//  Axes are to be colored white
    GLfloat black[]={0.0, 0.0, 0.0, 1.0}, red[]={1.0, 0.0, 0.0, 1.0},
    		green[]={0.0, 1.0, 0.0, 1.0}, blue[]={0.0, 0.0, 1.0, 1.0};
    GLfloat coneHeight, coneRad, axisLength, axisRad;

//	granularity of cone
#define GRAN 10

//	Set the sizes for the axes
	coneHeight = scale*0.05;
	coneRad = scale*0.05;
	axisRad = scale*0.01;
	axisLength = scale;
    glColor3fv(black);
//  Draw the standard axis in Z-orientation
    glBegin(GL_QUAD_STRIP);
      glVertex3f( axisRad, axisRad,  axisLength );
      glVertex3f( axisRad, axisRad, -axisLength );
      glVertex3f(-axisRad, axisRad,  axisLength );
      glVertex3f(-axisRad, axisRad, -axisLength );
      glVertex3f(-axisRad,-axisRad,  axisLength );
      glVertex3f(-axisRad,-axisRad, -axisLength );
      glVertex3f( axisRad,-axisRad,  axisLength );
      glVertex3f( axisRad,-axisRad, -axisLength );
      glVertex3f( axisRad, axisRad,  axisLength );
      glVertex3f( axisRad, axisRad, -axisLength );
    glEnd();
    glPushMatrix();
    glTranslatef( 0.0, 0.0, axisLength );
    switch(whichAxis) {
    case 'x':
        glColor3fv(red); break;
    case 'y':
        glColor3fv( green ); break;
    case 'z':
        glColor3fv( blue ); break;
	}
    glutSolidCone( coneHeight, coneRad, GRAN, GRAN );
    glPopMatrix();
}

void axes(float scale)
{
//  Draw the Z-axis
    axis(scale, 'z');
//  Draw the standard axis in X-orientation
    glPushMatrix();
    glRotatef( 90.0, 0.0, 1.0, 0.0 );
    axis(scale, 'x');
    glPopMatrix();
//  Draw the standard axis in Y-orientation
    glPushMatrix();
    glRotatef( -90.0, 1.0, 0.0, 0.0 );
    axis(scale, 'y');
    glPopMatrix();
}

void display( void )
{
	int i;
	float theta = 0.0;
	
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    axes(10.0); 
	for (i=0; i<8; i++) {
		glPushMatrix();
		glRotatef(theta, 0.0, 0.0, 1.0);
		if (i==0) glColor3f(1.0, 0.0, 0.0);
			else  glColor3f(1.0, 1.0, 1.0);
		square();
		theta += 45.0;
		glPopMatrix();
	}
	glutSwapBuffers();
}

void reshape(int w,int h)
{
	glViewport(0,0,(GLsizei)w,(GLsizei)h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0, (float)w/(float)h, 1.0, 300.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	//         eye point   center of view       up
	gluLookAt(vp/10.0, -vp, vp, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);
}

void main(int argc, char** argv)
{
/* Standard GLUT initialization */
	    glutInit(&argc,argv);
	    glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH); 
	    glutInitWindowSize(500,500);
	    glutInitWindowPosition(50,50);
		glutCreateWindow("Rotations in space");
	    glutDisplayFunc(display);
	    glutReshapeFunc(reshape);
		
        myinit();
	    glutMainLoop(); /* enter event loop */
}