#version 330

/// (C) Stratasys 2014-2015
///  Shaded Toolpath Selection Shader for INSIGHT software 
///  Takes in line (GL_LINES) as input primitive and generates vertices 
///		for a triangle strip for a circular line-offset geometry with end-caps.
///	 Currently only takes the first (i-1 = 0) and second vertex (i=1) for geometry offset (i.e. it does not work for strips)
///  HARDWARE LIMITATIONS:
///		Different hardware were found to have different limits for max_vertices and total # of components output.
///		CPU code now checks for this limitation (GLEngine33.cpp) and avoids using shaders if the hardware does not have 
///     the necessary  vertex emit capability required by this shader.
///		This limit is derived from hardware limit as well as the number of per-vertex attributes sent 
///		to the fragment shader. Currently, in the selection shader we only send per-vertex Position ( 4 components).
///     Example:
///		  On GeForce GTX550 Ti card, the GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS is 544. For this shader, Max Emit vertices = 544 /4 = 136.
///	 	  On Quadro K2000 card, GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS is 1024. For this shader, Max emit vertices = 1024/4 = 256.
///	

layout (lines) in;
layout (triangle_strip, max_vertices = 66) out;

layout (std140) uniform Matrices {
	mat4 m_pvm;
	mat3 m_normal;	
	mat4 m_model;
	mat4 m_viewModel;
};

in vData
{
	float beadsize;
} vertices[];

const float PI = 3.1415926;

void main()
{
	int i=1;
	//using the starting vertexes bead size as the offset distance
	float line_offset = vertices[i-1].beadsize;
	
	mat4 m_pvm_inv = inverse(m_pvm);
	//get line segment's direction unit vector
	vec4 lin_dir =   (gl_in[i].gl_Position - gl_in[i-1].gl_Position );
	lin_dir = normalize(m_pvm_inv *lin_dir);
	
	//get line segment's normal direction - will be uniform since we use the
	vec4 lin_norm = vec4( lin_dir.y, -lin_dir.x, lin_dir.z, 0.0) ;
		
/////   STRAIGHT OFFSETS
		gl_Position =  gl_in[i-1].gl_Position - m_pvm * (lin_norm*line_offset) ;		
		EmitVertex();
		
		gl_Position =  gl_in[i].gl_Position - m_pvm *(lin_norm*line_offset) ;
		EmitVertex();
		
		gl_Position =  gl_in[i-1].gl_Position ;
		EmitVertex();
		
		gl_Position =  gl_in[i].gl_Position ;
		EmitVertex();
		
		gl_Position =  gl_in[i-1].gl_Position + m_pvm *(lin_norm*line_offset) ;
		EmitVertex();
		
		gl_Position =  gl_in[i].gl_Position + m_pvm * (lin_norm*line_offset) ;
		EmitVertex();
		
	EndPrimitive();
	
/// END CAPS
	for(int nn=0; nn< 15; nn++)
	{
		float ang = PI * 0.134 *nn;
		vec4 off = vec4( cos(ang)*line_offset , -sin(ang)*line_offset , 0.0, 0.0);
		gl_Position =  gl_in[i].gl_Position +  m_pvm *off;
		EmitVertex();

		off = vec4( cos(PI-ang)*line_offset , -sin(PI-ang)*line_offset , 0.0, 0.0);
		gl_Position =  gl_in[i].gl_Position +  m_pvm *off;
		EmitVertex();
	}
	EndPrimitive();
	
	for(int nn=0; nn< 15; nn++)
	{
		float ang = PI * 0.134*nn;
		vec4 off = vec4( cos(ang)*line_offset , -sin(ang)*line_offset , 0.0, 0.0);
		gl_Position =  gl_in[i-1].gl_Position +  m_pvm *off;
		EmitVertex();

		off = vec4( cos(PI-ang)*line_offset , -sin(PI-ang)*line_offset , 0.0, 0.0);
		gl_Position =  gl_in[i-1].gl_Position +  m_pvm *off;
		EmitVertex();
	}
	EndPrimitive();
}