
/*
 *  scene.c
 *  
 *  This program demonstrates the use of the GL lighting model.
 *  Objects are drawn using a grey material characteristic. 
 *  A single light source illuminates the objects.  The program
 *  is used to demonstrate the difference between single and
 *  double buffering.
 *
*/

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

/*  Initialize material property and light source.  */

float spin = 0.0;

void myinit(void)
{
    // Light Properties
    GLfloat light_ambient[] = {0.0, 0.0, 0.0, 1.0};
    GLfloat light_diffuse[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light_specular[] = {1.0, 1.0, 1.0, 1.0};
    GLfloat light_position[] = {1.0, 1.0, 1.0, 0.0};
    GLfloat mat_specular[] = {0.5, 0.5, 0.5, 1.0};     
    GLfloat mat_shininess[]= {30.0};      

    glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
    glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
    glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
    glLightfv(GL_LIGHT0, GL_POSITION, light_position);

    // Material Properties
    glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);  
    glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess); 

    // Enable Various Components
    glEnable(GL_COLOR_MATERIAL);  
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_LIGHTING);

    glColorMaterial(GL_FRONT,GL_DIFFUSE); 
}

/* Draw various things using predefined GLUT objects */
void display(void)
{
    glLoadIdentity();
    gluPerspective( 40.0, 1.0 , 0.1,  120.0);
    glMatrixMode(GL_MODELVIEW);

    spin += 5.0;
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    gluLookAt(0.0, 0.0, 5.0,  0.0, 0.0, 0.0,  0.0, 1.0, 0.);

    glPushMatrix();

      glRotatef(20.0, 1.0,0.0, 0.0);
      glRotatef(spin, 0.0, 1.0, 0.0);

      glPushMatrix();  // Green Torus
        glTranslatef(-0.6, 0.0, 0.0);
        glRotatef(90.0, 1.0, 0.0, 0.0);
        glColor3f(0.0, 0.5, 0.0);
        glutSolidTorus(0.275, 0.85, 10, 15);
      glPopMatrix();

      glPushMatrix();  // Tall Yellow Box
        glTranslatef( 0.0, -0.5, -1.5);
        glRotatef(45.0, 0.0, 1.0, 0.0); 
        glScalef(1.0, 6.0, 1.0);    
        glColor3f(1.0, 1.0, 0.0);
        glutSolidCube(0.5);
      glPopMatrix();

      glPushMatrix();  // Flat Blue Box
        glTranslatef( 0.0, -2.0, -1.5);
        glRotatef(45.0, 0.0, 1.0, 0.0); 
        glScalef(1.0, 0.2, 1.0);    
        glColor3f(0.4, 0.5, 1.0);
        glutSolidCube(2.0);
      glPopMatrix();

      glPushMatrix();  // Red Ball
        glTranslatef(0.75, 0.0, -1.0);
        glColor3f(1.0, 0.0, 0.0);
        glutSolidSphere(0.8, 20, 10);
      glPopMatrix();

    glPopMatrix();
    glFlush();
    glutSwapBuffers();
    glutPostRedisplay();
}

void myReshape(int w, int h) 
{
    glViewport(0, 0, w, h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    
    gluPerspective( 40.0, (GLfloat) h / (GLfloat) w , 0.1,  120.0);
    glMatrixMode(GL_MODELVIEW);

}

int main(int argc, char **argv)
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH );
    glutInitWindowPosition(50, 50);
    glutInitWindowSize(500, 500);
    glutCreateWindow("3D Scene");
    myinit();
    glutReshapeFunc(myReshape);
    glutDisplayFunc(display);
    glutMainLoop();
    return 0;             /* ANSI C requires main to return int. */
}

