#include <cmath>
#include <GL/glut.h>

#include "globale.h"
#include "CVector3.h"
#include "CCamera.h"
#include "Temps.h"


void CCamera::CamLookAt(void)
{
	gluLookAt(Position.x, Position.y, Position.z,
			  Observation.x, Observation.y, Observation.z,
			  gCamera.Haut.x, gCamera.Haut.y, gCamera.Haut.z);
}




type_direction GetDirLookAt(void)
{
	float x = gCamera.Position.x - gCamera.Observation.x;
	float y = gCamera.Position.y - gCamera.Observation.y;

	if (abs(x) < abs(y))
	{
		if (y < 0)
			return AVANT;
		else
			return ARRIERE;
	}
	else
	{
		if (x < 0)
			return DROITE;
		else
			return GAUCHE;
	}
}




// Fonction qui vérifie qe la position de la caméra est valide

inline bool In(const CVector3& Point)
{
	switch (GetDirLookAt())
	{
	case AVANT: if (Point.y - gCamera.Observation.y > 0) return (true); break;
	case DROITE: if (Point.x - gCamera.Observation.x > 0) return (true); break;
	case ARRIERE: if (Point.y - gCamera.Observation.y < 0) return (true); break;
	case GAUCHE: if (Point.x - gCamera.Observation.x < 0) return (true); break;
	}

	return (false);
}





void CCamera::TournePosition(float Angle, const CVector3& Axe)
{
	CVector3 NouvPos;
	CVector3 Temp = Position - Observation;
	
	float LeCos = cos(Angle);
	float LeSin = sin(Angle);

	// Rotation à l'aide de multiplication de matrices

	NouvPos.x  = (LeCos + (1 - LeCos) * Axe.x * Axe.x)			* Temp.x;
	NouvPos.x += ((1 - LeCos) * Axe.x * Axe.y - Axe.z * LeSin)	* Temp.y;
	NouvPos.x += ((1 - LeCos) * Axe.x * Axe.z + Axe.y * LeSin)	* Temp.z;

	NouvPos.y  = ((1 - LeCos) * Axe.x * Axe.y + Axe.z * LeSin)	* Temp.x;
	NouvPos.y += (LeCos + (1 - LeCos) * Axe.y * Axe.y)			* Temp.y;
	NouvPos.y += ((1 - LeCos) * Axe.y * Axe.z - Axe.x * LeSin)	* Temp.z;

	NouvPos.z  = ((1 - LeCos) * Axe.x * Axe.z - Axe.y * LeSin)	* Temp.x;
	NouvPos.z += ((1 - LeCos) * Axe.y * Axe.z + Axe.x * LeSin)	* Temp.y;
	NouvPos.z += (LeCos + (1 - LeCos) * Axe.z * Axe.z)			* Temp.z;


	if (!In(NouvPos + Observation))
		Position = Observation + NouvPos;
}




void CCamera::Avance(float Delta)
{
	CVector3 Direction = Observation - Position;
	CVector3 NouvPos = Position + Direction / Direction.Norm() * Delta *
					   (GetTemps() - gCamera.TempsLastFrame);

	if (!In(NouvPos))
		Position = NouvPos;

	gCamera.TempsLastFrame = GetTemps();
}
