Exemple #1
0
void onInit() {
	//tex = loadImage("../textures/texture.png");
	tex = loadImage("../textures/dots.png");
	tex2 = loadImage("../textures/dots.png");
	ctv = new CTextureViewer(0, "../shaders/textureViewer.vs", "../shaders/textureViewer.frag");
	ctv->setTexture(tex);
	ctv->setTexture2(tex2);

	hist.LoadFromFile(GL_VERTEX_SHADER, "../shaders/histogram.vs");
	hist.LoadFromFile(GL_FRAGMENT_SHADER, "../shaders/histogram.frag");
	hist.CreateAndLinkProgram();

	hist.Use();

	//Create uniforms and attributes (filled later)
	hist.AddAttribute("vPosition");
	hist.AddUniform("tex");
	hist.AddUniform("textureWidth");
	hist.AddUniform("textureHeight");

	hist.UnUse();

	initTex();
	initPointVBO();
	initHistogramFBO();
}
Exemple #2
0
void InitShaders(void)
{
	shader.LoadFromFile(GL_VERTEX_SHADER, "../CGE_solarsystem/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "../CGE_solarsystem/shader.frag");
	shader.CreateAndLinkProgram();
	shader.Use();
	shader.AddAttribute("vVertex");
	shader.AddAttribute("vUV");
	shader.AddUniform("MVP");
	shader.AddUniform("textureMap");
	glUniform1i(shader("textureMap"), 0);
	shader.UnUse();

	GL_CHECK_ERRORS
}
//OpenGL initialization
void OnInit() {

	//set the instance modeling matrix
	M[0] = glm::translate(glm::mat4(1), glm::vec3(-5,0,-5));
	M[1] = glm::translate(M[0], glm::vec3(10,0,0));
	M[2] = glm::translate(M[1], glm::vec3(0,0,10));
	M[3] = glm::translate(M[2], glm::vec3(-10,0,0));

	GL_CHECK_ERRORS

	//load the shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_GEOMETRY_SHADER, "shaders/shader.geom");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//create and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attribute and uniform
		shader.AddAttribute("vVertex");
		shader.AddUniform("PV");
		shader.AddUniform("M");
		shader.AddUniform("sub_divisions");

		//set values of constant uniforms at initialization
		glUniform1i(shader("sub_divisions"), sub_divisions);
		glUniformMatrix4fv(shader("M"), 4, GL_FALSE, glm::value_ptr(M[0]));

	shader.UnUse();

	GL_CHECK_ERRORS

	//setup quad geometry
	//setup quad vertices
	vertices[0] = glm::vec3(-5,0,-5);
	vertices[1] = glm::vec3(-5,0,5);
	vertices[2] = glm::vec3(5,0,5);
	vertices[3] = glm::vec3(5,0,-5);

	//setup quad indices
	GLushort* id=&indices[0];
 	*id++ = 0;
	*id++ = 1;
	*id++ = 2;

	*id++ = 0;
	*id++ = 2;
	*id++ = 3;

	GL_CHECK_ERRORS

	//setup quad vao and vbo stuff
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);

		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass the quad vertices to buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0);
		GL_CHECK_ERRORS
		//pass the quad indices to element array buffer
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS

	//set the polygon mode to render lines
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	GL_CHECK_ERRORS
		
	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization function
