//scene rendering function
void DrawScene(const glm::mat4& View, const glm::mat4& Proj ) {

	GL_CHECK_ERRORS

	//bind the current shader
	shader.Use();

	//bind the cube vertex array object
	glBindVertexArray(cubeVAOID); {
		//set the cube's transform
		glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(-1,1,0));
		glm::mat4 M = T;			 //Model matrix
		glm::mat4 MV = View*M;		 //ModelView matrix
		glm::mat4 MVP = Proj*MV;	 //combined ModelView  Projection matrix

		//pass shader uniforms
		glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
		glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
		glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
		glUniform3f(shader("diffuse_color"), 1.0f,0.0f,0.0f);
		glUniform3fv(shader("light_position"),1, &(lightPosOS.x));
			//draw triangles
	 		glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
	}
	//bind the sphere vertex array object
	glBindVertexArray(sphereVAOID); {
		//set the sphere's transform
		glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(1,1,0));
		glm::mat4 M = T;
		glm::mat4 MV = View*M;
		glm::mat4 MVP = Proj*MV;
		//pass shader uniforms
		glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
		glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
		glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
		glUniform3f(shader("diffuse_color"), 0.0f, 0.0f, 1.0f);
			//draw triangles
		 	glDrawElements(GL_TRIANGLES, totalSphereTriangles, GL_UNSIGNED_SHORT, 0);
	}
	//unbind shader
	shader.UnUse();

	GL_CHECK_ERRORS

	//bind light gizmo vertex array object
	glBindVertexArray(lightVAOID); {
		//set light's transform
		glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS);
		//bind shader and draw 3 lines
		pFlatShader->Use();
			glUniformMatrix4fv((*pFlatShader)("MVP"), 1, GL_FALSE, glm::value_ptr(Proj*View*T));
				glDrawArrays(GL_LINES, 0, 6);
		//unbind shader
		pFlatShader->UnUse();
	}

	//unbind the vertex array object
	glBindVertexArray(0);

	//render grid object
	grid->Render(glm::value_ptr(Proj*View));
}
Beispiel #2
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() {

	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-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;
}
Beispiel #5
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);
}
//update and rendering of cloth particles
void RenderGPU_TF() {
	CHECK_GL_ERRORS

	//set the cloth vertex shader
	massSpringShader.Use();
	CHECK_GL_ERRORS
		//pass shader uniforms
		glUniformMatrix4fv(massSpringShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP));
	 
		CHECK_GL_ERRORS
		//run the iteration loop
		for(int i=0;i<NUM_ITER;i++) {
			//set the buffer texture for current position 
			glActiveTexture( GL_TEXTURE0);
			glBindTexture( GL_TEXTURE_BUFFER, texPosID[writeID]);

			//set the buffer texture for previous position
			glActiveTexture( GL_TEXTURE1);
			glBindTexture( GL_TEXTURE_BUFFER, texPrePosID[writeID]);

			//set the update vertex array object
			glBindVertexArray( vaoUpdateID[writeID]);
				//bind transform feedback buffers
				//index 0 -> current position
				//index 1 -> previous position
				glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vboID_Pos[readID]);
				glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, vboID_PrePos[readID]);
				// disable rasterization
				glEnable(GL_RASTERIZER_DISCARD);  
					//run hardware timer query
					glBeginQuery(GL_TIME_ELAPSED,t_query);
						//initiate transform feedback
						glBeginTransformFeedback(GL_POINTS);
							//render points, this call pushes all attributes to GPU
							glDrawArrays(GL_POINTS, 0, total_points);
						//end transform feedback
						glEndTransformFeedback();
					//end timer query
					glEndQuery(GL_TIME_ELAPSED);
					glFlush();
				//enable rasterizer
				glDisable(GL_RASTERIZER_DISCARD);

			//swap read/write pathways
			int tmp = readID;
			readID=writeID;
			writeID = tmp;
		}
		CHECK_GL_ERRORS
		// get the query result
		glGetQueryObjectui64v(t_query, GL_QUERY_RESULT, &elapsed_time);
		//get the transform feedback time
		delta_time = elapsed_time / 1000000.0f;
	//remove the cloth vertex shader
	massSpringShader.UnUse();

	CHECK_GL_ERRORS;

	//bind the render vertex array object
	glBindVertexArray(vaoRenderID[writeID]);
		//disable depth test
		glDisable(GL_DEPTH_TEST);
			//set the render shader
			renderShader.Use();
				//set the shader uniform
				glUniformMatrix4fv(renderShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP));
					//draw the cloth geometry
					glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT,0);
			//remove render shader
			renderShader.UnUse();
		//enable depth test
		glEnable(GL_DEPTH_TEST);

		//if we want to display masses
		if(bDisplayMasses) {
			//set the particle shader
			particleShader.Use();
				//set shader uniforms
				glUniform1i(particleShader("selected_index"), selected_index);
				glUniformMatrix4fv(particleShader("MV"), 1, GL_FALSE, glm::value_ptr(mMV));
				glUniformMatrix4fv(particleShader("MVP"), 1, GL_FALSE, glm::value_ptr(mMVP));
					//draw the masses last
			  		glDrawArrays(GL_POINTS, 0, total_points);
					//this also renders particles
					//glDrawTransformFeedbackStream(GL_POINTS, tfID, 0);
			//remove the particle shader
			particleShader.UnUse();
		}
	//remove the currently bound vertex array object
	glBindVertexArray( 0);

	CHECK_GL_ERRORS
}
//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;
}
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
void OnInit() {
	//get the OBJ mesh path
	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

	//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

	//load the 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 spherical harmonics shader
	sh_shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/sh_shader.vert");
	sh_shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/sh_shader.frag");
	//compile and link shader
	sh_shader.CreateAndLinkProgram();
	sh_shader.Use();
		//add attribute and uniform
		sh_shader.AddAttribute("vVertex");
		sh_shader.AddAttribute("vNormal");
		sh_shader.AddAttribute("vUV");
		sh_shader.AddUniform("MV");
		sh_shader.AddUniform("N");
		sh_shader.AddUniform("P");
		sh_shader.AddUniform("textureMap");
		sh_shader.AddUniform("light_position");
		sh_shader.AddUniform("useDefault");
		sh_shader.AddUniform("diffuse_color");
		//set values of constant uniforms as initialization
		glUniform1i(sh_shader("textureMap"), 0);
	sh_shader.UnUse();
	
	GL_CHECK_ERRORS

	//load mesh rendering shader
	shader.LoadFromFile(GL_VERTEX_SHADER, "shaders/shader.vert");
	shader.LoadFromFile(GL_FRAGMENT_SHADER, "shaders/sh_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("light_position");
		shader.AddUniform("useDefault");
		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);

	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(sh_shader["vVertex"]);
	glVertexAttribPointer(sh_shader["vVertex"], 3, GL_FLOAT, GL_FALSE,sizeof(Vertex),0);
	GL_CHECK_ERRORS
	//enable vertex attribute array for vertex normal
	glEnableVertexAttribArray(sh_shader["vNormal"]);
	glVertexAttribPointer(sh_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(sh_shader["vUV"]);
	glVertexAttribPointer(sh_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
			
	//set spherical harmonics as the current shader
	pCurrentShader = &sh_shader;

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

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

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

	//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 

	cout<<"Initialization successfull"<<endl;
}
//display callback function
void OnRender() {
	//clear the colour and depth buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//set the viewing transformation
	glm::mat4 T		= glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist));
	glm::mat4 Rx	= glm::rotate(T,  rX, glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 MV    = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f));

	//bind the mesh vertex array object
	glBindVertexArray(vaoID); {
		//bind the current shader
		pCurrentShader->Use();
			//pass the shader uniforms
			glUniformMatrix4fv((*pCurrentShader)("MV"), 1, GL_FALSE, glm::value_ptr(MV));
			glUniformMatrix3fv((*pCurrentShader)("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
			glUniformMatrix4fv((*pCurrentShader)("P"), 1, GL_FALSE, glm::value_ptr(P));
			glUniform3fv((*pCurrentShader)("light_position"),1, &(lightPosOS.x)); 

			//loop through all materials
			for(size_t i=0;i<materials.size();i++) {
				Material* pMat = materials[i];
				//if material texture filename is not empty
				if(pMat->map_Kd !="") {
					glUniform1f((*pCurrentShader)("useDefault"), 0.0);

					//get the currently bound texture and check if the current texture ID
					//is not equal, if so bind the new texture
					GLint whichID[1];
					glGetIntegerv(GL_TEXTURE_BINDING_2D, whichID);
					if(whichID[0] != textures[i])
						glBindTexture(GL_TEXTURE_2D, textures[i]);
				}
				else
					//otherwise we have no texture, we use a defaul colour
					glUniform1f((*pCurrentShader)("useDefault"), 1.0);

				//if we have a single material, we render the whole mesh in a single call
				if(materials.size()==1)
					glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, 0);
				else
					//otherwise we render the submesh
					glDrawElements(GL_TRIANGLES, pMat->count, GL_UNSIGNED_SHORT, (const GLvoid*)(&indices[pMat->offset]));
			}

		//unbind the current shader
		pCurrentShader->UnUse();
	}

	//draw the light gizmo
	glBindVertexArray(lightVAOID); {
		//set the modelling transform for the light crosshair gizmo
		glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS); 
		//bind the shader
		flatShader.Use();		
			//set shader uniforms and draw lines
			glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T)); 
				glDrawArrays(GL_LINES, 0, 6);

		//unbind the shader
		flatShader.UnUse();
	}

	//swap front and back buffers to show the rendered result
	glutSwapBuffers();
}
Beispiel #11
0
//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;
}
//display callback function
void OnRender() {
	GL_CHECK_ERRORS

	//camera transformation
	glm::mat4 Tr	= glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist));
	glm::mat4 Rx	= glm::rotate(Tr,  rX, glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 MV    = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f));

	//clear colour and depth buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//get the combined modelview projection matrix
    glm::mat4 MVP	= P*MV;

	//if we want to use depth peeling 
	if(bShowDepthPeeling) {
		//bind the colour blending FBO
		glBindFramebuffer(GL_FRAMEBUFFER, colorBlenderFBOID);
		//set the first colour attachment as the draw buffer
		glDrawBuffer(GL_COLOR_ATTACHMENT0);
		//clear the colour and depth buffer
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

		// 1. In the first pass, we render normally with depth test enabled to get the nearest surface
		glEnable(GL_DEPTH_TEST);
		DrawScene(MVP, cubeShader);

		// 2. Depth peeling + blending pass
		int numLayers = (NUM_PASSES - 1) * 2;

		//for each pass
		for (int layer = 1; bUseOQ || layer < numLayers; layer++) {
			int currId = layer % 2;
			int prevId = 1 - currId;

			//bind the current FBO
			glBindFramebuffer(GL_FRAMEBUFFER, fbo[currId]);
			//set the first colour attachment as draw buffer
			glDrawBuffer(GL_COLOR_ATTACHMENT0);

			//set clear colour to black
			glClearColor(0, 0, 0, 0);
			//clear the colour and depth buffers
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

			//disbale blending and depth testing
			glDisable(GL_BLEND);
			glEnable(GL_DEPTH_TEST);

			//if we want to use occlusion query, we initiate it
			if (bUseOQ) {
				glBeginQuery(GL_SAMPLES_PASSED_ARB, queryId);
			}

			GL_CHECK_ERRORS

			//bind the depth texture from the previous step
			glBindTexture(GL_TEXTURE_RECTANGLE, depthTexID[prevId]);

			//render scene with the front to back peeling shader
	 		DrawScene(MVP, frontPeelShader);

			//if we initiated the occlusion query, we end it 
			if (bUseOQ) {
				glEndQuery(GL_SAMPLES_PASSED_ARB);
			}

			GL_CHECK_ERRORS

			//bind the colour blender FBO
			glBindFramebuffer(GL_FRAMEBUFFER, colorBlenderFBOID);
			//render to its first colour attachment 
			glDrawBuffer(GL_COLOR_ATTACHMENT0);

			//enable blending but disable depth testing
			glDisable(GL_DEPTH_TEST);
			glEnable(GL_BLEND);

			//change the blending equation to add
			glBlendEquation(GL_FUNC_ADD);
			//use separate blending function
			glBlendFuncSeparate(GL_DST_ALPHA, GL_ONE,
								GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);

			//bind the result from the previous iteration as texture
			glBindTexture(GL_TEXTURE_RECTANGLE, texID[currId]);
			//bind the blend shader and then draw a fullscreen quad
			blendShader.Use();
				 DrawFullScreenQuad();
			blendShader.UnUse();

			//disable blending
			glDisable(GL_BLEND);

			GL_CHECK_ERRORS

			//if we initiated the occlusion query, we get the query result
			//that is the total number of samples
			if (bUseOQ) {
				GLuint sample_count;
				glGetQueryObjectuiv(queryId, GL_QUERY_RESULT, &sample_count);
				if (sample_count == 0) {
					break;
				}
			}
		}

		GL_CHECK_ERRORS

		// 3. Final render pass
		//remove the FBO 
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		//restore the default back buffer
		glDrawBuffer(GL_BACK_LEFT);
		//disable depth testing and blending
		glDisable(GL_DEPTH_TEST);
		glDisable(GL_BLEND);

		//bind the colour blender texture
		glBindTexture(GL_TEXTURE_RECTANGLE, colorBlenderTexID);
		//bind the final shader
		finalShader.Use();
			//set shader uniforms
			glUniform4fv(finalShader("vBackgroundColor"), 1, &bg.x);
			//draw full screen quad
			DrawFullScreenQuad();
		finalShader.UnUse();

	} else {
//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;
}
Beispiel #14
0
//display function
void OnRender() {
	//clear the color and depth buffers
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//setup the camera transform
	glm::mat4 T		= glm::translate(glm::mat4(1.0f),glm::vec3(-center.x, -center.y, -center.z+dist));
	glm::mat4 Rx	= glm::rotate(T,  rX, glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 MV    = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f));
	 
	//bind the mesh vertex array object
	glBindVertexArray(vaoID); {
		//bind the mesh's shader
		shader.Use();
			//pass the shader uniforms
			glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
			glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
			glUniformMatrix4fv(shader("P"), 1, GL_FALSE, glm::value_ptr(P));
			glUniform3fv(shader("light_position"),1, &(lightPosOS.x));

			//for all submeshes
			for(size_t i=0;i<submeshes.size();i++) {
				//if the material name is not empty
				if(strlen(submeshes[i].materialName)>0) {
					//get the OpenGL texture id from the material map using the material name
					GLuint id = materialMap[material2ImageMap[submeshes[i].materialName]];
					GLint whichID[1];
					glGetIntegerv(GL_TEXTURE_BINDING_2D, whichID);
					//if the currently bound texture id is not the same is the current texture id
					//if so bind the current texture
					if(whichID[0] != id)
						glBindTexture(GL_TEXTURE_2D, id);
					//let the shader know that we have a texture so no default colour needs to be used
					glUniform1f(shader("useDefault"), 0.0);
				} else {
					//there is no texture in submesh, use a default colour
					glUniform1f(shader("useDefault"), 1.0);
				}
				//draw the triangles using the submesh indices
 				glDrawElements(GL_TRIANGLES, submeshes[i].indices.size(), GL_UNSIGNED_INT, &submeshes[i].indices[0]);
			} //end for
		//unbind shader
		shader.UnUse();
	}

	//bind the light vertex array object to show the light crosshair gizmo
	glBindVertexArray(lightVAOID); {
		//get the modeling transform of the light gizmo
		glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS);

		//set the shader of the light crosshair gizmo
		flatShader.Use();
			//pass uniforms to the shader and render the crosshair gizmo as lines
			glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T));
				glDrawArrays(GL_LINES, 0, 6);

		//unbind the shader
		flatShader.UnUse();
	}
	//swap the back buffer and front buffer to display the result on screen
	glutSwapBuffers();
}
Beispiel #15
0
/* ---- Sonnensystem wird gezeichnet ----- */
void RenderScene(void)
{
	GLUquadricObj* pObj;
	/* ---- Drehwinkel ---- */
	static float fMoonRot = 0.0f;
	static float fEarthRot = 0.0f;
	static float fMercuryRot = 0.0f;
	static float fVenusRot = 0.0f;
	static float fMarsRot = 0.0f;
	static float fJupiterRot = 0.0f;
	static float fSaturnRot = 0.0f;
	static float fUranusRot = 0.0f;
	static float fNeptuneRot = 0.0f;
	static float fPlutoRot = 0.0f;
	static float fSaturnRingRot = 0.0f;

	// Löscht das Window mit der momentanten "Clearing-Color"
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	// Matrix-Zustand speichern
	glMatrixMode(GL_MODELVIEW);
	glPushMatrix();

	// Bewegungssteuerung des Spaceship aus Sicht des Spaceship
	gluLookAt(x, 1.0f, z,		// Gibt die Position des Betrachters an
		x + lx, 1.0f, z + lz,	// Gibt die Position des Refernenzpunktes an, auf den "geblickt" wird
		0.0f, 1.0f, 0.0f);		// Gibt die Richtung des Vektors an, der nach oben zeigt 

	// Verschiebt die Szene auf Basis der Sonnenposition
	glTranslatef(fSunX, fSunY, fSunZ);

#pragma region sun
	/* ----- Sonne ----- */
	glDisable(GL_LIGHTING); // Licht ausschalten

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren 
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Sonnen-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, sunTexture);

	// Rotation der Sonne
	glRotatef(fSunRotX, 1.0f, 0.0f, 0.0f); // Sonne rotiert um x-Achse
	glRotatef(fSunRotY, 0.0f, 1.0f, 0.0f); // Sonne rotiert um y-Achse
	glRotatef(fSunRotZ, 0.0f, 0.0f, 1.0f); // Sonne rotiert um z-Achse
	gluSphere(pObj, 172.8f, 30, 17); // Sonnen-Kugel zeichnen (Object, Radius, Slices, Stack) 
	
	glDisable(GL_TEXTURE_2D);

	// quadObject freigeben
	gluDeleteQuadric(pObj);

	glEnable(GL_LIGHTING); // Licht einschalten

	// Lighting-Position auf die Sonnen-Position setzen
	glLightfv(GL_LIGHT0, GL_POSITION, lightPos);
