ENH: Use imgui for status and input

This commit is contained in:
David Allemang
2023-02-05 22:30:50 -05:00
parent 600b18a8af
commit cb758166fa
3 changed files with 158 additions and 70 deletions

31
ext/imgui.cmake Normal file
View File

@@ -0,0 +1,31 @@
include(FetchContent)
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG v1.86
GIT_PROGRESS TRUE
)
FetchContent_GetProperties(imgui)
if (NOT ${imgui}_POPULATED)
FetchContent_MakeAvailable(imgui)
add_library(
imgui
${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_glfw.h
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.cpp
${imgui_SOURCE_DIR}/backends/imgui_impl_opengl3.h
${imgui_SOURCE_DIR}/imgui.cpp
${imgui_SOURCE_DIR}/imgui.h
${imgui_SOURCE_DIR}/imgui_demo.cpp
${imgui_SOURCE_DIR}/imgui_draw.cpp
${imgui_SOURCE_DIR}/imgui_tables.cpp
${imgui_SOURCE_DIR}/imgui_widgets.cpp
)
target_include_directories(imgui PUBLIC ${imgui_SOURCE_DIR})
target_link_libraries(imgui PRIVATE glfw)
endif ()

View File

@@ -14,6 +14,6 @@ add_executable(vis
target_include_directories(vis PRIVATE include) target_include_directories(vis PRIVATE include)
target_link_libraries(vis PRIVATE target_link_libraries(vis PRIVATE
tc shaders tc shaders
glad eigen glfw yaml-cpp fmt EnTT glad eigen glfw yaml-cpp fmt EnTT imgui
) )
add_dependencies(vis presets) add_dependencies(vis presets)

View File

@@ -1,8 +1,13 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cmath> #include <cmath>
#include <iostream> #include <iostream>
#include <imgui.h>
#include <backends/imgui_impl_glfw.h>
#include <backends/imgui_impl_opengl3.h>
#include <tc/groups.hpp> #include <tc/groups.hpp>
#include "util.hpp" #include "util.hpp"
@@ -37,17 +42,16 @@ struct Matrices {
}; };
struct State { struct State {
float time;
float time_delta;
float st;
int dimension; int dimension;
float time = 0;
Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
entt::registry registry; entt::registry registry;
}; };
Matrices build(GLFWwindow* window, State &state) { Matrices build(GLFWwindow* window, State &state, ImGuiContext* ctx) {
int width, height; int width, height;
glfwGetFramebufferSize(window, &width, &height); glfwGetFramebufferSize(window, &width, &height);
@@ -56,50 +60,63 @@ Matrices build(GLFWwindow* window, State &state) {
auto pwidth = aspect * pheight; auto pwidth = aspect * pheight;
Eigen::Matrix4f proj = orthographic(-pwidth, pwidth, -pheight, pheight, -10.0f, 10.0f); Eigen::Matrix4f proj = orthographic(-pwidth, pwidth, -pheight, pheight, -10.0f, 10.0f);
if (!glfwGetKey(window, GLFW_KEY_LEFT_SHIFT)) { auto &io = ImGui::GetIO();
state.st += state.time_delta / 8;
if (io.MouseDown[0] && !io.WantCaptureMouse) {
Eigen::Vector4f src{0, 0, 1, 0};
Eigen::Vector4f dst{io.MouseDelta.x, -io.MouseDelta.y, 300, 0};
dst.normalize();
auto rotate = rotor(src, dst);
state.view = rotate * state.view;
} }
static bool init = false; return Matrices(proj, state.view);
static Eigen::Vector2d last;
Eigen::Vector2d pos;
glfwGetCursorPos(window, &pos.x(), &pos.y());
if (!init) {
last = pos;
init = true;
}
Eigen::Vector2d dpos = pos - last;
last = pos;
static Eigen::Matrix4f view = Eigen::Matrix4f::Identity();
if (state.dimension < 4) {
view *= rot<4>(2, 3, M_PI_2f32 + 0.01f);
}
if (glfwGetMouseButton(window, 0)) {
float scale = 0.005;
auto rotate = rotor(
Eigen::Vector4f{0, 0, 1, 0},
Eigen::Vector4f{
dpos.x() * scale,
-dpos.y() * scale,
1, 0
}.normalized()
);
view = rotate * view;
}
return Matrices(proj, view);
} }
void run(const std::string &config_file, GLFWwindow* window) { void show_overlay(State &state) {
#ifndef NDEBUG static std::string gl_vendor = (const char*) glGetString(GL_VENDOR);
glEnable(GL_DEBUG_OUTPUT); static std::string gl_renderer = (const char*) glGetString(GL_RENDERER);
glDebugMessageCallback(log_gl_debug_callback, nullptr); static std::string gl_version = (const char*) glGetString(GL_VERSION);
#endif static std::string glsl_version = (const char*) glGetString(GL_SHADING_LANGUAGE_VERSION);
ImGuiWindowFlags window_flags =
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoSavedSettings |
ImGuiWindowFlags_NoFocusOnAppearing |
ImGuiWindowFlags_NoNav |
ImGuiWindowFlags_NoBringToFrontOnFocus |
ImGuiWindowFlags_NoMove;
ImGuiStyle &style = ImGui::GetStyle();
const auto PAD = style.DisplaySafeAreaPadding;
auto window_pos = PAD;
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always);
ImGui::SetNextWindowBgAlpha(0.35f * style.Alpha);
ImGui::SetNextWindowCollapsed(true, ImGuiCond_Appearing);
ImGui::Begin("Graphics Information", nullptr, window_flags);
ImGui::Text("GL Vendor | %s", gl_vendor.c_str());
ImGui::Text("GL Renderer | %s", gl_renderer.c_str());
ImGui::Text("GL Version | %s", gl_version.c_str());
ImGui::Text("GLSL Version | %s", glsl_version.c_str());
auto v2 = ImGui::GetWindowSize();
window_pos.y += v2.y + PAD.y;
ImGui::End();
}
void set_style() {
ImGui::StyleColorsDark();
ImGuiStyle &style = ImGui::GetStyle();
style.WindowRounding = 4;
style.FrameRounding = 2;
style.DisplaySafeAreaPadding.x = 10;
style.DisplaySafeAreaPadding.y = 10;
}
void run(GLFWwindow* window, ImGuiContext* ctx) {
if (glfwRawMouseMotionSupported()) { if (glfwRawMouseMotionSupported()) {
glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE); glfwSetInputMode(window, GLFW_RAW_MOUSE_MOTION, GLFW_TRUE);
} }
@@ -124,10 +141,13 @@ void run(const std::string &config_file, GLFWwindow* window) {
tc::schlafli({5, 3, 3, 2}), tc::schlafli({5, 3, 3, 2}),
vec5{0.80, 0.09, 0.09, 0.09, 0.09}, vec5{0.80, 0.09, 0.09, 0.09, 0.09},
vec3{0.90, 0.90, 0.90}, vec3{0.90, 0.90, 0.90},
std::vector<std::vector<size_t>>{{0, 1, 2}, std::vector<std::vector<size_t>>{
{0, 3, 4}, {0, 1, 2},
{1, 3, 4},
{2, 3, 4}} {0, 3, 4},
{1, 3, 4},
{2, 3, 4},
}
); );
registry.emplace<vis::VBOs>(entity); registry.emplace<vis::VBOs>(entity);
@@ -137,9 +157,20 @@ void run(const std::string &config_file, GLFWwindow* window) {
glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo); glBindBufferBase(GL_UNIFORM_BUFFER, 1, ubo);
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
auto time = (float) glfwGetTime(); glfwPollEvents();
state.time_delta = state.time - time;
state.time = time; ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
auto io = ImGui::GetIO();
if (io.KeysDown[GLFW_KEY_ESCAPE]) {
glfwSetWindowShouldClose(window, true);
continue;
}
ImGui::NewFrame();
show_overlay(state);
ImGui::Render();
int width, height; int width, height;
glfwGetFramebufferSize(window, &width, &height); glfwGetFramebufferSize(window, &width, &height);
@@ -147,37 +178,45 @@ void run(const std::string &config_file, GLFWwindow* window) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
ubo.put(build(window, state)); ubo.put(build(window, state, ctx));
{ {
auto &tform = registry.get<vis::VBOs>(entity).tform; auto &tform = registry.get<vis::VBOs>(entity).tform;
if (!io.KeysDown[GLFW_KEY_SPACE]) {
float speed = 1.0 / 8.0;
if (io.KeysDown[GLFW_KEY_LEFT_SHIFT] | io.KeysDown[GLFW_KEY_RIGHT_SHIFT]) {
speed /= 4;
}
state.time += io.DeltaTime * speed;
}
tform.linear().setIdentity(); tform.linear().setIdentity();
if (state.dimension > 1) { if (state.dimension > 1) {
tform.linear() *= rot<4>(0, 1, state.st * .40f); tform.linear() *= rot<4>(0, 1, state.time * .40f);
} }
if (state.dimension > 2) { if (state.dimension > 2) {
tform.linear() *= rot<4>(0, 2, state.st * .20f); tform.linear() *= rot<4>(0, 2, state.time * .20f);
tform.linear() *= rot<4>(1, 2, state.st * .50f); tform.linear() *= rot<4>(1, 2, state.time * .50f);
} }
if (state.dimension > 3) { if (state.dimension > 3) {
tform.linear() *= rot<4>(0, 3, state.st * 1.30f); tform.linear() *= rot<4>(0, 3, state.time * 1.30f);
tform.linear() *= rot<4>(1, 3, state.st * .25f); tform.linear() *= rot<4>(1, 3, state.time * .25f);
tform.linear() *= rot<4>(2, 3, state.st * 1.42f); tform.linear() *= rot<4>(2, 3, state.time * 1.42f);
} }
tform.translation().w() = std::sin(time * 0.3f) * 1.0f; tform.translation().w() = std::sin(state.time * 1.4) * 1.0;
} }
vis::upload_ubo(registry); vis::upload_ubo(registry);
renderer(registry); renderer(registry);
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
glfwSwapInterval(2); glfwSwapInterval(2);
glfwSwapBuffers(window); glfwSwapBuffers(window);
glfwPollEvents();
} }
} }
@@ -206,16 +245,34 @@ int main(int argc, char* argv[]) {
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
gladLoadGLLoader((GLADloadproc) glfwGetProcAddress); gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1); glfwSwapInterval(1);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
std::cout << utilInfo(); #ifndef NDEBUG
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageCallback(log_gl_debug_callback, nullptr);
#endif
std::string config_file = "presets/default.yaml"; IMGUI_CHECKVERSION();
if (argc > 1) config_file = std::string(argv[1]); auto* context = ImGui::CreateContext();
ImGui_ImplGlfw_InitForOpenGL(window, true);
ImGui_ImplOpenGL3_Init("#version 130");
run(config_file, window); set_style();
int exit_code = EXIT_SUCCESS;
try {
run(window, context);
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
exit_code = EXIT_FAILURE;
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown();
ImGui::DestroyContext();
glfwDestroyWindow(window);
glfwTerminate(); glfwTerminate();
return EXIT_SUCCESS;
return exit_code;
} }