/*****************************************************************************
 *
 *  Copyright (C) 2003 Cédric Brégardis <cedric.bregardis@free.fr>
 *
 *  This file is part of BRIQUOLO
 *
 *  BRIQUOLO is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  BRIQUOLO is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with BRIQUOLO; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 *****************************************************************************/
#include "MOGL_Afficheur.h"
#include <SDL/SDL.h>
#include <iostream>
#include "MOGL_NoeudOpenGL.h"

MOGL_Afficheur::MOGL_Afficheur() : _DernierIdentifiantObjet(0), _DessinerBord(false), _TailleBord(2), _ActiverLumiere(true)
{
}

MOGL_Afficheur::~MOGL_Afficheur()
{
}

int MOGL_Afficheur::AbonnerTriangle(MOGL_Texture * p_Texture, MOGL_MatriceTransformation * p_Matrice,int p_NbPoint, bool *p_DessinerBord,
                                    MOGL_Struct_Couleur * p_CouleurBord, unsigned int * p_TailleBord,
                                    GLfloat * p_TabPoints, GLfloat * p_TabNormale, GLfloat * p_TabTexture)
{
  MOGL_Struct_TableauTextureObjet Tab;
  Tab.Matrice=p_Matrice;
  Tab.TabNormale=p_TabNormale;
  Tab.TabTexture=p_TabTexture;
  Tab.TabPoint=p_TabPoints;
  Tab.NbPoint=p_NbPoint;
  Tab.DessinerBord=p_DessinerBord;
  Tab.CouleurBord = p_CouleurBord;
  Tab.TailleBord = p_TailleBord;

  _DernierIdentifiantObjet++;
  _MapTabTriangle[p_Texture][_DernierIdentifiantObjet]=Tab;

  return _DernierIdentifiantObjet;
}

bool MOGL_Afficheur::DesabonnerTriangle(MOGL_Texture * p_Texture, int p_Identifiant)
{
  MOGL_Map_TableauxTriangle & m=_MapTabTriangle[p_Texture];
        
  if (m.find(p_Identifiant)!=m.end())
  {
    _MapTabTriangle[p_Texture].erase(p_Identifiant);
    /**
       @todo enlever la texture de la map quand il n'y a plus d'identifiant
    */
    return true;
  }
  else
  {
    return false;
  }
}

// Si p_Matrice vaut null, alors les points fournis sont déjà transformés
int MOGL_Afficheur::AbonnerStrip(MOGL_Texture * p_Texture, MOGL_MatriceTransformation * p_Matrice,int p_NbPoint, bool * p_DessinerBord,
                                 MOGL_Struct_Couleur * p_CouleurBord, unsigned int * p_TailleBord,
                                 GLfloat * p_TabPoints, GLfloat * p_TabNormale, GLfloat * p_TabTexture)
{
  MOGL_Struct_TableauTextureObjet Tab;
  Tab.Matrice=p_Matrice;
  Tab.TabNormale=p_TabNormale;
  Tab.TabTexture=p_TabTexture;
  Tab.TabPoint=p_TabPoints;
  Tab.NbPoint=p_NbPoint;
  Tab.DessinerBord=p_DessinerBord;
  Tab.CouleurBord = p_CouleurBord;
  Tab.TailleBord = p_TailleBord;

  _DernierIdentifiantObjet++;
  //_MapTabStrip[_DernierIdentifiantObjet]=Tab;
  _MapTabStrip[p_Texture][_DernierIdentifiantObjet]=Tab;
  return _DernierIdentifiantObjet;
}

bool MOGL_Afficheur::DesabonnerStrip(MOGL_Texture * p_Texture, int p_Identifiant)
{
  MOGL_Map_TableauxStrip & m=_MapTabStrip[p_Texture];
        
  if (m.find(p_Identifiant)!=m.end())
  {
    _MapTabStrip[p_Texture].erase(p_Identifiant);
    /**
       @todo enlever la texture de la map quand il n'y a plus d'identifiant
    */
    return true;
  }
  else
  {
    return false;
  }
}

