#include<stdafx.h>

#include"TCTHeightField.h"
#include "MLRHeightField.hpp"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

TCTHeightField::TCTHeightField()  :
	MLRHeightField()
{ 
	Attached = FALSE;
}


void TCTHeightField::Create(Image &image)
{
	X = image.GetWidth()+1;
	Z = image.GetHeight()+1;
	
	ASSERT(image.GetBpp()==8);
	
	field.SetLength(X*Z);
	
	unsigned char *ptr;
	ptr=(unsigned char *)image.Lock();

	int i, j;
	for(i=0;i<Z-1;i++)
	{
		for(j=0;j<X-1;j++)
		{
			field[i*X+j] = ptr[i*(X-1)+j];
		}
		field[i*X+j] = ptr[i*(X-1)+j-1];
	}
	for(j=0;j<X-1;j++)
	{
		field[i*X+j] = ptr[(i-1)*(X-1)+j];
	}
	field[i*X+j] = ptr[(i-1)*(X-1)+j-1];

	image.UnLock();

	Blur2D();

/*
	Image diffImg;

	diffImg.CreateBlank(X, Z);
	diffImg.CreateDifferentialMap(field.GetData(), X);
	diffImg.SaveTiff("test1.tif");
*/
}



void TCTHeightField::Clone(TCTHeightField &hf)
{
	X = hf.X;
	Z = hf.Z;
	field.SetLength(X*Z);
	dX = hf.dX;
	dY = hf.dY;
	dZ = hf.dZ;

	SetOffset(hf.GetOffset());

	//state0=hf.state0;
	//state1=hf.state1;
	
	field = hf.field;

	nrOfIZs = hf.nrOfIZs;
	
	if(Attached)
	{
		BuildModel();  
	}//end of Attached
}

void TCTHeightField::Attach(ElementRenderer::ListElement *parent,int index)
{
	//state0=s0;
	//state1=s1;
	if(terrainGroup)
	{
		Unregister_Object(terrainGroup);
		delete terrainGroup;
		terrainGroup=0;
	}

#ifdef _DEBUG
#undef new 
#endif
	terrainGroup = new GroupElement();
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
	Register_Object(terrainGroup);
	parent->AttachIndexedChild(index, terrainGroup);
	BuildModel();
	Attached=1;
}

void TCTHeightField::BuildModel()
{
//	terrainGroup->DetachChildren();

	ChainIteratorOf<Element*> *children = terrainGroup->MakeIterator();
	Element *child;
	while ((child = children->ReadAndNext()) != NULL)
	{
		terrainGroup->DetachChild(child);
		Unregister_Object(child);
		delete child;
	}

	MakeTerrainFromField();
}

void
	SetStateForElement(
		ElementRenderer::Element *group,
		MidLevelRenderer::MLRState &state,
		int sn
	)
{
	Check_Object(group);
	if(group->IsDerivedFrom(ElementRenderer::GroupElement::DefaultData))
	{
		Stuff::ChainIteratorOf<ElementRenderer::Element *> *children;
		ElementRenderer::Element *curelt;
		children = Cast_Pointer(ElementRenderer::GroupElement*, group)->MakeIterator();

		int j;
		while ((curelt = children->ReadAndNext()) != NULL)
		{
			if(curelt->IsDerivedFrom(ElementRenderer::ShapeElement::DefaultData) )
			{
				MidLevelRenderer::MLRShape *Shape = Cast_Object(ElementRenderer::ShapeElement *,curelt)->GetMLRShape();

				for(j=0;j<Shape->GetNum();j++)
				{
					Check_Object(Shape->Find(j));
					Shape->Find(j)->SetReferenceState(state, sn);
				}
			}
			else
			{
				SetStateForElement(
					curelt,
					state,
					sn
				);
			}
		}
	}
	else if(group->IsDerivedFrom(ElementRenderer::ListElement::DefaultData))
	{
		ElementRenderer::Element *curelt;

		int i, j, end = Cast_Pointer(ElementRenderer::ListElement*, group)->GetActiveCount();
		for(i=0;i<end;i++)
		{
			curelt = Cast_Pointer(ElementRenderer::ListElement*, group)->GetIndexedElement(i);

			if(curelt->IsDerivedFrom(ElementRenderer::ShapeElement::DefaultData) )
			{
				MidLevelRenderer::MLRShape *Shape = Cast_Object(ElementRenderer::ShapeElement *,curelt)->GetMLRShape();

				for(j=0;j<Shape->GetNum();j++)
				{
					Check_Object(Shape->Find(j));
					Shape->Find(j)->SetReferenceState(state, sn);
				}
			}
			else
			{
				SetStateForElement(
					curelt,
					state,
					sn
				);
			}
		}
	}
}

void TCTHeightField::SetState(MidLevelRenderer::MLRState &state, int sn)
{
	if(!Attached) return;

	if(sn==0)
		state0=state;
	else
		state1=state;

	int i, j;
	
	for(i=0;i<terrain.GetLength();i++)
	{
		Check_Object(terrain[i]);
		for(j=0;j<terrain[i]->GetNum();j++)
		{
			Check_Object(terrain[i]->Find(j));
			terrain[i]->Find(j)->SetReferenceState(state, sn);
		}
	}

	if(simpleTerrainGroup!=NULL) 
	{
		SetStateForElement(simpleTerrainGroup, state, sn);
	}
}

TCTHeightField::~TCTHeightField()
{
	//if(Attached) terrainGroup->DetachChildren();
}

void TCTHeightField::SetScale(Stuff::Scalar xs, Stuff::Scalar ys, Stuff::Scalar zs)
{
	dX=xs;
	dY=ys;
	dZ=zs;
	
	if(Attached)
	{
		BuildModel();  
	}//end of Attached
	
}

void TCTHeightField::SetSize(Scalar xs,Scalar zs)
{
	X=(int)xs;
	Z=(int)zs;
	
	if(Attached)
	{
		BuildModel();
	}
}

void TCTHeightField::SetPara(ExportInfo &einf)
{
	double x, y, z, off;

 	einf.GetScale_Offset(&x, &y, &z, &off);

	dX = (float)x;
	dY = (float)y;
	dZ = (float)z;
	
	SetOffset((float)off);
	
	if(Attached)
	{
		BuildModel();
	}
}
