///////////////////////////////////////////////////////////////////////////////
/// @file deBrush.cpp
///
/// @brief Main brush interface
///
/// @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
///
///////////////////////////////////////////////////////////////////////////////

/*
 * Implemented:
 *  BlockBrush
 *  CylinderBrush
 *  LathedBrush
 *  ExtrudedBrush
 *  geometry LOD
 *
 * TODO:
 *  Lighting normals might need work
 *  (multi)Texturing
 *  BezierPatchBrush
 *  polygon (subdivision) LOD
 *
 */

#include "deBrush_priv.hpp"
#include "deStack.hpp"
//#include <cstdarg>
#include "deMath.hpp"
//#include "octree.hpp"
#include "deFileSystem.hpp"
#include "deDriver.hpp"
#include "deMesh_priv.hpp" // for initialization

volatile unsigned long GlobalCounter = 1;
long s_BrushWOInterfaceID = -1;

deBoolean IdeBrush_Initialize()
{
	IdeWorldManager * manager = IdeWorld_GetManager();
	s_BrushWOInterfaceID = manager->GetUniqueWOInterfaceID();
	
	if (!WorldObjectRegister(deGroupBrush))
		return deFALSE;
	if (!WorldObjectRegister(deBlockBrush))
		return deFALSE;
	if (!WorldObjectRegister(deCylinderBrush))
		return deFALSE;
	if (!WorldObjectRegister(deLathedBrush))
		return deFALSE;
	if (!WorldObjectRegister(deExtrudedBrush))
		return deFALSE;
	if (!WorldObjectRegister(deStaticBrush))
		return deFALSE;
	if (!WorldObjectRegister(deLineBrush))
		return deFALSE;
	if (!WorldObjectRegister(dePrismBrush))
		return deFALSE;
	if (!WorldObjectRegister(deBezierBrush))
		return deFALSE;
	if (!WorldObjectRegister(deLargeStaticBrush))
		return deFALSE;
	if (!IdeMesh_Initialize())
		return deFALSE;
	
	return deTRUE;
}

IdeBrush* IdeBrush_CreateBrush(IdeBrush::deBrushType Type)
{
	IdeBrush * pBrush = NULL;
	switch (Type)
	{
	case IdeBrush::Brush_Group:
		pBrush = new deGroupBrush; break;
	case IdeBrush::Brush_Block:
		pBrush = new deBlockBrush; break;
	case IdeBrush::Brush_Cylinder:
		pBrush = new deCylinderBrush; break;
	case IdeBrush::Brush_Lathed:
		pBrush = new deLathedBrush; break;
	case IdeBrush::Brush_Extruded:
		pBrush = new deExtrudedBrush; break;
	case IdeBrush::Brush_Static:
		pBrush = new deStaticBrush; break;
	case IdeBrush::Brush_Line:
		pBrush = new deLineBrush; break;
	case IdeBrush::Brush_Prism:
		pBrush = new dePrismBrush; break;
	case IdeBrush::Brush_Bezier:
		pBrush = new deBezierBrush; break;
	case IdeBrush::Brush_LargeStatic:
		pBrush = new deLargeStaticBrush; break;
	}
	return pBrush;
}

long IdeBrush_GetWOInterfaceID()
{
	return s_BrushWOInterfaceID;
}

deBrush::deBrush(deBrushType Type, const DataQuantity_t &QuantityDefs)
: m_Type(Type), m_QuantityDefs(QuantityDefs)
{
	m_CVNum = 0;
	m_LOD = 1;
	m_LOD2 = 1;
	m_Changed = deFALSE;
	m_SmoothNormals = deFALSE;
	m_SaveVBuffers = deFALSE;
//	m_GroupParent = NULL;
	m_UsingIndexedBuffer = false;
	m_DiffuseColor = 0x00ffffff;
//	m_Name[0] = '\0';
//	m_Octree = new BrushOctree;
	m_MainVBuffer = IdeVertexBuffer_CreateVBuffer();
	m_MainVBuffer->Lock();
	m_MainVBuffer->SetRenderType(IdeVertexBuffer::RENDER_POINTLIST);
	m_MainVBuffer->Unlock();
	RecalcListQuantities(deTRUE);
}

deBrush::~deBrush()
{
	int i, len = m_SubVBs.Length();
	for (i = 0; i < len; i++)
	{
		m_SubVBs[i]->Release();
		if (m_TextureList[i])
			m_TextureList[i]->Release();
	}
	m_MainVBuffer->Release();
}

void* deBrush::GetWOInterface(long interface_id)
{
	if (interface_id == s_BrushWOInterfaceID)
		return (IdeBrush*)(this);
	if (interface_id == 0)
		return (IdeWorldObject*)(this);
	return NULL;
}

void* deBrush::GetBrushInterface(deBrushType Type) const
{
	if (Type != m_Type)
		return NULL;

	switch (Type)
	{
	case IdeBrush::Brush_Group:
		return (IdeGroupBrush*)(deGroupBrush*)(this);
	case IdeBrush::Brush_Block:
		return (IdeBlockBrush*)(deBlockBrush*)(this);
	case IdeBrush::Brush_Cylinder:
		return (IdeCylinderBrush*)(deCylinderBrush*)(this);
	case IdeBrush::Brush_Lathed:
		return (IdeLathedBrush*)(deLathedBrush*)(this);
	case IdeBrush::Brush_Extruded:
		return (IdeExtrudedBrush*)(deExtrudedBrush*)(this);
	case IdeBrush::Brush_Static:
		return (IdeStaticBrush*)(deStaticBrush*)(this);
	case IdeBrush::Brush_Line:
		return (IdeLineBrush*)(deLineBrush*)(this);
	case IdeBrush::Brush_Prism:
		return (IdePrismBrush*)(dePrismBrush*)(this);
	case IdeBrush::Brush_Bezier:
		return (IdeBezierBrush*)(deBezierBrush*)(this);
	case IdeBrush::Brush_LargeStatic:
		return (IdeLargeStaticBrush*)(deLargeStaticBrush*)(this);
	}
	return NULL;
}