void MOGL_Afficheur::AjouterImage(MOGL_Texture * p_Texture, float p_X, float p_Y, float p_Z,
                                        float p_TailleX, float p_TailleY, const MOGL_Struct_Couleur & p_Couleur)
{
  if (p_Texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
  {
    _ListeImage.push_back(MOGL_Struct_Image(p_Texture, p_X, p_Y, p_Z, p_TailleX, p_TailleY, p_Couleur));
  }
  else
  {
    _MultimapImage.insert(make_pair(p_Z,MOGL_Struct_Image(p_Texture, p_X, p_Y, p_Z, p_TailleX, p_TailleY, p_Couleur)));
  }
}

void MOGL_Afficheur::AjouterPartieLensFlare(MOGL_Texture * p_Texture, float p_Position,
                                                        float p_OrigineX, float p_OrigineY, float p_OrigineZ,
                                                        float p_Taille, const MOGL_Struct_Couleur & p_Couleur)
{
  _ListeFlare.push_back(MOGL_Struct_Flare(p_Texture, p_Position, p_OrigineX, p_OrigineY, p_OrigineZ, p_Taille, p_Couleur));
}

void MOGL_Afficheur::AjouterPartieLensFlareTailleFixe(MOGL_Texture * p_Texture, float p_Position,
                                                                        float p_OrigineX, float p_OrigineY, float p_OrigineZ,
                                                                        float p_Taille, const MOGL_Struct_Couleur & p_Couleur)
{
  _ListeFlareTailleFixe.push_back(MOGL_Struct_Flare(p_Texture, p_Position, p_OrigineX, p_OrigineY, p_OrigineZ, p_Taille, p_Couleur));
}




void MOGL_Afficheur::AjouterImageTailleFixe(MOGL_Texture * p_Texture, float p_X, float p_Y, float p_Z,
                                                        float p_TailleX, float p_TailleY, const MOGL_Struct_Couleur & p_Couleur)
{
  if (p_Texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
  {
    _ListeImageTailleFixe.push_back(MOGL_Struct_Image(p_Texture, p_X, p_Y, p_Z, p_TailleX, p_TailleY, p_Couleur));
  }
  else
  {
    _MultimapImageTailleFixe.insert(make_pair(p_Z,MOGL_Struct_Image(p_Texture, p_X, p_Y, p_Z, p_TailleX, p_TailleY, p_Couleur)));
  }
}


void MOGL_Afficheur::DebutTnL()
{
  _ListPoint.clear();

  // Mise à zéro de la multimap des particules
  _MultimapImage.clear();
  _MultimapImageTailleFixe.clear();
        
  // On vide la liste des triangles d'ombrage
  _ListeTriangleOmbre.clear();
  // On vide la liste des lumières projeteusse d'ombre
  _ListeLumiereOmbre.clear();

  // On vide les listes des images
  _ListeImage.clear();
  _ListeImageTailleFixe.clear();
  _ListeFlare.clear();
  _ListeFlareTailleFixe.clear();
                
  // Initialisation de l'affichage OpenGL
  glLoadIdentity();
  _Camera->EnvoyerAOpenGL();
        
  // On récupère la matrice de la caméra
  _MatriceCamera.PrendreDeOpenGL();
  _MatriceInvCamera=_MatriceCamera;
  _MatriceInvCamera.Inverser();
}

void MOGL_Afficheur::AfficherOpaque()
{

  // Affichage des objets normaux
  if (_ActiverLumiere)
  {
    glEnable(GL_LIGHTING);
  }
  else
  {
    glDisable(GL_LIGHTING);
  }
        
  glEnable(GL_DEPTH_TEST);
  glDepthMask( 1 );
  glEnable(GL_CULL_FACE);
  glLoadIdentity();

  // Pour les ombres
  if (_ListeTriangleOmbre.size()>0 && _ListeLumiereOmbre.size()>0)
  {
    glDisable(GL_TEXTURE_2D);
    if (_ActiverLumiere)
    {
      glDisable(GL_LIGHTING);
    }
    glColor4f(0.25,0.25,0.25,1);
    glDisable(GL_BLEND);
    glDisable(GL_ALPHA_TEST);
    glDepthFunc(GL_LESS);
        
    glCullFace(GL_BACK);
    glColorMask(false,false,false,false);
    _AfficherAbonnementsOpaque(false);
    glColorMask(true, true, true, false);
    _AfficherOmbre();

    glBlendFunc(GL_DST_COLOR, GL_ZERO);
    glDepthFunc( GL_LEQUAL);
  }
  else
  {
    // Il n'y a pas d'ombre donc par la suite il n'y a pas besoin
    // de s'amuser avec le GL_BLEND pour ce qui est opaque
    glDisable(GL_BLEND);

    glDepthFunc( GL_LEQUAL);
  }

  // Pour les bord
  if (_DessinerBord)
  {
    glLineWidth(_TailleBord);
    glColor4f(0,0,0,1);
    glDisable(GL_TEXTURE_2D);
    if (_ActiverLumiere)
    {
      glDisable(GL_LIGHTING);
    }
    glCullFace(GL_FRONT);
    glPolygonMode(GL_BACK,GL_LINE);
    _AfficherAbonnementsOpaque(false);
  }
  else
  {
    glLineWidth(_TailleBord);
    glColor4f(0,0,0,1);
    glDisable(GL_TEXTURE_2D);
    if (_ActiverLumiere)
    {
      glDisable(GL_LIGHTING);
    }
    glCullFace(GL_FRONT);
    glPolygonMode(GL_BACK,GL_LINE);

    _AfficherBordAbonnementsOpaque();
  }
        
  // Pour le normal

  glLineWidth(1);
  glColor4f(1,1,1,1);
  glEnable(GL_TEXTURE_2D);
        
  if (_ActiverLumiere)
  {
    glEnable(GL_LIGHTING);
  }

  glCullFace(GL_BACK);
  glPolygonMode(GL_BACK,GL_FILL);


  _AfficherAbonnementsOpaque(true);

  // On affiche les MOGL_NoeudOpenGL
  glMatrixMode(GL_MODELVIEW);
  for(MOGL_ItSet_NoeudOpenGL it=_SetNoeudOpenGL.begin(); it!=_SetNoeudOpenGL.end(); it++)
  {
    glLoadIdentity();
    (*it)->GetMatriceFinale()->MultiplierDansOpenGL();
    (*it)->CodeOpenGL();
  }

  // On affiche les images opaques
  glDepthMask(1); 
  glDisable(GL_BLEND);
  glEnable(GL_ALPHA_TEST);
  if (_ActiverLumiere)
  {
    glDisable(GL_LIGHTING);
  }
  _AfficherImageOpaque();

/*
// Particules
if (_ActiverLumiere)
{
glDisable(GL_LIGHTING);
}
glDepthMask( 0 ); 
glLoadIdentity();
glDisable(GL_CULL_FACE);

//      _AfficherImageOpaque();

glDepthFunc(GL_LESS);
glDepthMask( 1 );*/
  // Les Lens Flare
  /*for (MOGL_ItList_LensFlare it=_ListLensFlare.begin(); it!=_ListLensFlare.end(); it++)
    {
    (*it)->Afficher();
    }*/
  }

void MOGL_Afficheur::AfficherNonOpaque()
{
  // Initialisation de l'affichage OpenGL
  glLoadIdentity();
//      _Camera->EnvoyerAOpenGL();

  //glEnable(GL_DEPTH_TEST);
        
  _AfficherAbonnementsNonOpaque(true);

  _AfficherImageNonOpaque();
  _AfficherLensFlare();
        
  // List points
  glLoadIdentity();
  if (_ActiverLumiere)
  {
    glDisable(GL_LIGHTING);
  }
  glDisable(GL_TEXTURE_2D);
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_BLEND);
  glColor4f(1,0,0,1);
  glPointSize(5);
  glBegin(GL_POINTS);
  for (MOGL_ItList_Vecteur itv=_ListPoint.begin(); itv!=_ListPoint.end(); itv++)
  {
    glVertex3f(itv->x, itv->y, itv->z);
  }
  glEnd();

  glEnable(GL_TEXTURE_2D);
}

void MOGL_Afficheur::_AfficherBordAbonnementsOpaque()
{
  MOGL_ItMap_TextureTriangles ItText;
  MOGL_ItMap_TextureStrips ItText2;
  MOGL_Texture * texture=NULL;

  glEnableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  for(ItText=_MapTabTriangle.begin(); ItText!=_MapTabTriangle.end(); ItText++)
  {
    if (!ItText->first->GetAutoriserTrou())
    {

      if (ItText->first!=texture)
      {
        texture=ItText->first;
        texture->Selectionner();
      }

      if (ItText->first->GetAutoriserTrou())
      {
        // La valeur alpha de la partie trouée d'une texture trouée vaut 0
        // Donc on affiche seuleument si alpha > 0.2 (on laisse un peu de marge)
        glAlphaFunc(GL_GREATER, 0.2f);
        glEnable(GL_ALPHA_TEST);
      }
      else
      {
        // La texture n'est pas trouée donc on ne fait pas de test alpha
        glDisable(GL_ALPHA_TEST);
      }

      if (texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
      {
        MOGL_ItMap_TableauxTriangle ItIdent;
        MOGL_MatriceTransformation * matrice;
        for(ItIdent=ItText->second.begin(); ItIdent!=ItText->second.end(); ItIdent++)
        {
          if (*ItIdent->second.DessinerBord)
          {

            glLineWidth(*ItIdent->second.TailleBord);
            glColor4f(ItIdent->second.CouleurBord->r,ItIdent->second.CouleurBord->g,ItIdent->second.CouleurBord->b,
                      ItIdent->second.CouleurBord->a);
            //glPolygonMode(GL_FRONT_AND_BACK,GL_LINE);
/*
  glDisable(GL_TEXTURE_2D);
  if (_ActiverLumiere)
  {
  glDisable(GL_LIGHTING);
  }
  glCullFace(GL_FRONT);
  glPolygonMode(GL_BACK,GL_LINE);
*/



            matrice=ItIdent->second.Matrice;
            // Si Mat vaut null, alors les points fournis sont déjà transformés
            if (matrice!=NULL)
            {
              glPushMatrix();
              matrice->MultiplierDansOpenGL();
            }

            glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);

            glDrawArrays(GL_TRIANGLES, 0, ItIdent->second.NbPoint);

            // Si Mat vaut null, alors les points fournis sont déjà transformés
            if (matrice!=NULL)
            {
              glPopMatrix();
            }
          }
        }
      }
    }
  }

  for(ItText2=_MapTabStrip.begin(); ItText2!=_MapTabStrip.end(); ItText2++)
  {
    if (ItText->first!=texture)
    {
      texture=ItText2->first;
      texture->Selectionner();
    }
    if (texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
    {
      MOGL_ItMap_TableauxStrip ItIdent;
      MOGL_MatriceTransformation * matrice;
      for(ItIdent=ItText2->second.begin(); ItIdent!=ItText2->second.end(); ItIdent++)
      {
        if (*ItIdent->second.DessinerBord)
        {
          matrice=ItIdent->second.Matrice;
          // Si Mat vaut null, alors les points fournis sont déjà transformés
          if (matrice!=NULL)
          {
            glPushMatrix();
            matrice->MultiplierDansOpenGL();
          }
          glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);

          glDrawArrays(GL_TRIANGLE_STRIP, 0, ItIdent->second.NbPoint);
          // Si Mat vaut null, alors les points fournis sont déjà transformés
          if (matrice!=NULL)
          {
            glPopMatrix();
          }
        }
      }
    }
  }
}

void MOGL_Afficheur::_AfficherAbonnementsOpaque(bool p_AvecNormalTexture)
{
  MOGL_ItMap_TextureTriangles ItText;
  MOGL_ItMap_TextureStrips ItText2;
  MOGL_Texture * texture=NULL;

  glEnableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  if (p_AvecNormalTexture)
  {
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  }
  else
  {
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  }

  for(ItText=_MapTabTriangle.begin(); ItText!=_MapTabTriangle.end(); ItText++)
  {
    if (p_AvecNormalTexture ||  !ItText->first->GetAutoriserTrou())
    {

      if (ItText->first!=texture)
      {
        texture=ItText->first;
        texture->Selectionner();
      }

      if (ItText->first->GetAutoriserTrou())
      {
        // La valeur alpha de la partie trouée d'une texture trouée vaut 0
        // Donc on affiche seuleument si alpha > 0.2 (on laisse un peu de marge)
        glAlphaFunc(GL_GREATER, 0.2f);
        glEnable(GL_ALPHA_TEST);
      }
      else
      {
        // La texture n'est pas trouée donc on ne fait pas de test alpha
        glDisable(GL_ALPHA_TEST);
      }

      if (texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
      {
        MOGL_ItMap_TableauxTriangle ItIdent;
        MOGL_MatriceTransformation * matrice;
        for(ItIdent=ItText->second.begin(); ItIdent!=ItText->second.end(); ItIdent++)
        {
          matrice=ItIdent->second.Matrice;
          // Si Mat vaut null, alors les points fournis sont déjà transformés
          if (matrice!=NULL)
          {
            glPushMatrix();
            matrice->MultiplierDansOpenGL();
          }

          glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);
          if (p_AvecNormalTexture)
          {
            glNormalPointer(GL_FLOAT, 0, ItIdent->second.TabNormale);
            glTexCoordPointer(2, GL_FLOAT, 0, ItIdent->second.TabTexture);
          }

          glDrawArrays(GL_TRIANGLES, 0, ItIdent->second.NbPoint);

          // Si Mat vaut null, alors les points fournis sont déjà transformés
          if (matrice!=NULL)
          {
            glPopMatrix();
          }
        }
      }
    }
  }

  for(ItText2=_MapTabStrip.begin(); ItText2!=_MapTabStrip.end(); ItText2++)
  {
    if (ItText->first!=texture)
    {
      texture=ItText2->first;
      texture->Selectionner();
    }
    if (texture->GetTypeTexture()==MOGL_Texture::TEXTURE_OPAQUE)
    {
      MOGL_ItMap_TableauxStrip ItIdent;
      MOGL_MatriceTransformation * matrice;
      for(ItIdent=ItText2->second.begin(); ItIdent!=ItText2->second.end(); ItIdent++)
      {
        matrice=ItIdent->second.Matrice;
        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPushMatrix();
          matrice->MultiplierDansOpenGL();
        }
        glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);
        if (p_AvecNormalTexture)
        {
          glNormalPointer(GL_FLOAT, 0, ItIdent->second.TabNormale);
          glTexCoordPointer(2, GL_FLOAT, 0, ItIdent->second.TabTexture);
        }

        glDrawArrays(GL_TRIANGLE_STRIP, 0, ItIdent->second.NbPoint);
        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPopMatrix();
        }
      }
    }
  }
}

