/** Initialisation de la fenêtre OpenGl, de la camera et des textures. */
  public final void initGL() {
    // Création de la fenetre
    try {
      if (Setting.getFullScreen()) {
        Display.setDisplayModeAndFullscreen(
            new DisplayMode(Setting.get3DWidth(), Setting.get3DHeight()));
      } else {
        Display.setDisplayMode(new DisplayMode(Setting.get3DWidth(), Setting.get3DHeight()));
      }

      Display.setTitle("Visualisation 3D");
      Display.sync(Setting.getFps());
      Display.create();

    } catch (LWJGLException e) {
      e.printStackTrace();
      System.exit(0);
    }

    float fAspect = (float) Setting.getWWidth() / (float) Setting.getWHeight();
    GL11.glViewport(0, 0, Setting.getWWidth(), Setting.getWHeight());
    GL11.glMatrixMode(GL11.GL_PROJECTION);
    GL11.glLoadIdentity();
    GLU.gluPerspective(45.0f, fAspect, 1.0f, 1000.0f);
    GL11.glMatrixMode(GL11.GL_MODELVIEW);
    GL11.glLoadIdentity();
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glDepthFunc(GL11.GL_LEQUAL);
    GL11.glShadeModel(GL11.GL_SMOOTH);
    GL11.glEnable(GL11.GL_CULL_FACE);

    // Initialisation de la Camera
    camera = new Camera("3D");
    camera.init();
    camera.yaw(140.0f);
    camera.pitch(20.0f);

    // Récupération des textures
    textures = new Textures();
    textures.init();
    textures.loadTexture();

    wind = new Wind();

    matrice.loadImg();
  }
  /** Boucle de rendu 3D. */
  @Override
  public final void run() {
    // Initialisation
    initGL();
    // Boucle du thread de rendu 3D

    matrice.addInterPoint();
    while (Setting.getView3DStart()) {
      // Si la fenêtre n'est pas fermée
      if (!Display.isCloseRequested()) {

        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
        GL11.glClearColor(0.6f, 0.9f, 1.0f, 1.0f);
        GL11.glLoadIdentity();

        Sys.initialize();
        time = Sys.getTime();

        dt = (time - lastTime) / 1000.0f;
        setLastInput(getLastInput() + (time - lastTime) / 1000.0f);
        lastTime = time;

        // Positionne la camera avant d'afficher le rendu
        camera.lookThrough();

        // Si le rendu n'est pas en pause
        if (!Setting.getView3DPause()) {
          int colonne = 0, ligne = 0;

          // Affichage de la matrice
          for (ligne = 0; ligne < Setting.getSide(); ligne++) {
            for (colonne = 0; colonne < Setting.getSide(); colonne++) {

              GL11.glColor3f(1.0f, 1.0f, 1.0f);
              // Si le mode Wireframe est activé
              if (Setting.getWireframe()) {
                GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
              } else {
                GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
              }

              if (Setting.getGradient()) {
                GL11.glBegin(GL11.GL_TRIANGLE_FAN);
                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getAltitude() / Setting.getAltitudeMax(),
                    ((Setting.getAltitudeMax() / this.echelle)
                            - (matrice.getSquare(ligne, colonne).getAltitude() / this.echelle))
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    matrice.getSquare(ligne, colonne).getAltitude() / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());

                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1]
                        / Setting.getAltitudeMax(),
                    (Setting.getAltitudeMax()
                            - matrice.getSquare(ligne, colonne).getCooHautGauche()[1])
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);

                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[1]
                        / Setting.getAltitudeMax(),
                    (Setting.getAltitudeMax()
                            - matrice.getSquare(ligne, colonne).getCooHautDroite()[1])
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);

                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[1]
                        / Setting.getAltitudeMax(),
                    (Setting.getAltitudeMax()
                            - matrice.getSquare(ligne, colonne).getCooBasDroite()[1])
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);

                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[1]
                        / Setting.getAltitudeMax(),
                    (Setting.getAltitudeMax()
                            - matrice.getSquare(ligne, colonne).getCooBasGauche()[1])
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);

                GL11.glColor3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1]
                        / Setting.getAltitudeMax(),
                    (Setting.getAltitudeMax()
                            - matrice.getSquare(ligne, colonne).getCooHautGauche()[1])
                        / Setting.getAltitudeMax(),
                    0);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);
                GL11.glEnd();
              }

              if (Setting.getTexture()) {
                GL11.glEnable(GL11.GL_TEXTURE_2D);
                GL11.glBindTexture(GL11.GL_TEXTURE_2D, matrice.getTextImgFile().getTextureID());
                GL11.glTexParameteri(
                    GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
                GL11.glTexParameteri(
                    GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
                GL11.glEnable(GL11.GL_ALPHA);
                GL11.glEnable(GL11.GL_BLEND);
                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
                GL11.glBegin(GL11.GL_TRIANGLES);

                float middlePointTextRow =
                    (1.0f / (float) (Setting.getSide() + 1)) * ligne
                        + ((1.0f / (float) (Setting.getSide() + 1)) / 2.0f);
                float middlePointTextCol =
                    (1.0f / (float) (Setting.getSide() + 1)) * (Setting.getSide() + 1 - colonne)
                        - ((1.0f / (float) (Setting.getSide() + 1)) / 2.0f);
                float percent = (1.0f / (float) (Setting.getSide() + 1));

                // Milieu
                GL11.glTexCoord2f(middlePointTextRow, middlePointTextCol);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    matrice.getSquare(ligne, colonne).getAltitude() / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());
                // bas gauche
                GL11.glTexCoord2f(percent * ligne, percent * (Setting.getSide() + 1 - colonne));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);
                // bas droite
                GL11.glTexCoord2f(
                    percent * ligne, percent * (Setting.getSide() + 1 - (colonne + 1)));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);

                // milieu
                GL11.glTexCoord2f(middlePointTextRow, middlePointTextCol);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    matrice.getSquare(ligne, colonne).getAltitude() / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());
                // bas droite
                GL11.glTexCoord2f(
                    percent * ligne, percent * (Setting.getSide() + 1 - (colonne + 1)));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);
                // haut droite
                GL11.glTexCoord2f(
                    percent * (ligne + 1), percent * (Setting.getSide() + 1 - (colonne + 1)));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);

                // milieu
                GL11.glTexCoord2f(middlePointTextRow, middlePointTextCol);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    matrice.getSquare(ligne, colonne).getAltitude() / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());
                // haut droite
                GL11.glTexCoord2f(
                    percent * (ligne + 1), percent * (Setting.getSide() + 1 - (colonne + 1)));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);
                // haut gauche
                GL11.glTexCoord2f(
                    percent * (ligne + 1), percent * (Setting.getSide() + 1 - colonne));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);

                // milieu
                GL11.glTexCoord2f(middlePointTextRow, middlePointTextCol);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    matrice.getSquare(ligne, colonne).getAltitude() / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());
                // haut gauche
                GL11.glTexCoord2f(
                    percent * (ligne + 1), percent * (Setting.getSide() + 1 - colonne));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);
                // bas gauche
                GL11.glTexCoord2f(percent * ligne, percent * (Setting.getSide() + 1 - colonne));
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);

                GL11.glEnd();

              } else {
                GL11.glDisable(GL11.GL_TEXTURE_2D);
              }

              /*
              if (Setting.getTexture()) {
              	GL11.glEnable(GL11.GL_TEXTURE_2D);
              	GL11.glBindTexture(GL11.GL_TEXTURE_2D, textures.getTextureByName(
              		terrains.getTerrainByName(matrice.getSquare(ligne, colonne).getTerrain()).getTexture()).getTextureID());
              	GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
               GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);
               GL11.glEnable(GL11.GL_ALPHA);
               GL11.glEnable(GL11.GL_BLEND);
               GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
              	GL11.glBegin(GL11.GL_TRIANGLES);

              	GL11.glTexCoord2f(0.5f, 0.5f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getHauteur(),
              	matrice.getSquare(ligne, colonne).getAltitude(),
              	matrice.getSquare(ligne, colonne).getLargeur());

              	GL11.glTexCoord2f(0.0f, 0.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
              	matrice.getSquare(ligne, colonne).getCooHautGauche()[1],
              	matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);

              	GL11.glTexCoord2f(0.0f, 1.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
              	matrice.getSquare(ligne, colonne).getCooHautDroite()[1],
              	matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);

              	GL11.glTexCoord2f(0.5f, 0.5f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getHauteur(),
              	matrice.getSquare(ligne, colonne).getAltitude(),
              	matrice.getSquare(ligne, colonne).getLargeur());
              	GL11.glTexCoord2f(0.0f, 1.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
              	matrice.getSquare(ligne, colonne).getCooHautDroite()[1],
              	matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);

              	GL11.glTexCoord2f(1.0f, 1.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
              	matrice.getSquare(ligne, colonne).getCooBasDroite()[1],
              	matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);

              	GL11.glTexCoord2f(0.5f, 0.5f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getHauteur(),
              	matrice.getSquare(ligne, colonne).getAltitude(),
              	matrice.getSquare(ligne, colonne).getLargeur());
              	GL11.glTexCoord2f(1.0f, 1.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
              	matrice.getSquare(ligne, colonne).getCooBasDroite()[1],
              	matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);

              	GL11.glTexCoord2f(1.0f, 0.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
              	matrice.getSquare(ligne, colonne).getCooBasGauche()[1],
              	matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);

              	GL11.glTexCoord2f(0.5f, 0.5f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getHauteur(),
              	matrice.getSquare(ligne, colonne).getAltitude(),
              	matrice.getSquare(ligne, colonne).getLargeur());
              	GL11.glTexCoord2f(1.0f, 0.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
              	matrice.getSquare(ligne, colonne).getCooBasGauche()[1],
              	matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);

              	GL11.glTexCoord2f(0.0f, 0.0f);
              	GL11.glVertex3f(matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
              	matrice.getSquare(ligne, colonne).getCooHautGauche()[1],
              	matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);

              	GL11.glEnd();

              }else {
              	GL11.glDisable(GL11.GL_TEXTURE_2D);
              }
               */

              if (Setting.getWind()) {
                GL11.glBegin(GL11.GL_TRIANGLES);
                double[][] tempWind =
                    wind.getLocalWind(ligne, colonne)
                        .trianglevent(
                            ligne * Setting.getSideUnit(),
                            1,
                            colonne * Setting.getSideUnit(),
                            camera.getZoom());

                GL11.glColor3f(
                    Setting.getColorWind().x, Setting.getColorWind().y, Setting.getColorWind().z);
                GL11.glVertex3d(
                    tempWind[0][0],
                    matrice.getSquare(ligne, colonne).getAltitude() + tempWind[0][1],
                    tempWind[0][2]);
                GL11.glVertex3d(
                    tempWind[1][0],
                    matrice.getSquare(ligne, colonne).getAltitude() + tempWind[1][1],
                    tempWind[1][2]);
                GL11.glVertex3d(
                    tempWind[2][0],
                    matrice.getSquare(ligne, colonne).getAltitude() + tempWind[2][1],
                    tempWind[2][2]);
                GL11.glEnd();
              }

              if (matrice.getSquare(ligne, colonne).getActive()) {
                GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
                GL11.glBegin(GL11.GL_TRIANGLE_FAN);
                GL11.glColor3f(
                    Setting.getColorActive().x,
                    Setting.getColorActive().y,
                    Setting.getColorActive().z);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getHauteur(),
                    (matrice.getSquare(ligne, colonne).getAltitude() + 1) / this.echelle,
                    matrice.getSquare(ligne, colonne).getLargeur());
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautDroite()[2]);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[0],
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasDroite()[2]);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooBasGauche()[2]);
                GL11.glVertex3f(
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[0],
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[1] / this.echelle,
                    matrice.getSquare(ligne, colonne).getCooHautGauche()[2]);
                GL11.glEnd();
              }
            }
          }
        }
        input();

        origin();

        Display.update();

        try {
          Renderer3D.sleep(30);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      } else {
        Setting.setView3DStart(false);
        Display.destroy();
      }
    }
  }