void deBrush::ResizeLists(long size)
{
	int i, j;
	IdeRenderTexture * tex;

	i = m_SubVBs.Length();
	if (size == i)
		return;
	if (size < i)
	{
		for (j = size; j < i; j++)
		{
			//m_FaceList[j] = NULL;
			m_SubVBs[j]->Release();
			tex = m_TextureList[j];
			DE3D_SAFE_RELEASE(tex);
		}
	}
	m_SubVBs.Resize(size);
	m_IndexedBuffers.Resize(size);
	m_FaceList.Resize(size);
	m_TextureList.ResizeQuick(size, deTRUE);
	m_DrawTypeList.ResizeQuick(size, deTRUE);
	for (j = i; j < size; j++)
	{
		//m_FaceList[j] = NULL;
		m_SubVBs[j] = IdeVertexBuffer_CreateSubVBuffer(m_MainVBuffer);
	}
}

deBoolean deBrush::RecalcListQuantities(deBoolean Creation)
{
	switch (m_QuantityDefs.QuantityRatio)
	{
	case DataQuantity_t::Quantity_Unmanaged:
		// do nothing
		return deTRUE;
	case DataQuantity_t::Quantity_Constant:
		// only do something on the first call
		if (m_CVNum < 0 || m_CVNum > m_QuantityDefs.CVNum)
			return deFALSE;
		if (Creation)
		{
			int i;
			int numfaces = m_QuantityDefs.NumFaces;
			m_CVList.Resize(m_QuantityDefs.CVNum);
			m_IndexedBuffers.Resize(numfaces);
			m_FaceList.Resize(numfaces);
			for (i = 0; i < numfaces; ++i)
				m_FaceList[i].ResizeQuick(m_QuantityDefs.CoordsPerFace, deTRUE);

			m_TextureList.ResizeQuick(numfaces, deTRUE);
			m_DrawTypeList.ResizeQuick(numfaces, deTRUE);
			m_SubVBs.ResizeQuick(numfaces, deTRUE);
			for (i = 0; i < numfaces; ++i)
				m_SubVBs[i] = IdeVertexBuffer_CreateSubVBuffer(m_MainVBuffer);
		}
		return deTRUE;
	case DataQuantity_t::Quantity_PerCV:
		{
			int i;
			int numfaces = (m_CVNum*m_QuantityDefs.NumFaces)/m_QuantityDefs.CVNum;
			m_FaceList.Resize(numfaces);
			for (i = 0; i < numfaces; ++i)
				m_FaceList[i].ResizeQuick(m_QuantityDefs.CoordsPerFace, deTRUE);
			
			m_TextureList.ResizeQuick(numfaces, deTRUE);
			m_SubVBs.ResizeQuick(numfaces, deTRUE);
			m_DrawTypeList.ResizeQuick(numfaces, deTRUE);
			for (i = 0; i < numfaces; ++i)
				m_SubVBs[i] = IdeVertexBuffer_CreateSubVBuffer(m_MainVBuffer);
		}
		return deTRUE;
	}
	return deFALSE;
}

void deBrush::GetWorldTransform(deTransformInfo & Matrix) const
{
	Matrix = m_WorldTransform;
}

/*
void deBrush::SetWorldTransform(deTransformInfo & Matrix)
{
	m_WorldTransform = Matrix;
}
*/

long deBrush::GetNumCVs()
{
	return m_CVNum;
}

void deBrush::GetCVList(deVec3d buffer[])
{
	for (int i = 0; i < m_CVNum; i++)
		buffer[i] = m_CVList[i];
}

deVec3d deBrush::GetCV(long num)
{
	return m_CVList[num];
}

deBoolean deBrush::SetCV(long num, deVec3d & CV)
{
	if (num < 0 || num >= m_CVNum)
		return deFALSE;
	
	m_CVList[num] = CV;

	m_Changed = deTRUE;

	return deTRUE;
}

deBoolean deBrush::AddCV(deVec3d & point)
{
	m_CVNum++;
	if (!RecalcListQuantities(deFALSE))
		return deFALSE;

	m_CVList.Resize(m_CVNum);
	m_CVList[m_CVNum-1] = point;

	m_Changed = deTRUE;
	
	return deTRUE;
}

deBoolean deBrush::SetCVList(long num, deVec3d CVList[])
{
	m_CVNum = num;
	if (!RecalcListQuantities(deFALSE))
		return deFALSE;
	
	m_CVList.Resize(0);
	m_CVList.Resize(num);
	for (int i = 0; i < m_CVNum; i++)
		m_CVList[i] = CVList[i];

	m_Changed = deTRUE;
	
	return deTRUE;
}

#pragma todo (implement this)
void deBrush::GetAABB(deVec3d& /*Mins*/, deVec3d& /*Maxs*/)
{
}

/*
deTList <deBPoly> & deBrush::GetPolyList()
{ 
	Update();
	return m_PolyList; 
}

void deBrush::GetPolyList(deTList <deBPoly*> & list)
{
	Update();
	m_Octree.GetAllPolys(list);
}
*/

long deBrush::GetNumVBs()
{
	return m_SubVBs.Length();
}

IdeVertexBuffer * deBrush::GetVertexBuffer(long index)
{
	Update();

	return m_SubVBs[index];
}

void deBrush::SetDiffuseColor(deARGB color)
{
	size_t i,j,PointCount;

	m_DiffuseColor = color;

	for (j = 0; j < m_SubVBs.Length(); j++)
	{
		PointCount = m_SubVBs[j]->GetVertexCount();
		if (PointCount <= 0)
			continue;
		m_SubVBs[j]->Lock();
		deARGB * ColorBuffer = (deARGB*)m_SubVBs[j]->GetBuffer(IdeVertexBuffer::BUFFER_DIFFUSE);
		if (!ColorBuffer)
		{
			m_SubVBs[j]->Unlock();
			continue;
		}
		for (i = 0; i < PointCount; ++i)
		{
			ColorBuffer[i] = m_DiffuseColor;
		}
		m_SubVBs[j]->DirtyBuffer(IdeVertexBuffer::BUFFER_DIFFUSE);
		m_SubVBs[j]->Unlock();
	}
}

deARGB deBrush::GetDiffuseColor()
{
	return m_DiffuseColor;
}

deBoolean deBrush::Update()
{
	if (!m_Changed)
		return deFALSE;
	m_Changed = deFALSE;
	UpdateBrush();
	if (m_UsingIndexedBuffer)
		FillIndexedBuffers();
	else
		FillVertexBuffers();

	return deTRUE;
}