void MOGL_Afficheur::_AfficherAbonnementsNonOpaque(bool p_AvecNormalTexture)
{
  MOGL_ItMap_TextureTriangles ItText;
  MOGL_ItMap_TextureStrips ItText2;
  MOGL_Texture * texture=NULL;

  glEnableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);

  if (p_AvecNormalTexture)
  {
    glEnableClientState(GL_NORMAL_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  }
  else
  {
    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
  }

  for(ItText=_MapTabTriangle.begin(); ItText!=_MapTabTriangle.end(); ItText++)
  {
    if (ItText->first!=texture)
    {
      texture=ItText->first;
      texture->Selectionner();
    }
    MOGL_Texture::MOGL_Enum_TypeTexture typeTexture=texture->GetTypeTexture();
        
    if (typeTexture!=MOGL_Texture::TEXTURE_OPAQUE)
    {
      if (typeTexture==MOGL_Texture::TEXTURE_TRANSPARENTE)
      {
        glDepthMask(1); 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        glDisable(GL_ALPHA_TEST);
      }
      else
      {
        glDepthMask(0); 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        glEnable(GL_BLEND);
        glDisable(GL_ALPHA_TEST);
      }
                
      MOGL_ItMap_TableauxTriangle ItIdent;
      MOGL_MatriceTransformation * matrice;
      for(ItIdent=ItText->second.begin(); ItIdent!=ItText->second.end(); ItIdent++)
      {
        matrice=ItIdent->second.Matrice;
        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPushMatrix();
          matrice->MultiplierDansOpenGL();
        }

        glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);
        if (p_AvecNormalTexture)
        {
          glNormalPointer(GL_FLOAT, 0, ItIdent->second.TabNormale);
          glTexCoordPointer(2, GL_FLOAT, 0, ItIdent->second.TabTexture);
        }

        glDrawArrays(GL_TRIANGLES, 0, ItIdent->second.NbPoint);

        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPopMatrix();
        }
      }
    }
  }

  for(ItText2=_MapTabStrip.begin(); ItText2!=_MapTabStrip.end(); ItText2++)
  {
    if (ItText->first!=texture)
    {
      texture=ItText2->first;
      texture->Selectionner();
    }
    if (texture->GetTypeTexture()!=MOGL_Texture::TEXTURE_OPAQUE)
    {
      if (texture->GetTypeTexture()==MOGL_Texture::TEXTURE_TRANSPARENTE)
      {
        glDepthMask(1); 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        glDisable(GL_ALPHA_TEST);
      }
      else
      {
        glDepthMask(0); 
        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
        glEnable(GL_BLEND);
        glDisable(GL_ALPHA_TEST);
      }

      MOGL_ItMap_TableauxStrip ItIdent;
      MOGL_MatriceTransformation * matrice;
      for(ItIdent=ItText2->second.begin(); ItIdent!=ItText2->second.end(); ItIdent++)
      {
        matrice=ItIdent->second.Matrice;
        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPushMatrix();
          matrice->MultiplierDansOpenGL();
        }
        glVertexPointer(3, GL_FLOAT, 0, ItIdent->second.TabPoint);
        if (p_AvecNormalTexture)
        {
          glNormalPointer(GL_FLOAT, 0, ItIdent->second.TabNormale);
          glTexCoordPointer(2, GL_FLOAT, 0, ItIdent->second.TabTexture);
        }

        glDrawArrays(GL_TRIANGLE_STRIP, 0, ItIdent->second.NbPoint);
        // Si Mat vaut null, alors les points fournis sont déjà transformés
        if (matrice!=NULL)
        {
          glPopMatrix();
        }
      }
    }
  }

  // On est susceptible de l'avoir modifier, alors on le remet.
  // Si par exemple il n'a pas été remis lors de la remise à zero du
  // zBuffer, alors celle-ci n'est pas effectuée.
  glDepthMask(1);
}

