#include "Scene.h"
#include <GL/gl.h>
#include "opengl.h"
#include <math.h>
#define _USE_MATHS_DEFINES
#include <GL/glut.h>
#include <GL/glu.h>


void draw_axes()
{
    glLineWidth(5);
    glBegin( GL_LINES );

    glColor3f( 1.f, 0.f, 0.f);
    glVertex3f( 0.f, 0.f, 0.f);
    glVertex3f( 1.f, 0.f, 0.f);

    glColor3f( 0.f, 1.f, 0.f);
    glVertex3f( 0.f, 0.f, 0.f);
    glVertex3f( 0.f, 1.f, 0.f);

    glColor3f( 0.f, 0.f, 1.f);
    glVertex3f( 0.f, 0.f, 0.f);
    glVertex3f( 0.f, 0.f, 1.f);

    glEnd();
}


void draw_grid()
{
    int i;
    glLineWidth(1);
    glColor3f( 1.f, 1.f, 1.f);

    glPushMatrix();
    glTranslatef( -5, 0, -5);

    glBegin( GL_LINES );

    for (i=0;i<=10;++i)
    {
        glVertex3f( i, 0, 0);
        glVertex3f( i, 0, 10);
    }

    for (i=0;i<=10;++i)
    {
        glVertex3f( 0, 0, i);
        glVertex3f( 10, 0, i);
    }

    glEnd();
    glPopMatrix();
}



void draw_cube()
{
    static float pt[8][3] = { {0,0,0}, {1,0,0}, {1,0,1}, {0,0,1}, {0,1,0}, {1,1,0}, {1,1,1}, {0,1,1} };
    static int f[6][4] = { {0,1,2,3}, {5,4,7,6}, {1,5,6,2}, {0,3,7,4}, {3,2,6,7}, {0,4,5,1} };
    static float n[6][3] = { {0,-1,0}, {0,1,0}, {1,0,0}, {-1,0,0}, {0,0,1}, {0,0,-1} };
    static float uv[6][4][2] = { { {0,0}, {1,0}, {1,1}, {0,1} },
                                 { {0,0}, {1,0}, {1,1}, {0,1} },
                                 { {0,0}, {1,0}, {1,1}, {0,1} },
                                 { {0,0}, {1,0}, {1,1}, {0,1} },
                                 { {0,0}, {1,0}, {1,1}, {0,1} },
                                 { {0,0}, {1,0}, {1,1}, {0,1} } };
    int i,j;

    glTranslatef(-0.5,-0.5,-0.5);
    glBegin(GL_QUADS);
    for (i=0;i<6;i++)
    {
        glNormal3f( n[ i ][0], n[ i ][1], n[ i ][2] );
        for (j=0;j<4;j++)
        {
            glTexCoord2f( uv[i][j][0], uv[i][j][1] );
            glVertex3f( pt[ f[i][j] ][0], pt[ f[i][j] ][1], pt[ f[i][j] ][2] );
        }
    }
    glEnd();
}



void draw_sphere()
{
    float divBeta=30;
    float divAlpha=divBeta/2;
    float beta,alpha,alpha2;
    glBegin(GL_TRIANGLE_STRIP);
    for (int i=0;i<divAlpha;i++)
    {
        alpha=-0.5*M_PI+float(i)*M_PI/divAlpha;
        alpha2=-0.5*M_PI+float(i+1)*M_PI/divAlpha;
        for(int j=0;j<=divBeta;j++)
        {
            beta=float(j)*2.*M_PI/divBeta;
            glTexCoord2f(float(j)/divBeta,float(i)/divAlpha);
            glNormal3f(cos(alpha)*cos(beta),sin(alpha),cos(alpha)*sin(beta));
            glVertex3f(cos(alpha)*cos(beta),sin(alpha),cos(alpha)*sin(beta));

            glTexCoord2f(float(j)/divBeta,float(i+1)/divAlpha);
            glNormal3f(cos(alpha2)*cos(beta),sin(alpha2),cos(alpha2)*sin(beta));
            glVertex3f(cos(alpha2)*cos(beta),sin(alpha2),cos(alpha2)*sin(beta));

        }
    }
    glEnd();
}






