/* Auteur: Nicolas JANEY                */
/* nicolas.janey@univ-fcomte.fr         */
/* Fevrier 2016                         */
/* Modelisation en fil de fer d'un cube */
/* Animation par rotation               */

#include <stdio.h>
#include <math.h>

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

#include "MathematiquesIG/Rotation3D.h"
#include "MathematiquesIG/Position3D.h"

static float r1 = 0.0F;
static float r2 = 0.0F;
static int scn = 0;

void init(void) {
  glDepthFunc(GL_LESS);
  glEnable(GL_DEPTH_TEST);
  glEnable(GL_NORMALIZE);
}

static float vertices[8][3] = { {  1.0F, 1.0F, 1.0F },
                                { -1.0F, 1.0F, 1.0F },
                                { -1.0F,-1.0F, 1.0F },
                                {  1.0F,-1.0F, 1.0F },
                                {  1.0F, 1.0F,-1.0F },
                                { -1.0F, 1.0F,-1.0F },
                                { -1.0F,-1.0F,-1.0F },
                                {  1.0F,-1.0F,-1.0F } };
static int edges[12][2] = { {  0, 1 },
                            {  1, 2 },
                            {  2, 3 },
                            {  3, 0 },
                            {  0, 4 },
                            {  1, 5 },
                            {  2, 6 },
                            {  3, 7 },
                            {  5, 4 },
                            {  6, 5 },
                            {  7, 6 },
                            {  4, 7 } };

void scene1(void) {
  glPushMatrix();
  glRotatef(r1,1.0F,1.0F,1.0F);
  glRotatef(r2,1.0F,0.0F,0.0F);
  glBegin(GL_LINES);
  for ( int i = 0 ; i < 12 ; i++ ) {
    glVertex3fv(vertices[edges[i][0]]);
    glVertex3fv(vertices[edges[i][1]]); }    
  glEnd();
  glPopMatrix();
}

void scene2(void) {
  TransformationGeometrique3D *tg = new TransformationGeometrique3D();
  Rotation3D *rt1 = new Rotation3D(r1,1.0,1.0,1.0);
  Rotation3D *rt2 = new Rotation3D(r2,1.0,0.0,0.0);
  tg->compose(rt2);
  tg->compose(rt1);
  glPushMatrix();
  glBegin(GL_LINES);
  for ( int i = 0 ; i < 12 ; i++ ) {
    Position3D *v0 = new Position3D(vertices[edges[i][0]][0],
                                    vertices[edges[i][0]][1],
                                    vertices[edges[i][0]][2]);
    Position3D *v1 = new Position3D(vertices[edges[i][1]][0],
                                    vertices[edges[i][1]][1],
                                    vertices[edges[i][1]][2]);
    tg->transforme(v0);
    tg->transforme(v1);
    glVertex3dv((double *) v0);
    glVertex3dv((double *) v1);
    delete(v0);
    delete(v1); }    
  glEnd();
  glPopMatrix();
  delete(tg);
  delete(rt1);
  delete(rt2);
}

void display(void) {
  glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  glPushMatrix();
  glColor4f(1.0F,1.0F,1.0F,1.0F);
  switch ( scn ) {
    case 0 : scene1();
             break;
    case 1 : scene2();
             break; }
  glPopMatrix();
  glFlush();
  glutSwapBuffers();
}

void key(unsigned char key,int x,int y) {
  switch ( key ) {
    case 0x0D : scn = (scn+1)%2;
                break;
    case 0x1B : exit(0);
                break; }
}

static void reshape(int w,int h) {
  glViewport(0,0,w,h); 
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  if ( w > h )
    glOrtho(w*-2.0/h,w*2.0/h,-2.0,2.0,-2.0,2.0);
    else
    glOrtho(-2.0,2.0,h*-2.0/w,h*2.0/w,-2.0,2.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();
}

static void idle(void) {
  r1 += 0.03F;
  r2 += 0.02F;
  glutPostRedisplay();
}

int main(int argc,char **argv) {
  glutInit(&argc,argv);
  glutInitDisplayMode(GLUT_RGBA|GLUT_DEPTH|GLUT_DOUBLE);
  glutInitWindowSize(400,400); 
  glutInitWindowPosition(50,50); 
  glutCreateWindow("Un cube animé");
  init();
  glutIdleFunc(idle);
  glutReshapeFunc(reshape);
  glutKeyboardFunc(key);
  glutDisplayFunc(display);
  glutMainLoop();
  return(0);
}