void MOGL_Afficheur::SetCamera(MOGL_Camera * p_Camera)
{
  _Camera=p_Camera;
}

MOGL_Camera * MOGL_Afficheur::GetCamera() const
{
  return _Camera;
}


const MOGL_MatriceTransformation & MOGL_Afficheur::GetMatriceCamera() const
{
  return _MatriceCamera;
}

const MOGL_MatriceTransformation & MOGL_Afficheur::GetMatriceInvCamera() const
{
  return _MatriceInvCamera;
}

void MOGL_Afficheur::DessinerBord(bool p_Val)
{
  _DessinerBord=p_Val;
}


void MOGL_Afficheur::SetTailleBord(unsigned int p_Taille)
{
  _TailleBord=p_Taille;
}

void MOGL_Afficheur::SetDimension(unsigned int p_Largeur, unsigned int p_Hauteur)
{
  _Largeur=p_Largeur;
  _Hauteur=p_Hauteur;
}

void MOGL_Afficheur::GetDimension(unsigned int & p_Largeur, unsigned int & p_Hauteur)
{
  p_Largeur=_Largeur;
  p_Hauteur=_Hauteur;
}




void MOGL_Afficheur::ActiverLumiere(bool p_Activation)
{
  _ActiverLumiere=p_Activation;
}

void MOGL_Afficheur::AjouterTriangleOmbre(const MOGL_List_TriangleOmbre & p_ListeTriangle)
{
  _ListeTriangleOmbre.insert(_ListeTriangleOmbre.end(), p_ListeTriangle.begin(), p_ListeTriangle.end());
}

void MOGL_Afficheur::AjouterTriangleOmbre(const MOGL_Liste_Triangle & p_ListeTriangle)
{
  for(MOGL_ItListe_Triangle it=p_ListeTriangle.begin(); it!=p_ListeTriangle.end(); it++)
  {
    MOGL_Struct_Vecteur p1,p2,p3;
    p1.x=it->GetPoint(0).xp;
    p1.y=it->GetPoint(0).yp;
    p1.z=it->GetPoint(0).zp;
        
    p2.x=it->GetPoint(1).xp;
    p2.y=it->GetPoint(1).yp;
    p2.z=it->GetPoint(1).zp;

    p3.x=it->GetPoint(2).xp;
    p3.y=it->GetPoint(2).yp;
    p3.z=it->GetPoint(2).zp;

    MOGL_TriangleOmbre tr(p1, p2, p3);
        
    _ListeTriangleOmbre.push_back(tr);
  }
}

