#include "AdeptHeaders.hpp"

#include "VideoHeaders.hpp"

#include <MLR\MLR_I_C_TMesh.hpp>
#include <MLR\MLRShape.hpp>

using namespace MidLevelRenderer;

//############################################################################
//###############################  ConeComponent  ############################
//############################################################################

//
// Class Data Support
//
Component::ClassData*
	ConeComponent::DefaultData = NULL;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ConeComponent::InitializeClass()
{
	Verify(!DefaultData);
	DefaultData =
		new ClassData(
			ConeComponentClassID,
			"Adept::ConeComponent",
			BaseClass::DefaultData,
			0,
			NULL
		);
	Check_Object(DefaultData);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
	ConeComponent::TerminateClass()
{
	Check_Object(DefaultData);
	delete DefaultData;
	DefaultData = NULL;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ConeComponent::ConeComponent(
	ClassData *class_data,
	MemoryStream *stream,
	VideoComponentWeb *owning_web
):
	VideoComponent(
		class_data,
		stream,
		owning_web,
		ReadShape(stream)
	)
{
	Check_Object(this);

	Scalar length;
	Scalar start_falloff;
	Scalar end_falloff;
	Scalar angle;
	RGBAColor color;
	RGBAColor color2;

	*stream >> length;
	*stream >> start_falloff;
	*stream >> end_falloff;
	*stream >> angle;
	*stream >> color;
	*stream >> color2;

	
	MLRShape *mlr_cone = MidLevelRenderer::CreateIndexedTriCone_Color_NoLit(
		start_falloff,
		end_falloff,
		angle,
		&color,
		&color2,
		2
	);

	Point3D p_0, p_1;
	Vector3D diaganol;

	Scalar falloff = end_falloff > start_falloff ? end_falloff : start_falloff;

	p_0.x = falloff / 2;
	p_0.y = 0.0f;
	p_0.z = 0.0f;

	p_1.x = falloff;
	p_1.y = falloff * Tan(angle);
	p_1.z = p_1.y;

	diaganol.Subtract(p_1, p_0);
	Scalar bounds_length;
	bounds_length = diaganol.GetLength();
	LinearMatrix4D origin = LinearMatrix4D::Identity;
	origin.BuildTranslation(p_0);
	Vector3D extents(0.0f, 0.0f, falloff);
	Stuff::OBB bounds(origin, extents, bounds_length);

	Check_Object(componentElement);
	componentElement->m_localOBB = bounds;
	Cast_Object(ElementRenderer::ShapeElement*,componentElement)->SetMLRShape(mlr_cone);
	mlr_cone->DetachReference();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ConeComponent::~ConeComponent()
{
	Check_Object(this);

}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Element*
	ConeComponent::ReadShape(MemoryStream *stream)
{
	Check_Object(stream);

	gos_PushCurrentHeap(ElementRenderer::ShapeElement::s_Heap);
	Element *element = new ElementRenderer::ShapeElement;
	gos_PopCurrentHeap();
	return element;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
ConeComponent*
	ConeComponent::Create(
		MemoryStream *stream,
		VideoComponentWeb *owning_web
	)
{
	Check_Object(stream);
	Check_Object(owning_web);
	ConeComponent *object;
	object = new ConeComponent(DefaultData, stream, owning_web);
	Check_Object(object);
	return object;
}

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