deBoolean deBrush::FillVertexBuffers()
{
	size_t i = 0, j;
	size_t NumBuffers;
	int TotalVerts = 0;
	int * ActualVerts = NULL;
	void * ptr = NULL;
	deBPoly * poly;
//	deTList <deBPoly*> polylist;
//	m_Octree->GetAllPolys(polylist);

	TotalVerts = m_PolyList.Length() * 3;

	NumBuffers = m_SubVBs.Length();
	deVertex ** Points = new deVertex*[NumBuffers];
	deVertex ** Norms = new deVertex*[NumBuffers];
	deTexCoord ** Coords = new deTexCoord*[NumBuffers];
	deARGB ** Colors = new deARGB*[NumBuffers];
	ActualVerts = new int[NumBuffers];

	for (j = 0; j < NumBuffers; j++)
	{
		Points[j] = new deVertex[TotalVerts];
		Norms[j] = new deVertex[TotalVerts];
		Coords[j] = new deTexCoord[TotalVerts];
		Colors[j] = new deARGB[TotalVerts];
		ActualVerts[j] = 0;
	}

	ptr = m_PolyList.GetNext(NULL, poly);
	while (ptr != NULL)
	{
		j = poly->TextureIndex;
		i = ActualVerts[j];
		{
			Points[j][i*3+0] = deMake_Vertex(poly->Verts[0].Pos);
			Points[j][i*3+1] = deMake_Vertex(poly->Verts[1].Pos);
			Points[j][i*3+2] = deMake_Vertex(poly->Verts[2].Pos);
			Norms[j][i*3+0] = deMake_Vertex(poly->Verts[0].Norm);
			Norms[j][i*3+1] = deMake_Vertex(poly->Verts[1].Norm);
			Norms[j][i*3+2] = deMake_Vertex(poly->Verts[2].Norm);
			Coords[j][i*3+0] = poly->Verts[0].UV;
			Coords[j][i*3+1] = poly->Verts[1].UV;
			Coords[j][i*3+2] = poly->Verts[2].UV;
			Colors[j][i*3+0] = m_DiffuseColor;
			Colors[j][i*3+1] = m_DiffuseColor;
			Colors[j][i*3+2] = m_DiffuseColor;
			ActualVerts[j]++;
		}
		ptr = m_PolyList.GetNext(ptr, poly);
	}

	for (j = 0; j < NumBuffers; j++)
	{
		ActualVerts[j] *= 3;
	}

	for (j = 0; j < NumBuffers; j++)
	{
		if (ActualVerts[j] <= 0)
			continue;

		m_SubVBs[j]->Lock();

		// this does the resize
		m_SubVBs[j]->SetBufferSize(ActualVerts[j], DE_FALSE);
		if (m_SubVBs[j]->GetBuffer(IdeVertexBuffer::BUFFER_POSITION) == NULL)
		{
			m_MainVBuffer->Lock();
			m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_POSITION, DE_FALSE);
			m_MainVBuffer->Unlock();
		}
		if (!m_SubVBs[j]->FillBuffer(IdeVertexBuffer::BUFFER_POSITION, Points[j], 0, ActualVerts[j]))
			DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling position buffer");

		if (m_SubVBs[j]->GetBuffer(IdeVertexBuffer::BUFFER_NORMAL) == NULL)
		{
			m_MainVBuffer->Lock();
			m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_NORMAL, DE_FALSE);
			m_MainVBuffer->Unlock();
		}
		if (!m_SubVBs[j]->FillBuffer(IdeVertexBuffer::BUFFER_NORMAL, Norms[j], 0, ActualVerts[j]))
			DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling normals buffer");

		if (m_SubVBs[j]->GetBuffer(IdeVertexBuffer::BUFFER_DIFFUSE) == NULL)
		{
			m_MainVBuffer->Lock();
			m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_DIFFUSE, DE_FALSE);
			m_MainVBuffer->Unlock();
		}
		if (!m_SubVBs[j]->FillBuffer(IdeVertexBuffer::BUFFER_DIFFUSE, Colors[j], 0, ActualVerts[j]))
			DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling diffuse buffer");

		if (m_TextureList.Length() > j)
		{
			if (m_SubVBs[j]->GetBuffer(IdeVertexBuffer::BUFFER_TEXTURECOORDS0) == NULL)
			{
				m_MainVBuffer->Lock();
				m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_TEXTURECOORDS0, DE_FALSE);
				m_MainVBuffer->Unlock();
			}
			if (!m_SubVBs[j]->FillBuffer(IdeVertexBuffer::BUFFER_TEXTURECOORDS0, Coords[j], 0, ActualVerts[j]))
				DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling texcoords buffer");
		}

		m_SubVBs[j]->SetRenderType(IdeVertexBuffer::RENDER_TRIANGLELIST);
//		m_VBuffers[j]->SetTriCount(ActualVerts[j]/3);
		
		m_SubVBs[j]->Unlock();

		delete[] Points[j];
		delete[] Norms[j];
		delete[] Coords[j];
		delete[] Colors[j];
	}
	delete[] Points;
	delete[] Norms;
	delete[] Coords;
	delete[] Colors;
	delete[] ActualVerts;

	return deTRUE;
}

