/*
*	math_lib.h
*
*	Programmé par Hillaire Sébastien
*
*
*	- utilité :
*		Structure permettant de représenter un vecteur à trois composante, un plan ou encor une
*	matrice 4x4.
*
*	- version :
*		1.0
*
*	- update :
*		04/09/2004 : - paramètre des méthode mis en référence
*					 - structure 'sphère' ajouté avec méthode d'intersection
*		27/06/2004 : première version
*		05/07/2004 : diverse modification et ajout de fonction dans plane.
*
*	- NOTE :
*			Les angles utilisé sont en radiant
*			structure avec fonctions inline pour performance :-))
*		=>donc pas de .cpp associé.
*
*/

#ifndef VECTOR3
#define VECTOR3


#include <iostream>
#include "math.h"

#include "MemoryManager/DebugNew.h"


struct vector3;
struct plane;
struct sphere;
struct matrix44;


//valeur
#define PI 3.14159265358979323846f
#define DEG2RAD (PI / 180.0f)
#define RAD2DEG (180.0f / PI)



//////////////////////////////////////////////////////////////////
//////////// FUNCTIONS ///////////////////////////////////////////
//////////////////////////////////////////////////////////////////

inline float ABS(float x)
{
	if(x<0)
		return -x;

	return x;
}


//////////////////////////////////////////////////////////////////
//////////// VECTOR3 /////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

struct vector3
{
	/************
	* Attributs *
	************/

	/**
	* coordonnée x du vecteur
	*/
	float x;
	/**
	* coordonnée y du vecteur
	*/
	float y;
	/**
	* coordonnée z du vecteur
	*/
	float z;


	vector3()
	{
		x=y=z=0;
	}


	vector3(float _x,float _y,float _z)
	{
		x=_x;
		y=_y;
		z=_z;
	}


	vector3(const vector3 &v)
	{
		x = v.x;
		y = v.y;
		z = v.z;
	}


	/***********
	* Méthodes *
	***********/

	/**
	* Renvoie la valeur du produit scalaire entre ce vecteur et celui passé en paramètre.
	*
	* @param v le pointeur sur le vecteur qui servira au produit scalair
	*/
	inline float dot( const vector3* v )
	{
		return ( v->x*x + v->y*y + v->z*z );
	}

	/**
	* Le vecteur prend la valeur du produit vectoriel entre le deux vecteur passé en paramètre.
	* v^w dans cette ordre
	*
	* @param v le pointeur sur le vecteur x de la base
	* @param w le pointeur sur le vecteur y de la base
	*/
	inline void cross( const vector3* v, const vector3* w )
	{
		x = v->y*w->z - v->z*w->y;
		y = v->z*w->x - v->x*w->z;
		z = v->x*w->y - v->y*w->x;
	}

	/**
	* Renvoie la longueur du vecteur.
	*/
	inline float length()
	{
		return( sqrt( x*x + y*y + z*z ) );
	}

	/**
	* Normalisation du vecteur.
	*/
	inline void normalize()
	{
		float l = length();

	/*	!!! sécurité non utilisé pour performance :-)) !!!
		if ( l == 0.0f )
		{
			std::cout << "division par 0....\n";
			exit(1);
		}*/

		x /= l;
		y /= l;
		z /= l;

	}
	
	/**
	* Ecrit le vector sur la sortie standard.
	*/
	inline void cout()
	{
		std::cout<< '(' << x << ',' << y << ',' << z <<')';
	}

	/**
	* opére une rotation autour de l'axe X
	*
	* @param a l'angle de rotation en radiant
	*/
	inline void rotate_x(float a)
	{
		float _cos = cos((float)a);
		float _sin = sin((float)a);
		float tmp;

		tmp=y;
		tmp=y*_cos-z*_sin;
		z=y*_sin+z*_cos;
		y=tmp;
	}

	/**
	* opére une rotation autour de l'axe Y
	*
	* @param a l'angle de rotation en radiant
	*/
	inline void rotate_y(float a)
	{
		float _cos = cos((float)a);
		float _sin = sin((float)a);
		float tmp;

		tmp=z;
		tmp=z*_cos-x*_sin;
		x=z*_sin+x*_cos;
		z=tmp;
	}

