/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


#ifndef	__NGEOMETRYKDTREE__
#define	__NGEOMETRYKDTREE__


		#include "core/geometry_tree.h"
		#include "container/narray.h"
		#include "container/nlist.h"


namespace GS {
	namespace Core {
		class Geometry;

/*!
	@short	Geometry polygon KD-tree.
	@author	Thomas Simonnet (thomas@movida-mail.com)
*/
class	GeometryKDTree : public IGeometryTree
{
private:

	Array <sMaterial> material_table;
	Array <uint> pol_index;

	struct KDTreeNode
	{
		char	m_KDTREE_NODE_TYPE_SPLIT;
		int		m_KDTREE_NODE_ID_ROPE[6];
		float	m_KDTREE_NODE_AABB[6];
		float	m_KDTREE_NODE_VALUE_SPLIT;
		int		m_KDTREE_NODE_ID;
		int		m_KDTREE_NODE_ID_CHILD_LEFT;
		int		m_KDTREE_NODE_ID_CHILD_RIGHT;
		bool	m_KDTREE_NODE_IS_LEAF;
		int		m_KDTREE_NODE_COUNT_POLY;
		int*	m_KDTREE_NODE_ID_VTX;
		int*	m_KDTREE_NODE_ID_POLY;

		KDTreeNode();
		~KDTreeNode(){delete []m_KDTREE_NODE_ID_POLY; delete []m_KDTREE_NODE_ID_VTX;};
	};
 	/*#define KDTREE_NODE_TYPE_SPLIT			0
 	#define KDTREE_NODE_ID_ROPE				1
 	#define KDTREE_NODE_AABB				25
 	#define KDTREE_NODE_VALUE_SPLIT			49
 	#define KDTREE_NODE_ID					53
 	#define KDTREE_NODE_ID_CHILD_LEFT		57
 	#define KDTREE_NODE_ID_CHILD_RIGHT		61
 	#define KDTREE_NODE_IS_LEAF				65
 	#define KDTREE_NODE_COUNT_POLY			66
 	#define KDTREE_NODE_ID_POLY				70
*/
	#define KDTREE_X_AXIS					0
	#define KDTREE_Y_AXIS					1
	#define KDTREE_Z_AXIS					2

	#define KDTREE_SIDE_LEFT				0
	#define KDTREE_SIDE_RIGHT				1
	#define KDTREE_SIDE_BOTTOM				2
	#define KDTREE_SIDE_TOP					3
	#define KDTREE_SIDE_BACK				4
	#define KDTREE_SIDE_FRONT				5

	int m_count_bih;
	float * m_TempFloatBih;

	List <int> m_ArrayCountPoly;
	List <Geometry*> m_PointerGeo;

	KDTreeNode*	m_NodeTree;
	int		m_SizeTree;

	int* m_RealIdPoly;

	float* m_Vtx;
	Vector4* m_OptimizeEdgePoly;

protected:

		int					planeBoxOverlap(float normal[3], float vert[3], float maxbox[3]);
		int					triBoxOverlap(float boxcenter[3],float boxhalfsize[3],float Verts1[3],float Verts2[3],float Verts3[3]);
		int					GetKDtreeSideAABB(float* _AABB, Vector4 &_EntryPoint, int &_LastEntrySide);
		bool				IntersectTriangle(const Vector4 &s, const Vector4 &d, float* Vtx1, float* Vtx2, float* Vtx3, Vector4* _Edge1, Vector4* _Edge2, float &l_Dist, float &u, float &v, bool& _Backface);
		bool				AABBIntersectRay(float* _AABB, const Vector4 &o, const Vector4 &d, float &tmin, float &tmax);
		void				CreateRope(int &_CurrentNode, int *_RopeArray);
		void				IncreaseSizeNodeKdtreeBuffer(int _IncreaseSize);
		void				CreateNodeKdtree(int &_CurrentNode, int *_IdPoly, int *_IdVtx, int _CountPoly, float *_Vtx, int _CountVtx, int _CurrentDepth);

public:

/*!
	@name	KD-Tree specific functions.
	@{
*/
		/// Retrieve the index of the closest KD-tree node to a given location in world space.
		int					InsideKdTreeNode(const Vector4 &p, bool CheckInside=false);
/// @}

/*!
	@name	Interface core functions.
	@{
*/
		/// Raytrace the geometry tree.
virtual	void				RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f);
		/// Build tree from a geometry.
virtual	bool				BuildFromGeometry(ResourceFactory &gf, Geometry *geo);
		/// Free all internal structures.
virtual	void				Free();
/// @}

		GeometryKDTree();
		~GeometryKDTree()
		{	Free();	}
};

	} // Core
} // GS


#endif	// __NGEOMETRYKDTREE__
