///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// ZParticule File
///
///		- Emitter Class, Particule Class
///		- Manage the Particule properties of the 3D scene
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////





#ifndef __ZOOPART_H__
#define __ZOOPART_H__



#include	"..\Basic\ZooStd.h"
#include	"..\Scene Graph\ZooNodeGraph.h"
#include	"..\Datas\ZooMesh.h"



#define PARAM_COLOR			1
#define PARAM_SIZE			2
#define PARAM_SPIN			3

#define PI					3.14159

/**************************************************************/
enum {
	EFFECT_CONSTANT=1,					// Constant force
	EFFECT_ELECTRIC,					// Electric charge
	EFFECT_MAGNETIC,					// Electric charge
	EFFECT_HELICOID,					// Helicoidal trajectory
	EFFECT_CHAOTIC0,					// Chaotic influance
	EFFECT_PLANCOLL,					// Helicoidal trajectory
	EFFECT_CHAOTIC1};					// Chaotic influance
/**************************************************************/


/***************************************************************
****					VOLUME MASK							***/
enum {
	VOLUME_CONE=1,						// Cone Volume mask
	VOLUME_SPHERE,						// Sphere Volume mask
	VOLUME_PLAN,						// Plan Volume mask
	VOLUME_LINE};						// Cylinder Volume mask
/**************************************************************/

/**************************************************************/
#define PCL_DISABLE			0x00		// Emitter is disable
#define PCL_ACTIVE			0x01		// Emitter has some alive particles left
#define PCL_ENABLE			0x02		// Emitter is enable
#define PCL_RESTART			0x04		// Restart the emitter
/**************************************************************/

#define PCL_BILLBOARD		0x01		// Particles are billboarded
#define PCL_RAINBOW			0x02		// Particles are random colored
#define PCL_JITTER			0x04		// Particles are jittered (works for billborded and not billborded)

#define PCL_INFINIT			0x01		// Emitter has infinit life
#define PCL_ADDITIVE		0x02		// Emitter is rendered with additive color


typedef struct
{
	float		pos;
	ZVector4	value;
} T_COLOR;

typedef struct
{
	float		pos;
	float		value;
} T_PARAM;

typedef struct
{
	int			type;			// Id to know what kind of volume it is
	ZVector3	vectorA;		// volume first vector definission
	ZVector3	vectorB;		// volume first vector definission
} T_VOLUME;

typedef struct
{
	float		age;
	float		size;
	float		spin;
	float		weight;
	ZVector3	rot;				// A random axe and a random angle for jitter effect

	ZVector4	color;
	ZVector3	speed;	
	ZVector3	position;	
} T_PARTICLE;



///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///		ZParticle Class
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class ZParticle  : public ZData
{
protected:
	ZMesh			*mesh;

public:
	int				mask;
	float			life;
	float			rate;
	float			weight;
	float			polarity;

	vector<T_PARAM> spin;
	vector<T_PARAM> size;
	vector<T_COLOR>	color;

	void	SortLists();
	void	SetMesh(ZMesh *newMesh);
	void	SetParam(T_PARTICLE *part);
	int		SetParticle(ZMesh *_mesh, int _mask, float _life, float _rate, float _weight, float _size, float _spin, float _polarity);
	

	///////////////////////////////////////////////////////////////////////////
	/// Get the mesh														///
	///////////////////////////////////////////////////////////////////////////
	inline ZMesh* ZParticle::GetMesh()
	{
		return mesh;
	}

	///////////////////////////////////////////////////////////////////////////
	/// Constructor/Destructor												///
	///////////////////////////////////////////////////////////////////////////
	ZParticle(int s3d, ZMesh *_mesh,  int _mask, float _life, float _rate, float _weight, float _size, float _spin, float _polarity);
	virtual ~ZParticle();
};








///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///		ZEffect Class
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class ZEffect  : public ZData
{
public:
	int			etype;
	ZVector3	vectorA;
	ZVector3	vectorB;
	ZVector3	vectorC;

	int			SetEffect(int type, ZVector3 _vA, ZVector3 _vB, ZVector3 _vC);

	///////////////////////////////////////////////////////////////////////////
	/// Constructor/Destructor												///
	///////////////////////////////////////////////////////////////////////////
	ZEffect(int s3d, int type, ZVector3 _vA, ZVector3 _vB, ZVector3 _vC);
	virtual ~ZEffect();

};



typedef struct
{
	int					nbpart;
	int					nbNew;

	ZParticle			*parttype;
	vector<T_PARTICLE*>	list;
} T_PCL_LIST;




///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///		ZEmitter Class
///
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class ZEmitter : public ZNodeGraph
{

public:
	int					state;
	int					nbMaxPart;
	bool				visible;							// Flag to know if the system is visible
	bool				hasEffects;							// Flag to know if it has effect(s) or not
	float				dt;									// Timestep for numerical integration
	int					nbFrame;

	// Emitter parameters
	int					mask;
	float				life;
	float				age;

	ZNodeGraph			*pFather;
	ZVector3			RealPos;
	ZMatrix				RealAngleMat;
	ZMatrix				RealWorldMat;
	ZMatrix				RealFatherMat;
	T_VOLUME			volume;



	// Particles
	vector<T_PCL_LIST>	particlelist;
	vector<ZEffect*>	effectlist;

	
	
	
	int		SetEmitter(int _mask, float _life, T_VOLUME _volume);
	int		LinkParticle(ZParticle *newType);
	int		LinkEffect(ZEffect *newEffect);
	int		NextStep();
	void	AddParticle(T_PCL_LIST *pcl);
	int		ApplyEffect(T_PARTICLE *part, float polarity);
	int		Render(ZVector3 camRot, ZMatrix matCam);
	int		RenderAdditive(ZVector3 camRot, ZMatrix matCam);


	///////////////////////////////////////////////////////////////////////////
	/// Constructor/Destructor												///
	///////////////////////////////////////////////////////////////////////////
	ZEmitter(int s3d, int _mask, float _life, T_VOLUME _volume);
	~ZEmitter();
};


#endif