	/**
	* opére une rotation autour de l'axe Z
	*
	* @param a l'angle de rotation en radiant
	*/
	inline void rotate_z(float a)
	{
		float _cos = cos((float)a);
		float _sin = sin((float)a);
		float tmp;

		tmp=x;
		tmp=x*_cos-y*_sin;
		y=x*_sin+y*_cos;
		x=tmp;
	}

	/**
	* Affecte les différente composante du vector
	*
	* @param _x la nouvelle valeur de la composante x
	* @param _y la nouvelle valeur de la composante y
	* @param _z la nouvelle valeur de la composante z
	*/
	inline void setValues(float _x, float _y, float _z)
	{
		x = _x;
		y = _y;
		z = _z;
	}

	/*********************
	* Opérateur surchargé*
	*********************/

	inline void operator= ( const vector3* v )
	{
		x = v->x;
		y = v->y;
		z = v->z;
	}
	inline void operator= ( const vector3& v )
	{
		x = v.x;
		y = v.y;
		z = v.z;
	}

	inline vector3 operator+ ( const vector3* v )
	{
		vector3 vtmp;
		vtmp.x = x + v->x;
		vtmp.y = y + v->y;
		vtmp.z = z + v->z;
		return vtmp;
	}
	inline vector3 operator+ ( const vector3& v )
	{
		vector3 vtmp;
		vtmp.x = x + v.x;
		vtmp.y = y + v.y;
		vtmp.z = z + v.z;
		return vtmp;
	}

	inline vector3 operator- ( const vector3* v )
	{
		vector3 vtmp;
		vtmp.x = x - v->x;
		vtmp.y = y - v->y;
		vtmp.z = z - v->z;
		return vtmp;
	}
	inline vector3 operator- ( const vector3& v )
	{
		vector3 vtmp;
		vtmp.x = x - v.x;
		vtmp.y = y - v.y;
		vtmp.z = z - v.z;
		return vtmp;
	}

	inline vector3 operator* ( const vector3* v )
	{
		vector3 vtmp;
		vtmp.x = x * v->x;
		vtmp.y = y * v->y;
		vtmp.z = z * v->z;
		return vtmp;
	}
	inline vector3 operator* ( const vector3& v )
	{
		vector3 vtmp;
		vtmp.x = x * v.x;
		vtmp.y = y * v.y;
		vtmp.z = z * v.z;
		return vtmp;
	}

	inline vector3 operator/ ( const vector3* v )
	{
		vector3 vtmp;
		vtmp.x = x / v->x;
		vtmp.y = y / v->y;
		vtmp.z = z / v->z;
		return vtmp;
	}
	inline vector3 operator/ ( const vector3& v )
	{
		vector3 vtmp;
		vtmp.x = x / v.x;
		vtmp.y = y / v.y;
		vtmp.z = z / v.z;
		return vtmp;
	}

	inline vector3 operator* ( const float* scale )
	{
		vector3 vtmp;
		vtmp.x = x * (*scale);
		vtmp.y = y * (*scale);
		vtmp.z = z * (*scale);
		return vtmp;
	}
	inline vector3 operator* ( const float& scale )
	{
		vector3 vtmp;
		vtmp.x = x * scale;
		vtmp.y = y * scale;
		vtmp.z = z * scale;
		return vtmp;
	}

	inline float& operator[] (const int& i)
	{
		return( *((&x)+i) );
	};

	inline const float& operator[] (const int& i) const
	{
		return( *((&x)+i) );
	};

	inline bool operator== ( const vector3* v )
	{
		if ( x != v->x )
		{
			return false;
		}
		if ( y != v->y )
		{
			return false;
		}
		if ( z != v->z )
		{
			return false;
		}
		return true;
	}
	inline bool operator== ( const vector3& v )
	{
		if ( x != v.x )
		{
			return false;
		}
		if ( y != v.y )
		{
			return false;
		}
		if ( z != v.z )
		{
			return false;
		}
		return true;
	}