void MOGL_Afficheur::AjouterTriangleOmbre(const MOGL_TriangleOmbre & p_Triangle)
{
  _ListeTriangleOmbre.push_back(p_Triangle);
}

void MOGL_Afficheur::AjouterLumiereOmbre(const MOGL_Struct_Vecteur & p_Vecteur, bool p_VecteurEstDirection)
{
  MOGL_Struct_LumiereOmbre lum;
  lum.Vecteur=p_Vecteur;
  lum.VecteurEstDirection=p_VecteurEstDirection;
        
  _ListeLumiereOmbre.push_back(lum);
}

void MOGL_Afficheur::_GetProjectionPoint(const MOGL_Struct_Vecteur & p_Point, const MOGL_Struct_Vecteur & p_Direction,
                                         float * p_PointResultat)
{
  float z;
        
  if (p_Direction.z<0)
  {
    z=_zMax;
  }
  else
  {
    z=_zMin;
  }

  float t=(z-p_Point.z)/p_Direction.z;

  p_PointResultat[0] = t*p_Direction.x + p_Point.x;
  p_PointResultat[1] = t*p_Direction.y + p_Point.y;
  p_PointResultat[2] = z;
}


void MOGL_Afficheur::_AfficherOmbre()
{
  _zMax=-_Camera->GetClippingMax()+(_Camera->GetClippingMax()-_Camera->GetClippingMin())/1000;
  _zMin=-_Camera->GetClippingMin()-(_Camera->GetClippingMax()-_Camera->GetClippingMin())/1000;

  unsigned int tailleTab=_ListeLumiereOmbre.size()*_ListeTriangleOmbre.size();
        

  GLfloat * tabQuadri=new GLfloat[tailleTab*3*4*3]; // 4 points par quadrilataire, et 3 float par point
  bool vecteurEstDirection;
  MOGL_Struct_Vecteur vecteur;
  unsigned int indicePoint=0;
  for(MOGL_ItListe_LumiereOmbre it=_ListeLumiereOmbre.begin(); it!=_ListeLumiereOmbre.end(); it++)
  {
    vecteurEstDirection=it->VecteurEstDirection;
    vecteur=it->Vecteur;

    for(MOGL_ItList_TriangleOmbre itTriOmbre=_ListeTriangleOmbre.begin(); itTriOmbre!=_ListeTriangleOmbre.end(); itTriOmbre++)
    {
      bool memeDirection;
      if (vecteurEstDirection)
      {
        memeDirection=((itTriOmbre->GetNormale().x*vecteur.x +
                        itTriOmbre->GetNormale().y*vecteur.y +
                        itTriOmbre->GetNormale().z*vecteur.z) < 0);
      }
      else
      {
        /** @todo voir si on peut améliorer ça */
        MOGL_Struct_Vecteur centreTriangle, dir;
        centreTriangle.x=(itTriOmbre->GetPoint(0).x+itTriOmbre->GetPoint(1).x+itTriOmbre->GetPoint(2).x)/3;
        centreTriangle.y=(itTriOmbre->GetPoint(0).y+itTriOmbre->GetPoint(1).y+itTriOmbre->GetPoint(2).y)/3;
        centreTriangle.z=(itTriOmbre->GetPoint(0).z+itTriOmbre->GetPoint(1).z+itTriOmbre->GetPoint(2).z)/3;
                
        dir.x=centreTriangle.x-vecteur.x;
        dir.y=centreTriangle.y-vecteur.y;
        dir.z=centreTriangle.z-vecteur.z;
                
                
        memeDirection=((itTriOmbre->GetNormale().x*dir.x +
                        itTriOmbre->GetNormale().y*dir.y +
                        itTriOmbre->GetNormale().z*dir.z) < 0);
      }
                

      if (!memeDirection)
      {
        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(0), itTriOmbre->GetPoint(1));
        indicePoint+=12;

        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(1), itTriOmbre->GetPoint(2));
        indicePoint+=12;

        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(2), itTriOmbre->GetPoint(0));
        indicePoint+=12;
      }
      else
      {
        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(1), itTriOmbre->GetPoint(0));
        indicePoint+=12;
                
        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(2), itTriOmbre->GetPoint(1));
        indicePoint+=12;

        _FabriqueQuadrilatere(&tabQuadri[indicePoint], vecteur, vecteurEstDirection, itTriOmbre->GetPoint(0), itTriOmbre->GetPoint(2));
        indicePoint+=12;
      }
    }
  }

  glLoadIdentity();
        
  glEnableClientState(GL_VERTEX_ARRAY);
  glDisableClientState(GL_COLOR_ARRAY);
  glDisableClientState(GL_NORMAL_ARRAY);
  glDisableClientState(GL_TEXTURE_COORD_ARRAY);

  glVertexPointer(3, GL_FLOAT, 0, tabQuadri);
  glDisable(GL_LIGHTING);
  glEnable(GL_DEPTH_TEST);
  glDisable(GL_TEXTURE_2D);

  glEnable(GL_BLEND);

// Initialisation du buffer
  glDepthMask(0);
        
