I am trying to create an app, where the user can run a (time-consuming) backend physics simulation with the press of a button. But at the same time, I would like the rest of the GUI to remain functional and not to "freeze" until the simulation is over. Now I know that it is not a good idea to combine many threads for rendering in OpenGL, so my thought is rather simple : 1) Use one thread (I suppose the default one) to run everything apart from the physics. 2) Use another thread, only to run the physics which I have limited in one function as you will see. But even like this, the whole GUI still "freezes" and as a result it is useless until the physics ends. How can I fix that issue?
Below follows the code that I thought it would work. It renders a "Test button" in order to check if I can actually press it while the physics is running and the "Run physics" button that triggers a heavy computation.
#include"imgui.h"
#include"imgui_impl_glfw.h"
#include"imgui_impl_opengl3.h"
#include<GL/glew.h>
#include<GLFW/glfw3.h>
#include<cstdio>
#include<cmath>
#include<thread>
//Hypothetical "heavy" computation
void run_physics()
{
for (double z = 0.0; z < 10000.0; z += 0.001)
{
double y = exp(sin(sqrt(z*abs(z)+ cos(z))));
}
return;
}
int main()
{
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow *window = glfwCreateWindow(800,600, "Test", NULL, NULL);
if (window == NULL)
{
printf("Failed to open a glfw window. Exiting...\n");
return 0;
}
glfwMakeContextCurrent(window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
printf("Failed to initialize glew. Exiting...\n");
return 0;
}
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO &io = ImGui::GetIO();
(void)io;
ImGui::StyleColorsDark();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 330");
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
while (!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
ImGui::Begin("Test");
ImGui::Button("Test button");
if (ImGui::Button("Run physics"))
{
//This pauses the render loop until run_physics is done. Good.
//run_physics();
//This also pauses the render loop. Why?
std::thread thr(run_physics);
thr.join();
}
ImGui::End();
ImGui::Render();
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapBuffers(window);
glfwPollEvents();
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwTerminate();
return 0;
}