	inline bool operator!= ( const vector3* v )
	{
		if ( x != v->x )
		{
			return true;
		}
		if ( y != v->y )
		{
			return true;
		}
		if ( z != v->z )
		{
			return true;
		}
		return false;
	}
	inline bool operator!= ( const vector3& v )
	{
		if ( x != v.x )
		{
			return true;
		}
		if ( y != v.y )
		{
			return true;
		}
		if ( z != v.z )
		{
			return true;
		}
		return false;
	}

};



//////////////////////////////////////////////////////////////////
//////////// PLANE ///////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

struct plane
{
	/************
	* Attributs *
	************/

	/**
	* la coordonnée de la normal
	*/
	vector3 n;

	/**
	* composante 'd' de l'équation du plan
	*/
	float d;


	plane()
	{
		n[0]=0;
		n[1]=0;
		n[2]=1;
		d=0;
	}


	plane(const plane& p)
	{
		n[0]=p.n[0];
		n[1]=p.n[1];
		n[2]=p.n[2];
		d=p.d;
	}


	/***********
	* Méthodes *
	***********/

	/**
	* créer l'équation du plan à partie de deux vecteur et d'un point dans l'espace
	*
	* @pre v1 et v2 ne doivent pas être parallèle
	*
	* @param v1 le pointeur sur le premier vecteur contenue dans le plan(x)
	* @param v2 le pointeur sur le premier vecteur contenue dans le plan(y)
	*/
	inline void create(vector3 *v1, vector3 *v2, vector3 *p)
	{
		//calcul et normalisation de la normal du plan
		n.cross(v2,v1);	//ordre v2,v1 pour repere orienté main droite
		n.normalize();

		//on calcul d pour le point par lequel le plan passe
		d = -( (*p)[0]*n[0]+(*p)[1]*n[1]+(*p)[2]*n[2] );
	}

	/**
	* calcul la distance entre le plan et le point
	*
	* TODO méthode non vérifier dans gros cas
	* Pour developeur : ne devrait t'on pas utilisé sqrt(dotp)
	*
	* @param p le pointeur sur la position du point
	*/
	inline float distanceFromPointToPlane(vector3 *p)
	{
		float dotp = p->dot(&n);	//la distance de l'origine au projeté du point sur la normal

		return ABS(-dotp-d);		//valeur absolue
	}

	/**
	* projete un point sur le plan.
	*
	* @param p le pointeur sur la position du point
	* @param dest le pointeur sur la position du point projeté calculé
	*/
	inline void projectOnPlane(vector3 *p, vector3 *dest)
	{
		float dotp = p->dot(&n);	//la distance de l'origine au projeté du point sur la normal

		(*dest)[0] = (*p)[0] - dotp*n[0] - d*n[0];
		(*dest)[1] = (*p)[1] - dotp*n[1] - d*n[1];
		(*dest)[2] = (*p)[2] - dotp*n[2] - d*n[2];
	}

	/**
	* projete un point sur ce plan passant par l'origine.
	* On ignore donc la valeur de d
	*
	* @param p le pointeur sur la position du point
	* @param dest le pointeur sur la position du point projeté calculé
	*/
	inline void projectOnPlane_origin(vector3 *p, vector3 *dest)
	{
		float dotp = p->dot(&n);	//la distance de l'origine au projeté du point sur la normal

		(*dest)[0] = (*p)[0] - dotp*n[0];
		(*dest)[1] = (*p)[1] - dotp*n[1];
		(*dest)[2] = (*p)[2] - dotp*n[2];
	}

	/**
	*	calcul la distance du point d'intersection entre ce plan et le point passant par une droite 
	* (définie par un point et une direction)
	*
	* @param origin un point passant pas la droite
	* @param direction la direction de la droite
	* @param dest le pointeur sur la position du point calculé
	* @return la distance
	*/
	inline float intersect_value(vector3 *origin, vector3 *direction, vector3 *dest)
	{
		float numer = n.dot(origin) + d;
		float denom = n.dot(direction);
		return (numer/denom);	//TODO : pas de test si denom==0(paralléle au plan)
	}

	/**
	* calcul le point d'intersection entre ce plan et une droite (définie par un point et une direction)
	*
	* @param origin un point passant pas la droite
	* @param direction la direction de la droite
	* @param dest le pointeur sur la position du point calculé
	*/
	inline void intersect(vector3 *origin, vector3 *direction, vector3 *dest)
	{
		float numer = n.dot(origin) + d;
		float denom = n.dot(direction);
		*dest = *origin - (*direction)*(numer/denom);	//TODO : pas de test si denom==0(paralléle au plan)
	}
	