deBoolean deBrush::FillIndexedBuffers()
{
	int i,j;
	int PointCount=0, IndexCount=0;
	int StartPointCount=0;
	int StartIndexCount=0;
	int TexNum = m_SubVBs.Length();
	int BufferNum=0;
	void *listptr;
	BIndexList * buffer;
	IdeVertexBuffer* VBuffer;
	deARGB Colors[128];
	for (i = 0; i < 128; i++)
		Colors[i] = m_DiffuseColor;

	for (j = 0; j < TexNum; j++)
	{
		VBuffer = m_SubVBs[j];
		
		BufferNum = m_IndexedBuffers[j].Length();
		if (BufferNum <= 0)
			continue;
		VBuffer->Lock();
		listptr = m_IndexedBuffers[j].RemoveElementGetNext(NULL, buffer);
		StartPointCount = 0;
		StartIndexCount = 0;
		while (listptr)
		{
			PointCount = buffer->numpoints;
			IndexCount = buffer->numindices;

			VBuffer->SetBufferSize(IndexCount+StartIndexCount, DE_TRUE);
			VBuffer->SetBufferSize(PointCount+StartPointCount, DE_FALSE);

			if (!VBuffer->BufferExists(IdeVertexBuffer::BUFFER_INDICES16))
			{
				m_MainVBuffer->Lock();
				m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_INDICES16, DE_FALSE);
				m_MainVBuffer->Unlock();				
			}
			if (!VBuffer->FillBuffer(IdeVertexBuffer::BUFFER_INDICES16, buffer->indices, StartIndexCount, IndexCount))
				DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling index buffer");

			if (!VBuffer->BufferExists(IdeVertexBuffer::BUFFER_POSITION))
			{
				m_MainVBuffer->Lock();
				m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_POSITION, DE_FALSE);
				m_MainVBuffer->Unlock();				
			}
			if (!VBuffer->FillBuffer(IdeVertexBuffer::BUFFER_POSITION, buffer->positions, StartPointCount, PointCount))
				DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling position buffer");

			if (buffer->normals)
			{
				if (!VBuffer->BufferExists(IdeVertexBuffer::BUFFER_NORMAL))
				{
					m_MainVBuffer->Lock();
					m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_NORMAL, DE_FALSE);
					m_MainVBuffer->Unlock();				
				}
				if (!VBuffer->FillBuffer(IdeVertexBuffer::BUFFER_NORMAL, buffer->normals, StartPointCount, PointCount))
					DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling normals buffer");
			}

			if (!VBuffer->BufferExists(IdeVertexBuffer::BUFFER_DIFFUSE))
			{
				m_MainVBuffer->Lock();
				m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_DIFFUSE, DE_FALSE);
				m_MainVBuffer->Unlock();				
			}
			{
				deARGB * ColorBuffer = (deARGB*)VBuffer->GetBuffer(IdeVertexBuffer::BUFFER_DIFFUSE);
				for (i = StartPointCount; i < PointCount; i += 128)
				{
					if (StartPointCount + i <= PointCount - 128)
					{
						memcpy(ColorBuffer, Colors, 128*4);
					}
					else
					{
						memcpy(ColorBuffer, Colors, ((PointCount-StartPointCount)-i)*4);
					}
					ColorBuffer += 128;
				}
				VBuffer->DirtyBuffer(IdeVertexBuffer::BUFFER_DIFFUSE);
			}

			for(i = 0; i < (int)(buffer->numtexstages); ++i)
			{
				IdeVertexBuffer::BufferType t = (IdeVertexBuffer::BufferType)(IdeVertexBuffer::BUFFER_TEXTURECOORDS0 + i);
				if (!VBuffer->BufferExists(t))
				{
					m_MainVBuffer->Lock();
					m_MainVBuffer->CreateBuffer(t, DE_FALSE);
					m_MainVBuffer->Unlock();				
				}
				if (!VBuffer->FillBuffer(t, &(buffer->uvcoords[PointCount*i]), StartPointCount, PointCount))
					DEBUGRETURN(deFALSE, "FillVertexBuffers: failure filling texcoords buffer");
			}


			StartPointCount = m_SubVBs[j]->GetVertexCount();
			StartIndexCount = m_SubVBs[j]->GetIndexCount();
			
			listptr = m_IndexedBuffers[j].RemoveElementGetNext(listptr, buffer);
		}
		VBuffer->SetRenderType(IdeVertexBuffer::RENDER_TRIANGLELIST);
//		m_VBuffers[j]->SetTriCount((StartIndexCount+IndexCount)/3);
		VBuffer->Unlock();
	}

	return deTRUE;
}

void deBrush::ClearGeometry()
{
	int i, length;
	IdeVertexBuffer* pVB;

	length = m_SubVBs.Length();
	for (i = 0; i < length; ++i)
	{
		pVB = m_SubVBs[i];
		if (pVB)
		{
			if (pVB->Lock())
			{
				pVB->SetBufferSize(0, deTRUE);
				pVB->SetBufferSize(0, deFALSE);
				pVB->Unlock();
			}
		}
	}
}

void deBrush::Rotate(deVec3d &Center, deVec3d &Axis, deDouble Degrees)
{
	// x=0 y=1 z=2
	int AxisID;
	deTransform M;

	if (Axis.y > Axis.x)
	{
		if (Axis.z > Axis.y)
			AxisID = 2;
		else
			AxisID = 1;
	}
	else
	{
		if (Axis.z > Axis.x)
			AxisID = 2;
		else
			AxisID = 0;
	}
	switch (AxisID)
	{
	case 0:
		M.RotateX(Degrees*(DE_PI/180));
		break;
	case 1:
		M.RotateY(Degrees*(DE_PI/180));
		break;
	case 2:
		M.RotateZ(Degrees*(DE_PI/180));
		break;
	default:
		return;
	}
	Rotate(Center, M);
	m_Changed = deTRUE;
}

void deBrush::Rotate(deVec3d &Center, deTransformInfo &M)
{
	deTransform XForm(M);
	int i, VertNum = m_CVList.Length();
	deVec3d *pVerts = m_CVList.GetCArray();
	deVec3d * Verts = new deVec3d[VertNum];
	for (i = 0; i < VertNum; i++)
	{
		pVerts[i] = pVerts[i] - Center;
		XForm.Transform(pVerts[i], Verts[i]);
		Verts[i] = Verts[i] + Center;
	}
	SetCVList(VertNum, Verts);
	delete[] Verts;
	SpecificRotate(Center, XForm);
	m_Changed = deTRUE;
}

void deBrush::Translate(deVec3d &Delta)
{
	int i;
	int VertNum = m_CVList.Length();
	deVec3d * Verts = new deVec3d[VertNum];
	for (i = 0; i < VertNum; i++)
	{
		Verts[i] = m_CVList[i] + Delta;
	}
	SetCVList(VertNum, Verts);
	delete[] Verts;
	SpecificTranslate(Delta);
	m_Changed = deTRUE;
}

void deBrush::Scale(deVec3d &Center, deDouble Scale)
{
	int i;
	int VertNum = m_CVList.Length();
	deVec3d * Verts = new deVec3d[VertNum];
	for (i = 0; i < VertNum; i++)
	{
		Verts[i] = Verts[i] - Center;
		Verts[i] = Verts[i] * Scale;
		Verts[i] = Verts[i] + Center;
	}
	SetCVList(VertNum, Verts);
	delete[] Verts;
	SpecificScale(Center, Scale);
	m_Changed = deTRUE;
}