void OnInit() {

	GL_CHECK_ERRORS

	//initialize FBO
	initFBO();

	//generate hardwre query
	glGenQueries(1, &queryId);

	//create a uniform grid of size 20x20 in XZ plane
	grid = new CGrid(20,20);

	GL_CHECK_ERRORS

	//generate the quad vertices
	glm::vec2 quadVerts[4];
	quadVerts[0] = glm::vec2(0,0);
	quadVerts[1] = glm::vec2(1,0);
	quadVerts[2] = glm::vec2(1,1);
	quadVerts[3] = glm::vec2(0,1);

	//generate quad indices
	GLushort quadIndices[]={ 0,1,2,0,2,3};

	//generate quad  vertex array and vertex buffer objects
	glGenVertexArrays(1, &quadVAOID);
	glGenBuffers(1, &quadVBOID);
	glGenBuffers(1, &quadIndicesID);

	glBindVertexArray(quadVAOID);
		glBindBuffer (GL_ARRAY_BUFFER, quadVBOID);
		//pass quad vertices to buffer object memory
		glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW);

		GL_CHECK_ERRORS

		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0);

		//pass the quad indices to the element array buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW);

	//setup unit cube vertex array and vertex buffer objects
	glGenVertexArrays(1, &cubeVAOID);
	glGenBuffers(1, &cubeVBOID);
	glGenBuffers(1, &cubeIndicesID);

	//unit cube vertices 
	glm::vec3 vertices[8]={	glm::vec3(-0.5f,-0.5f,-0.5f),
							glm::vec3( 0.5f,-0.5f,-0.5f),
							glm::vec3( 0.5f, 0.5f,-0.5f),
							glm::vec3(-0.5f, 0.5f,-0.5f),
							glm::vec3(-0.5f,-0.5f, 0.5f),
							glm::vec3( 0.5f,-0.5f, 0.5f),
							glm::vec3( 0.5f, 0.5f, 0.5f),
							glm::vec3(-0.5f, 0.5f, 0.5f)};

	//unit cube indices
	GLushort cubeIndices[36]={0,5,4,
							  5,0,1,
							  3,7,6,
							  3,6,2,
							  7,4,6,
							  6,4,5,
							  2,1,3,
							  3,1,0,
							  3,0,7,
							  7,0,4,
							  6,5,2,
							  2,5,1};
	glBindVertexArray(cubeVAOID);
		glBindBuffer (GL_ARRAY_BUFFER, cubeVBOID);
		//pass cube vertices to buffer object memory
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &(vertices[0].x), GL_STATIC_DRAW);

		GL_CHECK_ERRORS

		//enable vertex attributre array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0,0);

		//pass cube indices to element array  buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesID);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), &cubeIndices[0], GL_STATIC_DRAW);

	glBindVertexArray(0);

	//Load the cube shader
	cubeShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/cube_shader.vert");
	cubeShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/cube_shader.frag");

	//compile and link the shader
	cubeShader.CreateAndLinkProgram();
	cubeShader.Use();
		//add attributes and uniforms
		cubeShader.AddAttribute("vVertex");
		cubeShader.AddUniform("MVP");
		cubeShader.AddUniform("vColor");
	cubeShader.UnUse();

	//Load the front to back peeling shader
	frontPeelShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/front_peel.vert");
	frontPeelShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/front_peel.frag");
	//compile and link the shader
	frontPeelShader.CreateAndLinkProgram();
	frontPeelShader.Use();
		//add attributes and uniforms
		frontPeelShader.AddAttribute("vVertex");
		frontPeelShader.AddUniform("MVP");
		frontPeelShader.AddUniform("vColor");
		frontPeelShader.AddUniform("depthTexture");
		//pass constant uniforms at initialization
		glUniform1i(frontPeelShader("depthTexture"), 0);
	frontPeelShader.UnUse();

	//Load the blending shader
	blendShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/blend.vert");
	blendShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/blend.frag");
	//compile and link the shader
	blendShader.CreateAndLinkProgram();
	blendShader.Use();
		//add attributes and uniforms
		blendShader.AddAttribute("vVertex");
		blendShader.AddUniform("tempTexture");
		//pass constant uniforms at initialization
		glUniform1i(blendShader("tempTexture"), 0);
	blendShader.UnUse();

	//Load the final shader
	finalShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/blend.vert");
	finalShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/final.frag");
	//compile and link the shader
	finalShader.CreateAndLinkProgram();
	finalShader.Use();
		//add attributes and uniforms
		finalShader.AddAttribute("vVertex");
		finalShader.AddUniform("colorTexture");
		finalShader.AddUniform("vBackgroundColor");
		//pass constant uniforms at initialization
		glUniform1i(finalShader("colorTexture"), 0);
	finalShader.UnUse();
	cout<<"Initialization successfull"<<endl;
}
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());

  
}
//OpenGL initialization function
void OnInit() {

	GL_CHECK_ERRORS

	//create a uniform grid of size 20x20 in XZ plane
	grid = new CGrid(20,20);

	GL_CHECK_ERRORS

	//create a new TetrahedraMarcher instance
	marcher = new TetrahedraMarcher();
	//set the volume dataset dimensions
	marcher->SetVolumeDimensions(256,256,256);
	//load the volume dataset
	marcher->LoadVolume(volume_file);
	//set the isosurface value
	marcher->SetIsosurfaceValue(48);
	//set the number of sampling voxels 
	marcher->SetNumSamplingVoxels(128,128,128);
	//begin tetrahedra marching
	marcher->MarchVolume();

	//setup the volume marcher vertex array object and vertex buffer object
	glGenVertexArrays(1, &volumeMarcherVAO);
	glGenBuffers(1, &volumeMarcherVBO);
	glBindVertexArray(volumeMarcherVAO);
	glBindBuffer (GL_ARRAY_BUFFER, volumeMarcherVBO);

	//pass the obtained vertices from the tetrahedra marcher and pass to the
	//buffer object memory
	glBufferData (GL_ARRAY_BUFFER, marcher->GetTotalVertices()*sizeof(Vertex), marcher->GetVertexPointer(), GL_STATIC_DRAW);

	//enable vertex attribute array for position
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);

	//enable vertex attribute array for normals
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),(const GLvoid*)offsetof(Vertex, normal));

	GL_CHECK_ERRORS

	//load the shader 
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/marcher.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/marcher.frag");

	//compile and link the shader program
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attribute and uniform
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddUniform("MVP");
	shader.UnUse();

	GL_CHECK_ERRORS

	//set the background colour
	glClearColor(bg.r, bg.g, bg.b, bg.a);

	//enable depth test and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {

    GL_CHECK_ERRORS

    //create a uniform grid of size 20x20 in XZ plane
    grid = new CGrid(20,20);

    GL_CHECK_ERRORS

    //Load the raycasting shader
    shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/raycaster.vert");
    shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/raycaster.frag");

    //compile and link the shader
    shader.CreateAndLinkProgram();
    shader.Use();
    //add attributes and uniforms
    shader.AddAttribute("vVertex");
    shader.AddUniform("MVP");
    shader.AddUniform("volume");
    shader.AddUniform("camPos");
    shader.AddUniform("step_size");

    //pass constant uniforms at initialization
    glUniform3f(shader("step_size"), 1.0f/XDIM, 1.0f/YDIM, 1.0f/ZDIM);
    glUniform1i(shader("volume"),0);
    shader.UnUse();

    GL_CHECK_ERRORS

    //load volume data
    if(LoadVolume()) {
        std::cout<<"Volume data loaded successfully."<<std::endl;
    } else {
        std::cout<<"Cannot load volume data."<<std::endl;
        exit(EXIT_FAILURE);
    }

    //set background colour
    glClearColor(bg.r, bg.g, bg.b, bg.a);

    //setup unit cube vertex array and vertex buffer objects
    glGenVertexArrays(1, &cubeVAOID);
    glGenBuffers(1, &cubeVBOID);
    glGenBuffers(1, &cubeIndicesID);

    //unit cube vertices
    glm::vec3 vertices[8]= {	glm::vec3(-0.5f,-0.5f,-0.5f),
                                glm::vec3( 0.5f,-0.5f,-0.5f),
                                glm::vec3( 0.5f, 0.5f,-0.5f),
                                glm::vec3(-0.5f, 0.5f,-0.5f),
                                glm::vec3(-0.5f,-0.5f, 0.5f),
                                glm::vec3( 0.5f,-0.5f, 0.5f),
                                glm::vec3( 0.5f, 0.5f, 0.5f),
                                glm::vec3(-0.5f, 0.5f, 0.5f)
                           };

    //unit cube indices
    GLushort cubeIndices[36]= {0,5,4,
                               5,0,1,
                               3,7,6,
                               3,6,2,
                               7,4,6,
                               6,4,5,
                               2,1,3,
                               3,1,0,
                               3,0,7,
                               7,0,4,
                               6,5,2,
                               2,5,1
                              };
    glBindVertexArray(cubeVAOID);
    glBindBuffer (GL_ARRAY_BUFFER, cubeVBOID);
    //pass cube vertices to buffer object memory
    glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &(vertices[0].x), GL_STATIC_DRAW);

    GL_CHECK_ERRORS

    //enable vertex attributre array for position
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,0,0);

    //pass indices to element array  buffer
    glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesID);
    glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), &cubeIndices[0], GL_STATIC_DRAW);

    glBindVertexArray(0);

    //enable depth test
    glEnable(GL_DEPTH_TEST);

    //set the over blending function
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {
	//set the polygon mode to render lines
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	GL_CHECK_ERRORS
	//load shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add shader attribute and uniforms
		shader.AddAttribute("vVertex");
		shader.AddUniform("MVP");
		shader.AddUniform("time");
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup plane geometry
	//setup plane vertices
	int count = 0;
	int i=0, j=0;
	for( j=0;j<=NUM_Z;j++) {
		for( i=0;i<=NUM_X;i++) {
			vertices[count++] = glm::vec3( ((float(i)/(NUM_X-1)) *2-1)* HALF_SIZE_X, 0, ((float(j)/(NUM_Z-1))*2-1)*HALF_SIZE_Z);
		}
	}

	//fill plane indices array
	GLushort* id=&indices[0];
	for (i = 0; i < NUM_Z; i++) {
		for (j = 0; j < NUM_X; j++) {
			int i0 = i * (NUM_X+1) + j;
			int i1 = i0 + 1;
			int i2 = i0 + (NUM_X+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;
			}
		}
	}

	GL_CHECK_ERRORS

	//setup plane vao and vbo stuff
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);

		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass plane vertices to array buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attrib array for position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0);
		GL_CHECK_ERRORS
		//pass the plane indices to element array buffer
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
			  
	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {
	GL_CHECK_ERRORS

	//load shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attributes and uniforms
		shader.AddAttribute("vVertex");
		shader.AddUniform("textureMap");
		//pass values of constant uniforms at initialization
		glUniform1i(shader("textureMap"), 0);
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup quad geometry
	//setup quad vertices
	vertices[0] = glm::vec2(0.0,0.0);
	vertices[1] = glm::vec2(1.0,0.0);
	vertices[2] = glm::vec2(1.0,1.0);
	vertices[3] = glm::vec2(0.0,1.0);

	//fill quad indices array
	GLushort* id=&indices[0];
	*id++ =0;
	*id++ =1;
	*id++ =2;
	*id++ =0;
	*id++ =2;
	*id++ =3;

	GL_CHECK_ERRORS

	//setup quad vao and vbo stuff
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);

		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass quad vertices to buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 2, GL_FLOAT, GL_FALSE,0,0);
		GL_CHECK_ERRORS
		//pass quad indices to element array buffer
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS


	//load the image using SOIL
	int texture_width = 0, texture_height = 0, channels=0;
	GLubyte* pData = SOIL_load_image(filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO);
	if(pData == NULL) {
		cerr<<"Cannot load image: "<<filename.c_str()<<endl;
		exit(EXIT_FAILURE);
	}
	//vertically flip the image on Y axis since it is inverted
	int i,j;
	for( j = 0; j*2 < texture_height; ++j )
	{
		int index1 = j * texture_width * channels;
		int index2 = (texture_height - 1 - j) * texture_width * channels;
		for( i = texture_width * channels; i > 0; --i )
		{
			GLubyte temp = pData[index1];
			pData[index1] = pData[index2];
			pData[index2] = temp;
			++index1;
			++index2;
		}
	}
	//setup OpenGL texture and bind to texture unit 0
	glGenTextures(1, &textureID);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, textureID);
		//set texture parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

		//allocate texture 
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, texture_width, texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, pData);

	//free SOIL image data
	SOIL_free_image_data(pData);

	GL_CHECK_ERRORS

	cout<<"Initialization successfull"<<endl;
}
Exemple #10
0
//OpenGL initialization function
void OnInit() {
	//setup fullscreen quad geometry
	glm::vec2 quadVerts[4];
	quadVerts[0] = glm::vec2(-1,-1);
	quadVerts[1] = glm::vec2(1,-1);
	quadVerts[2] = glm::vec2(1,1);
	quadVerts[3] = glm::vec2(-1,1);
	//setup quad indices
	GLushort quadIndices[]={ 0,1,2,0,2,3};
	//setup quad vertex array and vertex buffer objects
	glGenVertexArrays(1, &quadVAOID);
	glGenBuffers(1, &quadVBOID);
	glGenBuffers(1, &quadIndicesID);

	glBindVertexArray(quadVAOID);
		glBindBuffer (GL_ARRAY_BUFFER, quadVBOID);
		//pass quad vertices to vertex buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW);

		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0);

		//pass quad indices to element array buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW);

	//get the mesh path for loading of textures	
	std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1);

	//load the obj model
	vector<unsigned short> indices2;
	vector<glm::vec3> vertices2;
	if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials, aabb, vertices2, indices2)) {
		cout<<"Cannot load the 3ds mesh"<<endl;
		exit(EXIT_FAILURE);
	}
	
	GL_CHECK_ERRORS

	int total =0;
	//check the total number of non empty textures since we will use this
	//information to creare a single array texture to store all textures 
	for(size_t k=0;k<materials.size();k++) {
		if(materials[k]->map_Kd != "") {
			total++;
		}
	}

	//load material textures
	for(size_t k=0;k<materials.size();k++) {
		//if the diffuse texture name is not empty
		if(materials[k]->map_Kd != "") {
			if(k==0) {
				//generate a new OpenGL array texture
				glGenTextures(1, &textureID);
				glBindTexture(GL_TEXTURE_2D_ARRAY, textureID);
				glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
				glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP);
				glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP);
			}
			int texture_width = 0, texture_height = 0, channels=0;

			const string& filename =  materials[k]->map_Kd;

			std::string full_filename = mesh_path;
			full_filename.append(filename);

			//use SOIL to load the texture
			GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO);
			if(pData == NULL) {
				cerr<<"Cannot load image: "<<full_filename.c_str()<<endl;
				exit(EXIT_FAILURE);
			}

			//Flip the image on Y axis
			int i,j;
			for( j = 0; j*2 < texture_height; ++j )
			{
				int index1 = j * texture_width * channels;
				int index2 = (texture_height - 1 - j) * texture_width * channels;
				for( i = texture_width * channels; i > 0; --i )
				{
					GLubyte temp = pData[index1];
					pData[index1] = pData[index2];
					pData[index2] = temp;
					++index1;
					++index2;
				}
			}
			//get the image format
			GLenum format = GL_RGBA;
			switch(channels) {
				case 2:	format = GL_RG32UI; break;
				case 3: format = GL_RGB;	break;
				case 4: format = GL_RGBA;	break;
			}

			//if this is the first texture, allocate the array texture
			if(k==0) {
				glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, format, texture_width, texture_height, total, 0, format, GL_UNSIGNED_BYTE, NULL);
			}
			//modify the existing texture
			glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0,0,0,k, texture_width, texture_height, 1, format, GL_UNSIGNED_BYTE, pData);

			//release the SOIL image data
			SOIL_free_image_data(pData);
		}
	}
	GL_CHECK_ERRORS

	//load flat shader
	flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert");
	flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag");
	//compile and link shader
	flatShader.CreateAndLinkProgram();
	flatShader.Use();
		//add attribute and uniform
		flatShader.AddAttribute("vVertex");
		flatShader.AddUniform("MVP");
	flatShader.UnUse();

	//load raytracing shader
	raytraceShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/raytracer.vert");
	raytraceShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/raytracer.frag");
	//compile and link shader
	raytraceShader.CreateAndLinkProgram();
	raytraceShader.Use();
		//add attribute and uniform
		raytraceShader.AddAttribute("vVertex");
		raytraceShader.AddUniform("eyePos");
		raytraceShader.AddUniform("invMVP");
		raytraceShader.AddUniform("light_position");
		raytraceShader.AddUniform("backgroundColor");
		raytraceShader.AddUniform("aabb.min");
		raytraceShader.AddUniform("aabb.max");
		raytraceShader.AddUniform("vertex_positions");
		raytraceShader.AddUniform("triangles_list");
		raytraceShader.AddUniform("VERTEX_TEXTURE_SIZE");
		raytraceShader.AddUniform("TRIANGLE_TEXTURE_SIZE");

		//set values of constant uniforms as initialization		
		glUniform1f(raytraceShader("VERTEX_TEXTURE_SIZE"), (float)vertices2.size());
		glUniform1f(raytraceShader("TRIANGLE_TEXTURE_SIZE"), (float)indices2.size()/4);
		glUniform3fv(raytraceShader("aabb.min"),1, glm::value_ptr(aabb.min));
		glUniform3fv(raytraceShader("aabb.max"),1, glm::value_ptr(aabb.max));
		glUniform4fv(raytraceShader("backgroundColor"),1, glm::value_ptr(bg));
		glUniform1i(raytraceShader("vertex_positions"), 1);
		glUniform1i(raytraceShader("triangles_list"), 2);
	raytraceShader.UnUse();

	GL_CHECK_ERRORS

	//load mesh rendering shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attribute and uniform
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddAttribute("vUV");
		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("P");
		shader.AddUniform("textureMap");
		shader.AddUniform("textureIndex");
		shader.AddUniform("useDefault");
		shader.AddUniform("diffuse_color");
		shader.AddUniform("light_position");
		//set values of constant uniforms as initialization	
		glUniform1i(shader("textureMap"), 0);
	shader.UnUse();

	GL_CHECK_ERRORS
		
	//setup the vertex array object and vertex buffer object for the mesh
	//geometry handling 
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);
		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass mesh vertices
		glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		
		//enable vertex attribute array for vertex normal
		glEnableVertexAttribArray(shader["vNormal"]);
		glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) );

		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex texture coordinates
		glEnableVertexAttribArray(shader["vUV"]);
		glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) );

		GL_CHECK_ERRORS

		//if we have a single material, it means the 3ds model contains one mesh
		//we therefore load it into an element array buffer
		if(materials.size()==1) {
			//pass indices to the element array buffer if there is a single material			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW);
		}
		GL_CHECK_ERRORS

	glBindVertexArray(0);

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);
	
	//setup light gizmo vertex array and vertex buffer object IDs
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);
	glBindVertexArray(lightVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
		//pass crosshair vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);

	GL_CHECK_ERRORS

	//use spherical coordinates to get the light position
	lightPosOS.x = radius * cos(theta)*sin(phi);
	lightPosOS.y = radius * cos(phi);
	lightPosOS.z = radius * sin(theta)*sin(phi);

	//pass position to 1D texture bound to texture unit 1
	glGenTextures(1, &texVerticesID);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture( GL_TEXTURE_2D, texVerticesID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	GLfloat* pData = new GLfloat[vertices2.size()*4];
	int count = 0;
	for(size_t i=0;i<vertices2.size();i++) {
		pData[count++] = vertices2[i].x;
		pData[count++] = vertices2[i].y;
		pData[count++] = vertices2[i].z;
		pData[count++] = 0;				
	}
	//allocate a floating point texture
 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, vertices2.size(),1, 0, GL_RGBA, GL_FLOAT, pData);

	//delete the data pointer
	delete [] pData;

	GL_CHECK_ERRORS

	//store the mesh topology in another texture bound to texture unit 2
	glGenTextures(1, &texTrianglesID);
	glActiveTexture(GL_TEXTURE2);
	glBindTexture( GL_TEXTURE_2D, texTrianglesID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

	GLushort* pData2 = new GLushort[indices2.size()];
	count = 0;
	for(size_t i=0;i<indices2.size();i+=4) {
		pData2[count++] = (indices2[i]);
		pData2[count++] = (indices2[i+1]);
		pData2[count++] = (indices2[i+2]);
		pData2[count++] = (indices2[i+3]);
	}
	//allocate an integer format texture
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16I, indices2.size()/4,1, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, pData2);
	
	//delete heap allocated buffer
	delete [] pData2;

	GL_CHECK_ERRORS

	//set texture unit 0 as active texture unit
	glActiveTexture(GL_TEXTURE0);

	//enable depth test and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	//set the background colour
	glClearColor(bg.x, bg.y, bg.z, bg.w);

	cout<<"Initialization successfull"<<endl;

	//get the initial time
	lastTime = (float)glutGet(GLUT_ELAPSED_TIME);
}
Exemple #11
0
//OpenGL initialization
void OnInit() {

	//init high performance timer
	QueryPerformanceFrequency(&freq);
	QueryPerformanceCounter(&last);

	//get mesh path
	std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("//")+1);

	glm::vec3 min, max;

	//load the EZmesh file
	if(!ezm.Load(mesh_filename.c_str(), skeleton, animations, submeshes, vertices, indices, material2ImageMap, min, max)) {
		cout<<"Cannot load the EZMesh file"<<endl;
		exit(EXIT_FAILURE);
	}

	//check the absolute value y and z dimensions of the bounding box
	float dy = fabs(max.y-min.y);
	float dz = fabs(max.z-min.z);
	bYup = (dy>dz);


	//get the combined bone transform
	UpdateCombinedMatrices();

	//resize bind pose, inverse bind pose, animatedXform and dualQuaternion vectors
	bindPose.resize(skeleton.size());
	invBindPose.resize(skeleton.size());
	animatedXform.resize(skeleton.size());
	dualQuaternions.resize(skeleton.size());

	//store the bind pose matrices which are the absolute transform of
	//each bone. Also store their inverse which is used in skinning
	for(size_t i=0;i<skeleton.size();i++) {
		bindPose[i] = (skeleton[i].comb);
		invBindPose[i] = glm::inverse(bindPose[i]);
	}

	GL_CHECK_ERRORS

	//store the loaded material names into a vector
	for(iter i = material2ImageMap.begin();i!=material2ImageMap.end();++i) {
		materialNames.push_back(i->second);
	}

	//calculate the distance the camera has to be moved to properly view the EZMesh model
	center = (max + min) * 0.5f;
	glm::vec3 diagonal = (max-min);
	radius = glm::length(center- diagonal * 0.5f);
	dist = -glm::length(diagonal);

	//generate OpenGL textures from the loaded material names
	for(size_t k=0;k<materialNames.size();k++) {
		if(materialNames[k].length()==0)
			continue;

		//get the full image name
		int texture_width = 0, texture_height = 0, channels=0;
		const string& filename =  materialNames[k];
		std::string full_filename = mesh_path;
		full_filename.append(filename);

		//pass the full image name including the path and use SOIL library to load the image		
		GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO);
		if(pData == NULL) {
			cerr<<"Cannot load image: "<<full_filename.c_str()<<endl;
			exit(EXIT_FAILURE);
		}

		//Flip the image on Y axis
		int i,j;
		for( j = 0; j*2 < texture_height; ++j )
		{
			int index1 = j * texture_width * channels;
			int index2 = (texture_height - 1 - j) * texture_width * channels;
			for( i = texture_width * channels; i > 0; --i )
			{
				GLubyte temp = pData[index1];
				pData[index1] = pData[index2];
				pData[index2] = temp;
				++index1;
				++index2;
			}
		}

		//determine the image format
		GLenum format = GL_RGBA;
			switch(channels) {
				case 2:	format = GL_RG32UI; break;
				case 3: format = GL_RGB;	break;
				case 4: format = GL_RGBA;	break;
			}
		
		GLuint id = 0;
		//generate new texture id
		glGenTextures(1, &id);
		glBindTexture(GL_TEXTURE_2D, id);
		//set texture parameters
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
		//allocate the texture 
		glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData);
		
		//delete the SOIL image data
		SOIL_free_image_data(pData);

		//store the texture id into the material map. Refer to the texture by name 
		//will give us its OpenGL texture id
		materialMap[filename] = id ;
	}
	GL_CHECK_ERRORS
	//setup shaders
	flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert");
	flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag");
	//compile and link flat shader
	flatShader.CreateAndLinkProgram();
	flatShader.Use();
		//add shader attributes and uniforms
		flatShader.AddAttribute("vVertex");
		flatShader.AddUniform("MVP");
	flatShader.UnUse();

	//For the skinning vertex shader, we pass the Bones array dynamcially
	//since we may not know the total number of bones in the model at compile
	//time. Since the GLSL arrays have to be a compile time constant, we 
	//dynamically generate the shader string to add the uniform in the shader.
	//To achieve this, we overload the GLSLShader::LoadFromFile function with
	//a thid parameter, the string we want to add before the shader main function.
	stringstream str( ios_base::app | ios_base::out);
	str<<"\nconst int NUM_BONES="<<skeleton.size()*2<<";"<<endl;
	str<<"uniform vec4 Bones[NUM_BONES];"<<endl;
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert", str.str());
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
		
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add shader attributes and uniforms
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddAttribute("vUV");
		shader.AddAttribute("vBlendWeights");
		shader.AddAttribute("viBlendIndices");

		shader.AddUniform("Bones");
		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("P");
		shader.AddUniform("textureMap");
		shader.AddUniform("useDefault");

		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");

		glUniform1i(shader("textureMap"), 0);
		//pass values to uniforms at initialization, since we have a dual quaternion we pass
		//it as 2 vec4 variables hence the multiplication by 2
		glUniform4fv(shader("Bones"), skeleton.size()*2, &(dualQuaternions[0].ordinary.x));

	shader.UnUse();

	GL_CHECK_ERRORS

	//setup geometry
	//setup vao and vbo stuff
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);
		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass vertices to buffer object memory
		glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_DYNAMIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute 
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable normal attribute 
		glEnableVertexAttribArray(shader["vNormal"]);
		glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) );

		GL_CHECK_ERRORS
		//enable texture coordinate attribute 
		glEnableVertexAttribArray(shader["vUV"]);
		glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) );

		GL_CHECK_ERRORS
		//enable blend weights attribute array
		glEnableVertexAttribArray(shader["vBlendWeights"]);
		glVertexAttribPointer(shader["vBlendWeights"], 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, blendWeights)) );

		GL_CHECK_ERRORS
		//enable blend indices attribute array
		glEnableVertexAttribArray(shader["viBlendIndices"]);
		glVertexAttribIPointer(shader["viBlendIndices"], 4, GL_INT, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, blendIndices)) );

	GL_CHECK_ERRORS
		 

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);

	//generate light vertex array and buffer object
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);
	glBindVertexArray(lightVAOID);

	//pass the cross hair data to the buffer object memory
	glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
	glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_DYNAMIC_DRAW);
	GL_CHECK_ERRORS
	//enable vertex attribute array
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);

	GL_CHECK_ERRORS
	//get the light position using the center and the spherical coordinates
	lightPosOS.x = center.x + radius * cos(theta)*sin(phi);
	lightPosOS.y = center.y + radius * cos(phi);
	lightPosOS.z = center.z + radius * sin(theta)*sin(phi);
	
	//enable depth test and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	//set clear color to corn blue
	glClearColor(0.5,0.5,1,1);

	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() { 

	//load the per-fragment point light shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/PointLight.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/PointLight.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attributes and uniforms
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddUniform("MVP");
		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup sphere geometry
	CreateSphere(1.0f,10,10, vertices, indices);

	//setup sphere vao and vbo stuff
	glGenVertexArrays(1, &sphereVAOID);
	glGenBuffers(1, &sphereVerticesVBO);
	glGenBuffers(1, &sphereIndicesVBO);
	glBindVertexArray(sphereVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass sphere indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	//store the total number of sphere triangles
	totalSphereTriangles = indices.size();

	//clear the vertices and indices vectors as we will reuse them
	//for cubes
	vertices.clear();
	indices.clear();

	//setup cube geometry
	CreateCube(2,vertices, indices);

	//setup cube vao and vbo stuff
	glGenVertexArrays(1, &cubeVAOID);
	glGenBuffers(1, &cubeVerticesVBO);
	glGenBuffers(1, &cubeIndicesVBO);
	glBindVertexArray(cubeVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, cubeVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		
		//enable vertex attribute array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS

		//pass cube indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	GL_CHECK_ERRORS

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);

	//setup light gizmo vertex array and buffer object
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);
	glBindVertexArray(lightVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
		//pass light crosshair gizmo vertices to buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);

		GL_CHECK_ERRORS

	//enable depth testing and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);
	
	GL_CHECK_ERRORS

	//create a grid of 10x10 size in XZ plane
	grid = new CGrid();

	GL_CHECK_ERRORS

	//get the grid shader for rendering of the light's crosshair gizmo
	pFlatShader = grid->GetShader();

	//get the light position using the spherical coordinates
	lightPosOS.x = radius * cos(theta)*sin(phi);
	lightPosOS.y = radius * cos(phi);
	lightPosOS.z = radius * sin(theta)*sin(phi);

	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {

	GL_CHECK_ERRORS
	//load heightmap shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();	
		//add attributes and uniforms
		shader.AddAttribute("vVertex"); 
		shader.AddUniform("heightMapTexture");
		shader.AddUniform("scale");
		shader.AddUniform("half_scale");
		shader.AddUniform("HALF_TERRAIN_SIZE");
		shader.AddUniform("MVP");
		//set values of constant uniforms as initialization	
		glUniform1i(shader("heightMapTexture"), 0);
		glUniform2i(shader("HALF_TERRAIN_SIZE"), TERRAIN_WIDTH>>1, TERRAIN_DEPTH>>1);
		glUniform1f(shader("scale"), scale);
		glUniform1f(shader("half_scale"), half_scale);
	shader.UnUse();

	GL_CHECK_ERRORS
		 
		
	//fill indices array
	GLuint* id=&indices[0];
	int i=0, j=0;
	
	//setup vertices 
	int count = 0;
	//fill terrain vertices
	for( j=0;j<TERRAIN_DEPTH;j++) {		 
		for( i=0;i<TERRAIN_WIDTH;i++) {	  
			vertices[count] = glm::vec3( (float(i)/(TERRAIN_WIDTH-1)), 
										 0, 
										 (float(j)/(TERRAIN_DEPTH-1)));
			count++;
		}
	}
	 
	//fill terrain indices
	for (i = 0; i < TERRAIN_DEPTH-1; i++) {        
		for (j = 0; j < TERRAIN_WIDTH-1; j++) {			
			int i0 = j+ i*TERRAIN_WIDTH;
			int i1 = i0+1;
			int i2 = i0+TERRAIN_WIDTH;
			int i3 = i2+1;
			*id++ = i0; 
			*id++ = i2; 
			*id++ = i1; 
			*id++ = i1; 
			*id++ = i2; 
			*id++ = i3; 
		}    
	}

	GL_CHECK_ERRORS

	//setup terrain vertex array and vertex buffer objects 
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);
	 
	glBindVertexArray(vaoID);	

		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass terrain vertices to buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0);
		GL_CHECK_ERRORS 
		//pass the terrain indices array to element array buffer
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
			
	//load the heightmap texture using SOIL	
	int texture_width = 0, texture_height = 0, channels=0;		 
	GLubyte* pData = SOIL_load_image(filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_L);
	
	//vertically flip the heightmap image on Y axis since it is inverted 
	for( j = 0; j*2 < texture_height; ++j )
	{
		int index1 = j * texture_width ;
		int index2 = (texture_height - 1 - j) * texture_width ;
		for( i = texture_width ; i > 0; --i )
		{
			GLubyte temp = pData[index1];
			pData[index1] = pData[index2];
			pData[index2] = temp;
			++index1;
			++index2;
		}
	} 

	//setup OpenGL texture
	glGenTextures(1, &heightMapTextureID);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, heightMapTextureID);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture_width, texture_height, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
	
	//free SOIL image data
	SOIL_free_image_data(pData);
	
	GL_CHECK_ERRORS

	//set polygon mode to draw lines
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	GL_CHECK_ERRORS

	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {
	
	//load the per-vertex lighting shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/perVertexLighting.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/perVertexLighting.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attributes and uniforms
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddUniform("MVP");
		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");
		shader.AddUniform("specular_color");
		shader.AddUniform("shininess");
	shader.UnUse();

	GL_CHECK_ERRORS

	//cerate sphere geometry
	CreateSphere(1.0f,10,10, vertices, indices);

	//setup sphere vao and vbo stuff
	glGenVertexArrays(1, &sphereVAOID);
	glGenBuffers(1, &sphereVerticesVBO);
	glGenBuffers(1, &sphereIndicesVBO);
	glBindVertexArray(sphereVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		
		//pass sphere indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	//store the total number of sphere triangles
	totalSphereTriangles = indices.size();

	//clear the vertices and indices vectors as we will reuse them
	//for cubes
	vertices.clear();
	indices.clear();

	//setup cube geometry
	CreateCube(1,vertices, indices);

	//setup cube vao and vbo stuff
	glGenVertexArrays(1, &cubeVAOID);
	glGenBuffers(1, &cubeVerticesVBO);
	glGenBuffers(1, &cubeIndicesVBO);
	glBindVertexArray(cubeVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, cubeVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribut array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribut array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass cube indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	GL_CHECK_ERRORS

	//enable depth testing and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	//create a grid of 10x10 size in XZ plane
	grid = new CGrid();

	GL_CHECK_ERRORS

	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() {

	//load the flat shader
	flatshader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	flatshader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	flatshader.CreateAndLinkProgram();
	flatshader.Use();
		//add attributes and uniforms
		flatshader.AddAttribute("vVertex");
		flatshader.AddUniform("MVP");
	flatshader.UnUse();

	//load the shadow mapping shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/PointLightShadowMapped.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/PointLightShadowMapped.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attributes and uniforms
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddUniform("MVP");
		shader.AddUniform("MV");
		shader.AddUniform("M");
		shader.AddUniform("N");
		shader.AddUniform("S");
		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");
		shader.AddUniform("bIsLightPass");
		shader.AddUniform("shadowMap");
		//pass value of constant uniforms at initialization
		glUniform1i(shader("shadowMap"),0);
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup sphere geometry
	CreateSphere(1.0f,10,10, vertices, indices);

	//setup sphere vao and vbo stuff
	glGenVertexArrays(1, &sphereVAOID);
	glGenBuffers(1, &sphereVerticesVBO);
	glGenBuffers(1, &sphereIndicesVBO);
	glBindVertexArray(sphereVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass sphere indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	//store the total number of sphere triangles
	totalSphereTriangles = indices.size();

	//clear the vertices and indices vectors as we will reuse them
	//for cubes
	vertices.clear();
	indices.clear();

	//setup cube geometry
	CreateCube(2,vertices, indices);

	//setup cube vao and vbo stuff
	glGenVertexArrays(1, &cubeVAOID);
	glGenBuffers(1, &cubeVerticesVBO);
	glGenBuffers(1, &cubeIndicesVBO);
	glBindVertexArray(cubeVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, cubeVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normals
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass cube indices to element array buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, cubeIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	GL_CHECK_ERRORS

	//clear the vertices and indices vectors as we will reuse them
	//for plane
	vertices.clear();
	indices.clear();
	//create a plane object
	CreatePlane(100,100,vertices, indices);

	//setup plane VAO and VBO
	glGenVertexArrays(1, &planeVAOID);
	glGenBuffers(1, &planeVerticesVBO);
	glGenBuffers(1, &planeIndicesVBO);
	glBindVertexArray(planeVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, planeVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normals
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass plane indices to element array buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, planeIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);

	GL_CHECK_ERRORS

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);

	//setup light gizmo vertex array and buffer object
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);
	glBindVertexArray(lightVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
		//pass light crosshair gizmo vertices to buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);


	GL_CHECK_ERRORS

	//get light position from spherical coordinates
	lightPosOS.x = radius * cos(theta)*sin(phi);
	lightPosOS.y = radius * cos(phi);
	lightPosOS.z = radius * sin(theta)*sin(phi);

	//setup the shadowmap texture
	glGenTextures(1, &shadowMapTexID);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, shadowMapTexID);

	//set texture parameters
	GLfloat border[4]={1,0,0,0};
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_MODE,GL_COMPARE_REF_TO_TEXTURE);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_COMPARE_FUNC,GL_LEQUAL);
	glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,border);
	glTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT24,SHADOWMAP_WIDTH,SHADOWMAP_HEIGHT,0,GL_DEPTH_COMPONENT,GL_UNSIGNED_BYTE,NULL);

	//set up FBO to get the depth component
	glGenFramebuffers(1,&fboID);
	glBindFramebuffer(GL_FRAMEBUFFER,fboID);
	glFramebufferTexture2D(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_TEXTURE_2D,shadowMapTexID,0);

	//check framebuffer completeness status
	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if(status == GL_FRAMEBUFFER_COMPLETE) {
		cout<<"FBO setup successful."<<endl;
	} else {
		cout<<"Problem in FBO setup."<<endl;
	}

	//unbind FBO
	glBindFramebuffer(GL_FRAMEBUFFER,0);

	//set the light MV, P and bias matrices
	MV_L = glm::lookAt(lightPosOS,glm::vec3(0,0,0),glm::vec3(0,1,0));
	P_L  = glm::perspective(glm::radians(50.0f),1.0f,1.0f, 25.0f);
	B    = glm::scale(glm::translate(glm::mat4(1),glm::vec3(0.5,0.5,0.5)), glm::vec3(0.5,0.5,0.5));
	BP   = B*P_L;
	S    = BP*MV_L;

	//enable depth testing and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	cout<<"Initialization successfull"<<endl;  
}
//OpenGL initialization function
void OnInit() {

	//generate the pseudorandom noise data
	glm::vec4 pData[64][64];
	for(int j=0;j<64;j++) {
		for(int i=0;i<64;i++) {
			pData[i][j].x = (float)rand() / RAND_MAX;
			pData[i][j].y = (float)rand() / RAND_MAX;
			pData[i][j].z = (float)rand() / RAND_MAX;
			pData[i][j].w = (float)rand() / RAND_MAX;
		}
	}

	//use the pseudorandom noise data to generate a 64x64 nosie texture
	glGenTextures(1, &noiseTexID);
	glActiveTexture(GL_TEXTURE2);
	glBindTexture(GL_TEXTURE_2D, noiseTexID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 64, 64, 0, GL_BGRA, GL_FLOAT, pData);

	//get the mesh path for loading of textures
	std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1);

	//load the obj model
	if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials)) {
		cout<<"Cannot load the Obj mesh"<<endl;
		exit(EXIT_FAILURE);
	}
	GL_CHECK_ERRORS

	//bind texture 0 as active texture unit
	glActiveTexture(GL_TEXTURE0);
	//load material textures
	for(size_t k=0;k<materials.size();k++) {
		//if the diffuse texture name is not empty
		if(materials[k]->map_Kd != "") {
			GLuint id = 0;

			//generate a new OpenGL texture
			glGenTextures(1, &id);
			glBindTexture(GL_TEXTURE_2D, id);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
			int texture_width = 0, texture_height = 0, channels=0;

			const string& filename =  materials[k]->map_Kd;

			std::string full_filename = mesh_path;
			full_filename.append(filename);

			//use SOIL to load the texture
			GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO);
			if(pData == NULL) {
				cerr<<"Cannot load image: "<<full_filename.c_str()<<endl;
				exit(EXIT_FAILURE);
			}

			//Flip the image on Y axis
			int i,j;
			for( j = 0; j*2 < texture_height; ++j )
			{
				int index1 = j * texture_width * channels;
				int index2 = (texture_height - 1 - j) * texture_width * channels;
				for( i = texture_width * channels; i > 0; --i )
				{
					GLubyte temp = pData[index1];
					pData[index1] = pData[index2];
					pData[index2] = temp;
					++index1;
					++index2;
				}
			}
			//get the image format
			GLenum format = GL_RGBA;
			switch(channels) {
				case 2:	format = GL_RG32UI; break;
				case 3: format = GL_RGB;	break;
				case 4: format = GL_RGBA;	break;
			}
			//allocate the texture
			glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData);

			//release the SOIL image data
			SOIL_free_image_data(pData);

			//add the texture id to a vector
			textures.push_back(id);
		}
	}
	GL_CHECK_ERRORS

	//setup flat shader
	flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert");
	flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag");
	//compile and link shader
	flatShader.CreateAndLinkProgram();
	flatShader.Use();
		//add attribute and uniform
		flatShader.AddAttribute("vVertex");
		flatShader.AddUniform("MVP");
	flatShader.UnUse();

	//load final shader
	finalShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert");
	finalShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/final.frag");
	//compile and link shader
	finalShader.CreateAndLinkProgram();
	finalShader.Use();
		//add attribute and uniform
		finalShader.AddAttribute("vVertex");
		finalShader.AddUniform("MVP");
		finalShader.AddUniform("textureMap");
		//set values of constant uniforms as initialization
		glUniform1i(finalShader("textureMap"), 4);
	finalShader.UnUse();

	//load the point light rendering shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	shader.CreateAndLinkProgram();
	shader.Use();
		//add attribute and uniform
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddAttribute("vUV");

		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("P");
		shader.AddUniform("textureMap");
		shader.AddUniform("useDefault");

		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");
		//set values of constant uniforms as initialization
		glUniform1i(shader("textureMap"), 0);
	shader.UnUse();

	//load the horizontal Gaussian blurring shader
	gaussianH_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert");
	gaussianH_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/GaussH.frag");

	//compile and link shader
	gaussianH_shader.CreateAndLinkProgram();
	gaussianH_shader.Use();
		//add attribute and uniform
		gaussianH_shader.AddAttribute("vVertex");
		gaussianH_shader.AddUniform("textureMap");
		//set values of constant uniforms as initialization
		glUniform1i(gaussianH_shader("textureMap"),5);
	gaussianH_shader.UnUse();

	//load the vertical Gaussian blurring shader
	gaussianV_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert");
	gaussianV_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/GaussV.frag");

	//compile and link shader
	gaussianV_shader.CreateAndLinkProgram();
	gaussianV_shader.Use();
		//add attribute and uniform
		gaussianV_shader.AddAttribute("vVertex");
		gaussianV_shader.AddUniform("textureMap");
		//set values of constant uniforms as initialization
		glUniform1i(gaussianV_shader("textureMap"),4);
	gaussianV_shader.UnUse();

	//load the first step SSAO shader
	ssaoFirstShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/SSAO_FirstStep.vert");
	ssaoFirstShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/SSAO_FirstStep.frag");
	//compile and link shader
	ssaoFirstShader.CreateAndLinkProgram();
	ssaoFirstShader.Use();
		//add attribute and uniform
		ssaoFirstShader.AddAttribute("vVertex");
		ssaoFirstShader.AddAttribute("vNormal");
		ssaoFirstShader.AddUniform("MVP");
		ssaoFirstShader.AddUniform("N");
	ssaoFirstShader.UnUse();

	//load the second step SSAO shader
	ssaoSecondShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/Passthrough.vert");
	ssaoSecondShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/SSAO_SecondStep.frag");
	//compile and link shader
	ssaoSecondShader.CreateAndLinkProgram();
	ssaoSecondShader.Use();
		//add attribute and uniform
		ssaoSecondShader.AddAttribute("vVertex");
		ssaoSecondShader.AddUniform("samples");
		ssaoSecondShader.AddUniform("invP");
		ssaoSecondShader.AddUniform("normalTex");
		ssaoSecondShader.AddUniform("depthTex");
		ssaoSecondShader.AddUniform("noiseTex");
		ssaoSecondShader.AddUniform("radius");
		ssaoSecondShader.AddUniform("viewportSize");
		ssaoSecondShader.AddUniform("invViewportSize");

		//set values of constant uniforms as initialization
		glUniform2f(ssaoSecondShader("viewportSize"), float(RTT_WIDTH), float(RTT_HEIGHT));
		glUniform2f(ssaoSecondShader("invViewportSize"), 1.0f/float(RTT_WIDTH), 1.0f/float(RTT_HEIGHT));
		glUniform1i(ssaoSecondShader("normalTex"),1);
		glUniform1i(ssaoSecondShader("noiseTex"),2);
		glUniform1i(ssaoSecondShader("depthTex"),3);

		glm::mat4 biasMat;
		biasMat = glm::translate(glm::mat4(1),glm::vec3(0.5,0.5,0.5));
		biasMat = glm::scale(biasMat, glm::vec3(0.5,0.5,0.5));
		glm::mat4 invP = biasMat*glm::inverse(P);
		glUniformMatrix4fv(ssaoSecondShader("invP"), 1, GL_FALSE, glm::value_ptr(invP));

		glm::vec2 samples[16];
		float angle = (float)M_PI_4;
		for(int i=0;i<16;i++) {
			samples[i].x = cos(angle) * (float)(i+1)/16.0f;
			samples[i].y = sin(angle) * (float)(i+1)/16.0f;
			angle += (float)M_PI_2;
			if(((i + 1) % 4) == 0)
				angle += (float)M_PI_4;
		}
		glUniform2fv(ssaoSecondShader("samples"), 16, &(samples[0].x));
	ssaoSecondShader.UnUse();

	GL_CHECK_ERRORS


	//setup the vertex array object and vertex buffer object for the mesh
	//geometry handling 
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);

	glBindVertexArray(vaoID);
		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass mesh vertices
		glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex normal
		glEnableVertexAttribArray(shader["vNormal"]);
		glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) );

		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex texture coordinates
		glEnableVertexAttribArray(shader["vUV"]);
		glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) );

		//if we have a single material, it means the 3ds model contains one mesh
		//we therefore load it into an element array buffer
		if(materials.size()==1) {
			//pass indices to the element array buffer if there is a single material
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW);
		}
		GL_CHECK_ERRORS

	//setup fullscreen quad vertices
	glm::vec2 quadVerts[4];
	quadVerts[0] = glm::vec2(0,0);
	quadVerts[1] = glm::vec2(1,0);
	quadVerts[2] = glm::vec2(1,1);
	quadVerts[3] = glm::vec2(0,1);

	//setup quad indices
	GLushort quadIndices[]={ 0,1,2,0,2,3};

	//setup quad vertex array and vertex buffer objects
	glGenVertexArrays(1, &quadVAOID);
	glGenBuffers(1, &quadVBOID);
	glGenBuffers(1, &quadIndicesID);

	glBindVertexArray(quadVAOID);
		glBindBuffer (GL_ARRAY_BUFFER, quadVBOID);
		//pass quad vertices to vertex buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(quadVerts), &quadVerts[0], GL_STATIC_DRAW);

		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,0,0);
		//pass quad indices to element array buffer
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, quadIndicesID);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(quadIndices), &quadIndices[0], GL_STATIC_DRAW);


	//glBindVertexArray(0);

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);

	//setup light gizmo vertex array and vertex buffer object IDs
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);
	glBindVertexArray(lightVAOID);

	glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
	//pass crosshair vertices to the buffer object
	glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW);
	GL_CHECK_ERRORS
	//enable vertex attribute array for vertex position
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);

	GL_CHECK_ERRORS

	//use spherical coordinates to get the light position
	lightPosOS.x = radius * cos(theta)*sin(phi);
	lightPosOS.y = radius * cos(phi);
	lightPosOS.z = radius * sin(theta)*sin(phi);

	//enable depth test and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	//set clear colour to corn blue
	glClearColor(0.5,0.5,1,1);

	//initializa FBO
	InitFBO();
	cout<<"Initialization successfull"<<endl;
}
void OnInit() {
	GL_CHECK_ERRORS
	//setup shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_GEOMETRY_SHADER, "shaders/shader.geom");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	shader.CreateAndLinkProgram();
	shader.Use();	
		shader.AddAttribute("vVertex"); 
		shader.AddUniform("heightMapTexture");
		shader.AddUniform("scale");
		shader.AddUniform("half_scale");
		shader.AddUniform("HALF_TERRAIN_SIZE");
		shader.AddUniform("MVP");

		glUniform1i(shader("heightMapTexture"), 0);
		glUniform2i(shader("HALF_TERRAIN_SIZE"), TERRAIN_WIDTH>>1, TERRAIN_DEPTH>>1);
		glUniform1f(shader("scale"), scale);
		glUniform1f(shader("half_scale"), half_scale);
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup geometry
	

	//fill indices array
	GLuint* id=&indices[0];
	int i=0, j=0;
	
	//setup vertices 
	int count = 0;

	
	for( j=0;j<TERRAIN_DEPTH;j++) {		 
		for( i=0;i<TERRAIN_WIDTH;i++) {	 
			/*
			vertices[count] = glm::vec3( ( (float(i)/(TERRAIN_WIDTH-1))*2.0f-1)*TERRAIN_HALF_WIDTH, 
										 (pData[count]/255.0f)*scale-half_scale, 
										 ( (float(j)/(TERRAIN_DEPTH-1))*2.0-1)*TERRAIN_HALF_DEPTH);
										 */
			vertices[count] = glm::vec3( (float(i)/(TERRAIN_WIDTH-1)), 
										 0, 
										 (float(j)/(TERRAIN_DEPTH-1)));
			count++;
		}
	}
	 
	for (i = 0; i < TERRAIN_DEPTH-1; i++) {        
		for (j = 0; j < TERRAIN_WIDTH-1; j++) {			
			int i0 = j+ i*TERRAIN_WIDTH;
			int i1 = i0+1;
			int i2 = i0+TERRAIN_WIDTH;
			int i3 = i2+1;
			*id++ = i0; 
			*id++ = i2; 
			*id++ = i1; 
			*id++ = i1; 
			*id++ = i2; 
			*id++ = i3; 
		}    
	}

	GL_CHECK_ERRORS

	//setup vao and vbo stuff
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID);
	 
	glBindVertexArray(vaoID);	

		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		glBufferData (GL_ARRAY_BUFFER, sizeof(vertices), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,0,0);
		GL_CHECK_ERRORS 
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
						
			
	//load the heightmap texture using SOIL	
	int texture_width = 0, texture_height = 0, format=0;		 
	GLubyte* pData = SOIL_load_image(filename.c_str(), &texture_width, &texture_height, &format, SOIL_LOAD_L);
	
	//setup OpenGL texture
	glGenTextures(1, &heightMapTextureID);
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, heightMapTextureID);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, texture_width, texture_height, 0, GL_RED, GL_UNSIGNED_BYTE, pData);
	
	free(pData);
	
	GL_CHECK_ERRORS

	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

	GL_CHECK_ERRORS

	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization function