	/**
	* Ecrit le plan sur la sortie standard.
	*/
	inline void cout()
	{
		std::cout<< '(' << n[0] << ',' << n[1] << ',' << n[2] << ',' << d <<')';
	}

	/*********************
	* Opérateur surchargé*
	*********************/

	inline void operator= ( const plane* p )
	{
		n = p->n;
		d = p->d;
	}
	inline void operator= ( const plane& p )
	{
		n = p.n;
		d = p.d;
	}

	inline bool operator== ( const plane* p )
	{
		if ( n != p->n )
		{
			return false;
		}
		if ( d != p->d )
		{
			return false;
		}
		return true;
	}
	inline bool operator== ( const plane& p )
	{
		if ( n != p.n )
		{
			return false;
		}
		if ( d != p.d )
		{
			return false;
		}
		return true;
	}

	inline bool operator!= ( const plane* p )
	{
		if ( n != p->n )
		{
			return true;
		}
		if ( d != p->d )
		{
			return true;
		}
		return false;
	}
	inline bool operator!= ( const plane& p )
	{
		if ( n != p.n )
		{
			return true;
		}
		if ( d != p.d )
		{
			return true;
		}
		return false;
	}

};



////////////////////////////////////////////////////////////////
//////////// SPHERE ////////////////////////////////////////////
////////////////////////////////////////////////////////////////

struct sphere
{
	/************
	* Attributs *
	************/

	/**
	* le centre de la sphère
	*/
	vector3 center;
	/**
	* le rayon de la sphere
	*/
	float radius;


	/***********
	* Méthodes *
	***********/

	sphere()
	{
		//par défaut, on charge la matrice identité
		center.setValues(0,0,0);
		radius = 1.0f;
	}

	sphere(const sphere &s)
	{
		center = s.center;
		radius = s.radius;
	}

	
	///// UTILE /////

	/**
	*	Calcul le point d'intersection entre une droite et la sphère. Le point est le plus
	* proche sur la sphere sur la droite suivant la 'direction' du vecteur directeur orientation
	* de cette droite.
	*
	* @param rO le pointeur sur la position d'un point par lequel passe la droite
	* @param rV le pointeur sur la direction de la droite
	*
	* @return rien, mais dest prend la valeur (0,0,0) si pas de point d'intersection...attention avec sa!
	*/
	inline void intersectSphere(vector3 *dO, vector3 *dV, vector3 *dest)
	{
		vector3 Q = center - (*dO);
		float c = Q.length();
		float v = Q.dot(dV);
		float d = radius*radius - ( c*c - v*v );

		if(d<0.0f)
		{
			dest->setValues(0,0,0);
		}

		*dest = (*dO) + (*dV)*(v - sqrt(d));
	}

	/**
	*	Calcul la distance entre le point d'intersection d'une sphere et d'une droite.
	* Le point est le plus proche sur la sphere sur la droite suivant la 'direction' du vecteur
	* directeur orientation de cette droite.
	* 
	*
	* @param rO le pointeur sur la position d'un point par lequel passe la droite
	* @param rV le pointeur sur la direction de la droite
	* @return La distance entre le point d'intersection et le point par lequel passe la droite. -1 si par de point d'intersection.
	*/
	inline float intersectSphere_value(vector3 *dO, vector3 *dV)
	{
		vector3 Q = center - (*dO);
		float c = Q.length();
		float v = Q.dot(dV);
		float d = radius*radius - ( c*c - v*v );

		if(d<0.0f)
		{
			return -1.0f;
		}

		return (v - sqrt(d));
	}

	/*********************
	* Opérateur surchargé*
	*********************/

	inline void operator= ( const sphere* p )
	{
		center = p->center;
		radius = p->radius;
	}
	inline void operator= ( const sphere& p )
	{
		center = p.center;
		radius = p.radius;
	}

