
/*  This is the starter code for our textureing tutorial.		*/
/*																*/
#include <iostream>
#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <windows.h>
#include "geometry.h"


using namespace std;

#define PI 3.14159


// function prototypes

void display(void);
void reshape(int width, int height);
void motion(int x, int y);
void init(void);
void keyboard(unsigned char key, int x, int y);


 // viewpoint
double theta=0, phi=0, distanceToViewpoint=200;
// window
int width=400;
int height=400;




	

int 
main(int argc, char **argv)
{

  // set up window
  glutInitWindowSize(width,height);
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutCreateWindow("Blending demo");

  // register callback functions
  glutDisplayFunc(display);
  glutReshapeFunc(reshape); 
  glutKeyboardFunc(keyboard);
  glutMotionFunc(motion);
  
  // initalize opengl parameter
  init();


  // loop until something happens
  glutMainLoop();
  return 0;           
}

void init()
{
  // initialize viewing system
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0, 1.0, 10.0, 1000.0);
  glMatrixMode(GL_MODELVIEW);
 

  // initialize background color to black
  glClearColor(0.0,0.0,0.0,0.0);

  // enable depth buffering
  glEnable(GL_DEPTH_TEST);

  // enable lighting
  glEnable(GL_LIGHT0);
  glEnable(GL_LIGHTING);

  	// set light position in world coordinates
	float position[]={5,10,0,1};
	glLightfv(GL_LIGHT0,GL_POSITION, position);


 
}


void reshape(int newWidth, int newHeight)
{
  width=newWidth;
  height=newHeight;
  glViewport(0,0,width,height);
}

void display()
{

	// check for openGL errors
	GLenum errCode;
	if ((errCode = glGetError()) != GL_NO_ERROR)
		cout << gluErrorString(errCode) << endl;

	// set up modelview matrix
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	// compute eye position
	Tuple eye(0,0,0);
	eye[0] = (float) -distanceToViewpoint * cos(theta) * sin(phi);
	eye[1] = (float) distanceToViewpoint * sin(theta);
	eye[2] = (float) distanceToViewpoint * cos(theta) * cos(phi);

	// compute up vector
	// the is the vector orthogonal to eye that lies in the same
	// plane as eye and (0,1,0) and has a positive dot product with
	// (0,1,0)
	Tuple up = Tuple(0,1,0)-eye/eye.length();
	up.normalize();
	
	gluLookAt(eye[0],eye[1],eye[2], 0,0,0,up[0], up[1], up[2]);


	// clear buffers
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


	// draw cubes translated in z
	glPushMatrix();
	glTranslatef(0,0,-20);

	// draw cube 1
	float red[]={1,0,0,1};
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,red);
	glutSolidCube(20);



	// draw cube 2

	float blue[]={0,0,1,.5};
	glMaterialfv(GL_FRONT_AND_BACK,GL_DIFFUSE,blue);
	glutSolidCube(40);

	glPopMatrix();


	
	glutSwapBuffers();


}

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

	switch (key) 
	{
	case 'Z': 
		distanceToViewpoint+=10;
		break;

	case 'z':
		if (distanceToViewpoint>10)
			distanceToViewpoint-=10;
		break;

	case 'h':
	case 'H':
	case '?':
		cout << "Use 'z'/'Z' to zoom in/out" << endl;
		break;

	default:
		break;
	}

	glutPostRedisplay();


}


void motion(int x, int y)
{

	static int currX=-1;
	static int currY=-1;

	if (currX>0  && abs(x-currX) < width/6 && abs(y-currY) < height/6) {
		phi += (double) (x-currX)/ (double) width * 3.14159;
		theta += (double) (y-currY)/ (double) height * 3.14159;
	// limit theta to -4pi/9 and 4pi/9
	if (theta < -4*3.14159/9.0)
		theta = -4*3.14159/9.0;
	if (theta > 4*3.14159/9.0)
		theta = 4*3.14159/9.0;
	}
	currX = x;
	currY = y;
	glutPostRedisplay();
}