long deBrush::GetLOD() const
{
	return m_LOD;
}

long deBrush::GetLOD2() const
{
	return m_LOD2;
}

void deBrush::SetLOD(long LOD)
{
	if (m_LOD == LOD)
		return;
	m_LOD = LOD;
	m_Changed = deTRUE;
}

void deBrush::SetLOD2(long LOD2)
{
	if (m_LOD2 == LOD2)
		return;
	m_LOD2 = LOD2;
	m_Changed = deTRUE;
}

long deBrush::GetTexFacesNum()
{
	return m_FaceList.Length();
}

long deBrush::GetTexCoordsNum(long faceindex)
{
	return m_FaceList[faceindex].Length();
}

deTexCoord deBrush::GetTexCoord(long faceindex, long index)
{
	return m_FaceList[faceindex][index];
}

void deBrush::SetTexCoord(long faceindex, long index, deTexCoord &coord)
{
	m_FaceList[faceindex][index] = coord;
}

void deBrush::SetTexCoord(long faceindex, long index, deFloat u, deFloat v)
{
	m_FaceList[faceindex][index].u = u;
	m_FaceList[faceindex][index].v = v;
}

void deBrush::SetTexture(long faceindex, IdeRenderTexture * state)
{
	IdeRenderTexture * temp;
	temp = m_TextureList[faceindex];
	if (temp)
		temp->Release();
	if (state)
		state->Claim();
	m_TextureList[faceindex] = state;
}

IdeRenderTexture* deBrush::GetTexture(long faceindex)
{
	return m_TextureList[faceindex];
}

#pragma todo(implement normal-smoothing in specific brushes)
void deBrush::SetSmooth(deBoolean SmoothNotSharp)
{
	m_SmoothNormals = SmoothNotSharp;
}

deBoolean deBrush::GetSmooth()
{
	return m_SmoothNormals;
}

void deBrush::MakeTri(deBPoly & face, deVec3d &v1, deVec3d &v2, deVec3d &v3)
{
	face.Resize(3);

	face.Verts[0].Pos = v1;
	face.Verts[1].Pos = v2;
	face.Verts[2].Pos = v3;

	for (int i = 0; i < 3; i++)
	{
		face.Verts[i].Color.r = 1;
		face.Verts[i].Color.g = 1;
		face.Verts[i].Color.b = 1;
		face.Verts[i].Color.a = 1;
		face.Verts[i].UV = deZeroTex;
	}

	deVec3d vec1, vec2;
	vec1 = v1 - v2;
	vec2 = v1 - v3;
	face.Normal = Vec3d_Cross(vec1, vec2);
	Vec3d_Normalize(face.Normal);
	face.Verts[0].Norm = face.Normal;
	face.Verts[1].Norm = face.Normal;
	face.Verts[2].Norm = face.Normal;
	face.Dist = Vec3d_Dot(face.Normal, face.Verts[0].Pos);
	face.TextureIndex = 0;
}

void deBrush::MakeTri(deBPoly & face, 
					  deVec3d &v1, deVec3d &v2, deVec3d &v3, 
					  deVec3d &n1, deVec3d &n2, deVec3d &n3)
{
	face.Resize(3);

	face.Verts[0].Pos = v1;
	face.Verts[1].Pos = v2;
	face.Verts[2].Pos = v3;

	face.Verts[0].Norm = n1;
	face.Verts[1].Norm = n2;
	face.Verts[2].Norm = n3;

	for (int i = 0; i < 3; i++)
	{
		face.Verts[i].Color.r = 1;
		face.Verts[i].Color.g = 1;
		face.Verts[i].Color.b = 1;
		face.Verts[i].Color.a = 1;
		face.Verts[i].UV = deZeroTex;
	}

	deVec3d vec1, vec2;
	vec1 = v1 - v2;
	vec2 = v1 - v3;
	face.Normal = Vec3d_Cross(vec1, vec2);
	Vec3d_Normalize(face.Normal);
	face.Dist = Vec3d_Dot(face.Normal, face.Verts[0].Pos);
	face.TextureIndex = 0;
}

void deBrush::MakeTri(deBPoly & face, 
					  deVec3d &v1, deVec3d &v2, deVec3d &v3, 
					  deVec3d &n1, deVec3d &n2, deVec3d &n3,
					  deColor &c1, deColor &c2, deColor &c3)
{
	face.Resize(3);

	face.Verts[0].Pos = v1;
	face.Verts[1].Pos = v2;
	face.Verts[2].Pos = v3;

	face.Verts[0].Norm = n1;
	face.Verts[1].Norm = n2;
	face.Verts[2].Norm = n3;

	face.Verts[0].Color = c1;
	face.Verts[1].Color = c2;
	face.Verts[2].Color = c3;

	for (int i = 0; i < 3; i++)
	{
		face.Verts[i].UV = deZeroTex;
	}

	deVec3d vec1, vec2;
	vec1 = v1 - v2;
	vec2 = v1 - v3;
	face.Normal = Vec3d_Cross(vec1, vec2);
	Vec3d_Normalize(face.Normal);
	face.Dist = Vec3d_Dot(face.Normal, face.Verts[0].Pos);
	face.TextureIndex = 0;
}

void deBrush::MakeTri(deBPoly & face, 
					  deVec3d &v1, deVec3d &v2, deVec3d &v3, 
					  deVec3d &n1, deVec3d &n2, deVec3d &n3,
					  deTexCoord &t1, deTexCoord &t2, deTexCoord &t3)
{
	face.Resize(3);

	face.Verts[0].Pos = v1;
	face.Verts[1].Pos = v2;
	face.Verts[2].Pos = v3;

	face.Verts[0].Norm = n1;
	face.Verts[1].Norm = n2;
	face.Verts[2].Norm = n3;

	face.Verts[0].UV = t1;
	face.Verts[1].UV = t2;
	face.Verts[2].UV = t3;

	for (int i = 0; i < 3; i++)
	{
		face.Verts[i].Color.r = 1;
		face.Verts[i].Color.g = 1;
		face.Verts[i].Color.b = 1;
		face.Verts[i].Color.a = 1;
	}

	deVec3d vec1, vec2;
	vec1 = v1 - v2;
	vec2 = v1 - v3;
	face.Normal = Vec3d_Cross(vec1, vec2);
	Vec3d_Normalize(face.Normal);
	face.Dist = Vec3d_Dot(face.Normal, face.Verts[0].Pos);
	face.TextureIndex = 0;
}