	inline bool operator== ( const sphere* p )
	{
		if ( center != p->center )
		{
			return false;
		}
		if ( radius != p->radius )
		{
			return false;
		}
		return true;
	}
	inline bool operator== ( const sphere& p )
	{
		if ( center != p.center )
		{
			return false;
		}
		if ( radius != p.radius )
		{
			return false;
		}
		return true;
	}

	inline bool operator!= ( const sphere* p )
	{
		if ( center != p->center )
		{
			return true;
		}
		if ( radius != p->radius )
		{
			return true;
		}
		return false;
	}
	inline bool operator!= ( const sphere& p )
	{
		if ( center != p.center )
		{
			return true;
		}
		if ( radius != p.radius )
		{
			return true;
		}
		return false;
	}

};



//////////////////////////////////////////////////////////////////
//////////// MATRIX44 ////////////////////////////////////////////
//////////////////////////////////////////////////////////////////

struct matrix44
{
	/************
	* Attributs *
	************/

	/**
	* la matrice
	*/
	float mat[16];


	/***********
	* Méthodes *
	***********/

	matrix44()
	{
		//par défaut, on charge la matrice identité
		this->identity();
	}

	
	///// UTILE /////

	/**
	* charge la matrice null
	*/
	inline void zero() 
	{
		mat[0] = 0.0; mat[4] = 0.0; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = 0.0; mat[9] = 0.0; mat[13] = 0.0;
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = 0.0; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 0.0;
	}

	/**
	* charge la matrice identité
	*/
	inline void identity() 
	{
		mat[0] = 1.0; mat[4] = 0.0; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = 1.0; mat[9] = 0.0; mat[13] = 0.0;
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = 1.0; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}
	
	/**
	* transposition de la matrice
	*/
	inline void transpose() 
	{
		float ret[16];
		ret[0] = mat[0]; ret[4] = mat[1]; ret[8] = mat[2]; ret[12] = mat[3];
		ret[1] = mat[4]; ret[5] = mat[5]; ret[9] = mat[6]; ret[13] = mat[7];
		ret[2] = mat[8]; ret[6] = mat[9]; ret[10] = mat[10]; ret[14] = mat[11];
		ret[3] = mat[12]; ret[7] = mat[13]; ret[11] = mat[14]; ret[15] = mat[15];
		memcpy(ret,mat,sizeof(float)*16);
	}

	/**
	* calcul de la matrice inverse
	*/
	inline void inverse() 
	{
		float ret[16];
		float det;
		det = mat[0] * mat[5] * mat[10];
		det += mat[4] * mat[9] * mat[2];
		det += mat[8] * mat[1] * mat[6];
		det -= mat[8] * mat[5] * mat[2];
		det -= mat[4] * mat[1] * mat[10];
		det -= mat[0] * mat[9] * mat[6];
		det = 1.0f / det;				//pas de sécurité pour division pas zéro...
		ret[0] =  (mat[5] * mat[10] - mat[9] * mat[6]) * det;
		ret[1] = -(mat[1] * mat[10] - mat[9] * mat[2]) * det;
		ret[2] =  (mat[1] * mat[6] - mat[5] * mat[2]) * det;
		ret[3] = 0.0;
		ret[4] = -(mat[4] * mat[10] - mat[8] * mat[6]) * det;
		ret[5] =  (mat[0] * mat[10] - mat[8] * mat[2]) * det;
		ret[6] = -(mat[0] * mat[6] - mat[4] * mat[2]) * det;
		ret[7] = 0.0;
		ret[8] =  (mat[4] * mat[9] - mat[8] * mat[5]) * det;
		ret[9] = -(mat[0] * mat[9] - mat[8] * mat[1]) * det;
		ret[10] =  (mat[0] * mat[5] - mat[4] * mat[1]) * det;
		ret[11] = 0.0;
		ret[12] = -(mat[12] * ret[0] + mat[13] * ret[4] + mat[14] * ret[8]);
		ret[13] = -(mat[12] * ret[1] + mat[13] * ret[5] + mat[14] * ret[9]);
		ret[14] = -(mat[12] * ret[2] + mat[13] * ret[6] + mat[14] * ret[10]);
		ret[15] = 1.0;
		memcpy(ret,mat,sizeof(float)*16);
	}

	///// ROTATION /////