#pragma endregion

#pragma region skybox
	/* ----- Weltraum-Himmel ----- */
	// Speichert die aktuelle Matrix
	glPushMatrix();

	// Matrix wird nun transformiert

	glPushAttrib(GL_ENABLE_BIT);
	glEnable(GL_TEXTURE_2D);
	glColor4f(1, 1, 1, 1);
	GLfloat val = 5000.0f; // Größe der skybox

	// Texturen für das fordere Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(val, -val, val);
	glTexCoord2f(2, 0); glVertex3f(-val,-val, val);
	glTexCoord2f(2, 2); glVertex3f(-val, val, val);
	glTexCoord2f(0, 2); glVertex3f(val, val, val);
	glEnd();

	// Texturen für das linke Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(val, -val, -val);
	glTexCoord2f(2, 0); glVertex3f(val, -val, val);
	glTexCoord2f(2, 2); glVertex3f(val, val, val);
	glTexCoord2f(0, 2); glVertex3f(val, val, -val);
	glEnd();

	// Texturen für das hintere Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(-val, -val, -val);
	glTexCoord2f(2, 0); glVertex3f(val, -val, -val);
	glTexCoord2f(2, 2); glVertex3f(val, val, -val);
	glTexCoord2f(0, 2); glVertex3f(-val, val, -val);
	glEnd();

	// Texturen für das rechte Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(-val, val, -val);
	glTexCoord2f(2, 0); glVertex3f(-val, val, val);
	glTexCoord2f(2, 2); glVertex3f(-val, -val, val);
	glTexCoord2f(0, 2); glVertex3f(-val, -val, -val);
	glEnd();

	// Texturen für das obere Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(val, val, -val);
	glTexCoord2f(2, 0); glVertex3f(val, val, val);
	glTexCoord2f(2, 2); glVertex3f(-val, val, val);
	glTexCoord2f(0, 2); glVertex3f(-val, val, -val);
	glEnd();

	// Texturen für das untere Quadrat
	glBindTexture(GL_TEXTURE_2D, starsTexture);
	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex3f(-val, -val, -val);
	glTexCoord2f(2, 0); glVertex3f(-val, -val, val);
	glTexCoord2f(2, 2); glVertex3f(val, -val, val);
	glTexCoord2f(0, 2); glVertex3f(val, -val, -val);
	glEnd();

	glPopAttrib();
	glPopMatrix();
