/*
 * camera_rotation.c -- camera rotation
 *
 * Author  : Benjamin (prae) GIGON <benjamin#gigon.org>
 * Licence : BSD Licence
 * Notes   : gcc -Wall rotation_camera.cpp -o rotation_camera -lglut -lGLU -lGL
 *
 * Sample camera rotation with OpenGL API
 *
*/

#include <GL/glut.h>

// Only usefull for idle() function (sphere rotation)
#include <unistd.h>
#include <math.h>
#include <stdio.h>


// Camera Rotation variables
int rotation_camera_x = 0;
int rotation_camera_y = 0;
int rotation_camera_z = 0;
int mouse_x = 0;
int mouse_y = 0;

// Only usefull for sphere rotation
int rotation_petite_sphere = 30;


// Camera Settings ( call this function into DisplayFunc() );
void camera() {
    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    glTranslatef(0, 0, -5);
    glRotated (rotation_camera_x, 1, 0, 0);
    glRotated (rotation_camera_y, 0, 1, 0);
    glRotated (rotation_camera_z, 0, 0, 1);
}


// Reshape Settings (window modification: resize, etc... )
void reshape (int w, int h)
{
	glViewport (0, 0, (GLsizei)w, (GLsizei)h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective (45, (GLfloat)w/(GLfloat)h, 1, 1000);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}


// Usefull !  :-)
// Drawing main way
void display() {
	glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	camera();



	// Surface (without light)
	glPushMatrix();
		glTranslatef(-5, -2, -5);
		glBegin(GL_POLYGON);
			glColor3f(0.55, 0.55, 0.55);
			glVertex3f(0, 0, 0);
			glVertex3f(10, 0, 0);
			glVertex3f(10, 0, 10);
			glVertex3f(0, 0, 10);
		glEnd();
	glPopMatrix();
	// Big cube (+light)
	glPushMatrix();
		glEnable(GL_LIGHT0);
			glColor3f(0.75, 0.75, 0.75);
			glutSolidCube(1);
		glDisable(GL_LIGHT0);
	glPopMatrix();
	// Small cube
	glPushMatrix();
		glTranslatef(2, -1, 2);
		glEnable(GL_LIGHT0);
			glColor3f(1, 1, 1);
			glutSolidCube(0.2);
		glDisable(GL_LIGHT0);
	glPopMatrix();
	// Small sphere
	glPushMatrix();
		glRotatef(rotation_petite_sphere, 0, 1, 0);
		glRotatef(-rotation_petite_sphere, 1, 0, 0);
		glRotatef(-rotation_petite_sphere, 0, 0, 1);
		glTranslatef(-1, 0, -1);
		glEnable(GL_LIGHT0);
			glColor3f(1, 1, 1);
			glutSolidSphere(0.2, 30, 30);
		glDisable(GL_LIGHT0);
	glPopMatrix();



	glutSwapBuffers();
}



// Mouse Manager for camera
// Note: be careful with values which are incremented without limit
void mouse(int button, int state, int x, int y) {
	mouse_x = x;
	mouse_y = y;
}
void motion(int x, int y) {
	rotation_camera_x += (y - mouse_y);
	rotation_camera_y += (x - mouse_x);
	mouse_x = x;
	mouse_y = y;
	glutPostRedisplay ();
}


// Only usefull for sphere rotation
void idle() {
	usleep(1);
	rotation_petite_sphere = (rotation_petite_sphere+1)%360;
	glutPostRedisplay();
}



int main(int argc, char **argv)
{
	glutInit(&argc,argv);
    glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
    glutInitWindowSize(1024, 768);
    glutCreateWindow(argv[0]);

	glClearColor(0, 0, 0, 0);
	glEnable (GL_DEPTH_TEST);	// Depth
	glEnable(GL_LIGHTING);		// Light
	glShadeModel (GL_SMOOTH); 	// Smoothing

	
	glutReshapeFunc (reshape);
	glutDisplayFunc (display);
	glutMotionFunc (motion);
	glutMouseFunc (mouse);

	glutIdleFunc(idle); // Only usefull for sphere rotation
	
	glutMainLoop ();
	return(0);
}