void deBrush::MakeTri(deBPoly & face, 
					  deVec3d &v1, deVec3d &v2, deVec3d &v3, 
					  deVec3d &n1, deVec3d &n2, deVec3d &n3,
					  deColor &c1, deColor &c2, deColor &c3,
					  deTexCoord &t1, deTexCoord &t2, deTexCoord &t3)
{
	face.Resize(3);

	face.Verts[0].Pos = v1;
	face.Verts[1].Pos = v2;
	face.Verts[2].Pos = v3;

	face.Verts[0].Norm = n1;
	face.Verts[1].Norm = n2;
	face.Verts[2].Norm = n3;

	face.Verts[0].Color = c1;
	face.Verts[1].Color = c2;
	face.Verts[2].Color = c3;

	face.Verts[0].UV = t1;
	face.Verts[1].UV = t2;
	face.Verts[2].UV = t3;

	deVec3d vec1, vec2;
	vec1 = v1 - v2;
	vec2 = v1 - v3;
	face.Normal = Vec3d_Cross(vec1, vec2);
	Vec3d_Normalize(face.Normal);
	face.Dist = Vec3d_Dot(face.Normal, face.Verts[0].Pos);
	face.TextureIndex = 0;
}

#pragma todo (CSG operations)
void deBrush::Subtract(IdeBrush* /*BrushInput*/)
{
/*	deBrush* cutter = (deBrush*)BrushInput;
	if (m_Changed)
		UpdateBrush();
	if (cutter.m_Changed)
		cutter.UpdateBrush();

	m_Octree->Subtract(*(cutter.m_Octree));
	FillVertexBuffers();
	*/
	m_Changed = deFALSE;
}

#pragma todo (brushes might need copying in future)
IdeBrush * deBrush::Copy()
{
	deBrush * p = CopyBrush();
	p->m_CVList = m_CVList;
	p->m_FaceList = m_FaceList;
	p->m_TextureList = m_TextureList;
	p->m_DrawTypeList = m_DrawTypeList;
	p->m_CVNum = m_CVNum;
	p->m_LOD = m_LOD;
	p->m_LOD2 = m_LOD2;
	p->m_Changed = deTRUE;
	return p;
}

struct deBrush_Header_t
{
	short VersionMajor;
	short VersionMinor;
};
static const deBrush_Header_t deBrush_Header = {0,1};
#pragma todo (document file format)
/*
Version 0.1:
October 13, 2002

short		Version_Major
short		Version_Minor
*/
deBoolean deBrush::Serialize(IdeFile* FS)
{
	deBoolean TrueValue = deTRUE, FalseValue = deFALSE;
	long i, j, k, m, length;
	IdeWorld* pWorld;
	IdeRenderTexture* pTex;
	IdeVertexBuffer::BufferType BufType;
	IdeVertexBuffer* pVB;
	deWorldID WorldID;
	deObjectID ObjectID;

	// header information
	DE3D_STREAM_PUT(FS, deBrush_Header.VersionMajor, s16);
	DE3D_STREAM_PUT(FS, deBrush_Header.VersionMinor, s16);
	
	// number of CV's
	length = m_CVList.Length();
	length = min(m_CVNum, length);
	DE3D_STREAM_PUT(FS, length, s32); //sizeof(long)
	// the CV's themselves
	for (i = 0; i < length; i++)
	{
		DE3D_STREAM_PUT(FS, m_CVList[i].x, deDouble); // sizeof(deDouble)
		DE3D_STREAM_PUT(FS, m_CVList[i].y, deDouble); // sizeof(deDouble)
		DE3D_STREAM_PUT(FS, m_CVList[i].z, deDouble); // sizeof(deDouble)
	}
	// number of faces
	length = m_FaceList.Length();
	DE3D_STREAM_PUT(FS, length, s32); //sizeof(long)
	// face coordinates
	for (i = 0; i < length; i++)
	{
		k = m_FaceList[i].Length();
		DE3D_STREAM_PUT(FS, k, s32); //sizeof(long)
		for (m = 0; m < k; m++)
		{
			DE3D_STREAM_PUT(FS, m_FaceList[i][m].u, deFloat); //sizeof(deFloat)
			DE3D_STREAM_PUT(FS, m_FaceList[i][m].v, deFloat);//sizeof(deFloat)
		}
	}
	// some integers and booleans
	DE3D_STREAM_PUT(FS, m_LOD, s32); //sizeof(long)
	DE3D_STREAM_PUT(FS, m_LOD2, s32);//sizeof(long)
	DE3D_STREAM_PUT(FS, m_SmoothNormals, u8); //sizeof(deBoolean)
	DE3D_STREAM_PUT(FS, m_UsingIndexedBuffer, u8); //sizeof(deBoolean)
	DE3D_STREAM_PUT(FS, m_SaveVBuffers, u8); //sizeof(deBoolean)
	DE3D_STREAM_PUT(FS, m_DiffuseColor, u32); //sizeof(deARGB)
	// texture information
	length = m_TextureList.Length();
	DE3D_STREAM_PUT(FS, length, s32); //sizeof(long)
	for (i = 0; i < length; i++)
	{
		WorldID = 0;
		ObjectID = 0;
		pTex = m_TextureList[i];
		if (pTex)
		{
			WorldID = pTex->GetWorldID();
			pWorld = IdeWorld_GetManager()->GetWorld(((IdeWorldObject*)this)->GetWorldID());
			if (pWorld)
			{
				WorldID = pWorld->GetLocalIDFromLoadedWorld(WorldID);
				ObjectID = pTex->GetObjectID();
			}
			else
				WorldID = 0;
		}
		DE3D_STREAM_PUT(FS, WorldID, u16); //sizeof(deWorldID)
		DE3D_STREAM_PUT(FS, ObjectID, u32); //sizeof(deObjectID)
	}
	// the actual geometry, if it needs to be saved
	if (!m_SaveVBuffers)
	{
		DE3D_STREAM_PUT(FS, FalseValue, u8); //sizeof(deBoolean)
	}
	else
	{
		DE3D_STREAM_PUT(FS, TrueValue, u8); //sizeof(deBoolean)
		length = m_SubVBs.Length();
		DE3D_STREAM_PUT(FS, length, s32); //sizeof(long)
		for (i = 0; i < length; i++)
		{
			pVB = m_SubVBs[i];
			pVB->Lock();
			k = pVB->GetIndexCount();
			if (k <= 0)
			{
				DE3D_STREAM_PUT(FS, FalseValue, u8); //sizeof(deBoolean)
			}
			else
			{
				j = 2; //sizeof(short)
				DE3D_STREAM_PUT(FS, TrueValue, u8); //sizeof(deBoolean)
				DE3D_STREAM_PUT(FS, k, s32); //sizeof(long)
				DE3D_STREAM_PUTP(FS, pVB->GetBuffer(IdeVertexBuffer::BUFFER_INDICES16), j*k);
			}

			// number of verts
			k = pVB->GetVertexCount();
			DE3D_STREAM_PUT(FS, k, s32); //sizeof(long)
			// for each type of vert data, write out the whole block
			for (BufType = IdeVertexBuffer::BUFFER_POSITION; 
				BufType < IdeVertexBuffer::BUFFER_INDICES16;
				((int&)BufType)++)
			{
				if (!(pVB->BufferExists(BufType)))
				{
					DE3D_STREAM_PUT(FS, FalseValue, u8); //sizeof(deBoolean)
				}
				else
				{
					DE3D_STREAM_PUT(FS, TrueValue, u8); //sizeof(deBoolean)
					pVB->GetBufferDataType(BufType, &j);
					DE3D_STREAM_PUTP(FS, pVB->GetBuffer(BufType), j*k);
				}
			}

			k = (long)(pVB->GetRenderType());
			DE3D_STREAM_PUT(FS, k, s32); //sizeof(long)

			pVB->Unlock();
		}
	}

	return deTRUE;
}

