/*********************************************************************

Name:		Raytracer
Author:		Kamil Szatkowski "Netrix" (C)
Website:	http://www.netrix.org.pl/

*********************************************************************/
#pragma once
#include "NLib/nMath.hpp"
#include "NLib/nDynamicTable.hpp"
#include "NLib/nAlignedDynamicTable.hpp"
#include "NLib/nDataVector.hpp"
#include "RegionUtilities.hpp"
#include "Scene.hpp"

class UniformSpaceSubdivision
{
	typedef NIne::NDynamicTable<NIne::NMVector3f> NMVectorArray;
	typedef NIne::NDynamicTable<NIne::NUint32> NUint32Array;
	typedef NIne::NDataVector<NIne::NUint32> NUint32Vector;
	typedef NIne::NDataVector<NUint32Vector> NUint32VectorVector;
	typedef NIne::NAlignedDynamicTable<FaceData> FaceDataArray;

public:
	UniformSpaceSubdivision();

	void createSubdivision(Scene* pScene, bool bResetCache);

	bool loadSubdivision(const char* szFile);

	void saveSubdivision(const char* szFile);

	void releaseSubdivision();

	const FaceData* findNearestFace(const NIne::NMVector3f& v3Origin, const NIne::NMVector3f& v3Direction, float fMaxDistance, RayTestOutput* opRTO);
	bool findObstacle(const NIne::NMVector3f& v3Origin, const NIne::NMVector3f& v3Direction, float fMaxDistance);

	bool setUpTriangleSearch(const NIne::NMVector3f& v3Origin, const NIne::NMVector3f& v3Direction); // Sets up searching, returns validation of ray

	bool findNextVoxel();
	bool findNextVoxel(float fMaxT);

	NIne::NUint32 getVoxelIndex() const;

	const NUint32Vector* getTriangles() const;
	const NUint32Vector* getTriangles(NIne::NUint32 uIndex) const;

	void getSubdivisionSizes(NIne::NUint32* pX, NIne::NUint32* pY, NIne::NUint32* pZ) { *pX = m_subdivDim[0]; *pY = m_subdivDim[1]; *pZ = m_subdivDim[2]; }
	const NIne::NMVector3f& getVoxelSize() const { return m_v3Size; }

	bool checkPointInVoxel(const NIne::NMVector3f& v3Point);

	operator bool() { return m_bCreate; }

private:
	bool m_bCreate;

	Scene* m_pScene;

	NUint32VectorVector m_aCells;
	NUint32Array m_aHashes;

	NIne::NMVector3f m_v3Min,		// Global min
					 m_v3Max,		// Global max
					 m_v3Size;		// Voxel size
	int m_subdivDim[3];				// x, y, z

	// Search parameters
	int m_voxelIndex[3];
	int m_voxelSteps[3];

	NIne::NMVector3f m_v3TVec;		// movements on axises
	NIne::NMVector3f m_v3DtVec;		// Vec with move steps for every direction	

	// Temp local search
	bool m_bCalculated;
	NIne::NMVector3f m_v3LocalMin;
	NIne::NMVector3f m_v3LocalMax;
};