#pragma endregion

#pragma region mercury 
	/* ----- Merkur ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren 
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Merkur-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, mercuryTexture);

	// Rotationskoordinaten für Merkur
	glRotatef(fMercuryRot, 1.0f, 2.0f, 0.0f);

	// Merkur zeichnen
	glTranslatef(200.0f, -15.0f, 0.0f); // Merkur von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fMercuryRot * 3, 0.0f, 0.0f, 1.0f); // Merkur-Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 6.4f, 30, 17); // Merkur - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Merkur (Rotationsgeschwindigkeit um die Sonne)
	fMercuryRot += 20.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fMercuryRot >= 360.0f)
		fMercuryRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region venus
	/* ----- Venus ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren 
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Venus-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, venusTexture);

	// Rotationskoordinaten für Venus
	glRotatef(fVenusRot, 0.0f, 1.0f, 0.0f);

	// Venus zeichnen
	glTranslatef(350.0f, 0.0f, 0.0f); // Venus von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fVenusRot * 3, 0.0f, 0.0f, 1.0f); // Venus-Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 16.0f, 30, 17); // Venus - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Venus (Rotationsgeschwindigkeit um die Sonne)
	fVenusRot += 10.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fVenusRot >= 360.0f)
		fVenusRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region mars
	/* ----- Mars ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren 
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Mars-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, marsTexture);

	// Rotationskoordinaten für Mars
	glRotatef(fMarsRot, 0.0f, 1.0f, 0.3f);

	// Mars zeichnen
	glTranslatef(700.0f, 0.0f, 0.0f); // Mars von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fMarsRot * 3, 0.0f, 0.0f, 1.0f); // Mars - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 8.0f, 30, 17); // Mars - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Mars (Rotationsgeschwindigkeit um die Sonne)
	fMarsRot += 4.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fMarsRot >= 360.0f)
		fMarsRot = 0.0f;

	glPopMatrix();

#pragma endregion

#pragma region jupiter
	/* ----- Jupiter ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Jupiter-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, jupiterTexture); //sets it to jupiter's texture

	// Rotationskoordinaten für Jupiter
	glRotatef(fJupiterRot, 0.0f, 1.0f, -0.3f);

	// Jupiter zeichnen
	glTranslatef(1300.0f, 0.0f, 0.0f); // Jupiter von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fJupiterRot * 3, 0.0f, 0.0f, 1.0f); // Jupiter - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 88.0f, 30, 17); // Jupiter - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Jupiter (Rotationsgeschwindigkeit um die Sonne)
	fJupiterRot += 2.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fJupiterRot >= 360.0f)
		fJupiterRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region saturn
	/* ----- Saturn ----- */
	glPushMatrix(); //saves the view matrix

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Saturn-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, saturnTexture); //sets it to saturn's texture

	// Rotationskoordinaten für Saturn
	glRotatef(fSaturnRot, 0.0f, 0.8f, -0.2f);

	// Saturn zeichnen
	glTranslatef(2375.0f, 0.0f, 0.0f); // Saturn von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fSaturnRot * 3, 0.0f, 0.0f, 1.0f); // Saturn - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 72.0f, 30, 17); // Saturn - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Saturn (Rotationsgeschwindigkeit um die Sonne)
	fSaturnRot += 1.5f;
	// Rotation zurücksetzen bei 360 Grad
	if (fSaturnRot >= 360.0f)
		fSaturnRot = 0.0f;