	/**
	* créer un matrice de rotation autour de l'axe X
	*
	* @param rad l'angle de rotation en radian
	*/
	inline void rotation_x(float rad) 
	{
		float c = cos(rad);
		float s = sin(rad);
		mat[0] = 1.0; mat[4] = 0.0; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = c; mat[9] = -s; mat[13] = 0.0;
		mat[2] = 0.0; mat[6] = s; mat[10] = c; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}

	/**
	* créer un matrice de rotation autour de l'axe Y
	*
	* @param rad l'angle de rotation en radian
	*/
	inline void rotation_y(float rad) 
	{
		float c = cos(rad);
		float s = sin(rad);
		mat[0] = c; mat[4] = 0.0; mat[8] = s; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = 1.0; mat[9] = 0.0; mat[13] = 0.0;
		mat[2] = -s; mat[6] = 0.0; mat[10] = c; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}

	/**
	* créer un matrice de rotation autour de l'axe Z
	*
	* @param rad l'angle de rotation en radian
	*/
	inline void rotation_z(float rad) 
	{
		float c = cos(rad);
		float s = sin(rad);
		mat[0] = c; mat[4] = -s; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = s; mat[5] = c; mat[9] = 0.0; mat[13] = 0.0;
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = 1.0; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}

	///// TRANSLATE /////

	/**
	* créer une matrice de translation
	*
	* @param v le pointeur sur le vecteur de translation
	*/
	inline void translate(const vector3 *v) 
	{
		mat[0] = 1.0; mat[4] = 0.0; mat[8] = 0.0; mat[12] = (*v)[0];
		mat[1] = 0.0; mat[5] = 1.0; mat[9] = 0.0; mat[13] = (*v)[1];
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = 1.0; mat[14] = (*v)[2];
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}

	///// SCALE /////

	/**
	* créer une matrice de translation
	*
	* @param v le pointeur sur le vecteur de mise à l'echelle
	*/
	inline void scale(const vector3 *v) 
	{
		mat[0] = (*v)[0]; mat[4] = 0.0; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = (*v)[1]; mat[9] = 0.0; mat[13] = 0.0;
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = (*v)[2]; mat[14] = 0.0;
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = 0.0; mat[15] = 1.0;
	}

	///// PERSPECTIVE /////

	/**
	* créer une matrice de projection perspective pour OpenGL
	*
	* @param fov l'angle de vision
	* @param aspect le rapport largeur/hauteur
	* @param znear la distance du plan de clipping proche
	* @param zfar la distance du plan de clipping éloigné
	*/
	inline void perspective(float fov,float aspect,float znear,float zfar) 
	{
		float y = tan(fov * PI / 360.0f);
		float x = y * aspect;
		mat[0] = 1.0f / x; mat[4] = 0.0; mat[8] = 0.0; mat[12] = 0.0;
		mat[1] = 0.0; mat[5] = 1.0f / y; mat[9] = 0.0; mat[13] = 0.0;
		//pas de protection pour la dicision pas zéro...
		mat[2] = 0.0; mat[6] = 0.0; mat[10] = -(zfar + znear) / (zfar - znear); mat[14] = -(2.0f * zfar * znear) / (zfar - znear);
		mat[3] = 0.0; mat[7] = 0.0; mat[11] = -1.0; mat[15] = 0.0;
	}

	/*********************
	* Opérateur surchargé*
	*********************/

	inline void operator= ( const matrix44* _mat )
	{
		const float *m = _mat->mat;
		mat[0] = m[0]; mat[4] = m[4]; mat[8] = m[8]; mat[12] = m[12];
		mat[1] = m[1]; mat[5] = m[5]; mat[9] = m[9]; mat[13] = m[13];
		mat[2] = m[2]; mat[6] = m[6]; mat[10] = m[10]; mat[14] = m[14];
		mat[3] = m[3]; mat[7] = m[7]; mat[11] = m[11]; mat[15] = m[15];

	}
	inline void operator= ( const matrix44& _mat )
	{
		const float *m = _mat.mat;
		mat[0] = m[0]; mat[4] = m[4]; mat[8] = m[8]; mat[12] = m[12];
		mat[1] = m[1]; mat[5] = m[5]; mat[9] = m[9]; mat[13] = m[13];
		mat[2] = m[2]; mat[6] = m[6]; mat[10] = m[10]; mat[14] = m[14];
		mat[3] = m[3]; mat[7] = m[7]; mat[11] = m[11]; mat[15] = m[15];
	}
	