// Affichage des quadrilateres
  for(unsigned int i=0; i<tailleTab; i++)
  {
    glVertexPointer(3, GL_FLOAT, 0, tabQuadri+3*4*3*i);

    glBlendFunc(GL_DST_COLOR, GL_ONE);
    glColor4f(1,1,1,1);
    glCullFace(GL_BACK);
    glDrawArrays(GL_QUADS, 0, 4*3);

    glBlendFunc(GL_DST_COLOR, GL_ZERO);
    glColor4f(0.5, 0.5, 0.50, 0.50);
    glCullFace(GL_FRONT);
    glDrawArrays(GL_QUADS, 0, 4*3);
  }

  // On prépare l'affichage des carré sur toute la surface
  glMatrixMode(GL_PROJECTION);
  glPushMatrix();
  glLoadIdentity();
  gluOrtho2D(-10,10,-10,10);
  glDisable(GL_DEPTH_TEST);

  glCullFace(GL_BACK);

  glColor4f(1,1,1,1);
  glBlendFunc(GL_DST_COLOR, GL_ONE);
  glBegin(GL_QUADS);
  glVertex2f(-10,-10);
  glVertex2f(10,-10);
  glVertex2f(10,10);
  glVertex2f(-10,10);
  glEnd();      

  glColor4f(1,1,1,1);
  glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO);
  glBegin(GL_QUADS);
  glVertex2f(-10,-10);
  glVertex2f(10,-10);
  glVertex2f(10,10);
  glVertex2f(-10,10);
  glEnd();

  glColor4f(1,1,1,1);
  glBlendFunc(GL_DST_COLOR, GL_ONE );
  glBegin(GL_QUADS);
  glVertex2f(-10,-10);
  glVertex2f(10,-10);
  glVertex2f(10,10);
  glVertex2f(-10,10);
  glEnd();

  glColor4f(0.5,0.5,0.5,0.5);
  glBlendFunc(GL_ONE, GL_ONE );
  glBegin(GL_QUADS);
  glVertex2f(-10,-10);
  glVertex2f(10,-10);
  glVertex2f(10,10);
  glVertex2f(-10,10);
  glEnd();

  glPopMatrix();
  glMatrixMode(GL_MODELVIEW);
  glEnable(GL_DEPTH_TEST);

  // On est susceptible de l'avoir modifier, alors on le remet.
  // Si par exemple il n'a pas été remis lors de la remise à zero du
  // zBuffer, alors celle-ci n'est pas effectuée.
  glDepthMask(1);

  delete [] tabQuadri;
}


void MOGL_Afficheur::_FabriqueQuadrilatere(float * p_TabQuadri, const MOGL_Struct_Vecteur & p_Vecteur, bool p_VecteurEstDirection,
                                           const MOGL_Struct_Vecteur & p_Point1, const MOGL_Struct_Vecteur & p_Point2)
{
  p_TabQuadri[0]=p_Point1.x;
  p_TabQuadri[1]=p_Point1.y;
  p_TabQuadri[2]=p_Point1.z;
                
  p_TabQuadri[3]=p_Point2.x;
  p_TabQuadri[4]=p_Point2.y;
  p_TabQuadri[5]=p_Point2.z;

  if (p_VecteurEstDirection)
  {
    _GetProjectionPoint(p_Point2, p_Vecteur, &p_TabQuadri[6]);
    _GetProjectionPoint(p_Point1, p_Vecteur, &p_TabQuadri[9]);
  }
  else
  {
    MOGL_Struct_Vecteur direction;
    float norm;

    direction.x=(p_Point2.x-p_Vecteur.x);
    direction.y=(p_Point2.y-p_Vecteur.y);
    direction.z=(p_Point2.z-p_Vecteur.z);

    norm=sqrt(direction.x*direction.x+direction.y*direction.y+direction.z*direction.z);
    direction.x/=norm;
    direction.y/=norm;
    direction.z/=norm;
        
    _GetProjectionPoint(p_Point2, direction, &p_TabQuadri[6]);

    direction.x=(p_Point1.x-p_Vecteur.x);
    direction.y=(p_Point1.y-p_Vecteur.y);
    direction.z=(p_Point1.z-p_Vecteur.z);

    norm=sqrt(direction.x*direction.x+direction.y*direction.y+direction.z*direction.z);
    direction.x/=norm;
    direction.y/=norm;
    direction.z/=norm;

    _GetProjectionPoint(p_Point1, direction, &p_TabQuadri[9]);
  }
}

void MOGL_Afficheur::AjouterPoint(MOGL_Struct_Vecteur p_Point)
{
  _ListPoint.push_back(p_Point);
}

void MOGL_Afficheur::_AfficherImageOpaque()
{
  MOGL_ItListe_Image it;
  MOGL_Texture * texture=NULL;

  glBegin(GL_QUADS);    
  for(it=_ListeImage.begin(); it!=_ListeImage.end(); it++)
  {
    if (it->texture!=texture)
    {
      glEnd();
      texture=it->texture;
      texture->Selectionner();
      if (texture->GetAutoriserTrou())
      {
        // La valeur alpha de la partie trouée d'une texture trouée vaut 0
        // Donc on affiche seuleument si alpha > 0.2 (on laisse un peu de marge)
        glAlphaFunc(GL_GREATER, 0.2f);
        glEnable(GL_ALPHA_TEST);
      }
      else
      {
        // La texture n'est pas trouée donc on ne fait pas de test alpha
        glDisable(GL_ALPHA_TEST);
      }

      glBegin(GL_QUADS);
    }
    glColor4f(it->couleur.r,it->couleur.g,it->couleur.b,it->couleur.a);

    glTexCoord2f(0,0);
    glVertex3f(it->x-it->tailleX/2, it->y-it->tailleY/2, it->z);

    glTexCoord2f(1,0);
    glVertex3f(it->x+it->tailleX/2, it->y-it->tailleY/2, it->z);

    glTexCoord2f(1,1);
    glVertex3f(it->x+it->tailleX/2, it->y+it->tailleY/2, it->z);

    glTexCoord2f(0,1);
    glVertex3f(it->x-it->tailleX/2, it->y+it->tailleY/2, it->z);
  }
  glEnd();

  for(it=_ListeImageTailleFixe.begin(); it!=_ListeImageTailleFixe.end(); it++)
  {
    if (it->texture!=texture)
    {
      texture=it->texture;
      texture->Selectionner();
    }
    if (texture->GetAutoriserTrou())
    {
      // La valeur alpha de la partie trouée d'une texture trouée vaut 0
      // Donc on affiche seuleument si alpha > 0.2 (on laisse un peu de marge)
      glAlphaFunc(GL_GREATER, 0.2f);
      glEnable(GL_ALPHA_TEST);
    }
    else
    {
      // La texture n'est pas trouée donc on ne fait pas de test alpha
      glDisable(GL_ALPHA_TEST);
    }
    glRasterPos3f(it->x, it->y, it->z);
    GLboolean positionValide;
    glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, & positionValide);
        
    if (positionValide)
    {
      // On change de viewport
      glMatrixMode(GL_PROJECTION);
      glPushMatrix();
      glLoadIdentity();
      gluOrtho2D(0,_Largeur,0,_Hauteur);

      float pos[4];
      glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);

      glBegin(GL_QUADS);
        
      glColor4f(it->couleur.r, it->couleur.g, it->couleur.b, it->couleur.a);

      float tailleX=_Largeur*it->tailleX / 100.0;
      float tailleY;
      if (it->tailleY>=0)
      {
        tailleY=_Hauteur*it->tailleY / 100.0;
      }
      else
      {
        tailleY=tailleX;
      }
                
      glTexCoord2f(0,0);
      glVertex3f(pos[0]-tailleX/2, pos[1]-tailleY/2, 0);
                
      glTexCoord2f(1,0);
      glVertex3f(pos[0]+tailleX/2, pos[1]-tailleY/2, 0);
                
      glTexCoord2f(1,1);
      glVertex3f(pos[0]+tailleX/2, pos[1]+tailleY/2, 0);
                
      glTexCoord2f(0,1);
      glVertex3f(pos[0]-tailleX/2, pos[1]+tailleY/2, 0);

      glEnd();
      glPopMatrix();
      glMatrixMode(GL_MODELVIEW);
    }
  }
}