#pragma endregion

#pragma region saturnrings
	/* ----- Saturnringe ----- */

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricNormals(pObj, GLU_SMOOTH);
	gluQuadricTexture(pObj, GL_TRUE);

	// Saturnring-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, saturnRingsTexture);
	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);

	// Rotationskoordinaten für Saturnringe
	glRotatef(fSaturnRingRot, 0.0f, 0.0f, 1.0f);
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f);
	glRotatef(-90.0, 1.0, 0.0, 0.0);
	glScalef(1, 1, 0.02f);
	glRotatef(fSaturnRingRot * 3, 0.0f, 0.0f, 1.0f);
	gluSphere(pObj, 72.0f * 2, 48, 48); // Saturnringe zeichnen

	// neue Rotationsposition vom Saturnring
	fSaturnRingRot += 1.0;
	// Rotation zurücksetzen bei 360 Grad
	if (fSaturnRingRot >= 360.0f)
		fSaturnRingRot = 0.0f;

	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);
	glPopMatrix();

#pragma endregion

#pragma region uranus
	/* ----- Uranus ------ */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Uranus-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, uranusTexture); //sets texture to uranus' texture

	// Rotationskoordinaten für Uranus
	glRotatef(fUranusRot, 0.0f, 0.8f, 0.2f);

	// Uranus zeichnen
	glTranslatef(3167.0f, 0.0f, 0.0f); // Uranus von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fUranusRot * 3, 0.0f, 0.0f, 1.0f); // Uranus - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 32.0f, 30, 17); // Uranus - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Uranus (Rotationsgeschwindigkeit um die Sonne)
	fUranusRot += 1.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fUranusRot >= 360.0f)
		fUranusRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region neptune
	/* ----- Neptun ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Neptun-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, neptuneTexture); //sets it to neptune's texture

	// Rotationskoordinaten für Neptun
	glRotatef(fNeptuneRot, 0.0f, 0.8f, 0.2f);

	// Neptun zeichnen
	glTranslatef(4166.0f, 0.0f, 0.0f); // Neptun von der Sonne wegverschieben
	glRotatef(300.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fNeptuneRot * 3, 0.0f, 0.0f, 1.0f); // Neptun - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 32.0f, 30, 17); // Neptun - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Neptun (Rotationsgeschwindigkeit um die Sonne)
	fNeptuneRot += 0.6f;
	// Rotation zurücksetzen bei 360 Grad
	if (fNeptuneRot >= 360.0f)
		fNeptuneRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region pluto
	/* ----- Pluto ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Pluto-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, plutoTexture); //sets it to plutos texture

	// Rotationskoordinaten für Pluto
	glRotatef(fPlutoRot, 0.0f, 0.8f, 0.2f);

	// Pluto zeichnen
	glTranslatef(5000.0f, 0.0f, 0.0f); // Pluto von der Sonne wegverschieben
	glRotatef(300.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fPlutoRot * 3, 0.0f, 0.0f, 1.0f); // Pluto - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 3.2f, 30, 17); // Pluto - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);

	// neue Rotationsposition von Pluto (Rotationsgeschwindigkeit um die Sonne)
	fPlutoRot += 0.2f;
	// Rotation zurücksetzen bei 360 Grad
	if (fPlutoRot >= 360.0f)
		fPlutoRot = 0.0f;

	glPopMatrix();
#pragma endregion

#pragma region earth
	/* ----- Erde ----- */
	glPushMatrix();

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Erden-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, earthTexture);

	// Rotationskoordinaten für Erde (Rotation um die Sonne)
	glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);

	// Erde zeichnen
	glTranslatef(500.0f, 0.0f, 0.0f); // Erde von der Sonne wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fEarthRot * 3, 0.0f, 0.0f, 1.0f); // Erde - Rotation um sich selber - simuliert Eigenrotation
	gluSphere(pObj, 16.0f, 30, 17); // Erde - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);
