varying vec2 texcoord0;
vec4 pos;
float u, v, x, y, z;
varying float r, theta, s;
float lambda, phi;
float extent, scale, vis_mode, center_lambda, center_phi;

void main(void){

    texcoord0 = vec2(gl_MultiTexCoord0);
    pos = gl_Vertex;

    // getting paramters from the interface
    extent = gl_ProjectionMatrix[0].x;
    scale = gl_ProjectionMatrix[1].y;
    vis_mode = gl_ProjectionMatrix[2].z;
    center_lambda = gl_ModelViewMatrix[0].x;
    center_phi = gl_ModelViewMatrix[1].y;

    x = pos.x;
    y = pos.y;
    z = pos.z;

    //Rotation 1: (-center_lambda)-rotation on the xz-plane
    float x_copy = x;
    x = cos(-center_lambda)*x - sin(-center_lambda)*z;
    y = 1.0*y;
    z = sin(-center_lambda)*x_copy + cos(-center_lambda)*z;

    //Rotation 2: (-center_phi)-rotation on the yz-plane
    float y_copy = y;
    x = 1.0*x;
    y = cos(-center_phi)*y - sin(-center_phi)*z;
    z = sin(-center_phi)*y_copy + cos(-center_phi)*z;

    // stereographic projection
    u = 2.0*x/(-z+1.0);
    v = 2.0*y/(-z+1.0);

    // from cartesian to polar coordinates
    r = sqrt(u*u+v*v);
    theta = atan(u,v);

    // scaling the complex plane according to scale specified in the interface
    r *= scale;

    // mapping from polar coordinates to cartesian coordinates
    u = -r*sin(theta);
    v = r*cos(theta);

    // mapping back from the complex plane to the unit sphere
    x = (4.0*u)/(u*u+v*v+4.0);
    y = (4.0*v)/(u*u+v*v+4.0);
    z = (u*u+v*v-4.0)/(u*u+v*v+4.0);

    // mapping back to the equirectangular domain
    lambda = atan(x,-z)/3.1415;
    phi = asin(y)/1.5708;

    // perspective projection
    u = x/(-z);
    v = y/(-z);

    // Visualize using specified visualization (remove for timings in the paper! Use only "Perspective" in the paper!)
    if (vis_mode==1.0) gl_Position = vec4(u/extent,v/extent,z,1.0);
    else if (vis_mode==2.0) gl_Position = vec4(0.9*x,0.9*y,z,1.0);
    else if (vis_mode==3.0) gl_Position = vec4(lambda,phi,z,1.0);

//    gl_Position = vec4(u/2.0,v/2.0,z,1.0);

}
