#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <GL/glut.h>
#include <GL/gl.h>

int showTorus=1;
int order=1;
float viewRotY = 0, viewRotX = 0;


void drawCoordinateAxes(void)
	{
	glLineWidth(2.0);
	glColor3f(1.0, 1.0, 0.0);
	glBegin(GL_LINES);
	 glVertex3f(-1.0, 0.0, 0.0);
	 glVertex3f(1.0, 0.0, 0.0);
	 glVertex3f(0.0, -1.0, 0.0);
	 glVertex3f(0.0, 1.0, 0.0);
	 glVertex3f(0.0, 0.0, -1.0);
	 glVertex3f(0.0, 0.0, 1.0);
	glEnd();
	glLineWidth(1.0);
	glColor3f(1.0, 0.0, 0.0);
	glRasterPos3f(1.0, 0.0, 0.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'X');
	glRasterPos3f(0.0, 1.0, 0.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'Y');
	glRasterPos3f(0.0, 0.0, 1.0);
	glutBitmapCharacter(GLUT_BITMAP_TIMES_ROMAN_24, 'Z');
	}



/* drawTRS - This function shows the results of:
		glTranslatef(2.0, 2.0, 1.0);
		glRotatef(40.0, 1.0, 0.0, 0.0);
		glScalef(0.5, 0.5, 0.5);
		glutWireTorus(0.2, 1.0, 6, 12);
*/
void drawTRS(void)
	{
	drawCoordinateAxes();
	if (showTorus == 1)
		{
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glTranslatef(2.0, 2.0, 1.0);
	if (showTorus == 2)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glRotatef(40.0, 1.0, 0.0, 0.0);
	if (showTorus == 3)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glScalef(0.5, 0.5, 0.5);
	if (showTorus == 4)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}
	}


/* drawRTS - This function shows the results of:
		glRotatef(40.0, 1.0, 0.0, 0.0);
		glTranslatef(2.0, 2.0, 1.0);
		glScalef(0.5, 0.5, 0.5);
		glutWireTorus(0.2, 1.0, 6, 12);
*/
void drawRTS(void)
	{
	drawCoordinateAxes();
	if (showTorus == 1)
		{
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glRotatef(40.0, 1.0, 0.0, 0.0);
	if (showTorus == 2)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glTranslatef(2.0, 2.0, 1.0);
	if (showTorus == 3)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glScalef(0.5, 0.5, 0.5);
	if (showTorus == 4)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}
	}


/* drawSRT - This function shows the results of:
		glScalef(0.5, 0.5, 0.5);
		glRotatef(40.0, 1.0, 0.0, 0.0);
		glTranslatef(2.0, 2.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
*/
void drawSRT(void)
	{
	drawCoordinateAxes();
	if (showTorus == 1)
		{
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glScalef(0.5, 0.5, 0.5);
	if (showTorus == 2)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glRotatef(40.0, 1.0, 0.0, 0.0);
	if (showTorus == 3)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}

	glTranslatef(2.0, 2.0, 1.0);
	if (showTorus == 4)
		{
		drawCoordinateAxes();
		glColor3f(1.0, 1.0, 1.0);
		glutWireTorus(0.2, 1.0, 6, 12);
		}
	}



void drawEverything(void)
	{
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glEnable(GL_DEPTH_TEST);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(50.0, 1.0, 1.0, 10.0);
	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();
	glTranslatef(0.0, 0.0, -8.0);
	glRotatef(viewRotX, 1.0, 0.0, 0.0);
	glRotatef(viewRotY, 0.0, 1.0, 0.0);
	
	if (order == 1)
		drawTRS();
	else if (order == 2)
		drawRTS();
	else if (order == 3)
		drawSRT();
	
	glutSwapBuffers();
	}


static void key(unsigned char k, int x, int y)
	{
	if (k == 27)
		exit(0);
	else if (k == '1')
		showTorus = 1;
	else if (k == '2')
		showTorus = 2;
	else if (k == '3')
		showTorus = 3;
	else if (k == '4')
		showTorus = 4;
	else if (k == 't')
		order = 1;
	else if (k == 'r')
		order = 2;
	else if (k == 's')
		order = 3;
	glutPostRedisplay();
	}


static void specialkey(int k, int x, int y)
	{
	if (k == GLUT_KEY_LEFT)
		viewRotY += 3;
	else if (k == GLUT_KEY_RIGHT)
		viewRotY -= 3;
	else if (k == GLUT_KEY_UP)
		viewRotX += 3;
	else if (k == GLUT_KEY_DOWN)
		viewRotX -= 3;
	glutPostRedisplay();
	}



int main(int argc, char *argv[])
	{
	printf("Controls:\n"
		"  Transformation order:\n"
		"      t - Translate, Rotate, Scale\n"
		"      r - Rotate, Translate, Scale\n"
		"      s - Scale, Rotate, Translate\n"
		"  Drawing:\n"
		"      1 - draw untransformed torus\n"
		"      2 - draw torus after first transformation\n"
		"      3 - draw torus after second transformation\n"
		"      4 - draw torus after third transformation\n");
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutCreateWindow("example");
	glutDisplayFunc(drawEverything);
	glutKeyboardFunc(key);
	glutSpecialFunc(specialkey);
	glutMainLoop();
	return 0;
	}
