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


#ifndef	__NISOSURFACE__
#define	__NISOSURFACE__


		#include "math/vector.h"
		#include "thread/mutex.h"


namespace GS {
	namespace Core {
		class Geometry;

/*!
	@short	Isosurface.
	@author Thomas Simonnet (scorpheus@hotmail.com)
*/
class	Isosurface
{
private:

	static const int EdgeArray[256];
	static const int TriTable[256][16];

	Vector4		m_Pos;

	// grid definition
	Vector4		m_NbGridCase;
	float		*m_Grid;
	Vector4		m_GridSize;

	float		m_IsoValue;
	
	// to know on which point of the grid we have to create a triangle
	Vector4 *	m_TabIndexValid;
	int		m_NbIndexValid;

	// to precalculate
	Vector4 m_CaseSizeDivNbCase;


	struct STriangle
	{
		Vector4 m_Vertex[3];		// the 3 vertex of the triangle
		int m_Num[3];		// number of the side who have each vertex
	};	

	struct TVertex
	{
		float x, y, z;       // Position
		float nx, ny, nz;       // Normal
		float u, v;       // UV coordinate
		unsigned long Color; // Color

		TVertex(){x=y=z=nx=ny=u=0;  nz=v=1; Color =0xFF19E395;};
	};

	inline	void CalcNormalX(float &_x, float &_y, float &_z, Vector4 &_Normal);
	inline	void CalcNormalY(float &_x, float &_y, float &_z, Vector4 &_Normal);
	inline	void CalcNormalZ(float &_x, float &_y, float &_z, Vector4 &_Normal);

	// function permit to linear interpolate between vector
	void interpolateVect(Vector4 &_Vect1, Vector4 &_Vect2, float &_Val1, float &_Val2, Vector4&_Vect);

	// function permit to linear interpolate between val
	float interpolateVal(float &_Val1, float &_Val2, float _Val_cible1, float _Val_cible2);

	// Set the value of the vertex
	void EvalPos(float &_x, float &_y, float &_z, Vector4 &_CasePosition);

	// return the good float with the 3d parameter in the grid
	int GridIndex(float &_x, float &_y, float &_z)const;

	/// calcul the polygon for one case, and return the number of triangle for the polygon
	int	CalculPolygon(float &_x, float &_y, float &_z, STriangle* _TriangleList);

	// draw the triangle in the cellule x,y, z
	void		RenderCell(uint &vtx_count, float &_x, float &_y, float &_z);

	// compute the metaball array to fill the grid with ball
	void		ComputeMetaball(int nb_metaball, Vector4* pos_metaball, float* value_metaball);

	Threading::Mutex m_Mutex;

public:

	//max vertex to build the mesh
	static uint m_MaxNbVertex;

	// temp for build the mesh
	static int m_MaxIdx;
	int m_CountIdxBuffer;
	static int* m_TempIdxBuffer ; // index buffer containing the geometry

	// temp for build the mesh
	static TVertex* m_TempVertexBuffer ; // Vertex buffer containing the geometry

		/// Initialize the iso-surface field
		bool		Init(const Vector4 &_pos, const Vector4 &size, const Vector4 &step);

		/// Get the iso-surface field size
		void		GetFieldSize(int &x, int &y, int &z);

		/// Get the iso-surface field
		void		GetField(float *_Grid);

		/// Triangularize the iso-surface
		void		Triangularize(Geometry* geometry, int nb_metaball, Vector4* pos_metaball, float* value_metaball);

		Isosurface();
virtual	~Isosurface();
};

	} // Core
} // GS


#endif	// __NISOSURFACE__