#pragma endregion

#pragma region earthMoon
	/* ----- Mond ----- */

	// quadObject erstellen und Texturkoordinaten dafür spezifizieren
	pObj = gluNewQuadric();
	gluQuadricTexture(pObj, GL_TRUE);

	// Mond-Textur setzen
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, moonTexture);

	glRotatef(fMoonRot, 0.0f, 1.0f, 0.0f); // Mond-Rotation um die Erde
	glTranslatef(25.0f, 0.0f, 0.0f); // Mond von der Erde wegverschieben
	glRotatef(270.0f, 1.0f, 0.0f, 0.0f); // dreht die Textur
	glRotatef(fMoonRot * 3, 0.0f, 0.0f, 1.0f); // Mond - Rotation um sich selber - simuliert Eigenrotation

	// neue Rotationsposition vom Mond
	fMoonRot = 2.4f;
	// Rotation zurücksetzen bei 360 Grad
	if (fMoonRot >= 360.0f)
		fMoonRot = 0.0f;

	// Mond zeichnen
	gluSphere(pObj, 4.3f, 30, 17); // Mond - Kugel zeichnen(Object, Radius, Slices, Stack)
	glDisable(GL_TEXTURE_2D);

	gluDeleteQuadric(pObj);
	glPopMatrix();

	// neue Rotationsposition von der Erde
	fEarthRot += 5.0f;
	// Rotation zurücksetzen bei 360 Grad
	if (fEarthRot >= 360.0f)
		fEarthRot = 0.0f;
	
	glPopMatrix();