void MOGL_Afficheur::_AfficherImageNonOpaque()
{
  MOGL_ItMultimap_ProfondeurImage it;
  if (_MultimapImage.size()!=0)
  {
    MOGL_Texture * textureCourante=_MultimapImage.begin()->second.texture;
    textureCourante->Selectionner();
    if (textureCourante->GetTypeTexture()==MOGL_Texture::TEXTURE_TRANSPARENTE)
    {
      glDepthMask(1); 
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_BLEND);
      glDisable(GL_ALPHA_TEST);
    }
    else
    {
      glDepthMask(0); 
      glBlendFunc(GL_SRC_ALPHA, GL_ONE);
      glEnable(GL_BLEND);
      glDisable(GL_ALPHA_TEST);
    }


    glBegin(GL_QUADS);
    for(it=_MultimapImage.begin(); it!=_MultimapImage.end(); it++)
    {
      if (it->second.texture!=textureCourante)
      {
        glEnd();
        textureCourante=it->second.texture;
        textureCourante->Selectionner();
        if (textureCourante->GetTypeTexture()==MOGL_Texture::TEXTURE_TRANSPARENTE)
        {
          glDepthMask(1); 
          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
          glEnable(GL_BLEND);
          glDisable(GL_ALPHA_TEST);
        }
        else
        {
          glDepthMask(0); 
          glBlendFunc(GL_SRC_ALPHA, GL_ONE);
          glEnable(GL_BLEND);
          glDisable(GL_ALPHA_TEST);
        }

        glBegin(GL_QUADS);
      }
      glColor4f(it->second.couleur.r,it->second.couleur.g,it->second.couleur.b,it->second.couleur.a);

      glTexCoord2f(0,0);
      glVertex3f(it->second.x-it->second.tailleX/2, it->second.y-it->second.tailleY/2, it->second.z);
          
      glTexCoord2f(1,0);
      glVertex3f(it->second.x+it->second.tailleX/2, it->second.y-it->second.tailleY/2, it->second.z);
          
      glTexCoord2f(1,1);
      glVertex3f(it->second.x+it->second.tailleX/2, it->second.y+it->second.tailleY/2, it->second.z);
          
      glTexCoord2f(0,1);
      glVertex3f(it->second.x-it->second.tailleX/2, it->second.y+it->second.tailleY/2, it->second.z);
    }
    glEnd();
  }

  if (_MultimapImageTailleFixe.size()!=0)
  {
    MOGL_Texture * textureCourante=_MultimapImageTailleFixe.begin()->second.texture;
    textureCourante->Selectionner();
    if (textureCourante->GetTypeTexture()==MOGL_Texture::TEXTURE_TRANSPARENTE)
    {
      glDepthMask(1); 
      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
      glEnable(GL_BLEND);
      glDisable(GL_ALPHA_TEST);
    }
    else
    {
      glDepthMask(0); 
      glBlendFunc(GL_SRC_ALPHA, GL_ONE);
      glEnable(GL_BLEND);
      glDisable(GL_ALPHA_TEST);
    }

    for(it=_MultimapImageTailleFixe.begin(); it!=_MultimapImageTailleFixe.end(); it++)
    {
      if (it->second.texture!=textureCourante)
      {
        textureCourante=it->second.texture;
        textureCourante->Selectionner();
        if (textureCourante->GetTypeTexture()==MOGL_Texture::TEXTURE_TRANSPARENTE)
        {
          glDepthMask(1); 
          glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
          glEnable(GL_BLEND);
          glDisable(GL_ALPHA_TEST);
        }
        else
        {
          glDepthMask(0); 
          glBlendFunc(GL_SRC_ALPHA, GL_ONE);
          glEnable(GL_BLEND);
          glDisable(GL_ALPHA_TEST);
        }
      }

      const MOGL_Struct_Image & im=it->second;
      glRasterPos3f(im.x, im.y, im.z);
      GLboolean positionValide;
      glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, & positionValide);
  
      if (positionValide)
      {
        // On change de viewport
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0,_Largeur,0,_Hauteur);

        float pos[4];
        glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);

        glBegin(GL_QUADS);
  
        glColor4f(im.couleur.r, im.couleur.g, im.couleur.b, im.couleur.a);

        float tailleX=_Largeur*im.tailleX / 100.0;
        float tailleY;
        if (im.tailleY>=0)
        {
          tailleY=_Hauteur*im.tailleY / 100.0;
        }
        else
        {
          tailleY=tailleX;
        }

        glTexCoord2f(0,0);
        glVertex3f(pos[0]-tailleX/2, pos[1]-tailleY/2, 0);
          
        glTexCoord2f(1,0);
        glVertex3f(pos[0]+tailleX/2, pos[1]-tailleY/2, 0);
          
        glTexCoord2f(1,1);
        glVertex3f(pos[0]+tailleX/2, pos[1]+tailleY/2, 0);
          
        glTexCoord2f(0,1);
        glVertex3f(pos[0]-tailleX/2, pos[1]+tailleY/2, 0);

        glEnd();
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
      }
    }
  }

  // On est susceptible de l'avoir modifier, alors on le remet.
  // Si par exemple il n'a pas été remis lors de la remise à zero du
  // zBuffer, alors celle-ci n'est pas effectuée.
  glDepthMask(1);
}