void draw_cylinder()
{
  int div=25;
  float beta;
  float step=2.0*M_PI/div;
  glBegin(GL_TRIANGLE_STRIP);
  for(int i=0;i<=div;i++)
  {
      beta=i*step;
      glTexCoord2f(float(i)/div,0);
      glNormal3f(cos(beta),0,sin(beta));
      glVertex3f(cos(beta),0,sin(beta));
      glTexCoord2f(float(i)/div,1);
      glNormal3f(cos(beta),1,sin(beta));
      glVertex3f(cos(beta),1,sin(beta));
  }
  glEnd();

  glBegin(GL_TRIANGLE_FAN);

    glVertex3f(0,1,0);
    for(int j=0;j<=div;j++)
    {
        beta=j*2*M_PI/div;
        glNormal3f(cos(beta),1,sin(beta));
        glVertex3f(cos(beta),1,sin(beta));
    }
    glEnd();

    glBegin(GL_TRIANGLE_FAN);
    glVertex3f(0,0,0);
    for(int k=0;k<=div;k++){
        beta=k*(2*M_PI/div);
        glNormal3f(cos(beta),0,sin(beta));
        glVertex3f(cos(beta),0,sin(beta));

    }
    glEnd();

}






void draw_cone()
{

  int div=25;
  float beta;
  float step=2.0*M_PI/div;
  glBegin(GL_TRIANGLE_STRIP);
  for(int i=0;i<=div;i++)
  {
      beta=i*step;
      glTexCoord2f(float(i)/div,0);
      glNormal3f(cos(beta),1,sin(beta));
      glVertex3f(cos(beta),0,sin(beta));
      glTexCoord2f(0,1);
      glNormal3f(0,1,0);
      glVertex3f(0,1,0);
  }
  glEnd();

  glBegin(GL_TRIANGLE_FAN);
    glVertex3f(0,0,0);
    for(int i=0;i<=div;i++)
    {
        beta=i*(2*M_PI/div);
        glVertex3f(cos(beta),0,sin(beta));
    }
    glEnd();

}
 void draw_helico()
{
    //cockpit
glPushMatrix();
    glScalef( 0.55, 0.5, 0.5);
    glColor3f( 1, 1, 1);
    glTranslatef(-0.5,-0.5,-3);
    draw_sphere();
glPopMatrix();

    //corps de l'hélico
glPushMatrix();
    glScalef(0.5, 0.5, 1);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(-0.5,-1.5,0.5);
    draw_cylinder();
glPopMatrix();

    //queue de l'hélico
glPushMatrix();
    glScalef( 0.5,0.5,4.2);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(-0.5,-0.15,0.5);
    draw_cone();
glPopMatrix();
    //porte hélice principal
glPushMatrix();
    glScalef( 0.1 ,0.4,0.1 );
    glColor3f( 1, 1, 1);
    glTranslatef(-2.5,0.8,-8);
    draw_cube();
glPopMatrix();

//hélice principale
glPushMatrix();
    glScalef(2.5,0.05,0.2);
    glColor3f( 1, 1, 1);
    glTranslatef(0.42,8.2,-4);
    draw_cube();
glPopMatrix();
glPushMatrix();
    glScalef(2.5,0.05,0.2);
    glColor3f( 1, 1, 1);
    glTranslatef(-0.62,8.2,-4);
    draw_cube();
glPopMatrix();
glPushMatrix();
    glScalef(0.2,0.05,2.5);
    glColor3f( 1, 1, 1);
    glTranslatef(-1.3,8.2,0.2);
    draw_cube();
glPopMatrix();
glPushMatrix();
    glScalef(0.2,0.05,2.5);
    glColor3f( 1, 1, 1);
    glTranslatef(-1.3,8.2,-0.8);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef( 0.05, 0.5, 0.2);
    glColor3f( 1, 1, 1);
    glTranslatef(-5,-0.38,15);
    draw_cone();
glPopMatrix();

//hélice secondaire
glPushMatrix();
    glScalef( 0.25 ,0.1,0.1 );
    glColor3f( 1, 1, 1);
    glTranslatef(-1.5,0.8,30);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef(0.05,0.45,0.09);
    glColor3f( 1, 1, 1);
    glTranslatef(-7.5,0.8,33.34);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef(0.05,0.45,0.09);
    glColor3f( 1, 1, 1);
    glTranslatef(-7.5,-0.43,33.34);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef(0.05,0.09,0.45);
    glColor3f( 1, 1, 1);
    glTranslatef(-7.5,0.75,6.07);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef(0.05,0.09,0.45);
    glColor3f( 1, 1, 1);
    glTranslatef(-7.5,0.75,7.2);
    draw_cube();
glPopMatrix();

//rampes
glPushMatrix();
    glScalef( 0.03, 0.03, 2);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(15,-1,42);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(0.45,-1.25,-0.5);
    glRotatef(30,0,0,1);
    glScalef( 0.03,0.8,0.03);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(0.45,-1.25,-1.5);
    glRotatef(30,0,0,1);
    glScalef( 0.03,0.8,0.03);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(-0.95,-1.25,-1.5);
    glRotatef(-30,0,0,1);
    glScalef( 0.03,0.8,0.03);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(-0.95,-1.25,-0.5);
    glRotatef(-30,0,0,1);
    glScalef( 0.03,0.8,0.03);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(-0.96,-1.258,-1.98);
    glRotatef(-75,1,0,0);
    glScalef( 0.03,0.2,0.03);
    draw_cylinder();
glPopMatrix();

glPushMatrix();

    glColor3f( 1, 1, 1);
    glTranslatef(0.45,-1.258,-1.98);
    glRotatef(-75,1,0,0);
    glScalef( 0.03,0.2,0.03);
    draw_cylinder();
glPopMatrix();


glPushMatrix();
    glScalef( 0.03, 0.03, 2);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(-32,-1,42);
    draw_cylinder();
glPopMatrix();

}

