///////////////////////////////////////////////////////////////////////////////
/// @file StaticBrush.cpp
///
/// @brief Creation of a static brush
///
/// @author Assassin 
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Feb 2002
/// @author Assassin
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#include "deXLoader.hpp" // this has to come first when doing leak-hunts
#include "deList.hpp"
#include "deBitmap.hpp"

#include "deBrush_priv.hpp"
#include "deMath.hpp"

#pragma todo(remove or refactor deStaticBrush)

WorldObjectClassImp(deStaticBrush);

static const deBrush::DataQuantity_t s_StaticQuantities = 
{
	deBrush::DataQuantity_t::Quantity_Unmanaged, 
	0,	//CVNum
	0,	//NumFaces
	0	//CoordsPerFace
};

deStaticBrush::deStaticBrush()
:deBrush(Brush_Static, s_StaticQuantities)
{
	m_SaveVBuffers = deTRUE;
}

deStaticBrush::~deStaticBrush()
{
}

void deStaticBrush::UpdateBrush()
{
//	m_Octree->Generate();
}

deBrush * deStaticBrush::CopyBrush()
{
	deStaticBrush * b = NULL;
	b = new deStaticBrush;
//	b->m_VBuffers = m_VBuffers;
	return b;
}

void deStaticBrush::SpecificRotate(deVec3d Center, deTransformInfo &M)
{
	int i, j, BufferNum, PointCount;
	BufferNum = m_SubVBs.Length();
	deVertex *Verts = NULL;
	deVertex *Norms = NULL;
	deVertex SmallCenter = deMake_Vertex(Center);
	deTransform M2(M);
	for (i = 0; i < BufferNum; i++)
	{
		PointCount = m_SubVBs[i]->GetVertexCount();
		if (PointCount <= 0)
			continue;
		m_SubVBs[i]->Lock();
		Verts = (deVertex*)m_SubVBs[i]->GetBuffer(IdeVertexBuffer::BUFFER_POSITION);
		Norms = (deVertex*)m_SubVBs[i]->GetBuffer(IdeVertexBuffer::BUFFER_NORMAL);
		for (j = 0; j < PointCount; j++)
		{
			if (Verts)
			{
				Verts[j] = Verts[j] - SmallCenter;
				M2.Transform(Verts[j], Verts[j]);
				Verts[j] = Verts[j] + SmallCenter;
			}
			if (Norms)
			{
				M2.Transform(Norms[j], Norms[j]);
			}
		}
		m_SubVBs[i]->DirtyBuffer(IdeVertexBuffer::BUFFER_POSITION);
		//m_VBuffers[i]->FillBuffer(IdeVertexBuffer::BUFFER_POSITION, Verts, 0, PointCount);
		m_SubVBs[i]->Unlock();
	}
}

void deStaticBrush::SpecificTranslate(deVec3d Delta)
{
	int i, j, BufferNum, PointCount;
	BufferNum = m_SubVBs.Length();
	deVertex *Verts = NULL;
	deVertex SmallDelta = deMake_Vertex(Delta);
	for (i = 0; i < BufferNum; i++)
	{
		PointCount = m_SubVBs[i]->GetVertexCount();
		if (PointCount <= 0)
			continue;
		m_SubVBs[i]->Lock();
		Verts = (deVertex*)m_SubVBs[i]->GetBuffer(IdeVertexBuffer::BUFFER_POSITION);
		if (!Verts)
		{
			m_SubVBs[i]->Unlock();
			continue;
		}
		for (j = 0; j < PointCount; j++)
			Verts[j] = Verts[j] + SmallDelta;
		m_SubVBs[i]->DirtyBuffer(IdeVertexBuffer::BUFFER_POSITION);
		//m_VBuffers[i]->FillBuffer(IdeVertexBuffer::BUFFER_POSITION, Verts, 0, PointCount);
		m_SubVBs[i]->Unlock();
	}
}

void deStaticBrush::SpecificScale(deVec3d Center, deDouble Scale)
{
	int i, j, BufferNum, PointCount;
	BufferNum = m_SubVBs.Length();
	deVertex *Verts = NULL;
	deVertex SmallCenter = deMake_Vertex(Center);
	deFloat SmallScale = deFloat(Scale);
	for (i = 0; i < BufferNum; i++)
	{
		PointCount = m_SubVBs[i]->GetVertexCount();
		if (PointCount <= 0)
			continue;
		m_SubVBs[i]->Lock();
		Verts = (deVertex*)m_SubVBs[i]->GetBuffer(IdeVertexBuffer::BUFFER_POSITION);
		if (!Verts)
		{
			m_SubVBs[i]->Unlock();
			continue;
		}
		for (j = 0; j < PointCount; j++)
		{
			Verts[j] = Verts[j] - SmallCenter;
			Verts[j] = Verts[j] * SmallScale;
			Verts[j] = Verts[j] + SmallCenter;
		}
		m_SubVBs[i]->DirtyBuffer(IdeVertexBuffer::BUFFER_POSITION);
		//m_VBuffers[i]->FillBuffer(IdeVertexBuffer::BUFFER_POSITION, Verts, 0, PointCount);
		m_SubVBs[i]->Unlock();
	}
}

deBoolean deStaticBrush::Serialize(IdeFile* FS)
{
	if (!deBrush::Serialize(FS))
		return deFALSE;
	return deTRUE;
}

deBoolean deStaticBrush::DeSerialize(IdeFile* FS, long DataLength)
{
	if (!deBrush::DeSerialize(FS, DataLength))
		return deFALSE;
	return deTRUE;
}

void deStaticBrush::AddPoly(deBPoly & poly)
{
	m_Changed = deTRUE;
	poly.TextureIndex = m_CurrentTexture;
	m_PolyList.AddElement(poly);
//	m_Octree->AddPoly(poly);
}

void deStaticBrush::SetTextureState(IdeRenderTexture * texture)
{
	int i, x;
	i = m_TextureList.Length();
	for (x = 0; x < i; x++)
	{
		if (m_TextureList[x] == texture)
		{
			m_CurrentTexture = x;
			return;
		}
	}
	ResizeLists(i+1);
	SetTexture(i, texture);
	m_CurrentTexture = i;
}

void deStaticBrush::AddIndexedBuffer(BIndexList indexbuffer)
{
	m_UsingIndexedBuffer = true;
	m_IndexedBuffers[m_CurrentTexture].AddElement(indexbuffer);
}

void deStaticBrush::BuildIndexedBuffers()
{
	FillIndexedBuffers();
}

deBoolean deStaticBrush::AddVertices(const deBrushVertexData & /*vertexdata*/, long & /*indexoffset*/)
{
	return deFALSE;
}

deBoolean deStaticBrush::AddIndices(const deBrushIndexData & /*vertexdata*/, long /*indexoffset*/)
{
	return deFALSE;
}