void OnInit() { 
	//get the mesh path for loading of textures	
	std::string mesh_path = mesh_filename.substr(0, mesh_filename.find_last_of("/")+1);

	//load the obj model
	if(!obj.Load(mesh_filename.c_str(), meshes, vertices, indices, materials)) { 
		cout<<"Cannot load the 3ds mesh"<<endl;
		exit(EXIT_FAILURE);
	} 
	GL_CHECK_ERRORS

	//load material textures  
	for(size_t k=0;k<materials.size();k++) {
		//if the diffuse texture name is not empty
		if(materials[k]->map_Kd != "") { 
			//generate a new OpenGL array texture
			GLuint id = 0;
			glGenTextures(1, &id);
			glBindTexture(GL_TEXTURE_2D, id);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
			int texture_width = 0, texture_height = 0, channels=0;		 	

			const string& filename =  materials[k]->map_Kd;

			std::string full_filename = mesh_path;
			full_filename.append(filename);
			//use SOIL to load the texture
			GLubyte* pData = SOIL_load_image(full_filename.c_str(), &texture_width, &texture_height, &channels, SOIL_LOAD_AUTO);
			if(pData == NULL) {
				cerr<<"Cannot load image: "<<full_filename.c_str()<<endl;
				exit(EXIT_FAILURE);
			} 

			//Flip the image on Y axis
			int i,j;
			for( j = 0; j*2 < texture_height; ++j )
			{
				int index1 = j * texture_width * channels;
				int index2 = (texture_height - 1 - j) * texture_width * channels;
				for( i = texture_width * channels; i > 0; --i )
				{
					GLubyte temp = pData[index1];
					pData[index1] = pData[index2];
					pData[index2] = temp;
					++index1;
					++index2;
				}
			} 
			//get the image format
			GLenum format = GL_RGBA;
			switch(channels) {
				case 2:	format = GL_RG32UI; break;
				case 3: format = GL_RGB;	break;
				case 4: format = GL_RGBA;	break;
			}
			//allocate texture 
			glTexImage2D(GL_TEXTURE_2D, 0, format, texture_width, texture_height, 0, format, GL_UNSIGNED_BYTE, pData);

			//release the SOIL image data
			SOIL_free_image_data(pData);

			//add loaded texture ID to vector
			textures.push_back(id);
		}
	} 
	GL_CHECK_ERRORS

	//load flat shader
	flatShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/flat.vert");
	flatShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/flat.frag");
	//compile and link shader
	flatShader.CreateAndLinkProgram();
	flatShader.Use();	
		//add attribute and uniform
		flatShader.AddAttribute("vVertex");
		flatShader.AddUniform("MVP"); 
	flatShader.UnUse();

	//load mesh rendering shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/shader.frag");
	//compile and link shader
	shader.CreateAndLinkProgram();
	shader.Use();	
		//add attribute and uniform
		shader.AddAttribute("vVertex");
		shader.AddAttribute("vNormal");
		shader.AddAttribute("vUV");		
		shader.AddUniform("MV");
		shader.AddUniform("N");
		shader.AddUniform("P");
		shader.AddUniform("textureMap");
		shader.AddUniform("useDefault");		
		shader.AddUniform("light_position");
		shader.AddUniform("diffuse_color");
		//set values of constant uniforms as initialization	
		glUniform1i(shader("textureMap"), 0);
	shader.UnUse();

	GL_CHECK_ERRORS

	//setup the vertex array object and vertex buffer object for the mesh
	//geometry handling 
	glGenVertexArrays(1, &vaoID);
	glGenBuffers(1, &vboVerticesID);
	glGenBuffers(1, &vboIndicesID); 
	 
	//here we are using interleaved attributes so we can just push data to one
	//buffer object and then assign different atribute pointer to identofy the 
	//different attributes
	glBindVertexArray(vaoID);	
		glBindBuffer (GL_ARRAY_BUFFER, vboVerticesID);
		//pass mesh vertices
		glBufferData (GL_ARRAY_BUFFER, sizeof(Vertex)*vertices.size(), &(vertices[0].pos.x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(shader["vVertex"]);
		glVertexAttribPointer(shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS 
		//enable vertex attribute array for vertex normal
		glEnableVertexAttribArray(shader["vNormal"]);
		glVertexAttribPointer(shader["vNormal"], 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)) );
 
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex texture coordinates
		glEnableVertexAttribArray(shader["vUV"]);
		glVertexAttribPointer(shader["vUV"], 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, uv)) );
 
		GL_CHECK_ERRORS
			
		//if we have a single material, it means the 3ds model contains one mesh
		//we therefore load it into an element array buffer
		if(materials.size()==1) {
			//pass indices to the element array buffer if there is a single material			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vboIndicesID);
			glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*indices.size(), &(indices[0]), GL_STATIC_DRAW);
		}
		GL_CHECK_ERRORS
	glBindVertexArray(0); 

	//setup vao and vbo stuff for the light position crosshair
	glm::vec3 crossHairVertices[6];
	crossHairVertices[0] = glm::vec3(-0.5f,0,0);
	crossHairVertices[1] = glm::vec3(0.5f,0,0);
	crossHairVertices[2] = glm::vec3(0, -0.5f,0);
	crossHairVertices[3] = glm::vec3(0, 0.5f,0);
	crossHairVertices[4] = glm::vec3(0,0, -0.5f);
	crossHairVertices[5] = glm::vec3(0,0, 0.5f);

	//setup light gizmo vertex array and vertex buffer object IDs
	glGenVertexArrays(1, &lightVAOID);
	glGenBuffers(1, &lightVerticesVBO);   
	glBindVertexArray(lightVAOID);	

		glBindBuffer (GL_ARRAY_BUFFER, lightVerticesVBO);
		//pass crosshair vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, sizeof(crossHairVertices), &(crossHairVertices[0].x), GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for vertex position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,0);
	
	GL_CHECK_ERRORS 
	
	//use spherical coordinates to get the light position
	lightPosOS.x = radius * cos(theta)*sin(phi);
	lightPosOS.y = radius * cos(phi);
	lightPosOS.z = radius * sin(theta)*sin(phi);

	//enable depth test and culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE); 

	//set the background colour to corn blue 
	glClearColor(0.5,0.5,1,1);
	cout<<"Initialization successfull"<<endl;
}
//OpenGL initialization
void OnInit() { 

	//load the cubemap shader
	cubemapShader.LoadFromFile(GL_VERTEX_SHADER, "shaders/cubemap.vert");
	cubemapShader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/cubemap.frag");
	//compile and link shader
	cubemapShader.CreateAndLinkProgram();
	cubemapShader.Use();
		//add shader attribute and uniforms
		cubemapShader.AddAttribute("vVertex");
		cubemapShader.AddAttribute("vNormal");
		cubemapShader.AddUniform("MVP");
		cubemapShader.AddUniform("eyePosition");
		cubemapShader.AddUniform("cubeMap");
		//set values of constant uniforms at initialization
		glUniform1i(cubemapShader("cubeMap"), 1);
	cubemapShader.UnUse();

	GL_CHECK_ERRORS

	//setup sphere geometry
	createSphere(1,10,10);

	GL_CHECK_ERRORS

	//setup sphere vao and vbo stuff
	glGenVertexArrays(1, &sphereVAOID);
	glGenBuffers(1, &sphereVerticesVBO);
	glGenBuffers(1, &sphereIndicesVBO);
	glBindVertexArray(sphereVAOID);

		glBindBuffer (GL_ARRAY_BUFFER, sphereVerticesVBO);
		//pass vertices to the buffer object
		glBufferData (GL_ARRAY_BUFFER, vertices.size()*sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);
		GL_CHECK_ERRORS
		//enable vertex attribute array for position
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
		GL_CHECK_ERRORS
		//enable vertex attribute array for normal
		glEnableVertexAttribArray(1);
		glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE,sizeof(Vertex), (const GLvoid*)(offsetof(Vertex, normal)));
		GL_CHECK_ERRORS
		//pass sphere indices to element array buffer 
		glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, sphereIndicesVBO);
		glBufferData (GL_ELEMENT_ARRAY_BUFFER, indices.size()*sizeof(GLushort), &indices[0], GL_STATIC_DRAW);
		 
	//generate the dynamic cubemap texture and bind to texture unit 1
	glGenTextures(1, &dynamicCubeMapID);
	glActiveTexture(GL_TEXTURE1);	
	glBindTexture(GL_TEXTURE_CUBE_MAP, dynamicCubeMapID);
	//set texture parameters
	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	//for all 6 cubemap faces
	for (int face = 0; face < 6; face++) {
		//allocate a different texture for each face and assign to the cubemap texture target
		glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, 0, GL_RGBA, CUBEMAP_SIZE, CUBEMAP_SIZE, 0, GL_RGBA, GL_FLOAT, NULL);
	}

	GL_CHECK_ERRORS

	//setup FBO
	glGenFramebuffers(1, &fboID);
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboID);

	//setup render buffer object (RBO)
	glGenRenderbuffers(1, &rboID);
	glBindRenderbuffer(GL_RENDERBUFFER, rboID);

	//set the renderbuffer storage to have the same dimensions as the cubemap texture
	//also set the renderbuffer as the depth attachment of the FBO
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, CUBEMAP_SIZE, CUBEMAP_SIZE);
	glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fboID);

	//set the dynamic cubemap texture as the colour attachment of FBO
	glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, dynamicCubeMapID, 0);

	//check the framebuffer completeness status
	GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
	if(status != GL_FRAMEBUFFER_COMPLETE) {
		cerr<<"Frame buffer object setup error."<<endl;
		exit(EXIT_FAILURE);
	} else {
		cerr<<"FBO setup successfully."<<endl;
	}
	//unbind FBO
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
	//unbind renderbuffer
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	GL_CHECK_ERRORS

	//create a grid object
	grid = new CGrid();

	//create a unit cube object
	cube = new CUnitCube(glm::vec3(1,0,0));

	GL_CHECK_ERRORS

	//enable depth testing and back face culling
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_CULL_FACE);

	cout<<"Initialization successfull"<<endl;
}
//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);
}