/*****************************************************************************
 *
 *  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_Animation.h"
#include "MOGL_Temps.h"
#include <iostream>

MOGL_Animation::MOGL_Animation(): _TempsMin(-1), _TempsMax(-1)
{
  _Noeud=NULL;
}

MOGL_Animation::MOGL_Animation(MOGL_Noeud * p_Noeud): _TempsMin(-1), _TempsMax(-1)
{
  _Noeud=p_Noeud;
}

void MOGL_Animation::SetNoeud(MOGL_Noeud * p_Noeud)
{
  _Noeud=p_Noeud;
}

void MOGL_Animation::AjouterClefRotation(float p_Temps, const MOGL_Struct_Vecteur & p_Rotation)
{
  _MapRotation[p_Temps]=p_Rotation;
  if (_TempsMin < 0)
  {
        _TempsMin=_TempsMax=p_Temps;
  }
  else if (p_Temps>_TempsMax)
  {
        _TempsMax=p_Temps;
  }
  else if (p_Temps<_TempsMin)
  {
        _TempsMin=p_Temps;
  }
}

void MOGL_Animation::AjouterClefTranslation(float p_Temps, const MOGL_Struct_Vecteur & p_Translation)
{
  _MapTranslation[p_Temps]=p_Translation;
  if (_TempsMin < 0)
  {
        _TempsMin=_TempsMax=p_Temps;
  }
  else if (p_Temps>_TempsMax)
  {
        _TempsMax=p_Temps;
  }
  else if (p_Temps<_TempsMin)
  {
        _TempsMin=p_Temps;
  }

}

//void MOGL_Animation::Initialise(unsigned int p_TempsInitial)
void MOGL_Animation::Initialiser()
{
  //_TempsInitial=p_TempsInitial;
  _TempsInitial=MOGL_Temps::GetTemps();

  MOGL_ItMap_Vecteur ItR;
  ItR=_MapRotation.begin();
  MOGL_ItMap_Vecteur ItT;
  ItT=_MapTranslation.begin();

  MOGL_MatriceTransformation MatRot,MatTrans;
  _Noeud->ReinitialiserPosition();
  MatRot=MOGL_MatriceTransformation::FabriqueRotation(ItR->second.x,ItR->second.y,ItR->second.z);
  MatTrans=MOGL_MatriceTransformation::FabriqueTranslation(ItT->second.x,ItT->second.y,ItT->second.z);
  _Noeud->AjouteTransformation(MatRot);
  _Noeud->AjouteTransformation(MatTrans);

}

//bool MOGL_Animation::SetTemps(unsigned int p_Temps)
bool MOGL_Animation::SetTemps()
{
  float Temps=_TempsMin+(MOGL_Temps::GetTemps()-_TempsInitial)/_UniteTemps;
  return SetMatrice(Temps);
}

void MOGL_Animation::SetUniteTemps(float p_Temps)
{
  _UniteTemps=p_Temps;
}

bool MOGL_Animation::SetMatrice(float _Temps)
{
  MOGL_ItMap_Vecteur ItR,ItT,ItR2,ItT2;
  float Rx,Ry,Rz,Tx,Ty,Tz;
  float Avancement;
  bool fin=false;
  ItR=_MapRotation.lower_bound(_Temps); 
  ItT=_MapTranslation.lower_bound(_Temps);

  if (ItR==_MapRotation.end())
  {
    ItR--;
    Rx=ItR->second.x;
    Ry=ItR->second.y;
    Rz=ItR->second.z;
    fin=true;

  }
  else if (ItR==_MapRotation.begin())
  {
    Rx=ItR->second.x;
    Ry=ItR->second.y;
    Rz=ItR->second.z;
  }
  else
  {
    ItR2=ItR;
    ItR--;

    Avancement=(_Temps-ItR->first)/(ItR2->first-ItR->first);

    Rx=InterpolerAngle(ItR->second.x,ItR2->second.x,Avancement);
    Ry=InterpolerAngle(ItR->second.y,ItR2->second.y,Avancement);
    Rz=InterpolerAngle(ItR->second.z,ItR2->second.z,Avancement);
  }
  /*Rx=_MapRotation[15].x;
    Ry=_MapRotation[15].y;
    Rz=_MapRotation[15].z;*/

  if (ItT==_MapTranslation.end())
  {
    ItT--;
    Tx=ItT->second.x;
    Ty=ItT->second.y;
    Tz=ItT->second.z;
    if (!fin)
      fin=false;
  }
  else if (ItT==_MapTranslation.begin())
  {
    Tx=ItT->second.x;
    Ty=ItT->second.y;
    Tz=ItT->second.z;
    fin=false;
  }
  else
  {     
    ItT2=ItT;
    ItT--;

    float diviseur=(ItT2->first-ItT->first);
    if (diviseur!=0)
      Avancement=(_Temps-ItT->first)/diviseur;
    else
      Avancement=1;
    Tx=ItT->second.x+(ItT2->second.x-ItT->second.x)*Avancement;
    Ty=ItT->second.y+(ItT2->second.y-ItT->second.y)*Avancement;
    Tz=ItT->second.z+(ItT2->second.z-ItT->second.z)*Avancement;
    fin=false;
  }
  /*Tx=_MapTranslation[0].x;
    Ty=_MapTranslation[0].y;
    Tz=_MapTranslation[0].z;*/
        
  MOGL_MatriceTransformation MatRot,MatTrans;
  _Noeud->ReinitialiserPosition();
        

  MatRot=MOGL_MatriceTransformation::FabriqueRotation(Rx,Ry,Rz);
  //MatRot.Inverser();
  MatTrans=MOGL_MatriceTransformation::FabriqueTranslation(Tx,Ty,Tz);
  _Noeud->AjouteTransformation(MatRot);
  _Noeud->AjouteTransformation(MatTrans);       
  //_Noeud->AjouterTranslation(Tx,Ty,Tz);       

  return !fin;
}

float MOGL_Animation::InterpolerAngle(float p_AngleDeb,float p_AngleFin, float p_Avancement)
{
  if (fabs(p_AngleFin-p_AngleDeb)<180)
  {
        return p_AngleDeb+(p_AngleFin-p_AngleDeb)*p_Avancement;
  }
  else
  {
        if (p_Avancement<0.5)
        {
          float fin=(180+180-fabs(p_AngleFin))*Signe(p_AngleDeb);
          return p_AngleDeb+(fin-p_AngleDeb)*p_Avancement;
        }
        else
        {
          float debut=(180+180-fabs(p_AngleDeb))*Signe(p_AngleFin);
          return debut+(p_AngleFin-debut)*(p_Avancement);
        }
  }
}

int MOGL_Animation::Signe(float p_Nombre)
{
  if (fabs(p_Nombre)==p_Nombre)
        return 1;
  else
        return -1;
}
