


#include	"..\Scene Graph\ZooLight.h"













///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ZLight Class
///
///		- Classe des lumiéres
///		- Propriétésde couleur des lights (RVB) sur 3 composantes : amibante, diffuse, spéculaire
///		- methode propre de modification des pptés de light (PRS et composantes propres)
///		- texture pour le sprite et méthode d'affichage par display list
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
/// Constructor						      								///
///////////////////////////////////////////////////////////////////////////
ZLight::ZLight(int s3d) : ZNodeGraph(s3d)
{
	type = LGH_TYPE_ID;

	distance = 0.0f;
	
	SetDefaultVals();
	
	attenuate_const = 1.0f;
	attenuate_quadr = 0.0f;
	spot_cut_off	= 180.0f;
	exponent		= 0.0f;
}

ZLight::~ZLight()
{
	ZNodeGraph::~ZNodeGraph();
}





///////////////////////////////////////////////////////////////////////////
/// Put the GL parameters												///
///////////////////////////////////////////////////////////////////////////
void ZLight::PutGLparams(int numberOfThisLight)
{
	glEnable(GL_LIGHT0+numberOfThisLight);
	
	if(oldStyle)
	{
		if(LightType == LIGHT_AMBIENT)
		{
			GLfloat		tmpParam[] = { 0.0f, 0.0f, 0.0f, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, tmpParam);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  tmpParam);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  tmpParam);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, tmpParam);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, 0.0f);
		}
		else if(LightType == LIGHT_PARA)
		{
			GLfloat		tmpParam[] = { 0.0f, 0.0f, 0.0f, 1.0f};

			// Direction de la PARA (suivant Z -> derniere colone de la matrice)
			ZVector4	LightDir;
			LightDir.SetCoord(worldMat._13, worldMat._23, worldMat._33, 0.0f);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightDir.vals);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  tmpParam);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, 0.0f);
		}
		else if(LightType == LIGHT_OMNI)
		{
			float		distSQR = 1.0f / (distance * distance);

			GLfloat		LightPos[] = { worldPos.x, worldPos.y, worldPos.z, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightPos);

			// !! GROS HACK !!
			// pour simuler l'éclairage de SCOL, on utilise la composante diffuse en tant que compo ambiante
			// ceci permet d'obtenir l'éclairage des faces qui ne sont pas éclairées en temps normal (faces de dos à la light)
			ZVector4	LightAmb;
			LightAmb.SetCoord(diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
			LightAmb *= 0.5f;
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  LightAmb.vals);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  distSQR/10000.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, distSQR);
		}
		else if(LightType == LIGHT_SPOT)
		{
			float		distSQR = 1.0f / (distance * distance);

			GLfloat		LightPos[] = { worldPos.x, worldPos.y, worldPos.z, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightPos);

			// !! GROS HACK !!
			// pour simuler l'éclairage de SCOL, on utilise la composante diffuse en tant que compo ambiante
			// ceci permet d'obtenir l'éclairage des faces qui ne sont pas éclairées en temps normal (faces de dos à la light)
			ZVector4	LightAmb;
			LightAmb.SetCoord(diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
			LightAmb *= 0.5f;
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  LightAmb.vals);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			ZVector3	direc;
			direc.SetCoord(-worldMat._13, -worldMat._23, -worldMat._33);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPOT_DIRECTION, direc.vals);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	30.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  distSQR);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, distSQR);
		}
	}
	else	// New STYLE !!
	{
		if(LightType == LIGHT_AMBIENT)
		{
			GLfloat		tmpParam[] = { 0.0f, 0.0f, 0.0f, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, tmpParam);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  ambient);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  tmpParam);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, tmpParam);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, 0.0f);
		}
		else if(LightType == LIGHT_PARA)
		{
			// Direction de la PARA (suivant Z -> derniere colone de la matrice)
			ZVector4	LightDir;
			LightDir.SetCoord(-worldMat._13, -worldMat._23, -worldMat._33, 0.0f);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightDir.vals);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  ambient);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, 0.0f);
		}
		else if(LightType == LIGHT_OMNI)
		{
			GLfloat		LightPos[] = { worldPos.x, worldPos.y, worldPos.z, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightPos);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  ambient);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	180.0f);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  attenuate_const);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, attenuate_quadr);
		}
		else if(LightType == LIGHT_SPOT)
		{
			GLfloat		LightPos[] = { worldPos.x, worldPos.y, worldPos.z, 1.0f};
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_POSITION, LightPos);

			glLightfv(GL_LIGHT0+numberOfThisLight, GL_AMBIENT,  ambient);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_DIFFUSE,  diffuse);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPECULAR, specular);

			ZVector4	direc;
			direc.SetCoord(-worldMat._13, -worldMat._23, -worldMat._33, 0.0f);
			glLightfv(GL_LIGHT0+numberOfThisLight, GL_SPOT_DIRECTION, direc.vals);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_EXPONENT, 1.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_SPOT_CUTOFF,	spot_cut_off);

			glLightf(GL_LIGHT0+numberOfThisLight, GL_CONSTANT_ATTENUATION,  attenuate_const);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_LINEAR_ATTENUATION,	0.0f);
			glLightf(GL_LIGHT0+numberOfThisLight, GL_QUADRATIC_ATTENUATION, attenuate_quadr);
		}
	}
}



