#pragma once

#define SCALEFAC 50
#define INSKY 80.f // 130.f


struct blobstar
{
	float phases[64],dphases[64];
	float scal;
	int numring;
	float fatness;
	float fat;
	v3 curp1,curp2;
	DWORD col;
	int acol;

	bool CorrectPoint(v3 &p);

	blobstar()
	{
		
		numring=int(Random(3,8.9));
		fatness=Random(0.1f,0.3f);
		scal=GaussRandom(0.5,1.5f);
		fat=0;
		for (int c1=0;c1<64;c1++)
		{
			phases[c1]=Random(0,1000);
			dphases[c1]=GaussRandom();
		}
		acol = rand()&31;
	}

	void AddTri(SimpleBuffer &gb, v3 a, v3 b, v3 c)
	{
		a.y+=INSKY;
		b.y+=INSKY;
		c.y+=INSKY;
		v3 n=Normalize(CrossProduct(a-b,b-c));
		v3 m=(a+b+c)/3;
		/*
		float dot = (DotProduct(n,Normalize(m-sunpos)));
		dot=(dot*dot*dot+0.5f)*30;
		if (dot<0) dot=0; else if (dot>1) dot=1;
		int idot=dot*255;
		DWORD col=INTERP(0xc5000000,0xc5ffffff,idot);
		*/
		gb.AddTri(
			gb.AddVertex(a,col),
			gb.AddVertex(b,col),	
			gb.AddVertex(c,col)
				);

	}

	void Update(float dt)
	{
		for (int c1=0;c1<64;c1++)
		{
			phases[c1]+=dphases[c1]*dt;		
		}
	}

	void Draw(SimpleBuffer &b, float centerise, float outerrad, float innerrad, int alpha)
	{
		alpha+=acol-32;
		alpha=bound(0,alpha,255);
		if (!alpha) return;
		col=(alpha)<<24;
		v3 p1(Perlin::Noise1(phases[0]),Perlin::Noise1(phases[1]),Perlin::Noise1(phases[2]));
		v3 p2(Perlin::Noise1(phases[3]),Perlin::Noise1(phases[4]),Perlin::Noise1(phases[5]));
		v3 p3(Perlin::Noise1(phases[6]*3),Perlin::Noise1(phases[7]*3),Perlin::Noise1(phases[8]*3));
		p2+=(p1-p2)*centerise;
		p1=Normalize(p1)*outerrad*scal;
		p2=Normalize(p2)*innerrad*scal;
		curp1=p1;
		curp2=p2;
		
		p3=Normalize(p3);
		v3 p4=Normalize(CrossProduct(p3,p1-p2));
		fat = fatness*Length(p1-p2)*pow(2,Perlin::Noise1(phases[7])) * 0.1f;
		p3*=fat;
		p4*=fat;

		for (int r=0;r<numring;r++)
		{
			float theta1=r/float(numring)*PI*2;
			float theta2=(r+1)/float(numring)*PI*2;
			float ra=Perlin::Noise1(phases[8+r]*5)+2;				

			v3 a1 = (p1+p2)*0.5f + ra * (p3*sin(theta1) + p4*cos(theta1));
				  ra=Perlin::Noise1(phases[8+((r+1)%numring)]*5)+2;
			v3 a2 = (p1+p2)*0.5f + ra * (p3*sin(theta2) + p4*cos(theta2));
			AddTri(b,p1,a1,a2);
			AddTri(b,p2,a2,a1);
		}			
	}
};


struct psysBox 
{
	
	virtual int GetNumInputs()					{ return 14; }
	virtual int GetNumOutputs()					{ return 1; }
	const char *GetListOption(int idx, int option, char *obuf) {return "";}
	
	int totalrespawn;

	struct P
	{
		v3 p,v;
		float size;
		float age;
		float dummy;
	};

#define MAXP 8192
	P p[MAXP];

	/*
	virtual TypeDesc GetValTypeDesc(int idx)	
	{ 
		switch (idx)
		{
		default: return Box::GetValTypeDesc(idx);
		case 0: return TypeDesc("input",VAL_STREAM);
		case 1: return TypeDesc("num particles",VAL_FLOAT,true,0,0,1,0.125f);
		case 2: return TypeDesc("drag",VAL_FLOAT,true,0,0,1,0.5f);
		case 3: return TypeDesc("follow",VAL_FLOAT,true,0,0,1,0);
		case 4: return TypeDesc("gravity",VAL_FLOAT,true,0,-1,1,0);
		case 5: return TypeDesc("noise force",VAL_FLOAT3D,true,0,0,1,0.25f);
		case 6: return TypeDesc("noise freq",VAL_FLOAT3D,true,0,-4,4,0.25f);
		case 7: return TypeDesc("noise speed",VAL_FLOAT3D,true,0,-1,1,0.25f);
		case 8: return TypeDesc("seed radius",VAL_FLOAT3D,true,0,0,1,1);
		case 9: return TypeDesc("seed position",VAL_FLOAT3D,true,0,-1,1,0);
		case 10: return TypeDesc("reseed amount",VAL_FLOAT,true,0,0,1,0);
		case 11: return TypeDesc("seed shape",VAL_STREAM);
		case 12: return TypeDesc("tex scale",VAL_FLOAT2D,true,0,-2,2,1);
		case 13: return TypeDesc("speed",VAL_FLOAT,true,0,0,1,1);
		case 14: return TypeDesc("output",VAL_STREAM);
		}
	}
	*/

	/*
	texture is trans56
	0.286 particles
	0.8 drag
	0.514 follow
	1.0 gravity
	noise force 0.21,0.324,0.248
	noise freq 0.8,-0.8,0.8
	noise speed -0.15
	seed rad 0.162,0.105,0.762
	seed position slowly varying near 0
	reseed amount 0
	tex scale 0.512 0.372
	speed 1
	*/

	float EvaluatePort(int i)
	{
		switch (i)
		{
		case 1: return 0.8f;//0.386f; // num particles
		case 2: return 0.8f; // drag
		case 3: return 0.854f; // follow
		case 4: return 1.6f; // gravity
		case 5: return 0.35f; // noise force
		case 6: return 1.3f; // noise freq -4 4
		case 7: return -0.15f; // noise speed
		case 8: return 1; // seed rad
		case 9: return 0; // seed pos
		case 10: return 0.0f; // reseed amount
		default:
			return 0.f;
		case 12: return 1.f; // tex scale
		case 13: return 1.f; // speed
		}
	}

	v3 EvaluatePortV3(int i)
	{
		switch (i)
		{
		case 5: return v3(0.21,0.324,0.248)*1.2f; // noise force
		case 8: return v3(0.162,0.105,0.762); // seed rad
		case 12: return v3(0.512,0.372,1); // tex scale
		}
		float f=EvaluatePort(i);
		return v3(f,f,f);
	}

	v3 pos;

	void Update(float GETDT,  blobstar *stars, int numstars, float rainfall);
	virtual void Run(SimpleBufferUV2 &bout,  DWORD col, float size, float rainfall);
	
	
	psysBox() 
	{
		Reset();
	}

	void Reset()
	{
		totalrespawn=1;
		pos=v3(0,0,0);
	}
	
	~psysBox()
	{
	}
	
	
};

////////////////////////////////////////////////////////////////////// end of psys

