void InitGL() { 
	glClearColor(1,1,1,1);
	glGenQueries(1, &query); 
	glGenQueries(1, &t_query); 

	texture_size_x =  numX+1;
	texture_size_y =  numY+1;

	CHECK_GL_ERRORS
	startTime = (float)glutGet(GLUT_ELAPSED_TIME);
	// get ticks per second
    QueryPerformanceFrequency(&frequency);

    // start timer
    QueryPerformanceCounter(&t1);

	 
	size_t i=0, j=0, count=0;
	int l1=0, l2=0; 
	int v = numY+1;
	int u = numX+1;

	printf("Total triangles: %3d\n",numX*numY*2);
	indices.resize( numX*numY*2*3);
	 
	
	X.resize(total_points);
	X_last.resize(total_points); 
	F.resize(total_points);
  
	//fill in positions
	for(int j=0;j<=numY;j++) {		 
		for(int i=0;i<=numX;i++) {	 
			X[count] = glm::vec4( ((float(i)/(u-1)) *2-1)* hsize, sizeX+1, ((float(j)/(v-1) )* sizeY),1);
			X_last[count] = X[count];
			count++;
		}
	} 

	//fill in indices
	GLushort* id=&indices[0];
	for (int i = 0; i < numY; i++) {        
		for (int j = 0; j < numX; j++) {            
			int i0 = i * (numX+1) + j;            
			int i1 = i0 + 1;            
			int i2 = i0 + (numX+1);            
			int i3 = i2 + 1;            
			if ((j+i)%2) {                
				*id++ = i0; *id++ = i2; *id++ = i1;                
				*id++ = i1; *id++ = i2; *id++ = i3;            
			} else {                
				*id++ = i0; *id++ = i2; *id++ = i3;                
				*id++ = i0; *id++ = i3; *id++ = i1;            
			}        
		}    
	}

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	
	glEnable(GL_CULL_FACE);
	
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
	glCullFace(GL_BACK); 
	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

	//Disable vsync
	wglSwapIntervalEXT(0);

	// Setup springs
	// Horizontal
	for (l1 = 0; l1 < v; l1++)	// v
		for (l2 = 0; l2 < (u - 1); l2++) {
			AddSpring((l1 * u) + l2,(l1 * u) + l2 + 1,KsStruct,KdStruct);
		}

	// Vertical
	for (l1 = 0; l1 < (u); l1++)	
		for (l2 = 0; l2 < (v - 1); l2++) {
			AddSpring((l2 * u) + l1,((l2 + 1) * u) + l1,KsStruct,KdStruct);
		}

	// Shearing Springs
	for (l1 = 0; l1 < (v - 1); l1++)	
		for (l2 = 0; l2 < (u - 1); l2++) {
			AddSpring((l1 * u) + l2,((l1 + 1) * u) + l2 + 1,KsShear,KdShear);
			AddSpring(((l1 + 1) * u) + l2,(l1 * u) + l2 + 1,KsShear,KdShear);
		}

	// Bend Springs
	for (l1 = 0; l1 < (v); l1++) {
		for (l2 = 0; l2 < (u - 2); l2++) {
			AddSpring((l1 * u) + l2,(l1 * u) + l2 + 2,KsBend,KdBend);
		}
		AddSpring((l1 * u) + (u - 3),(l1 * u) + (u - 1),KsBend,KdBend);
	}
	for (l1 = 0; l1 < (u); l1++) {
		for (l2 = 0; l2 < (v - 2); l2++) {
			AddSpring((l2 * u) + l1,((l2 + 2) * u) + l1,KsBend,KdBend);
		}
		AddSpring(((v - 3) * u) + l1,((v - 1) * u) + l1,KsBend,KdBend);
	}


	massSpringShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Spring.vp");
	particleShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Basic.vp");
	particleShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Basic.fp");
	renderShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Passthrough.vp");
	renderShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Passthrough.fp");
	massSpringShader.CreateAndLinkProgram();
	massSpringShader.Use();
		massSpringShader.AddAttribute("position_mass");
		massSpringShader.AddAttribute("prev_position");		 
		massSpringShader.AddUniform("tex_position_mass");
		massSpringShader.AddUniform("tex_pre_position_mass");
		massSpringShader.AddUniform("MVP");		
		massSpringShader.AddUniform("dt");
		massSpringShader.AddUniform("gravity");
		massSpringShader.AddUniform("ksStr");
		massSpringShader.AddUniform("ksShr");
		massSpringShader.AddUniform("ksBnd");
		massSpringShader.AddUniform("kdStr");
		massSpringShader.AddUniform("kdShr");
		massSpringShader.AddUniform("kdBnd");
		massSpringShader.AddUniform("DEFAULT_DAMPING"); 
		massSpringShader.AddUniform("texsize_x"); 
		massSpringShader.AddUniform("texsize_y"); 
		massSpringShader.AddUniform("step"); 
		massSpringShader.AddUniform("inv_cloth_size");
		massSpringShader.AddUniform("ellipsoid");

		glUniform1i(massSpringShader("tex_position_mass"), 0); 
		glUniform1i(massSpringShader("tex_pre_position_mass"), 1); 
		
	massSpringShader.UnUse();

	CHECK_GL_ERRORS

	
	particleShader.CreateAndLinkProgram();
	particleShader.Use();
		particleShader.AddAttribute("position_mass");
		particleShader.AddUniform("pointSize");
		particleShader.AddUniform("MV");
		particleShader.AddUniform("MVP");
		particleShader.AddUniform("vColor");
		particleShader.AddUniform("selected_index");
		glUniform1f(particleShader("pointSize"), pointSize);
		glUniform4fv(particleShader("vColor"),1, vRed);
	particleShader.UnUse();
 
	renderShader.CreateAndLinkProgram();
	renderShader.Use();
		renderShader.AddAttribute("position_mass");
		renderShader.AddUniform("MVP");
		renderShader.AddUniform("vColor");
		glUniform4fv(renderShader("vColor"),1, vGray);
	renderShader.UnUse();

	CHECK_GL_ERRORS

	//create vbo 
	createVBO(); 
 
	//setup transform feedback attributes	    	 
	glGenTransformFeedbacks(1, &tfID);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID); 
	const char* varying_names[]={"out_position_mass", "out_prev_position"};	
	glTransformFeedbackVaryings(massSpringShader.GetProgram(), 2, varying_names, GL_SEPARATE_ATTRIBS);		
	glLinkProgram(massSpringShader.GetProgram());

  
}
//initialize OpenGL
void InitGL() {
	//set the background colour to white
	glClearColor(1,1,1,1);

	//generate hardware query objects
	glGenQueries(1, &query);
	glGenQueries(1, &t_query);

	//setup texture size for shaders
	texture_size_x =  numX+1;
	texture_size_y =  numY+1;

	CHECK_GL_ERRORS
	
	//get initial time
	startTime = (float)glutGet(GLUT_ELAPSED_TIME);
	// get ticks per second
    QueryPerformanceFrequency(&frequency);

    // start timer
    QueryPerformanceCounter(&t1);

	//local variables
	size_t i=0, j=0, count=0;
	int l1=0, l2=0;
	int v = numY+1;
	int u = numX+1;

	printf("Total triangles: %3d\n",numX*numY*2);
	
	//resize the cloth indices, position, previous position and force vectors
	indices.resize( numX*numY*2*3);
	X.resize(total_points);
	X_last.resize(total_points);
	F.resize(total_points);

	//fill in positions
	for(int j=0;j<=numY;j++) {
		for(int i=0;i<=numX;i++) {
			X[count] = glm::vec4( ((float(i)/(u-1)) *2-1)* hsize, sizeX+1, ((float(j)/(v-1) )* sizeY),1);
			X_last[count] = X[count];
			count++;
		}
	}

	//fill in indices
	GLushort* id=&indices[0];
	for (int i = 0; i < numY; i++) {
		for (int j = 0; j < numX; j++) {
			int i0 = i * (numX+1) + j;
			int i1 = i0 + 1;
			int i2 = i0 + (numX+1);
			int i3 = i2 + 1;
			if ((j+i)%2) {
				*id++ = i0; *id++ = i2; *id++ = i1;
				*id++ = i1; *id++ = i2; *id++ = i3;
			} else {
				*id++ = i0; *id++ = i2; *id++ = i3;
				*id++ = i0; *id++ = i3; *id++ = i1;
			}
		}
	}
	//set the polygon rendering to render them as lines
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	//enable back face culling
	glEnable(GL_CULL_FACE);
	glCullFace(GL_BACK);

	//set smooth line rendering
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	 
	//enable state to use the vertex shader to reset the particle size
	//by writing to gl_PointSize value
	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);

	// Setup springs
	// Horizontal
	for (l1 = 0; l1 < v; l1++)	// v
		for (l2 = 0; l2 < (u - 1); l2++) {
			AddSpring((l1 * u) + l2,(l1 * u) + l2 + 1,KsStruct,KdStruct);
		}

	// Vertical
	for (l1 = 0; l1 < (u); l1++)
		for (l2 = 0; l2 < (v - 1); l2++) {
			AddSpring((l2 * u) + l1,((l2 + 1) * u) + l1,KsStruct,KdStruct);
		}

	// Shearing Springs
	for (l1 = 0; l1 < (v - 1); l1++)
		for (l2 = 0; l2 < (u - 1); l2++) {
			AddSpring((l1 * u) + l2,((l1 + 1) * u) + l2 + 1,KsShear,KdShear);
			AddSpring(((l1 + 1) * u) + l2,(l1 * u) + l2 + 1,KsShear,KdShear);
		}

	// Bend Springs
	for (l1 = 0; l1 < (v); l1++) {
		for (l2 = 0; l2 < (u - 2); l2++) {
			AddSpring((l1 * u) + l2,(l1 * u) + l2 + 2,KsBend,KdBend);
		}
		AddSpring((l1 * u) + (u - 3),(l1 * u) + (u - 1),KsBend,KdBend);
	}
	for (l1 = 0; l1 < (u); l1++) {
		for (l2 = 0; l2 < (v - 2); l2++) {
			AddSpring((l2 * u) + l1,((l2 + 2) * u) + l1,KsBend,KdBend);
		}
		AddSpring(((v - 3) * u) + l1,((v - 1) * u) + l1,KsBend,KdBend);
	}

	//setup shader loading
	massSpringShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Spring.vert");
	particleShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Basic.vert");
	particleShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Basic.frag");
	renderShader.LoadFromFile(GL_VERTEX_SHADER,"shaders/Passthrough.vert");
	renderShader.LoadFromFile(GL_FRAGMENT_SHADER,"shaders/Passthrough.frag");
	
	//compile and link mass spring shader
	massSpringShader.CreateAndLinkProgram();
	massSpringShader.Use();
		//add attributes and uniforms
		massSpringShader.AddAttribute("position_mass");
		massSpringShader.AddAttribute("prev_position");
		massSpringShader.AddUniform("tex_position_mass");
		massSpringShader.AddUniform("tex_pre_position_mass");
		massSpringShader.AddUniform("MVP");
		massSpringShader.AddUniform("dt");
		massSpringShader.AddUniform("gravity");
		massSpringShader.AddUniform("ksStr");
		massSpringShader.AddUniform("ksShr");
		massSpringShader.AddUniform("ksBnd");
		massSpringShader.AddUniform("kdStr");
		massSpringShader.AddUniform("kdShr");
		massSpringShader.AddUniform("kdBnd");
		massSpringShader.AddUniform("DEFAULT_DAMPING");
		massSpringShader.AddUniform("texsize_x");
		massSpringShader.AddUniform("texsize_y");
		massSpringShader.AddUniform("step");
		massSpringShader.AddUniform("inv_cloth_size");
		massSpringShader.AddUniform("ellipsoid_xform");	
		massSpringShader.AddUniform("inv_ellipsoid");	
		massSpringShader.AddUniform("ellipsoid");		
	massSpringShader.UnUse();

	CHECK_GL_ERRORS

	//compile and link particle shader
	particleShader.CreateAndLinkProgram();
	particleShader.Use();
		//setup attributes and uniforms
		particleShader.AddAttribute("position_mass");
		particleShader.AddUniform("pointSize");
		particleShader.AddUniform("MV");
		particleShader.AddUniform("MVP");
		particleShader.AddUniform("vColor");
		particleShader.AddUniform("selected_index");
		//pass values to contant uniforms
		glUniform1f(particleShader("pointSize"), pointSize);
		glUniform4fv(particleShader("vColor"),1, vRed);
	particleShader.UnUse();

	//compile and link render shader
	renderShader.CreateAndLinkProgram();
	renderShader.Use();
		//setup attributes and uniforms
		renderShader.AddAttribute("position_mass");
		renderShader.AddUniform("MVP");
		renderShader.AddUniform("vColor");
		//pass values to constant uniforms
		glUniform4fv(renderShader("vColor"),1, vGray);
	renderShader.UnUse();

	CHECK_GL_ERRORS

	//create vbo
	createVBO();

	//collision ellipsoid
	ellipsoid = glm::translate(glm::mat4(1),glm::vec3(0,2,0));
	ellipsoid = glm::rotate(ellipsoid, 45.0f ,glm::vec3(1,0,0));
	ellipsoid = glm::scale(ellipsoid, glm::vec3(fRadius,fRadius,fRadius/2));
	inverse_ellipsoid = glm::inverse(ellipsoid);

	//setup transform feedback attributes
	glGenTransformFeedbacks(1, &tfID);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfID);
	//pass the vertex shader outputs for transform feedback
	const char* varying_names[]={"out_position_mass", "out_prev_position"};
	glTransformFeedbackVaryings(massSpringShader.GetProgram(), 2, varying_names, GL_SEPARATE_ATTRIBS);
	//relink the massSpringShader program
	glLinkProgram(massSpringShader.GetProgram());

	//set the mass spring shader and pass values to constant uniforms
	massSpringShader.Use();		
		glUniform1f(massSpringShader("dt"),  timeStep);
		glUniform3fv(massSpringShader("gravity"),1,&gravity.x);
		glUniform1i(massSpringShader("tex_position_mass"), 0);
		glUniform1i(massSpringShader("tex_pre_position_mass"), 1);
		glUniform1i(massSpringShader("texsize_x"),texture_size_x);
		glUniform1i(massSpringShader("texsize_y"),texture_size_y);
		glUniformMatrix4fv(massSpringShader("ellipsoid_xform"), 1, GL_FALSE, glm::value_ptr(ellipsoid));
		glUniformMatrix4fv(massSpringShader("inv_ellipsoid"), 1, GL_FALSE, glm::value_ptr(inverse_ellipsoid));
		glUniform4f(massSpringShader("ellipsoid"),0, 0, 0, fRadius);		
		glUniform2f(massSpringShader("inv_cloth_size"),float(sizeX)/numX,float(sizeY)/numY);
		glUniform2f(massSpringShader("step"),1.0f/(texture_size_x-1.0f),1.0f/(texture_size_y-1.0f));
		glUniform1f(massSpringShader("ksStr"),  KsStruct);
		glUniform1f(massSpringShader("ksShr"),  KsShear);
		glUniform1f(massSpringShader("ksBnd"),  KsBend);
		glUniform1f(massSpringShader("kdStr"),  KdStruct/1000.0f);
		glUniform1f(massSpringShader("kdShr"),  KdShear/1000.0f);
		glUniform1f(massSpringShader("kdBnd"),  KdBend/1000.0f);
		glUniform1f(massSpringShader("DEFAULT_DAMPING"),  DEFAULT_DAMPING);
	massSpringShader.UnUse();

	

	//disable vsync
	wglSwapIntervalEXT(0);
}