deBoolean deBrush::DeSerialize(IdeFile* FS, long DataLength)
{
	deBoolean TempBool;
	u32 AmtRead;
	size_t i, j, k, m, length;
	IdeVertexBuffer::BufferType BufType;
	IdeVertexBuffer* pVB;
	deWorldID WorldID;
	deObjectID ObjectID;

	short VersionMajor, VersionMinor;

	AmtRead = 0;
	
	// header information
	DE3D_STREAM_GET(FS, VersionMajor, s16, AmtRead, DataLength);
	DE3D_STREAM_GET(FS, VersionMinor, s16, AmtRead, DataLength);

	// check the version
	if (VersionMajor > deBrush_Header.VersionMajor ||
		(VersionMajor == deBrush_Header.VersionMajor && VersionMinor > deBrush_Header.VersionMinor))
		return deFALSE;

	// get ourselves a new main vertexbuffer
	if (m_MainVBuffer)
	{
		IdeVertexBuffer::BufferType BufType;
		m_MainVBuffer->Lock();
		for (BufType = IdeVertexBuffer::BUFFER_POSITION; BufType < IdeVertexBuffer::BUFFER_COUNT; ((int&)BufType)++)
		{
			if (m_MainVBuffer->BufferExists(BufType))
				m_MainVBuffer->DestroyBuffer(BufType);
		}
		m_MainVBuffer->SetRenderType(IdeVertexBuffer::RENDER_POINTLIST);
		m_MainVBuffer->Unlock();		
	}
	else
		return deFALSE;

	if (VersionMajor == 0 && VersionMinor == 1)
	{
		// number of CV's
		DE3D_STREAM_GET(FS, length, s32, AmtRead, DataLength); //long
		m_CVNum = length;
		if (!RecalcListQuantities(deFALSE))
			return deFALSE;
		m_CVList.Resize(m_CVNum);
		// the CV's themselves
		for (i = 0; i < length; i++)
		{
			DE3D_STREAM_GET(FS, m_CVList[i].x, deDouble, AmtRead, DataLength); //deDouble
			DE3D_STREAM_GET(FS, m_CVList[i].y, deDouble, AmtRead, DataLength); //deDouble
			DE3D_STREAM_GET(FS, m_CVList[i].z, deDouble, AmtRead, DataLength); //deDouble
		}
		// number of faces
		DE3D_STREAM_GET(FS, length, s32, AmtRead, DataLength); //long
		// if there should be a set amount, and we don't meet the amt, something's wrong
		if (m_QuantityDefs.QuantityRatio != DataQuantity_t::Quantity_Unmanaged && 
			length != m_FaceList.Length())
			return deFALSE;
		m_FaceList.Resize(0);
		m_FaceList.Resize(length);
		// face coordinates
		for (i = 0; i < length; i++)
		{
			DE3D_STREAM_GET(FS, k, s32, AmtRead, DataLength); //long
			// if there should be a set amount, and we don't meet the amt, something's wrong
			// there's a bit of leeway here, since these lists are sized to a "max"
			if (m_QuantityDefs.QuantityRatio != DataQuantity_t::Quantity_Unmanaged && 
				k < m_FaceList[i].Length())
				return deFALSE;
			m_FaceList[i].Resize(k);
			for (m = 0; m < k; m++)
			{
				DE3D_STREAM_GET(FS, m_FaceList[i][m].u, deFloat, AmtRead, DataLength); //deFloat
				DE3D_STREAM_GET(FS, m_FaceList[i][m].v, deFloat, AmtRead, DataLength); //deFloat
			}
		}
		// some integers and booleans
		DE3D_STREAM_GET(FS, m_LOD, s32, AmtRead, DataLength); //long
		DE3D_STREAM_GET(FS, m_LOD2, s32, AmtRead, DataLength); //long
		DE3D_STREAM_GET(FS, m_SmoothNormals, u8, AmtRead, DataLength); //deBoolean
		DE3D_STREAM_GET(FS, m_UsingIndexedBuffer, u8, AmtRead, DataLength); //deBoolean
		DE3D_STREAM_GET(FS, m_SaveVBuffers, u8, AmtRead, DataLength); //deBoolean
		DE3D_STREAM_GET(FS, m_DiffuseColor, u32, AmtRead, DataLength); //deARGB
		// texture information
		DE3D_STREAM_GET(FS, length, s32, AmtRead, DataLength); //long
		// if there should be a set amount, and we don't meet the amt, something's wrong
		if (m_QuantityDefs.QuantityRatio != DataQuantity_t::Quantity_Unmanaged && 
			length != m_TextureList.Length())
			return deFALSE;
		m_CachedTextures.Resize(length);
		for (i = 0; i < length; i++)
		{
			deIDPair TexEntry;
			DE3D_STREAM_GET(FS, WorldID, u16, AmtRead, DataLength); //deWorldID
			DE3D_STREAM_GET(FS, ObjectID, u32, AmtRead, DataLength); //deObjectID
			TexEntry.wid = WorldID;
			TexEntry.oid = ObjectID;
			m_CachedTextures[i] = TexEntry;
		}
		// the actual geometry, if it is there
		DE3D_STREAM_GET(FS, TempBool, u8, AmtRead, DataLength); //deBoolean
		if (TempBool)
		{
			DE3D_STREAM_GET(FS, length, s32, AmtRead, DataLength); //long
			// if there should be a set amount, and we don't meet the amt, something's wrong
			if (m_QuantityDefs.QuantityRatio != DataQuantity_t::Quantity_Unmanaged && 
				length != m_SubVBs.Length())
				return deFALSE;
			m_SubVBs.ResizeQuick(length, deTRUE);
			for (i = 0; i < length; i++)
			{
				pVB = m_SubVBs[i];
				if (!pVB)
				{
					pVB = IdeVertexBuffer_CreateSubVBuffer(m_MainVBuffer);
					if (!pVB)
						return deFALSE;
					m_SubVBs[i] = pVB;
				}
				pVB->Lock();
				j = sizeof(short);
				DE3D_STREAM_GET(FS, TempBool, u8, AmtRead, DataLength); //deBoolean
				if (TempBool)
				{
					m_MainVBuffer->Lock();
					m_MainVBuffer->CreateBuffer(IdeVertexBuffer::BUFFER_INDICES16, deFALSE);
					m_MainVBuffer->Unlock();
					DE3D_STREAM_GET(FS, k, s32, AmtRead, DataLength); //long
					pVB->SetBufferSize(k, deTRUE);
					DE3D_STREAM_GETP(FS, pVB->GetBuffer(IdeVertexBuffer::BUFFER_INDICES16), j*k, AmtRead, DataLength);
				}

				// number of verts
				DE3D_STREAM_GET(FS, k, s32, AmtRead, DataLength); //long
				pVB->SetBufferSize(k, deFALSE);
				// for each type of vert data, write out the whole block
				for (BufType = IdeVertexBuffer::BUFFER_POSITION; 
					BufType < IdeVertexBuffer::BUFFER_INDICES16;
					((int&)BufType)++)
				{
					DE3D_STREAM_GET(FS, TempBool, u8, AmtRead, DataLength); //deBoolean
					if (TempBool)
					{
						m_MainVBuffer->Lock();
						m_MainVBuffer->CreateBuffer(BufType, deFALSE);
						m_MainVBuffer->Unlock();
						long size;
						pVB->GetBufferDataType(BufType, &size);
						j = size;
						DE3D_STREAM_GETP(FS, pVB->GetBuffer(BufType), j*k, AmtRead, DataLength);
					}
				}

				DE3D_STREAM_GET(FS, k, s32, AmtRead, DataLength); //long
				pVB->SetRenderType((IdeVertexBuffer::RenderType)(k));

				pVB->Unlock();
			}
			m_Changed = deFALSE;
		}
		else
		{
			// no stored geometry, so we need to generate some
			m_Changed = deTRUE;		
		}
	}

	return deTRUE;
}