	inline matrix44 operator* ( const matrix44 *_mat )
	{
		const float *m = _mat->mat;
		matrix44 ret;
		float *rm = ret.mat;
		rm[0] = mat[0] * m[0] + mat[4] * m[1] + mat[8] * m[2] + mat[12] * m[3];
		rm[1] = mat[1] * m[0] + mat[5] * m[1] + mat[9] * m[2] + mat[13] * m[3];
		rm[2] = mat[2] * m[0] + mat[6] * m[1] + mat[10] * m[2] + mat[14] * m[3];
		rm[3] = mat[3] * m[0] + mat[7] * m[1] + mat[11] * m[2] + mat[15] * m[3];
		rm[4] = mat[0] * m[4] + mat[4] * m[5] + mat[8] * m[6] + mat[12] * m[7];
		rm[5] = mat[1] * m[4] + mat[5] * m[5] + mat[9] * m[6] + mat[13] * m[7];
		rm[6] = mat[2] * m[4] + mat[6] * m[5] + mat[10] * m[6] + mat[14] * m[7];
		rm[7] = mat[3] * m[4] + mat[7] * m[5] + mat[11] * m[6] + mat[15] * m[7];
		rm[8] = mat[0] * m[8] + mat[4] * m[9] + mat[8] * m[10] + mat[12] * m[11];
		rm[9] = mat[1] * m[8] + mat[5] * m[9] + mat[9] * m[10] + mat[13] * m[11];
		rm[10] = mat[2] * m[8] + mat[6] * m[9] + mat[10] * m[10] + mat[14] * m[11];
		rm[11] = mat[3] * m[8] + mat[7] * m[9] + mat[11] * m[10] + mat[15] * m[11];
		rm[12] = mat[0] * m[12] + mat[4] * m[13] + mat[8] * m[14] + mat[12] * m[15];
		rm[13] = mat[1] * m[12] + mat[5] * m[13] + mat[9] * m[14] + mat[13] * m[15];
		rm[14] = mat[2] * m[12] + mat[6] * m[13] + mat[10] * m[14] + mat[14] * m[15];
		rm[15] = mat[3] * m[12] + mat[7] * m[13] + mat[11] * m[14] + mat[15] * m[15];
		return ret;
	}
	inline matrix44 operator* ( const matrix44& _mat )
	{
		const float *m = _mat.mat;
		matrix44 ret;
		float *rm = ret.mat;
		rm[0] = mat[0] * m[0] + mat[4] * m[1] + mat[8] * m[2] + mat[12] * m[3];
		rm[1] = mat[1] * m[0] + mat[5] * m[1] + mat[9] * m[2] + mat[13] * m[3];
		rm[2] = mat[2] * m[0] + mat[6] * m[1] + mat[10] * m[2] + mat[14] * m[3];
		rm[3] = mat[3] * m[0] + mat[7] * m[1] + mat[11] * m[2] + mat[15] * m[3];
		rm[4] = mat[0] * m[4] + mat[4] * m[5] + mat[8] * m[6] + mat[12] * m[7];
		rm[5] = mat[1] * m[4] + mat[5] * m[5] + mat[9] * m[6] + mat[13] * m[7];
		rm[6] = mat[2] * m[4] + mat[6] * m[5] + mat[10] * m[6] + mat[14] * m[7];
		rm[7] = mat[3] * m[4] + mat[7] * m[5] + mat[11] * m[6] + mat[15] * m[7];
		rm[8] = mat[0] * m[8] + mat[4] * m[9] + mat[8] * m[10] + mat[12] * m[11];
		rm[9] = mat[1] * m[8] + mat[5] * m[9] + mat[9] * m[10] + mat[13] * m[11];
		rm[10] = mat[2] * m[8] + mat[6] * m[9] + mat[10] * m[10] + mat[14] * m[11];
		rm[11] = mat[3] * m[8] + mat[7] * m[9] + mat[11] * m[10] + mat[15] * m[11];
		rm[12] = mat[0] * m[12] + mat[4] * m[13] + mat[8] * m[14] + mat[12] * m[15];
		rm[13] = mat[1] * m[12] + mat[5] * m[13] + mat[9] * m[14] + mat[13] * m[15];
		rm[14] = mat[2] * m[12] + mat[6] * m[13] + mat[10] * m[14] + mat[14] * m[15];
		rm[15] = mat[3] * m[12] + mat[7] * m[13] + mat[11] * m[14] + mat[15] * m[15];
		return ret;
	}
	
