GUI Update

Making A User Interface

With the help of the IMGUI library I managed to make a quick GUI that would allow the the user to control the mesh & light transformations. Along with this, I have updated main.cpp to be able to update all the elements on screen by re-calculating the vertices and positions of the objects every loop.

How Did I Do It?

As I mentioned, I used IMGUI to be able to achieve this, I simply cut and pasted all the object calculations into the while loop and left all the variables outside the loop so it would be able to recalculate the positions of the objects in real-time. Small snipped of the main while loop:

    	//---------------------------------------------------------------------------------------------------------------------------------
    	lightModel = roml::translate(lightModel, lightPos);

    	//-----------------------Pyramid Control-----------------------------
    	glm::mat4 Loc = roml::translate(glm::mat4(1.0f), pyramidPos);
    	glm::mat4 Soc = roml::scale(glm::mat4(1.0f), scalepyr);

    	glm::mat4 rotX = roml::rotate(glm::mat4(1.0f), roml::radians(rotpyr.x), 'X');
    	glm::mat4 rotY = roml::rotate(glm::mat4(1.0f), roml::radians(rotpyr.y), 'Y');
    	glm::mat4 rotZ = roml::rotate(glm::mat4(1.0f), roml::radians(rotpyr.z), 'Z');
    	glm::mat4 Rot = rotZ * rotY * rotX;
    	pyramidModel = Loc * Rot * Soc;
    	//-----------------------Pyramid Control-----------------------------

    	//Exporting data
    	lightShader.Activate();
    	glUniformMatrix4fv(glGetUniformLocation(lightShader.ID, "model"), 1, GL_FALSE, glm::value_ptr(lightModel));
    	glUniform4f(glGetUniformLocation(lightShader.ID, "lightColor"), lightColor.x, lightColor.y, lightColor.z, lightColor.w);
    	shaderProgram.Activate();
    	glUniformMatrix4fv(glGetUniformLocation(shaderProgram.ID, "model"), 1, GL_FALSE, glm::value_ptr(pyramidModel));
    	glUniform4f(glGetUniformLocation(shaderProgram.ID, "lightColor"), lightColor.x, lightColor.y, lightColor.z, lightColor.w);
    	glUniform3f(glGetUniformLocation(shaderProgram.ID, "lightPos"), lightPos.x, lightPos.y, lightPos.z);
    	//---------------------------------------------------------------------------------------------------------------------------------
    	camera.Inputs(window); //Yay inputs!
    	//Updates and exports camera matrix to the vert shader
    	camera.updateMatrix(45.0f, 0.1f, 100.0f);

    	//IMGUI
    	ImGui_ImplGlfwGL3_NewFrame();

    	//---------------DRAW------------------
    	pyramid.Draw(shaderProgram, camera);
    	light.Draw(lightShader, camera);
    	//---------------DRAW------------------

    	{
    		ImGui::Begin("Debug Light");

    		bool resetPos = false;
    		ImGui::Text("Light Controls");
    		ImGui::Dummy(ImVec2(0.0f, 5.0f));
    		ImGui::SliderFloat("Translation X", &lightPos.x, -10.0f, 10.0f);
    		ImGui::SliderFloat("Translation Y", &lightPos.y, -10.0f, 10.0f);
    		ImGui::SliderFloat("Translation Z", &lightPos.z, -10.0f, 10.0f);
    		if (ImGui::Button("Reset Position"))
    			resetPos = true;

    		if (resetPos == true) {
    			lightPos = glm::vec3(0.5f, 0.5f, 0.5f);
    		}
    		ImGui::Dummy(ImVec2(0.0f, 5.0f));
    		ImGui::ColorEdit4("Color", (float*)&lightColor); // Edit 4 floats representing a color

    		ImGui::Dummy(ImVec2(0.0f, 5.0f));
    		ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    		ImGui::End();
    	}

    	{
    		ImGui::Begin("Debug Mesh");

    		bool resetScale = false;
    		bool resetPos = false;
    		bool resetRot = false;
    		ImGui::Text("Mesh Controls");
    		ImGui::Dummy(ImVec2(0.0f, 5.0f));
    		ImGui::SliderFloat("Scale X", &scalepyr.x, 0.0f, 10.0f);
    		ImGui::SliderFloat("Scale Y", &scalepyr.y, 0.0f, 10.0f);
    		ImGui::SliderFloat("Scale Z", &scalepyr.z, 0.0f, 10.0f);

    		if (ImGui::Button("Reset Scale"))
    			resetScale = true;

    		if (resetScale == true) {
    			scalepyr.x = 1.0f;
    			scalepyr.y = 1.0f;
    			scalepyr.z = 1.0f;
    		}

    		ImGui::Dummy(ImVec2(0.0f, 5.0f));

    		ImGui::SliderFloat("Translation X", &pyramidPos.x, -10.0f, 10.0f);
    		ImGui::SliderFloat("Translation Y", &pyramidPos.y, -10.0f, 10.0f);
    		ImGui::SliderFloat("Translation Z", &pyramidPos.z, -10.0f, 10.0f);
    		if (ImGui::Button("Reset Position"))
    			resetPos = true;

    		if (resetPos == true) {
    			pyramidPos = glm::vec3(0.0f, 0.0f, 0.0f);
    		}

    		ImGui::Dummy(ImVec2(0.0f, 5.0f));

    		ImGui::SliderFloat("Rotation X", &rotpyr.x, -90.0f, 90.0f);
    		ImGui::SliderFloat("Rotation Y", &rotpyr.y, -90.0f, 90.0f);
    		ImGui::SliderFloat("Rotation Z", &rotpyr.z, -90.0f, 90.0f);
    		if (ImGui::Button("Reset Rotation"))
    			resetRot = true;

    		if (resetRot == true) {
    			rotpyr = glm::vec3(1.0f, 1.0f, 1.0f);
    		}


    		ImGui::Dummy(ImVec2(0.0f, 5.0f));
    		ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);

    		ImGui::End();
    	}

    	ImGui::Render();
    	ImGui_ImplGlfwGL3_RenderDrawData(ImGui::GetDrawData());

}

To prevent the user from only being able to edit one transform, I had the apply all the transforms after calculating them all by multiplying them all together. As for the reset values I simply reset the value to the values of the original variable if the button is pressed. On the sliders the first first paramater is the name of the slider, the second is what value/variable we want to edit. The third and paramater states the range of the slider. e.g -90 Degrees to 90 Degrees

I have also added a new scale function that would be able scale a mat4 with the values of a vec3. It’s quite simple so i’ll also put a snippet here. roml::scale :

    glm::mat4 scale(glm::mat4 mat, glm::vec3 scalar) {
    	glm::mat4 result = glm::mat4(1.0f);

    	result[0][0] = scalar.x * mat[0][0];
    	result[1][1] = scalar.y * mat[1][1];
    	result[2][2] = scalar.z * mat[2][2];
    	return result;

    }

As you can see, I simply multiplied the X value of the vec3 to the X value of the mat4 and vice versa. Of course I could just multiply the mat4 by a scalar but this way made it easier for me to set up the GUI.

Hope you enjoyed reading!