#version 430
#extension GL_ARB_compute_shader : require
#extension GL_ARB_shader_storage_buffer_object : require

layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;

// Gravity
//const vec3 gravity = vec3(0, -9.8f, 0);

// Frame delta for calculations
uniform float deltaT;
uniform vec3 destPos;

// Viewport dimensions for border clamp
uniform vec2 vpDim;
uniform int borderClamp;

uniform float force_damping;
uniform float force_scale;
uniform float velocity_damping;

// GeeXLab particle structure
struct ParticleData
{
  vec4 p;
  vec4 uv0;
  vec4 n;
  vec4 c;
};

layout(std430, binding=0) buffer position_buffer
{
	ParticleData positions[];
};

layout(std430, binding=1) buffer velocity_buffer
{
	vec4 velocities[];
};



void main() {

    // Current SSBO index
    uint index = gl_GlobalInvocationID.x;

    // Read position and velocity

    vec3 vPos = positions[index].p.xyz;
    vec3 vVel = velocities[index].xyz;

    //vec3 destPos2 = vec3(200.0, -100.0, 0.0);
    //vVel += normalize(destPos2 - vPos) * 1.01 * deltaT;

    // Calculate new velocity depending on attraction point

    vec3 dir = (destPos - vPos) * 1.0;
    float d = length(dir) * force_scale;
    dir = normalize(dir);
    float F = force_damping / (d + 0.1);

    vVel.xyz += F * dir * deltaT * 10.0;
    vVel.xyz *= vec3(velocity_damping);

    //vVel += normalize(destPos - vPos) * 10.0 * deltaT;

    // Move by velocity
    vPos += vVel * deltaT;


    if (borderClamp == 1) 
    {
        if (vPos.x < -vpDim.x) 
        {
            vPos.x = -vpDim.x;
            vVel.x = -vVel.x;
        }

        if (vPos.x > vpDim.x) 
        {
            vPos.x = vpDim.x;
            vVel.x = -vVel.x;
        }

        if (vPos.y < -vpDim.y) 
        {
            vPos.y = -vpDim.y;
            vVel.y = -vVel.y;
        }

        if (vPos.y > vpDim.y) 
        {
            vPos.y = vpDim.y;
            vVel.y = -vVel.y;
        }

    }

    // Write back

    positions[index].p.xyz = vPos;
    velocities[index].xyz = vVel;
}