	inline matrix44 operator+ ( const matrix44 *_mat )
	{
		matrix44 ret;
		const float *m = _mat->mat;
		float *rm = ret.mat;
		rm[0] = mat[0] + m[0]; rm[4] = mat[4] + m[4]; rm[8] = mat[8] + m[8]; rm[12] = mat[12] + m[12];
		rm[1] = mat[1] + m[1]; rm[5] = mat[5] + m[5]; rm[9] = mat[9] + m[9]; rm[13] = mat[13] + m[13];
		rm[2] = mat[2] + m[2]; rm[6] = mat[6] + m[6]; rm[10] = mat[10] + m[10]; rm[14] = mat[14] + m[14];
		rm[3] = mat[3] + m[3]; rm[7] = mat[7] + m[7]; rm[11] = mat[11] + m[11]; rm[15] = mat[15] + m[15];
		return ret;
	}
	inline matrix44 operator+ ( const matrix44& _mat )
	{
		matrix44 ret;
		const float *m = _mat.mat;
		float *rm = ret.mat;
		rm[0] = mat[0] + m[0]; rm[4] = mat[4] + m[4]; rm[8] = mat[8] + m[8]; rm[12] = mat[12] + m[12];
		rm[1] = mat[1] + m[1]; rm[5] = mat[5] + m[5]; rm[9] = mat[9] + m[9]; rm[13] = mat[13] + m[13];
		rm[2] = mat[2] + m[2]; rm[6] = mat[6] + m[6]; rm[10] = mat[10] + m[10]; rm[14] = mat[14] + m[14];
		rm[3] = mat[3] + m[3]; rm[7] = mat[7] + m[7]; rm[11] = mat[11] + m[11]; rm[15] = mat[15] + m[15];
		return ret;
	}

	inline matrix44 operator- ( const matrix44 *_mat )
	{
		matrix44 ret;
		const float *m = _mat->mat;
		float *rm = ret.mat;
		rm[0] = mat[0] - m[0]; rm[4] = mat[4] - m[4]; rm[8] = mat[8] - m[8]; rm[12] = mat[12] - m[12];
		rm[1] = mat[1] - m[1]; rm[5] = mat[5] - m[5]; rm[9] = mat[9] - m[9]; rm[13] = mat[13] - m[13];
		rm[2] = mat[2] - m[2]; rm[6] = mat[6] - m[6]; rm[10] = mat[10] - m[10]; rm[14] = mat[14] - m[14];
		rm[3] = mat[3] - m[3]; rm[7] = mat[7] - m[7]; rm[11] = mat[11] - m[11]; rm[15] = mat[15] - m[15];
		return ret;
	}
	inline matrix44 operator- ( const matrix44& _mat )
	{
		matrix44 ret;
		const float *m = _mat.mat;
		float *rm = ret.mat;
		rm[0] = mat[0] - m[0]; rm[4] = mat[4] - m[4]; rm[8] = mat[8] - m[8]; rm[12] = mat[12] - m[12];
		rm[1] = mat[1] - m[1]; rm[5] = mat[5] - m[5]; rm[9] = mat[9] - m[9]; rm[13] = mat[13] - m[13];
		rm[2] = mat[2] - m[2]; rm[6] = mat[6] - m[6]; rm[10] = mat[10] - m[10]; rm[14] = mat[14] - m[14];
		rm[3] = mat[3] - m[3]; rm[7] = mat[7] - m[7]; rm[11] = mat[11] - m[11]; rm[15] = mat[15] - m[15];
		return ret;
	}
};

#include "MemoryManager/DebugNewOff.h"


#endif