#pragma once

#include "DXVector3.h"
#include "DXPlane.h"
#include "MeshContainer.h"

class VertexDeclaration;

class DXFUNCTIONS_API BSPTree
{
	enum BSPTRIANGLECLASS
	{
		BSP_UNKNOWN = 0,
		BSP_POS,
		BSP_NEG,
		BSP_SLICE,
		BSP_PLANAR
	};

	struct BSPTreeNode
	{
		DXPlane Splitter;
		unsigned TriangleCount;
		unsigned* pTriangleIndexList;
		//AABB Bound; TODO: optinal
		BSPTreeNode* pPos;
		BSPTreeNode* pNeg;

		BSPTreeNode(void) { ZeroMemory(this, sizeof(BSPTreeNode)); }

		~BSPTreeNode(void) 
		{ 
			delete pPos; 
			delete pNeg;
			delete pTriangleIndexList;
		}
	};

	BSPTreeNode* m_pRoot;

	//MeshContainer*  m_pMesh;
	//unsigned		m_iSubset;

	void* m_pVertexData;
	unsigned m_VertexStride;
	unsigned m_BaseVertexIndex;
	
	void SplitTriangle(const DXPlane& splitter, const unsigned i1, const unsigned i2, const unsigned i3);
	BSPTRIANGLECLASS ClassifyTriangle(const DXPlane& splitter, const unsigned i1, const unsigned i2, const unsigned i3) const;
	DXPlane FindSplitter(BSPTreeNode* const pNode, unsigned& pos, unsigned& neg, unsigned& slice, unsigned& planar) const;
	
	void SplitNode(BSPTreeNode* const pNode) const;

	void BuildIndex16(BSPTreeNode* const pNode, unsigned short* &pIBDst, const DXVector3& ViewPoint);
	void BuildIndex32(BSPTreeNode* const pNode, unsigned* &pIBDst, const DXVector3& ViewPoint);

public:
	//BSPTree(MeshContainer* const pMesh, unsigned iSubset);
	BSPTree(LPDIRECT3DVERTEXBUFFER9 pVB, LPDIRECT3DINDEXBUFFER9 pIB, VertexDeclaration* vdecl, const unsigned trianglecount, const unsigned basevertexindex, const unsigned StartIndex);
	~BSPTree(void) { delete m_pRoot; }

	BSPTreeNode* GetRoot(void) const { return m_pRoot; }

	void BuildIndexBuffer(void* pIBData, bool bIndex32, const DXVector3& ViewPoint, const DXMatrix& matWorldToMesh);
};
