/*****************************************************************************
 *
 *  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
 *
 *****************************************************************************/
#ifndef MOGL_MATRICETRANSFORMATION
#define MOGL_MATRICETRANSFORMATION

#include <cmath>

#ifdef _WIN32
        #include <windows.h>
        #include <windowsx.h>
#endif
#include <GL/gl.h>
#include "MOGL_Structure.h"

/**
   Représente un matrice de transformation 4x4.
 */
class MOGL_MatriceTransformation
{
  private :
    float _DeterminantMat3(float * p_Matrice);
    GLfloat * _Matrice;

  public :
    /**
       Constructeur.
     */
    MOGL_MatriceTransformation();

    /**
       Destructeur.
    */
    ~MOGL_MatriceTransformation();

    /**
       Constructeur par copie.
     */
    MOGL_MatriceTransformation(const MOGL_MatriceTransformation & p_Matrice);

    /**
       Redéfinition de l'opérateur d'égalité. Permet d'accéder directement aux éléments de la matrice.
       @param p_IndiceX : indice en X de l'élement.
       @param p_IndiceY : indice en Y de l'élement.
     */
    GLfloat & operator () (int p_IndiceX,int p_IndiceY);

    /**
       Pemet de lire un élément de la matrice
       @param p_IndiceX : indice en X de l'élement.
       @param p_IndiceY : indice en Y de l'élement.
     */
    GLfloat Lit(int p_IndiceX,int p_IndiceY) const;

    /** 
     * Permet de récupérer la rotation correspondant à la matrice de transformation.
     * 
     * @return Vecteur contenant la rotation selon chaque axe.
     */
    MOGL_Struct_Vecteur GetRotation();

    /**
       Redéfinition de l'opérateur d'affectation.
     */
    MOGL_MatriceTransformation & operator = (const MOGL_MatriceTransformation & p_Matrice);

    /**
       Permet de charger dans OpenGL la matrice. Cette méthode équivaut à glLoadMatrix()
     */
    void ChargerDansOpenGL();

    /**
       Permet de multiplier dans OpenGL la matrice. Cette méthode équivaut à glMultMatrix()
     */
    void MultiplierDansOpenGL();

    /**
       Permet de récupérer depuis OpenGL la matrice. Cette méthode équivaut à glGet()
     */
    void PrendreDeOpenGL();

    /**
       Effectue une multiplication de matrice.
       Il s'agit d'une multiplication à gauche : <i>this=UneMatrice*this</i>
    */
    void Multiplier(const MOGL_MatriceTransformation & UneMatrice);
    /**
       Multiplie la vecteur passé en paramètre avec la matrice de transformation.
    */
    MOGL_Struct_Vecteur MultiplierVecteur(const MOGL_Struct_Vecteur & p_Vecteur) const;

    /**
       Effectue la rotation correspondant à la matrice de transformation sur le vecteur passé en paramètre
    */
    MOGL_Struct_Vecteur EffectuerRotationVecteur(const MOGL_Struct_Vecteur & p_Vecteur) const;
    void Inverser();

    /**
       Permet de récupérer le déterminant de la matrice.
       @return Déterminant de la matrice.
     */
    float Determinant();

    /**
       Permet de réinitialiser la matrice. La matrice est alors égale à la matrice d'identité.
     */
    void Reinitialiser();

    /**
       Permet d'ajouter une translation à la matrice de transformation/
     */
    void AjouterTranslation(GLfloat p_X, GLfloat p_Y, GLfloat p_Z);

    /**
       Permet d'écrire sur la sortie standard ma matrice.
     */
    void Print() const; 

    /**
       Permet de fabriquer une matrice de translation.
       @param p_X : valeur X de la translation.
       @param p_Y : valeur Y de la translation.
       @param p_Z : valeur Z de la translation.
     */
    static MOGL_MatriceTransformation FabriqueTranslation(GLfloat p_X, GLfloat p_Y, GLfloat p_Z);

    /**
       Permet de fabriquer une matrice de Rotation.
       @param p_AngleX : valeur en X de la rotation (en degrés).
       @param p_AngleY : valeur en Y de la rotation (en degrés).
       @param p_AngleZ : valeur en Z de la rotation (en degrés).
     */
    static MOGL_MatriceTransformation FabriqueRotation(GLfloat p_AngleX, GLfloat p_AngleY, GLfloat p_AngleZ);

    /**
       Permet de fabriquer une matrice de translation selon un vecteur quelconque.
       @param p_Vecteur : axe de rotation.
       @param p_Angle : angle de rotation (en degrés)
     */
    static MOGL_MatriceTransformation FabriqueRotation(const MOGL_Struct_Vecteur & p_Vecteur, GLfloat p_Angle);

    /**
       Permet de fabriquer une matrice de changement d'échel.
     */
    static MOGL_MatriceTransformation FabriqueEchelle(GLfloat p_X,GLfloat p_Y, GLfloat p_Z);
};

#endif