deBoolean deBrush::DeSerializeLoad()
{
	IdeWorldObject*		pObject;
	IdeRenderState*		pState;
	IdeRenderTexture*	pTex;
	IdeWorld*			pWorld;
	deWorldID			WorldID;
	deObjectID			ObjectID;
	size_t				i, length;

	length = m_CachedTextures.Length();
	m_TextureList.Resize(length);

	for (i = 0; i < length; ++i)
	{
		WorldID = m_CachedTextures[i].wid;
		ObjectID = m_CachedTextures[i].oid;
		
		pTex = NULL;
		pWorld = IdeWorld_GetManager()->GetWorld(((IdeWorldObject*)this)->GetWorldID());
		if (pWorld)
		{
			WorldID = pWorld->GetWorldIDUsingLocalID(WorldID, deFALSE);
			pWorld = IdeWorld_GetManager()->GetWorld(WorldID);
			if (pWorld)
			{
				pObject = pWorld->GetWorldObject(ObjectID);
				if (pObject)
				{
					pState = (IdeRenderState*)(pObject->GetWOInterface(IdeRenderState_GetWOInterfaceID()));
					if (pState)
						pTex = (IdeRenderTexture*)(pState->GetRSInterface(IdeRenderState::TYPE_TEXTURE));
				}
			}
		}
		if (pTex)
			pTex->Claim();
		m_TextureList[i] = pTex;	
	}

	return deTRUE;
}

void deBrush::SpecificRotate(deVec3d , deTransformInfo &)
{
}

void deBrush::SpecificTranslate(deVec3d )
{
}

void deBrush::SpecificScale(deVec3d , deDouble )
{
}


//==============================================
deBPoly::deBPoly(long verts)
{
	Verts=new deLVert[verts];
	NumVerts=verts;
	TextureIndex = -1;
}
deBPoly::~deBPoly()
{
	if(Verts)delete Verts;
}
deBPoly::deBPoly(const deBPoly & ref) 
{
	Normal=ref.Normal;
	Dist=ref.Dist;
	NumVerts=ref.NumVerts;
	Verts=new deLVert[NumVerts];
	memcpy(Verts,ref.Verts,NumVerts*sizeof(deLVert));
	TextureIndex = ref.TextureIndex;
}
deBPoly & deBPoly::operator=(deBPoly & ref)
{
	Normal=ref.Normal;
	Dist=ref.Dist;
	NumVerts=ref.NumVerts;
	if(Verts)
		delete[]Verts;
	Verts=new deLVert[NumVerts];
	memcpy(Verts,ref.Verts,NumVerts*sizeof(deLVert));
	TextureIndex = ref.TextureIndex;
	return *this;
}
void deBPoly::Resize(long verts)
{
	if (Verts && verts == NumVerts)
		return;
	if(Verts)
		delete[]Verts;
	Verts=new deLVert[verts];
	NumVerts=verts;
}

