#ifndef _PSTREAM_H
#define _PSTREAM_H

#if C2504 
#pragma message("PStream.h")
#endif

#include "D3D11Client.h"

#define MAXPARTICLE 3000

//==============================================
//				GS-based particle stream
//==============================================

struct GSCB_Particle {
	D3DXMATRIX VP;
	D3DXVECTOR4 Light;
	UINT32 isShadow;
	D3DXVECTOR3 CDir;
};

struct PARTICLE_VERTEX {
	D3DXVECTOR3 pos;	//12
	float size;			//16
	float mix;			//20
	UINT32 tidx;		//24
};

struct ParticleSpec {
	VECTOR3
		pos,
		vel;
	double
		size,
		alpha0,
		t0;
	int texidx;
	DWORD flag;
	ParticleSpec
		*prev,		//links with previous particle in a chain
		*next;		//links with next particle
};

class D3D11ParticleStream : public oapi::ParticleStream {
public:
	D3D11ParticleStream( PARTICLESTREAMSPEC *_pss, OBJHANDLE _obj );
	~D3D11ParticleStream();

	static void GlobalInit();
	static void GlobalExit();

	virtual void Update();

	static void InitRender();
	virtual void Render();

	static void InitRenderShadow();
	virtual void RenderShadow();

protected:
	ParticleSpec *CreateParticle( const VECTOR3 &pos, const VECTOR3 &vel, double &size, double &alpha );
	void DeleteParticle( ParticleSpec *P );
	float LevelToAlpha( double level );
	float AtmToAlpha( double adens );
	void ComputeSpriteNormal( const VECTOR3 &ppos, D3DXVECTOR3 *vtx );

	void RenderDiffuse();
	void RenderEmissive();

	ParticleSpec
		*pfirst,	//first particle in a stream
		*plast;		//last particle

	DWORD np;		//current number of particles
	bool diffuse, reentry;	//true for diffuse particle streams

	double simt, dt;
	vVessel *vobj;		//vVessel class object
	VESSEL *VSL;
	OBJHANDLE hSrf, hVsl;	//planet and vessel
	vPlanet *vSrf;

	//specs of current particle stream
	struct D3D11PSSpec {
		double
			interval,
			exp_rate,
			ipht2,
			pdensity,
			speed,			// emission velocity
			vrand,			// velocity randomisation
			growthrate,		// particle growth rate				alpha
			atmslowdown,	// atmospheric slowdown rate		beta
			size0,			// particle base size at creation
			t0;				// time of last particle created

	//	bool
	//		active;

		PARTICLESTREAMSPEC::LEVELMAP lmap;	//level mapping
		float
			lmin,
			lmax;
		PARTICLESTREAMSPEC::ATMSMAP amap;	//atmospheric mapping
		float
			amin,
			afac;
		Texture *tex;
	} PS;

	//effect vars
	static ID3D11InputLayout
		*IL_Particle;

	static ID3D11VertexShader
		*VS_Particle;

	static ID3D11GeometryShader
		*GS_Particle;

	static ID3D11PixelShader
		*PS_Particle_D,
		*PS_Particle_E,
		*PS_Particle_S;

	static ID3D11Buffer
		*VB,
		*cb_GS_Particle_0;

	static GSCB_Particle GSCB_Particle_0;
	static bool bShadows;
	static Texture *def_tex;
};

//==============================================
//				Exhaust stream
//==============================================

class ExhaustStream : public D3D11ParticleStream {
public:
	ExhaustStream( 
		OBJHANDLE _vsobj, const double *lvl, const VECTOR3 *ref,
		const VECTOR3 *dir, PARTICLESTREAMSPEC *pss = NULL );
	ExhaustStream( 
		 OBJHANDLE _vsobj, const double *lvl, const VECTOR3 &ref,
		 const VECTOR3 &dir, PARTICLESTREAMSPEC *pss = NULL );
	~ExhaustStream();

	void Update();
private:
};

//==============================================
//				Reentry stream
//==============================================

class ReentryStream : public D3D11ParticleStream {
public:
	ReentryStream( PARTICLESTREAMSPEC *pss,	OBJHANDLE _vsobj );
	~ReentryStream();

	void Update();
private:
	double llevel;
};

#endif