#version 400 core

layout( isolines, fractional_even_spacing, ccw ) in;

out Vertex {
    vec3 color;
} te_out;

uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;
uniform mat4 projectionMatrix;
uniform mat4 mvp;

// Calculate RGB triplet from HSV
vec3 hsvToRGB( float h, float s, float v )
{
    if ( s <= 0.0 )
        return vec3( v );

    h = h * 6.0;
    float c = v * s;
    float x = ( 1.0 - abs( ( mod( h, 2 ) - 1 ) ) ) * c;
    float m = v - c;
    float r = 0.0;
    float g = 0.0;
    float b = 0.0;

    if ( h < 1.0 )      { r = c;   g = x;   b = 0.0;}
    else if ( h < 2.0 ) { r = x;   g = c;   b = 0.0; }
    else if ( h < 3.0 ) { r = 0.0; g = c;   b = x; }
    else if ( h < 4.0 ) { r = 0.0; g = x;   b = c; }
    else if ( h < 5.0 ) { r = x;   g = 0.0; b = c; }
    else                { r = c;   g = 0.0; b = x; }

    return vec3( r + m, g + m, b + m );
}

void main()
{
    float u = gl_TessCoord.x;
    float v = gl_TessCoord.y;

    vec4 a = gl_in[0].gl_Position;
    vec4 b = gl_in[1].gl_Position;
    vec4 c = gl_in[2].gl_Position;
    vec4 d = gl_in[3].gl_Position;

    // Use the (u,v) parametric coords to calculate the vertex.
    // u is the position along an isoline
    // v is isoline number

    // Let's make a sinusoidal curve as a function of u that varies
    // in the v direction which we will define as orthogonal to u

    // Interpolate in u along top and bottom edges of the patch
    vec4 q0 = mix( a, b, u );
    vec4 q1 = mix( d, c, u );

    // Interpolate in v between the above positions. This gives the
    // nominal position for our vertex
    vec4 p = mix( q0, q1, v );

    // Find "vertical" direction
    vec4 vBasis = normalize( q1 - q0 );

    // Offset vertex in this direction using sinusoid
    vec4 pos = p + 0.2 * vBasis * sin( 20.0 * u );

    // Use a hue value based on v
    te_out.color = hsvToRGB( v, 1.0, 1.0 );

    // Transform to clip-space
    gl_Position = mvp * pos;
}