void MOGL_Afficheur::_AfficherLensFlare()
{
  MOGL_Texture * texture=NULL;
  
  MOGL_ItListe_Flare it;
  for(it=_ListeFlare.begin(); it!=_ListeFlare.end(); it++)
  {
    glRasterPos3f(it->x, it->y, it->z);
    GLboolean positionValide;
    glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, & positionValide);
  
    if (positionValide)
    {
      float pos[4];
      glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);

      float valDepthBuffer;
      glReadPixels(static_cast<int>(pos[0]), static_cast<int>(pos[1]), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &valDepthBuffer);
      if (valDepthBuffer>pos[2])
      {
        // On paramètre la texture
        if (it->texture!=texture)
        {
          texture=it->texture;
          texture->Selectionner();
          switch (texture->GetTypeTexture())
          {
            case MOGL_Texture::TEXTURE_OPAQUE:
            {
              glDepthMask(0); 
              glDisable(GL_BLEND);
              glEnable(GL_ALPHA_TEST);
              glAlphaFunc(GL_GREATER,0.5);
              break;
            }
            case MOGL_Texture::TEXTURE_TRANSPARENTE:
            {
              glDepthMask(0); 
              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
              glEnable(GL_BLEND);
              glDisable(GL_ALPHA_TEST);
              break;
            }
            case MOGL_Texture::TEXTURE_SATURE:
            {
              glDepthMask(0); 
              glBlendFunc(GL_SRC_ALPHA, GL_ONE);
              glEnable(GL_BLEND);
              glDisable(GL_ALPHA_TEST);
              break;
            }
          }
        }

        // On change de viewport
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0,_Largeur,0,_Hauteur);

        //float pos[4];
        glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);

        float x=pos[0]*it->position+_Largeur/2;
        float y=pos[1]*it->position+_Hauteur/2;
          

        glBegin(GL_QUADS);
  
        glColor4f(it->couleur.r, it->couleur.g, it->couleur.b, it->couleur.a);

        float taille=_Largeur*it->taille / 100.0;
        /** @todo Spécifier la taille de manière à être conforme à la caméra */

        glTexCoord2f(0,0);
        glVertex3f(x-taille/2, y-taille/2, 0);
          
        glTexCoord2f(1,0);
        glVertex3f(x+taille/2, y-taille/2, 0);
          
        glTexCoord2f(1,1);
        glVertex3f(x+taille/2, y+taille/2, 0);
          
        glTexCoord2f(0,1);
        glVertex3f(x-taille/2, y+taille/2, 0);

        glEnd();
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
      }
    }
  }
  
  for(it=_ListeFlareTailleFixe.begin(); it!=_ListeFlareTailleFixe.end(); it++)
  {
    glRasterPos3f(it->x, it->y, it->z);
    GLboolean positionValide;
    glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, & positionValide);
  
    if (positionValide)
    {
      float pos[4];
      glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);

      float valDepthBuffer;
      glReadPixels(static_cast<int>(pos[0]), static_cast<int>(pos[1]), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &valDepthBuffer);
      if (valDepthBuffer>pos[2])
      {
                
        // On paramètre la texture
        if (it->texture!=texture)
        {
          texture=it->texture;
          texture->Selectionner();
          switch (texture->GetTypeTexture())
          {
            case MOGL_Texture::TEXTURE_OPAQUE:
            {
              glDepthMask(0); 
              glDisable(GL_BLEND);
              glEnable(GL_ALPHA_TEST);
              glAlphaFunc(GL_GREATER,0.5);
              break;
            }
            case MOGL_Texture::TEXTURE_TRANSPARENTE:
            {
              glDepthMask(0); 
              glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
              glEnable(GL_BLEND);
              glDisable(GL_ALPHA_TEST);
              break;
            }
            case MOGL_Texture::TEXTURE_SATURE:
            {
              glDepthMask(0); 
              glBlendFunc(GL_SRC_ALPHA, GL_ONE);
              glEnable(GL_BLEND);
              glDisable(GL_ALPHA_TEST);
              break;
            }
          }
        }
        // On change de viewport
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        gluOrtho2D(0,_Largeur,0,_Hauteur);

        float x=(pos[0]-_Largeur/2)*it->position+_Largeur/2;
        float y=(pos[1]-_Hauteur/2)*it->position+_Hauteur/2;
          

        glBegin(GL_QUADS);
  
        glColor4f(it->couleur.r, it->couleur.g, it->couleur.b, it->couleur.a);

        float taille=_Largeur*it->taille / 100.0;

        glTexCoord2f(0,0);
        glVertex3f(x-taille/2, y-taille/2, 0);
          
        glTexCoord2f(1,0);
        glVertex3f(x+taille/2, y-taille/2, 0);
          
        glTexCoord2f(1,1);
        glVertex3f(x+taille/2, y+taille/2, 0);
          
        glTexCoord2f(0,1);
        glVertex3f(x-taille/2, y+taille/2, 0);

        glEnd();
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
      }
    }
  }
  // On est susceptible de l'avoir modifier, alors on le remet.
  // Si par exemple il n'a pas été remis lors de la remise à zero du
  // zBuffer, alors celle-ci n'est pas effectuée.
  glDepthMask(1);

}

void MOGL_Afficheur::AjouterNoeudOpenGL(MOGL_NoeudOpenGL * p_NoeudOpenGL)
{
  _SetNoeudOpenGL.insert(p_NoeudOpenGL);
}


bool MOGL_Afficheur::RetirerNoeudOpenGL(MOGL_NoeudOpenGL * p_NoeudOpenGL)
{
  MOGL_ItSet_NoeudOpenGL it=_SetNoeudOpenGL.find(p_NoeudOpenGL);
  if (it!=_SetNoeudOpenGL.end())
  {
    _SetNoeudOpenGL.erase(it);
    return true;
  }
  else
  {
    return false;
  }
}
