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


#ifndef	__NGEOMETRYBIH__
#define	__NGEOMETRYBIH__


		#include "bih/bih.h"
		#include "core/shader_tree.h"
		#include "core/material.h"
		#include "core/geometry.h"
		#include "core/geometry_tree.h"


namespace GS {
	namespace Core {
		struct ResourceFactory;

/// BIH ray/triangle intersection acceleration structure.
struct	GeometryBIHAccel
{
	char		cu, cv;
	Array <float> k;
	float		d;
};

struct	GeometryBIHMaterial
{
	sMaterial	material;
	sShaderTree	shader_tree;
};

/*
	@short	Geometry polygon bounding interval hierarchy.

	Raytracing/intersection acceleration structure theoretically
	performing within 70% of the SAH/KD-Tree performances.

	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	GeometryBIH : public IGeometryTree, public BIH::Tree
{
		Array <GeometryBIHMaterial> material_table;	///< Material table.
		Array <uint> pol_index;

		Array <GeometryBIHAccel> acc;					///< Raytracing lookup tables.

		/// Trace leaf content.
		void			TraceLeaf(BIH::Node *leaf, float tmin, float tmax, BIH::Trace &trace, void *parm = 0);
		/// Build raytracing lookup tables.
		bool			BuildLUT();

public:

		/// Return the raytracing LUT structure.
		const GeometryBIHAccel *GetRaytracingAccelerationStructure() const { return acc; }

		/// Fast polygon test.
		bool			FastPolyTest(uint ip, Vector4 &s, Vector4 &d, float l = -1.f);

		void			RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l = -1.f);
		bool			BuildFromGeometry(ResourceFactory &, Geometry *);
		void			Free();
};

/*!
	@short	Geometry BIH tree.
	@author	Emmanuel Julien (ejulien@gsworks.fr)
*/
class	GeometryBIHTree : public IGeometryTree
{
		GeometryBIH		bih;

public:

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

		~GeometryBIHTree()
		{	Free();	}
};

	} // Core
} // GS


#endif	// __NGEOMETRYBIH__
