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


#ifndef	__NRAYTRACERSCENE__
#define	__NRAYTRACERSCENE__


		#include "core/geometry_tree.h"
		#include "bih/bih.h"


namespace GS {

	namespace Core {
		class Object;
		class Geometry;
		struct Material;
	}
	namespace S3D {
		class Scene;
		struct MLight;
		struct MObject;
	}
	namespace Raytrace {
		using Core::IGeometryTree;

//
struct	Trace : public Core::GeometryTrace
{
		Vector4			pi;					///< Intersection point.
		Vector4			n;					///< Normal.

		float			ir;					///< Current media index of refraction.
		float			td;					///< Total distance traveled by the ray.

		Core::Object	*o;					///< Object intersected.

		Trace(bool closest = true) : Core::GeometryTrace(closest)
		{
			ir = 1;
			td = 0;
			m = NULL;
		}
};

///
struct	Object
{
		Core::Object	*o;					///< Object.
		Core::sGeometry	og, g;				///< Associated geometry.

		AutoPtr <IGeometryTree> tree;

		Object() : o(0) {}
};

///
struct	Light
{
		IGeometryTree	*g;					///< Shadow cache tree.
		uint			ip;					///< Shadow cache polygon index.

		S3D::MLight		*l;

		Light() : l(0) {}
};

/*!
	@short	Raytracer scene acceleration structure.
*/
class	SceneBIH : BIH::Tree
{
		Array <Object> obj;					///< Object array.

		/// Trace leaf content.
		void		TraceLeaf(BIH::Node *, float tmin, float tmax, BIH::Trace &, void *parm = 0);

		/// Add an object to the scene BIH.
		void		AddObject(Core::ResourceFactory &, S3D::MObject *, uint &obj_count, MinMax *varray, bool shadow);

public:

		/*!
			@short	Translate proxy geometry.

			The raytracer may need to make a hard copy of a geometry for example
			to freeze its modifiers before building the acceleration structure.

			This function returns the original geometry from the proxy one as
			returned by a primary ray test.

			@note	If the geometry is not a proxy, it will be returned as is.
		*/
		Core::Geometry *TranslateGeometry(Core::Geometry *) const;

/*!
	@group	Statistics
	@{
*/
		uint		ray_count;				///< Number of ray traced.

		/// Reset internal statistic counters.
		void		ResetStats();
/// @}

		/// Build scene tree based on a scene instance.
virtual bool		SetScene(Core::ResourceFactory &, const S3D::Scene *, bool shadow = false);
		/// Free tree structures.
virtual void		Free();

		/// Raytrace hierarchy.
virtual	void		RaytraceScene(Trace &, const Vector4 &s, const Vector4 &d, float l = -1.f);

		SceneBIH() { min_leaf_vcount = 3; }
};

	} // Raytrace
} // GS


#endif	// __NRAYTRACERSCENE__