void draw_avion()
{
//Aîles de l'avion
glPushMatrix();
    glScalef( 7 , 0.2 , 0.6 );
    glColor3f( 1, 1, 1);
    glTranslatef(0,-0.4, 0);
    draw_cube();
glPopMatrix();

glPushMatrix();
    glScalef( 4 , 0.2 , 0.6 );
    glColor3f( 1, 1, 1);
    glTranslatef(0,-0.4,2);
    draw_cube();
glPopMatrix();

//Aîleron de l'avion
glPushMatrix();
    glScalef( 0.2, 0.8, 0.8);
    glColor3f( 1, 1, 1);
    glTranslatef(0,0.1,2.5);
    draw_cone();
glPopMatrix();

//Corps de l'avion
glPushMatrix();
    glScalef( 0.5, 0.5, 3);
    glColor3f( 1, 1, 1);
    draw_sphere();
glPopMatrix();

//Réacteurs
glPushMatrix();
    glScalef( 0.3, 0.2, 0.5);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(5,2,1.3);
    draw_cylinder();
glPopMatrix();

glPushMatrix();
    glScalef(0.3, 0.2, 0.5);
    glColor3f( 1, 1, 1);
    glRotatef(90, 1,0,0);
    glTranslatef(-5,2,1.3);
    draw_cylinder();
glPopMatrix();
}

void normal(const Image& im, int i, int j){
	Vec3f Ouest,Est,Nord,Sud,OE,NS,N;
	vecInit(Ouest,i-1,getPix(im, i-1,j),j);
	vecInit(Est,i+1,getPix(im, i+1,j),j);
	vecInit(Nord,i,getPix(im, i,j-1),j-1);
	vecInit(Sud,i,getPix(im, i,j+1),j+1);
	vecSub(OE,Est,Ouest);
	vecSub(NS, Nord, Sud);
	vecCross(N,OE,NS);
	glNormal3f(N.x, N.y, N.z);
}



void terrainNormal(const Image &im, const int i, const int j)
{
    Vec3f a, b, c, d, x, y, n;
    vecInit(a, float(i-1), getPixConst(im, float(i-1), j), j);
    vecInit(b, float(i+1), getPixConst(im, float(i+1), j), j);
    vecInit(c, float(i), getPixConst(im, i, float(j+1)), j+1);
    vecInit(d, float(i), getPixConst(im, i, float(j-1)), j-1);
    vecSub(x, b, a);
    vecSub(y, d, c);
    vecCross(n, x, y);
    glNormal3f(n.x, n.y, n.z);
}

void draw_terrain(const Image &im)
{
    for(int i=1; i<imGetDimX(im)-2; i++)
    {
        glBegin(GL_TRIANGLE_STRIP);
        for(int j=1; j<imGetDimY(im)-2; j++)
        {
            terrainNormal(im, i, j);
            glTexCoord2f(float(i)/imGetDimX(im),float(j)/imGetDimY(im));
            glVertex3f(i, getPixConst(im, i, j), j);
            terrainNormal(im, i+1, j);
            glTexCoord2f(float((i+1))/imGetDimX(im),float(j)/imGetDimX(im));
            glVertex3f(i+1, getPixConst(im, i+1, j), j);
        }
        glEnd();
    }

}




