

#ifndef PI
#define PI 3.14159265359
#endif

#define PTR_BUFF_ATTR

layout (std430) PTR_BUFF_ATTR buffer ParticlePositionsData {
	float prt_positions[];
};

layout (std430) PTR_BUFF_ATTR buffer ParticlePrevPositionsData {
	float prt_prev_positions[];
};

struct ParticleState
{
	float life_time;
	float life_span;
	float generation_id;
	uint  color;
};

layout (std430) PTR_BUFF_ATTR buffer ParticleStatesData {
	ParticleState prt_states[];
};

bool prt_is_alive(uint id)
{
	return prt_states[id].life_time < prt_states[id].life_span;
}

bool prt_is_alive(ParticleState state)
{
	return state.life_time < state.life_span;	
}

void prt_kill(inout ParticleState state)
{
	state.life_time = state.life_span;
}

ParticleState prt_get_state(uint id)
{
	return prt_states[id];
}

void prt_set_state(uint id, ParticleState state)
{
	prt_states[id] = state;
}

void prt_spawn(uint id, float life_span)
{
	prt_states[id].life_time      = 0.0;
	prt_states[id].life_span      = life_span;
	prt_states[id].generation_id += 1.0;
}

void prt_spawn(inout ParticleState state, float life_span)
{
	state.life_time      = 0.0;
	state.life_span      = life_span;
	state.generation_id += 1.0;
}

void prt_set_position(uint id, vec3 p)
{	
	prt_positions[id * 3 + 0] = p.x;
	prt_positions[id * 3 + 1] = p.y;
	prt_positions[id * 3 + 2] = p.z;
}

vec3 prt_get_position(uint id)
{	
	return vec3(prt_positions[id * 3 + 0], prt_positions[id * 3 + 1], prt_positions[id * 3 + 2]);
}

vec3 prt_get_prev_position(uint id)
{	
	return vec3(prt_prev_positions[id * 3 + 0], prt_prev_positions[id * 3 + 1], prt_prev_positions[id * 3 + 2]);
}

float prt_get_generation_id(uint id)
{
	return prt_states[id].generation_id;
}

vec4 prt_get_color(uint id)
{
	vec4 c = vec4(1.0);
	c.rgb = color_convert_uint_to_float3(prt_states[id].color);
	return c;
}

vec4 prt_get_color(ParticleState state)
{
	vec4 c = vec4(1.0);
	c.rgb = color_convert_uint_to_float3(state.color);
	return c;
}

void prt_set_color(uint id, vec3 c)
{
	uint v = color_convert_rgb_float3_uint(c);
	prt_states[id].color = v;
}

void prt_set_color(inout ParticleState state, vec3 c)
{
	uint v = color_convert_rgb_float3_uint(c);
	state.color = v;
}

void prt_advance_life(uint id, float time_step, float max_lifespan)
{
	prt_states[id].life_time += time_step;
	prt_states[id].life_span  = min(prt_states[id].life_span, max_lifespan);
}

void prt_advance_life(inout ParticleState state, float time_step, float max_lifespan)
{
	state.life_time += time_step;
	state.life_span = min(state.life_span, max_lifespan);
}