#include<GL/gl.h>
#include<GL/glu.h>
#include<GL/glut.h>
#include<stdlib.h>
#include<iostream.h>

void axis(double length)
{
  glPushMatrix();
  glBegin(GL_LINES);
  glVertex3d(0,0,0);
  glVertex3d(0,0,length);
  glEnd();
  glTranslated(0,0,length-0.2);
  glutSolidCone(0.04,0.2,12,9);
  glPopMatrix();
}

void displaySolid(void)
{
  // properties of surface material:
  GLfloat mat_ambient[] = { 0.7f, 0.7f, 0.7f, 1.0f };
  GLfloat mat_diffuse[] = { 0.6f, 0.6f, 0.6f, 1.0f };
  GLfloat mat_specular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  GLfloat mat_shininess[] = { 50.0f };
  glMaterialfv(GL_FRONT, GL_AMBIENT, mat_ambient);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialfv(GL_FRONT, GL_SHININESS, mat_shininess);

  // properties of a light source, entitled GL_LIGHT0:
  GLfloat lightIntensity[] = { 0.7f, 0.7f, 0.7f, 1.0f };
  GLfloat lightPosition[] = { 2.0f, 6.0f, 3.0f, 0.0f };  
  glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);  // Note: 0, not O
  glLightfv(GL_LIGHT0, GL_DIFFUSE, lightIntensity);  
  // (NB: the actual enable for this light source is down in main)

  // the camera:
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  double winHt = 1.0; 
  glOrtho(-winHt*64/48.0, winHt*64/48.0, -winHt, winHt, 0.1, 100);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
  gluLookAt(2.0, 2.0, 2.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);

  // the axes:
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );  
  glColor3d(0,0,0);  
  axis(0.5);
  glPushMatrix();
  glRotated(90, 0, 1.0, 0);
  axis(0.5);
  glRotated(-90, 1.0, 0.0, 0); 
  axis(0.5);
  glPopMatrix();

  // the big cube:
  glPushMatrix();
  glTranslated(0.5, 0.5, 0.5);
  glutSolidCube(1.0);
  glPopMatrix();

  // the sphere:
  glPushMatrix();
  glTranslated(1.0, 1.0, 0.0);
  glutSolidSphere(0.25, 10, 8);
  glPopMatrix();

  // the cone:
  glPushMatrix();
  glTranslated(1.0, 0.0, 1.0);
  glutSolidCone(0.2, 0.5, 10, 8);
  glPopMatrix();

  // the teapot:
  glPushMatrix();
  glTranslated(1.0, 1.0, 1.0);
  glutSolidTeapot(0.2);
  glPopMatrix();

  // the torus:
  glPushMatrix();
  glTranslated(0.0, 1.0, 0.0);
  glRotated(90.0, 1, 0, 0);
  glutSolidTorus(0.1, 0.3, 10, 10);
  glPopMatrix();

  // the dodecahedron:
  glPushMatrix();
  glTranslated(1.0, 0.0, 0.0);
  glScaled(0.15, 0.15, 0.15);
  glutSolidDodecahedron();
  glPopMatrix();

  // the small cube:
  glPushMatrix();
  glTranslated(0.0, 1.0, 1.0);
  glutSolidCube(0.25);
  glPopMatrix();

  // the cylinder:
  glPushMatrix();
  glTranslated(0.0, 0.0, 1.0);
  GLUquadricObj * qobj;
  qobj = gluNewQuadric();
  gluQuadricDrawStyle(qobj,GLU_FILL); 
  gluCylinder(qobj, 0.2, 0.2, 0.4, 8, 8);
  glPopMatrix();

  glFlush();
}

void main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  glutInitWindowSize(640, 480);
  glutInitWindowPosition(100, 100);
  glutCreateWindow("3D scene with shading, HSR, light sources");
  glutDisplayFunc(displaySolid);

  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glShadeModel(GL_FLAT);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
  
  glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
  glViewport(0, 0, 640, 480);
  glutMainLoop();
}



