#include "common.hpp" #include "ui.hpp" #include #include #include #include #include #include // Different packaging defines this inconsistently, e.g. Xrepo but not most Linux distros // We need it, so define just in case #define GLFW_INCLUDE_NONE #include #include static void glfw_error_handler(int err, const char* desc) { fprintf(stderr, MSG_ERROR "GLFW error %d: %s", err, desc); } static const char* imgui_glsl_version = nullptr; struct GlfwInit { GlfwInit() { if (!glfwInit()) { throw std::runtime_error("failed to init GLFW"); } glfwSetErrorCallback(&glfw_error_handler); // Decide GL+GLSL versions #if defined(IMGUI_IMPL_OPENGL_ES2) // GL ES 2.0 + GLSL 100 imgui_glsl_version = "#version 100"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); #elif defined(__APPLE__) // GL 3.2 + GLSL 150 imgui_glsl_version = "#version 150"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac #else // GL 3.0 + GLSL 130 imgui_glsl_version = "#version 130"; glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); #endif } ~GlfwInit() { glfwTerminate(); } }; struct GlfwWindow { GLFWwindow* _h; GlfwWindow(int width, int height, const char* title) { _h = glfwCreateWindow(width, height, title, nullptr, nullptr); if (_h == nullptr) throw std::runtime_error("failed to create GLFW window"); } ~GlfwWindow() { glfwDestroyWindow(_h); } }; struct ImGuiInit { ImGuiInit(GLFWwindow* window) { IMGUI_CHECKVERSION(); ImGui::CreateContext(); ImGui_ImplGlfw_InitForOpenGL(window, true); ImGui_ImplOpenGL3_Init("#version 130"); } ~ImGuiInit() { ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); ImGui::DestroyContext(); } }; int main() { GlfwInit i_glfw; GlfwWindow i_window(1280, 730, "Sand Physics"); GLFWwindow* window = i_window._h; glfwMakeContextCurrent(window); // V-sync to make timing easier, we don't really care about latency glfwSwapInterval(1); ImGuiInit i_imgui(window); ImVec4 bg_col(1.0f, 1.0f, 1.0f, 1.0f); bg_col.x *= bg_col.w; bg_col.y *= bg_col.w; bg_col.z *= bg_col.w; while (!glfwWindowShouldClose(window)) { glfwPollEvents(); ImGui_ImplOpenGL3_NewFrame(); ImGui_ImplGlfw_NewFrame(); ImGui::NewFrame(); ShowEverything(); ImGui::Render(); int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(bg_col.x * bg_col.w, bg_col.y * bg_col.w, bg_col.z * bg_col.w, bg_col.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(window); } }