/*****************************************************************************
 *
 *  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_GenerateurParticule.h"
#include "MOGL_Afficheur.h"
#include "MOGL_Temps.h"
#include <iostream>
using namespace std;

MOGL_GenerateurParticule::MOGL_GenerateurParticule(unsigned int p_NbParticulesMax,
                                                   bool p_Recreer,
                                                   MOGL_Texture * p_Texture): MOGL_Noeud(), _EstInactif(true)
{
  _ParticuleACreer=0;
  _NbParticuleMax=p_NbParticulesMax;


  _TabParticule=new MOGL_Particule *[_NbParticuleMax];

  for(unsigned int i=0;i<_NbParticuleMax;i++)
  {
    _TabParticule[i]=new MOGL_Particule();
  }

        
  _Recreer=p_Recreer;
  _Texture=p_Texture;

  _TabPoint=new GLfloat[_NbParticuleMax*3*2*3];
  _TabCouleur=new GLfloat[_NbParticuleMax*4*2*3];
  _TabTexture=new GLfloat[_NbParticuleMax*2*2*3];
}

MOGL_GenerateurParticule::~MOGL_GenerateurParticule()
{
  for(unsigned int i=0;i<_NbParticuleMax;i++)
  {
    delete _TabParticule[i];
  }
  delete [] _TabParticule;

  delete [] _TabPoint;
  delete [] _TabCouleur;
  delete [] _TabTexture;
}

void MOGL_GenerateurParticule::CreerParticules(unsigned int p_NbParticule)
{
  _ParticuleACreer+=p_NbParticule;
  _EstInactif=false;
}

void MOGL_GenerateurParticule::TnL(MOGL_Afficheur * p_Afficheur)
{
  _Camera=p_Afficheur->GetCamera();
  
  glPushMatrix();
  // On multiplie la matrice du noeud dans l'environnement OpenGL
  // de manière à avoir la matrice totale de transformation
  _Matrice.MultiplierDansOpenGL();
  
  // On fait le TnL des objets enfants
  MOGL_ItSet_ElementArbre it;
  for(it=_SetElement.begin();it!=_SetElement.end();it++)
  {
    (*it)->TnL(p_Afficheur);
  }

  // On récupère cette matrice
  _MatriceSansCamera.PrendreDeOpenGL();

  // On multiplie par la matrice inverse de la caméra
  // de manière à avoir la matrice de transformation de comprenant pas la caméra
  _MatriceSansCamera.Multiplier(p_Afficheur->GetMatriceInvCamera());

  glPopMatrix();

  // On récupère la matrice de la caméra
  const MOGL_MatriceTransformation & matCamera=p_Afficheur->GetMatriceCamera();
  //MOGL_MatriceTransformation matCamera;

  unsigned int i;
  //int IndiceTabTexture=0;
  _NbParticule=0;
  unsigned int nbParticulesMortes=0;
  for(i=0;i<_NbParticuleMax;i++)
  {
    if ((_TabParticule[i]->_Age) < (_TabParticule[i]->_DureeVie))
    {
      _TabParticule[i]->_Age+=MOGL_Temps::GetVariationTemps();
      _NbParticule++;

      MajParticule(_TabParticule[i]->_Position,
                   _TabParticule[i]->_Velocite,
                   _TabParticule[i]->_Couleur);
                        
      GLfloat pt3=matCamera.Lit(0,3)*_TabParticule[i]->_Position.x+
        matCamera.Lit(1,3)*_TabParticule[i]->_Position.y+
        matCamera.Lit(2,3)*_TabParticule[i]->_Position.z+
        matCamera.Lit(3,3);

      MOGL_Struct_Vecteur p2;   
      p2.x=(matCamera.Lit(0,0)*_TabParticule[i]->_Position.x+
            matCamera.Lit(1,0)*_TabParticule[i]->_Position.y+
            matCamera.Lit(2,0)*_TabParticule[i]->_Position.z+
            matCamera.Lit(3,0))/pt3;

      p2.y=(matCamera.Lit(0,1)*_TabParticule[i]->_Position.x+
            matCamera.Lit(1,1)*_TabParticule[i]->_Position.y+
            matCamera.Lit(2,1)*_TabParticule[i]->_Position.z+
            matCamera.Lit(3,1))/pt3;
                                                
      p2.z=(matCamera.Lit(0,2)*_TabParticule[i]->_Position.x+
            matCamera.Lit(1,2)*_TabParticule[i]->_Position.y+
            matCamera.Lit(2,2)*_TabParticule[i]->_Position.z+
            matCamera.Lit(3,2))/pt3;

      GLfloat alpha=1;
      if (_TabParticule[i]->_DureeVie!=0)
      {
        alpha=1-(_TabParticule[i]->_Age/_TabParticule[i]->_DureeVie);
        if (alpha<0)
        {
          alpha=0;
        }
      }
      _TabParticule[i]->_Couleur.a=alpha;
         
      p_Afficheur->AjouterImage(_Texture, p2.x, p2.y, p2.z,
                                _TabParticule[i]->_Taille, _TabParticule[i]->_Taille, _TabParticule[i]->_Couleur);
    }
    else
    {
      if ((_TabParticule[i]->_Vivant && _Recreer) || _ParticuleACreer!=0)
      {

        if (!(_TabParticule[i]->_Vivant && _Recreer))
        {
          _ParticuleACreer--;
        }
                                        
        CreerParamInitiaux(_TabParticule[i]->_Position,
                           _TabParticule[i]->_Velocite,
                           _TabParticule[i]->_Couleur,
                           _TabParticule[i]->_DureeVie,
                           _TabParticule[i]->_Taille);

        _TabParticule[i]->_Position=_MatriceSansCamera.MultiplierVecteur(_TabParticule[i]->_Position);
                

        _TabParticule[i]->_Age=0;
        _TabParticule[i]->_Texture=_Texture;
        _TabParticule[i]->_Vivant=true;
      }
      else
      {
        nbParticulesMortes++;
        _TabParticule[i]->_Vivant=false;
      }
    }
  }
  if (!_EstInactif && nbParticulesMortes==_NbParticuleMax)
  {
    GenerateurInactif.Emettre();
    _EstInactif=true;
  }
}


float MOGL_GenerateurParticule::Random()
{
  return rand()/(RAND_MAX+0.0);
}

float MOGL_GenerateurParticule::RandomNeg()
{
  return 2*(rand()/(RAND_MAX+0.0))-1;
}
