#include <stdlib.h>
#include <math.h>
#include <GLUT/glut.h>

int turn,turn1;

#define VIEW_TURN_RATE	10


/* start of light source position functions */
void
TurnRight(void)
{
    turn = (turn - VIEW_TURN_RATE) % 360;
}

void
TurnLeft(void)
{
    turn = (turn + VIEW_TURN_RATE) % 360;
}

void
TurnForwards(void)
{
    turn1 = (turn1 - VIEW_TURN_RATE) % 360;
}

void
TurnBackwards(void)
{
    turn1 = (turn1 + VIEW_TURN_RATE) % 360;
}



void
lighting(void)
{

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    
    glPushMatrix();
#ifdef MOVE_LIGHT
    glRotatef((GLfloat) lightturn1, 1.0, 0.0, 0.0);
    glRotatef((GLfloat) lightturn, 0.0, 1.0, 0.0);
    glRotatef(0.0, 1.0, 0.0, 0.0);
#endif

    glDisable(GL_LIGHTING); // to draw the wire cube    
    glTranslatef(2.0, 2.0, 2.0);
    glScaled(0.1,0.1,0.1);
    glutWireCube(1.0);
    glEnable(GL_LIGHTING);

    glPopMatrix();



    
}

int walls()
{

    glPushMatrix();
    glTranslated(1.0,0.01,1.0);
    glScaled(2.0,0.02,2.0);
    glutSolidCube(1.0);
    glPopMatrix();

    glPushMatrix();
    glRotated(90.0,0.0,0.0,1.0);
    glTranslated(1.0,0.01,1.0);
    glScaled(2.0,0.02,2.0);
    glutSolidCube(1.0);
    glPopMatrix();

    glPushMatrix();
    glRotated(-90.0,1.0,0.0,0.0);
    glTranslated(1.0,0.01,1.0);
    glScaled(2.0,0.02,2.0);
    glutSolidCube(1.0);
    glPopMatrix();
    
    
}

int leg(double thick, double len)
{
    glPushMatrix();
    glTranslated(0,len/2,0);
    glScaled(thick,len,thick);
    glutSolidCube(1.0);
    glPopMatrix();
}

int table()
{
    double distx=0.95*1.2/2-0.05/2;
    double distz=0.95*.8/2-0.05/2;

    //tabletop
    glPushMatrix();
    glTranslated(0,0.9,0);
    glScaled(1.2,0.02,0.8);
    glutSolidCube(1.0);
    glPopMatrix();
    glPushMatrix();
    glTranslated(distx,0,distz);
    leg(0.05,0.9);
    glTranslated(0,0,-2*distz);
    leg(0.05,0.9);
    glTranslated(-2*distx,0,2*distz);
    leg(0.05,0.9);
    glTranslated(0,0,-2*distz);
    leg(0.05,0.9);
    glPopMatrix();
    
    
}


teapot()
{
    glutSolidTeapot(0.15);

}


void
display(void)
{
    // setup OpenGL
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    // set view position
    glPushMatrix();
    glRotatef((GLfloat) turn, 0.0, 1.0, 0.0);
    glRotatef((GLfloat) turn1, 1.0, 0.0, 0.0);
    glTranslated(-1.0,-1.0,-1.0);
    // create lights
    glPushMatrix();
    lighting();
    glPopMatrix();

    // and draw some objects
    walls();
    glPushMatrix();
    glTranslated(1.0,0.0,1.0);
    table();
    glPopMatrix();
    glPushMatrix();
    glTranslated(1.0,1.0,1.0);
    glRotated(45.0,0.0,1.0,0.0);
    teapot();
    glPopMatrix();
    //glutSolidCube(0.2);

    // remove rotation from stack, flush and swap buffers
    glPopMatrix();
    glFlush();
    glutSwapBuffers();
}

void PrintMVMatrix()
{
    GLfloat mat[16];
    int i,j;
    printf("Modelview Matrix\n");
    glGetFloatv(GL_MODELVIEW_MATRIX,mat);
    for (i=0;i<4;i++){
        for (j=0;j<4;j++)
        {
            printf("%f\t",mat[4*j+i]);  
        }
        printf("\n");
    }
    printf("\n");

}



void
myReshape(int w, int h)
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(65.0, (GLfloat) w / (GLfloat) h, 1.0, 20.0);
    //glOrtho(-5.0,5.0,-5.0,5.0, -5.0, 5.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    //gluLookAt(0.0,0.0,-5.0,
    //          0.0,0.0,5.0,
    //          0.0,1.0,0.0);
    glTranslatef(0.0, 0.0, -4.5);  /* viewing transform  */
    PrintMVMatrix();
}


void
keyboard(unsigned char key, int x, int y)
{

    int i = 0;

    if (i)
        glutPostRedisplay();
}

void
special(int key, int x, int y)
{

    int i = 0;

    switch (key) {
        /* start of view position functions */
        case GLUT_KEY_RIGHT:{
            TurnRight();
            i++;
        }
            break;
        case GLUT_KEY_LEFT:{
            TurnLeft();
            i++;
        }
            break;
        case GLUT_KEY_DOWN:{
            TurnForwards();
            i++;
        }
            break;
        case GLUT_KEY_UP:{
            TurnBackwards();
            i++;
        }
            break;
            /* end of view postions functions */
    }
    if (i)
        glutPostRedisplay();
}

int
main(int argc, char **argv)
{
    /* start of glut windowing and control functions */
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
    glutInitWindowSize(800, 600);
    glutCreateWindow("GLUT playground");
    glutDisplayFunc(display);
    glutReshapeFunc(myReshape);
    glutKeyboardFunc(keyboard);
    glutSpecialFunc(special);
    glutMainLoop();

    return 0;             /* ANSI C requires main to return int. */
}

