// ============================================================
// VISUALITY WIND - VISIBLE FOLIAGE MOTION
// ============================================================
#ifndef VISUALITY_WIND_GLSL
#define VISUALITY_WIND_GLSL

// Main tuning
float getWindHeight(float localY)
{
    // Bottom of the plant stays calmer; the top moves more.
    float h = clamp(localY, 0.0, 1.0);
    return smoothstep(0.05, 0.95, h);
}

float getWeatherWind(float rain)
{
    return mix(1.0, RAIN_WIND_FACTOR, clamp(rain, 0.0, 1.0));
}

vec2 getWindWave(vec3 worldPos, float time)
{
    // World-space phase keeps neighbouring blocks from moving together and is camera-independent.
    float p1 = sin(time * WIND_SPEED + worldPos.x * 0.78 + worldPos.z * 0.61);
    float p2 = sin(time * (WIND_SPEED * 0.63) - worldPos.x * 0.43 + worldPos.z * 1.07 + 1.7);
    float p3 = sin(time * (WIND_SPEED * 1.37) + worldPos.x * 0.21 - worldPos.z * 0.49 + 3.1);

    vec2 wave;
    wave.x = p1 * 0.62 + p2 * 0.23 + p3 * 0.15;
    wave.y = p2 * 0.60 - p1 * 0.22 + p3 * 0.18;
    return wave;
}

vec3 applyWind(vec3 position, vec3 worldPos, float localY, float rain, float time)
{
    float height = getWindHeight(localY);
    float weather = getWeatherWind(rain);

    // A slowly changing gust keeps the motion from becoming a perfect loop.
    float gust = 1.0 + sin(time * 0.42 + worldPos.x * 0.035 + worldPos.z * 0.029) * WIND_GUST_STRENGTH;

    vec2 wave = getWindWave(worldPos, time);
    float amount = WIND_STRENGTH * height * weather * gust;

    position.x += wave.x * amount;
    position.z += wave.y * amount;

    // Tiny vertical motion at the tips makes grass/leaf planes feel alive.
    position.y += (wave.x + wave.y) * amount * 0.055;

    return position;
}

#endif