void sceneInit(Scene& sc)
{
    animInit( sc.anim, "data/anim1.ani" );
    sc.tex_papillon = LoadGLTexture("data/papillon.ppm", true, 230, 230, 230, LOADGLTEX_GREATER);
    sc.tex_mario = LoadGLTexture("data/Caissemario.ppm", true);
    sc.tex_terre = LoadGLTexture("data/terre.ppm", true);
    sc.tex_mars = LoadGLTexture("data/mars.ppm", true);
    sc.tex_lune = LoadGLTexture("data/lune.ppm", true);
    sc.tex_jupiter = LoadGLTexture("data/jupiter.ppm", true);
    sc.tex_soleil = LoadGLTexture("data/soleil.ppm", true);
    sc.tex_tonneau = LoadGLTexture("data/tonneau.ppm", true);
    sc.tex_metal = LoadGLTexture("data/metal.ppm", true);
    sc.tex_arlequin = LoadGLTexture("data/arlequin.ppm", true);

   // imInitPPM(sc.terrain, "./data/terrain/map.ppm");
    imInitPPM(sc.terrain,"data/terrain/terrain_texture_bruit.ppm");
    sc.tex_terrain = LoadGLTexture("./data/terrain/moutain.ppm", true);
    //sc.tex_terrain  =   LoadGLTexture("data/terrain/terrain.ppm",true);

}


void sceneDraw(const Scene& sc)
{
    // A MODIFIER : CETTE FONCTION AFFICHE LA SCENE PRINCIPALE


    // Mon 1er cube
    glColor3f( 1, 1, 1);
    glBindTexture( GL_TEXTURE_2D, sc.tex_mario);
    glPushMatrix();	// sauvegarde la transformation courante
    glTranslatef( -2, 2, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_mario);
    draw_cube();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();		// récupère la transformation sauvegardée avant


  /*  glPushMatrix();
    glColor3f( 1,1,1);
    glEnable(GL_TEXTURE_2D);
    glScalef( 100,100,100);
    glBegin( GL_QUADS );
    glNormal3f( 0,1,0);
    glTexCoord2f( 0,0);
    glVertex3f( -1, 0, -1);
    glTexCoord2f( 1,0);
    glVertex3f( 1, 0, -1);
    glTexCoord2f( 1,1);
    glVertex3f( 1, 0, 1);
    glTexCoord2f( 0,1);
    glVertex3f( -1, 0, 1);
    glEnd();
    glPopMatrix(); */

    // tracage du terrain

    glPushMatrix();
    glEnable(GL_TEXTURE_2D);
    glBindTexture(GL_TEXTURE_2D,sc.tex_terrain);

    glScalef(0.5, 0.020, 0.5);
	glTranslatef(-100, -200, -100);
    draw_terrain(sc.terrain);
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();


    // **************** FORME DE BASE ***********************/
    glPushMatrix();
    glTranslatef( 0, 2, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_arlequin);
    draw_cone();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();


    glPushMatrix();
    glTranslatef( 3, 5, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_tonneau);
    glScalef(0.5,1.5,0.5);
    draw_cylinder();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();


    /*glBindTexture( GL_TEXTURE_2D, sc.tex_terre);
    glPushMatrix();
    glTranslatef( 3, 0, 0);
    glColor3f( 1, 0, 1);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_terre);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix(); */

    //terre
    glPushMatrix();
    glTranslatef( 6, 25, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_terre);
    glScalef(2,2,2);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();

    //lune
    glPushMatrix();
    glTranslatef(10, 25, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_lune);
    glScalef(0.5,0.5,0.5);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();

    //mars
    glPushMatrix();
    glTranslatef(14, 25, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_mars);
    glScalef(2.5,2.5,2.5);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();

    //jupiter
    glPushMatrix();
    glTranslatef(21, 25, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_jupiter);
    glScalef(4,4,4);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();

    //soleil
    glPushMatrix();
    glTranslatef(34, 25, 0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_soleil);
    glScalef(8,8,8);
    draw_sphere();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();



    glPushMatrix();
    glTranslatef(4,18,0);
    glColor3f(1,0,0);
    glScalef(2,2,2);
    draw_avion();
    glPopMatrix();

    glPushMatrix();
    glTranslatef(-4,10,0);
    glEnable(GL_TEXTURE_2D);
    glBindTexture( GL_TEXTURE_2D, sc.tex_metal);
    draw_helico();
    glDisable(GL_TEXTURE_2D);
    glPopMatrix();
}
