#include "MLRHeaders.hpp"

//#############################################################################
//###########################    MLRCenterPointLight    #############################
//#############################################################################

MLRCenterPointLight::ClassData*
	MLRCenterPointLight::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::InitializeClass()
{
	Verify(!DefaultData);
	Verify(gos_GetCurrentHeap() == StaticHeap);
	DefaultData =
		new ClassData(
			MLRCenterPointLightClassID,
			"MidLevelRenderer::MLRCenterPointLight",
			MLRInfiniteLightWithFalloff::DefaultData
		);
	Register_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::TerminateClass()
{
	Unregister_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRCenterPointLight::MLRCenterPointLight() :
	MLRInfiniteLightWithFalloff(DefaultData)
{
	Verify(gos_GetCurrentHeap() == LightsHeap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRCenterPointLight::MLRCenterPointLight(
	Stuff::MemoryStream *stream,
	int version
) :
	MLRInfiniteLightWithFalloff(DefaultData, stream, version)
{
	Check_Object(stream);
	Verify(gos_GetCurrentHeap() == LightsHeap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRCenterPointLight::MLRCenterPointLight(Stuff::Page *page):
	MLRInfiniteLightWithFalloff(DefaultData, page)
{
	Check_Object(page);
	Verify(gos_GetCurrentHeap() == LightsHeap);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
MLRCenterPointLight::~MLRCenterPointLight()
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::Save(Stuff::MemoryStream *stream)
{
	Check_Object(this);
	Check_Object(stream);

	MLRInfiniteLightWithFalloff::Save(stream);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::Write(Stuff::Page *page)
{
	Check_Object(this);
	Check_Object(page);

	MLRInfiniteLightWithFalloff::Write(page);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::SetLightToShapeMatrix(const LinearMatrix4D& worldToShape)
{
	Check_Object(this);

	MLRLight::SetLightToShapeMatrix(worldToShape);

	Point3D vertex_to_light;
	GetInShapePosition(vertex_to_light);

	Scalar lightToShapeDistance = vertex_to_light.GetApproximateLength();
	
	falloff = 1.0f;
	if(!GetFalloff(lightToShapeDistance, falloff))
	{
		falloff = -1.0f;
	}
	else
	{
		falloff *= intensity;
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::TestInstance()
{
	Verify(IsDerivedFrom(DefaultData));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::LightVertex(const MLRVertexData& vertexData)
{
	UnitVector3D light_z;
	RGBColor light_color(color);

	//
	//--------------------------------------------------------------
	// If the distance to the vertex is zero, the light will not
	// contribute to the vertex coloration.  Otherwise, decrease the
	// light level as appropriate to the distance
	//--------------------------------------------------------------
	//
	if(falloff<0.0f)
	{
		return;
	}
	else
	{
		light_color.red *= falloff;
		light_color.green *= falloff;
		light_color.blue *= falloff;
	}

	Stuff::RGBAColor *t = const_cast<Stuff::RGBAColor*>(vertexData.color);
	Check_Pointer(t);
	t->red += light_color.red;
	t->green += light_color.green;
	t->blue += light_color.blue;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	MLRCenterPointLight::LightCenter(RGBAColor& rcol)
{
	UnitVector3D light_z;
	RGBColor light_color(color);

	//
	//--------------------------------------------------------------
	// If the distance to the vertex is zero, the light will not
	// contribute to the vertex coloration.  Otherwise, decrease the
	// light level as appropriate to the distance
	//--------------------------------------------------------------
	//
	if(falloff<0.0f)
	{
		return;
	}
	else
	{
		light_color.red *= falloff;
		light_color.green *= falloff;
		light_color.blue *= falloff;
	}

	rcol.red += light_color.red;
	rcol.green += light_color.green;
	rcol.blue += light_color.blue;
}