#pragma endregion

#pragma region DreiD-Model
	GL_CHECK_ERRORS

	// Matrizen
	glm::mat4 T = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -100.0f, -300)); // Position des Raumschiffes in der Skybox
	glm::mat4 Rx = glm::rotate(T, rotation_x, glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 Ry = glm::rotate(Rx, rotation_y, glm::vec3(0.0f, 1.0f, 0.0f));
	glm::mat4 MV = glm::rotate(Ry, rotation_z, glm::vec3(0.0f, 0.0f, 1.0f));
	glm::mat4 MVP = P*MV;

	glBindVertexArray(vaoID);
	shader.Use();
	glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
	glDrawElements(GL_TRIANGLES, object.polygons_qty * 3, GL_UNSIGNED_SHORT, 0);
	shader.UnUse();
	glBindVertexArray(0);
#pragma endregion

	// Sonnensystem anzeigen
	glutSwapBuffers();

}
Beispiel #16
0
//idle callback which is called when there is no other processing to do
void OnIdle() {
	//get the current timer value
	QueryPerformanceCounter(&current);
    dt = (double)(current.QuadPart - last.QuadPart) / (double)freq.QuadPart;
	last = current;

	static double t  = 0;
	//increment time
	t+=dt; 

	//get the current mesh animation and store the frame rate
	//if the current time is greater than the framerate, we move
	//to the next frame
	NVSHARE::MeshAnimation* pAnim = &animations[0];
	float fps = pAnim->GetFrameCount() / pAnim->GetDuration();
	if( t > 1.0f/fps) {
		currentFrame++;
		t=0;
	}

	//if looped playback is on, we do a modulus operation of the current frame with
	//the total number of frames
	if(bLoop) {
		currentFrame = currentFrame%pAnim->mFrameCount;
	} else {
		//otherwise, we just restrict the current frame to be in range
		currentFrame = std::fmax(-1, std::fmin(currentFrame, pAnim->mFrameCount-1));
	}

	//if the current frame is -1, means we are in bind pose
	//just use the bind  pose matrix and the bones absolute 
	//transforms to get the aniamted transform
	if(currentFrame == -1) {
		for(size_t i=0;i<skeleton.size();i++) {
			skeleton[i].comb = bindPose[i];
			animatedXform[i] = skeleton[i].comb*invBindPose[i];
		}
	} else {
		//otherwise, we loop through all tracks in the current animation
		//and determine the pose.
		for(int j=0;j<pAnim->mTrackCount;j++) {
			NVSHARE::MeshAnimTrack* pTrack = pAnim->mTracks[j];
			NVSHARE::MeshAnimPose* pPose = pTrack->GetPose(currentFrame);
			
			//using the pose, we estimate the local transform of the current bone
			//in the given animation track
			//first get positions
			skeleton[j].position.x = pPose->mPos[0];
			skeleton[j].position.y = pPose->mPos[1];
			skeleton[j].position.z = pPose->mPos[2];

			//then orientation
			glm::quat q;
			q.x = pPose->mQuat[0];
			q.y = pPose->mQuat[1];
			q.z = pPose->mQuat[2];
			q.w = pPose->mQuat[3];

			//then scale
			skeleton[j].scale  = glm::vec3(pPose->mScale[0], pPose->mScale[1], pPose->mScale[2]);

			//handle the Zup case
			if(!bYup) {
				skeleton[j].position.y = pPose->mPos[2];
				skeleton[j].position.z = -pPose->mPos[1];
				q.y = pPose->mQuat[2];
				q.z = -pPose->mQuat[1];

				skeleton[j].scale.y = pPose->mScale[2];
				skeleton[j].scale.z = -pPose->mScale[1];
			}

			skeleton[j].orientation = q;
			
			//use the stored scale, orientation and translation to obtain the 
			//local transform of bone
			glm::mat4 S = glm::scale(glm::mat4(1),skeleton[j].scale);
			glm::mat4 R = glm::toMat4(q);
			glm::mat4 T = glm::translate(glm::mat4(1), skeleton[j].position);
			skeleton[j].xform = T*R*S;

			//get the absolute transform of the bone
			Bone& b = skeleton[j];
			if(b.parent==-1)
				b.comb = b.xform;
			else
				b.comb = skeleton[b.parent].comb * b.xform;

			//multiply the absolute transform of the current bone with
			//the inverse bind pose of the bone to get the new animated 
			//transform
			animatedXform[j] = b.comb * invBindPose[j];

			//in case of dual quaternion, extract the position and orientation and then use
			//QuatTrans2UDQ function to obtain a dual quaternion for the given animatedXform
			glm::vec3 t = glm::vec3( animatedXform[j][3][0], animatedXform[j][3][1], animatedXform[j][3][2]);
			dualQuaternions[j].QuatTrans2UDQ(glm::toQuat(animatedXform[j]),  t); 

		}//for all animation tracks
	} //else

	//pass the new dual quaternions to the shader by updating the uniform
	shader.Use();
		//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();

	//call the display callback
	glutPostRedisplay();
}
//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;
}
Beispiel #18
0
//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;
}
//scene rendering function
void DrawScene(const glm::mat4& View, const glm::mat4& Proj ) {

	GL_CHECK_ERRORS

	//bind the current shader
	shader.Use();

	//bind the cube vertex array object
	glBindVertexArray(cubeVAOID);

	//draw the 8 cubes first
	for(int i=0;i<8;i++)
	{
		//set the cube's transform
		float theta = (float)(i/8.0f*2*M_PI);
		glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(radius*cos(theta),0.5,radius*sin(theta)));
		glm::mat4 M = T;			//Model matrix
		glm::mat4 MV = View*M;		//ModelView matrix
		glm::mat4 MVP = Proj*MV;	//combined ModelView  Projection matrix

		//pass shader uniforms
		glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
		glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
		glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
		glUniform3fv(shader("diffuse_color"),1, &(colors[i].x));
		glUniform3f(shader("specular_color"), 1.0f, 1.0f, 1.0f);
		glUniform1f(shader("shininess"), 100);
		glUniform3fv(shader("light_position"),1, &(lightPosOS.x));
			//draw triangles
		 	glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, 0);
		GL_CHECK_ERRORS
	}

	//bind the sphere vertex array object
	glBindVertexArray(sphereVAOID);
		//set the sphere's transform
		glm::mat4 T = glm::translate(glm::mat4(1), glm::vec3(0,1,0));
		glm::mat4 M = T;
		glm::mat4 MV = View*M;
		glm::mat4 MVP = Proj*MV;
		//pass shader uniforms
		glUniformMatrix4fv(shader("MVP"), 1, GL_FALSE, glm::value_ptr(MVP));
		glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
		glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
		glUniform3f(shader("diffuse_color"), 0.9f, 0.9f, 1.0f);
		glUniform3f(shader("specular_color"), 1.0f, 1.0f, 1.0f);
		glUniform1f(shader("shininess"), 300);
		glUniform3fv(shader("light_position"),1, &(lightPosOS.x));
			//draw triangles
		 	glDrawElements(GL_TRIANGLES, totalSphereTriangles, GL_UNSIGNED_SHORT, 0);

	//unbind shader
	shader.UnUse();

	//unbind vertex array object
	glBindVertexArray(0);

	GL_CHECK_ERRORS

	//render the grid object
	grid->Render(glm::value_ptr(Proj*View));
}
Beispiel #20
0
//display callback function
void OnRender() {

	//FPS calculation
	++total_frames;
	float current = (float)glutGet(GLUT_ELAPSED_TIME);
	if((current-lastTime)>1000) {
		fps = 1000.0f*total_frames/(current-lastTime);
		std::cout<<"FPS: "<<fps<<std::endl;
		lastTime= current;
		total_frames = 0;
	}
	//clear colour and depth buffer
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	//set the camera transformation
	glm::mat4 T		= glm::translate(glm::mat4(1.0f),glm::vec3(0.0f, 0.0f, dist));
	glm::mat4 Rx	= glm::rotate(T,  rX, glm::vec3(1.0f, 0.0f, 0.0f));
	glm::mat4 MV    = glm::rotate(Rx, rY, glm::vec3(0.0f, 1.0f, 0.0f));

	//get the eye position and inverse of MVP matrix
	glm::mat4 invMV  = glm::inverse(MV);
	glm::vec3 eyePos = glm::vec3(invMV[3][0],invMV[3][1],invMV[3][2]);
	glm::mat4 invMVP = glm::inverse(P*MV);
	
	//if raytracing is enabled
	if(bRaytrace) {
		//set the raytracing shader
		raytraceShader.Use();
			//pass shader uniforms
			glUniform3fv(raytraceShader("eyePos"), 1, glm::value_ptr(eyePos));
			glUniformMatrix4fv(raytraceShader("invMVP"), 1, GL_FALSE, glm::value_ptr(invMVP));
			glUniform3fv(raytraceShader("light_position"),1, &(lightPosOS.x));
				//draw a fullscreen quad
				DrawFullScreenQuad();
		//unbind raytracing shader
		raytraceShader.UnUse();
	} else {
		//do rasterization
		//bind the mesh vertex array object
		glBindVertexArray(vaoID); {
			//bind the mesh rendering shader
			shader.Use();
				//set the shader uniforms
				glUniformMatrix4fv(shader("MV"), 1, GL_FALSE, glm::value_ptr(MV));
				glUniformMatrix3fv(shader("N"), 1, GL_FALSE, glm::value_ptr(glm::inverseTranspose(glm::mat3(MV))));
				glUniformMatrix4fv(shader("P"), 1, GL_FALSE, glm::value_ptr(P));
				glUniform3fv(shader("light_position"),1, &(lightPosOS.x));

				//loop through all materials
				for(size_t i=0;i<materials.size();i++) {
					Material* pMat = materials[i];

					//if material texture filename is not empty
					//dont use the default colour
					if(pMat->map_Kd !="") {
						glUniform1f(shader("useDefault"), 0.0);
						glUniform1i(shader("textureIndex"), i);
					}
					else
						//otherwise we have no texture, we use a default colour
						glUniform1f(shader("useDefault"), 1.0);
			
					//if we have a single material, we render the whole mesh in a single call
					if(materials.size()==1)
						glDrawElements(GL_TRIANGLES,  indices.size() , GL_UNSIGNED_SHORT, 0);
					else
						//otherwise we render the submesh
						glDrawElements(GL_TRIANGLES, pMat->count, GL_UNSIGNED_SHORT, (const GLvoid*)(&indices[pMat->offset]));
					
				}

			//unbind the shader
			shader.UnUse();
		}
	}

	//disable depth testing
	glDisable(GL_DEPTH_TEST);

	//draw the light gizmo, set the light vertexx array object
	glBindVertexArray(lightVAOID); {
		//set the modelling transform for the light crosshair gizmo
		glm::mat4 T = glm::translate(glm::mat4(1), lightPosOS);
		//bind the shader
		flatShader.Use();
			//set shader uniforms and draw lines
			glUniformMatrix4fv(flatShader("MVP"), 1, GL_FALSE, glm::value_ptr(P*MV*T));
				glDrawArrays(GL_LINES, 0, 6);
		//unbind the shader
		flatShader.UnUse();
	}
	//enable depth test
	glEnable(GL_DEPTH_TEST);

	//swap front and back buffers to show the rendered result
	glutSwapBuffers();
}
//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);
}