/*
   Program to display a GLUsphere with multiple resolutions as an example of LOD modeling.

   Sample for introductory computer graphics course.  Copyright © 2000, Steve Cunningham
*/

#include "glut.h"
#include <stdlib.h>
#include <math.h>

#define initDist 10.0
GLfloat distance = initDist, howFar = initDist;
GLint resolution;
char ch = ' ';

//	set up overall light and body color data
GLfloat light_position[]={ initDist/10.0, initDist, initDist, 1.0 };
GLfloat light_color[]=  { 1.0, 1.0, 1.0, 1.0};
GLfloat body_color[]=   { 1.0, 1.0, 0.0, 1.0 };
GLfloat ambient_color[]={ 0.4, 0.4, 0.0, 1.0 };
GLfloat mat_specular[]= { 1.0, 1.0, 1.0, 1.0 };
GLfloat origin[] = {0.0, 0.0, 0.0};

void myinit( void );
void display( void );
void reshape(int,int);
void keyboard(unsigned char, int, int);

void myinit(void)
{
	glClearColor( 0.0, 0.0, 1.0, 0.0 );
	glShadeModel(GL_SMOOTH);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT,   ambient_color);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE,   body_color);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR,  mat_specular );
	glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 30.0);
	glLightfv(GL_LIGHT0, GL_POSITION, light_position );
	glLightfv(GL_LIGHT0, GL_AMBIENT,  ambient_color );
	glLightfv(GL_LIGHT0, GL_DIFFUSE,  body_color );
	glLightfv(GL_LIGHT0, GL_SPECULAR, light_color );
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glEnable(GL_DEPTH_TEST);
}

void display( void )
{
	GLUquadric *myQuad;
	GLdouble radius = 1.0;
	GLint slices, stacks;

	//	light position is set to maintain constant light geometry as eye point moves
	light_position[0] = distance/10.0;
	light_position[1] = light_position[2] = distance;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0,1.0,1.0,30.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt( distance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0);

	myQuad=gluNewQuadric();
	glRasterPos3fv( origin );
 //	howFar = distance from eye to center of sphere
 	glGetFloatv( GL_CURRENT_RASTER_DISTANCE, &howFar );
	resolution = (GLint) (200.0/howFar);
	slices = stacks = resolution;
	gluSphere( myQuad , radius , slices , stacks  );
    glutSwapBuffers();
 }

void reshape(int w,int h)
{
        glViewport(0,0,(GLsizei)w,(GLsizei)h);
}

void keyboard(unsigned char key, int x, int y)
{
        ch = ' ';
        switch (key)
        {
    	    case 'f' :
    	    	if (distance >= 1.2) distance = distance - 0.2; break;
    	    case 'b' :
				distance = distance + 0.2; break;
        }
        glutPostRedisplay();
}

void main(int argc, char** argv)
{
        glutInit(&argc,argv);
        glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
        glutInitWindowSize(500,500);
        glutInitWindowPosition(70,70);
        glutCreateWindow("GLU Spheres");
        glutDisplayFunc(display);
        glutReshapeFunc(reshape);
        glutKeyboardFunc(keyboard);

        myinit();
        glutMainLoop();
}
