diff --git a/src/viewer/UIMenu.cpp b/src/viewer/UIMenu.cpp index bc7ee99..644920a 100644 --- a/src/viewer/UIMenu.cpp +++ b/src/viewer/UIMenu.cpp @@ -40,10 +40,11 @@ namespace ipc::rigid { // CCD_IM_ARRAYSIZE(level_strings))) { // set_logger_level(static_cast(log_level)); // } - set_logger_level(spdlog::level::level_enum::off); +// set_logger_level(spdlog::level::level_enum::off); draw_io(); + draw_legends(); if (m_has_scene) { if (ImGui::CollapsingHeader( @@ -68,15 +69,8 @@ namespace ipc::rigid { ImGui::SetNextWindowSizeConstraints( ImVec2(200.0f, 30.0f), ImVec2(legends_width, -1.0f)); bool _colors_menu_visible = true; - // TODO: only add edge - // ImGui::Begin( - // "Legend", &_colors_menu_visible, - // ImGuiWindowFlags_NoSavedSettings - // | ImGuiWindowFlags_AlwaysAutoResize); - // { - // draw_legends(); - // } - // ImGui::End(); + + } } // namespace ipc::rigid @@ -103,10 +97,7 @@ namespace ipc::rigid { } ImGui::EndChild(); - if (ImGui::Button("Save simulation", ImVec2(-1, 0))) { - std::string fname = igl::file_dialog_save(); - save(fname); - } + // if (ImGui::Button("Save OBJ sequence", ImVec2(-1, 0))) { // std::string dir_name = igl::file_dialog_save(); @@ -122,7 +113,7 @@ namespace ipc::rigid { // } // } - if (ImGui::Button("Start recording", ImVec2(-1, 0))) { + if (ImGui::Button("记录gif", ImVec2(-1, 0))) { std::string fname = igl::file_dialog_save(); start_recording(fname); } @@ -145,7 +136,7 @@ namespace ipc::rigid { } m_player_state = static_cast(player_state); - if (ImGui::Button("Step##SimPlayer", ImVec2(-1, 0))) { + if (ImGui::Button("逐步仿真##SimPlayer", ImVec2(-1, 0))) { m_player_state = PlayerState::Playing; pre_draw_loop(); m_player_state = PlayerState::Paused; @@ -161,13 +152,56 @@ namespace ipc::rigid { void UISimState::draw_settings() { auto config = m_state.get_active_config(); - ImGui::BeginChild( - "##config", ImVec2(ImGui::GetWindowContentRegionWidth(), 300), false, - ImGuiWindowFlags_HorizontalScrollbar); + static auto get_display_json = [&](const nlohmann::json &cur_state) { + + nlohmann::json display_json = { + {"总模型", {{"角动量", cur_state["angular_momentum"]}, + {"线动量", cur_state["linear_momentum"]}, + {"动能", cur_state["kinetic_energy"]}, + {"势能", cur_state["potential_energy"]},} + } + }; + auto v_rigid_bodies = cur_state["rigid_bodies"]; + for (int i = 0; i < v_rigid_bodies.size(); ++i) { + char str_i[10]; + sprintf(str_i, "刚体%3d", i + 1); + display_json["子模型"][str_i] = { + {"角速度", v_rigid_bodies[i]["angular_velocity"]}, + {"线速度", v_rigid_bodies[i]["linear_velocity"]}, + {"位置", v_rigid_bodies[i]["position"]}, + {"旋转角", v_rigid_bodies[i]["rotation"]}, + }; + } + display_json["时间步"]= m_state.problem_ptr->timestep(); + return display_json; + // Eigen::Vector3d angular_momentum(current_state[" angular_momentum"][0], current_state[" angular_momentum"][1], current_state[" angular_momentum"][2]); + // angular_momentum + // kinetic_energy + // linear_momentum + // potential_energy + // for () // rigid_bodies + // angular_velocity + // linear_velocity + // position + // rotation + }; + + ImGui::BeginChild("##config", ImVec2(ImGui::GetWindowContentRegionWidth(), 300), false, + ImGuiWindowFlags_HorizontalScrollbar); { - ImGui::TreeNodeJson(config); +// ImGui::TreeNodeJson(config); + assert(!m_state.state_sequence.empty()); + auto cur_state = m_state.state_sequence.back(); + auto disp_state = get_display_json(cur_state); + ImGui::TreeNodeJson(disp_state); + } + + if (ImGui::Button("导出仿真结果", ImVec2(-1, 0))) { + std::string fname = igl::file_dialog_save(); + save(fname); } ImGui::EndChild(); + } void UISimState::draw_legends() { @@ -180,18 +214,19 @@ namespace ipc::rigid { /// visibility checkbox bool tmp = ptr->visibility(); if (!ptr->is_com()) { - if (ImGui::Checkbox(("##UI-" + label).c_str(), &tmp)) { + if (ImGui::Checkbox(("网格可视化##UI-" + label).c_str(), &tmp)) { ptr->visibility(tmp); } - /// Color - ImGui::SameLine(); - if (ImGui::DoubleColorEdit3( - (label + "##UI-color").c_str(), ptr->m_color)) { - ptr->recolor(); - } +// /// Color +// ImGui::SameLine(); +// if (ImGui::DoubleColorEdit3( +// (label + "##UI-color").c_str(), ptr->m_color)) { +// ptr->recolor(); +// } } else if (ImGui::Checkbox((label + "##UI-check").c_str(), &tmp)) { ptr->visibility(tmp); } + break; } } diff --git a/src/viewer/UISimState.cpp b/src/viewer/UISimState.cpp index d6bab91..7e6479e 100644 --- a/src/viewer/UISimState.cpp +++ b/src/viewer/UISimState.cpp @@ -55,7 +55,7 @@ void UISimState::init(igl::opengl::glfw::Viewer* _viewer) io.Fonts->Clear(); io.Fonts->AddFontFromFileTTF( CMAKE_SOURCE_DIR "/src/viewer/Arial Unicode MS.TTF", - 14.0f, nullptr, io.Fonts->GetGlyphRangesChineseFull()); + 14.0f*2, nullptr, io.Fonts->GetGlyphRangesChineseFull()); viewer->data().clear(); @@ -272,7 +272,7 @@ void UISimState::start_recording(const std::string& filename) height = static_cast(m_gif_scale * height); GifBegin(&m_gif_writer, filename.c_str(), width, height, m_gif_delay); m_scene_changed = true; - // post_draw_loop(); +// post_draw_loop(); m_is_gif_recording = true; } diff --git a/src/viewer/imgui_ext.cpp b/src/viewer/imgui_ext.cpp index 13b7ed4..8d07e73 100644 --- a/src/viewer/imgui_ext.cpp +++ b/src/viewer/imgui_ext.cpp @@ -1,127 +1,138 @@ #include "imgui_ext.hpp" #include "imgui.h" #include +#include +#include namespace ImGui { -bool InputIntBounded( - const char* label, - int* val, - int lower_bound, - int upper_bound, - int step, - int step_fast, - ImGuiInputTextFlags flags) -{ - int unbounded_val = *val; - if (ImGui::InputInt(label, &unbounded_val, step, step_fast, flags)) { - if (unbounded_val >= lower_bound && unbounded_val <= upper_bound) { - *val = unbounded_val; - return true; + bool InputIntBounded( + const char *label, + int *val, + int lower_bound, + int upper_bound, + int step, + int step_fast, + ImGuiInputTextFlags flags) { + int unbounded_val = *val; + if (ImGui::InputInt(label, &unbounded_val, step, step_fast, flags)) { + if (unbounded_val >= lower_bound && unbounded_val <= upper_bound) { + *val = unbounded_val; + return true; + } } + return false; } - return false; -} -bool InputDoubleBounded( - const char* label, - double* val, - double lower_bound, - double upper_bound, - double step, - double step_fast, - const char* format, - ImGuiInputTextFlags flags) -{ - double unbounded_val = *val; - if (ImGui::InputDouble( - label, &unbounded_val, step, step_fast, format, flags)) { - if (unbounded_val >= lower_bound && unbounded_val <= upper_bound) { - *val = unbounded_val; - return true; + bool InputDoubleBounded( + const char *label, + double *val, + double lower_bound, + double upper_bound, + double step, + double step_fast, + const char *format, + ImGuiInputTextFlags flags) { + double unbounded_val = *val; + if (ImGui::InputDouble( + label, &unbounded_val, step, step_fast, format, flags)) { + if (unbounded_val >= lower_bound && unbounded_val <= upper_bound) { + *val = unbounded_val; + return true; + } } + return false; } - return false; -} -bool DragDouble( - const char* label, - double* v, - double v_speed, - double v_min, - double v_max, - const char* format, - float power) -{ + bool DragDouble( + const char *label, + double *v, + double v_speed, + double v_min, + double v_max, + const char *format, + float power) { - return DragScalar( - label, ImGuiDataType_Double, v, float(v_speed), &v_min, &v_max, format, - power); -} + return DragScalar( + label, ImGuiDataType_Double, v, float(v_speed), &v_min, &v_max, format, + power); + } -bool DoubleColorEdit3(const char* label, Eigen::RowVector3d& color) -{ - Eigen::Vector3f color_f = color.cast(); - bool changed = false; - if (ImGui::ColorEdit3( - label, color_f.data(), - ImGuiColorEditFlags_NoInputs + bool DoubleColorEdit3(const char *label, Eigen::RowVector3d &color) { + Eigen::Vector3f color_f = color.cast(); + bool changed = false; + if (ImGui::ColorEdit3( + label, color_f.data(), + ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_PickerHueWheel)) { - color = color_f.cast(); - changed = true; + color = color_f.cast(); + changed = true; + } + return changed; } - return changed; -} -void HelpMarker(const char* desc) -{ - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(desc); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); + void HelpMarker(const char *desc) { + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(desc); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } } -} -void TreeNodeJson(const nlohmann::json json) -{ - static const ImVec4 label_color = - ImVec4(241.f / 255.f, 196.f / 255.f, 15.f / 255.f, 1.0f); - ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing() * 0.1f); - ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize() * 1); - for (auto& j : json.items()) { - if (j.value().is_object()) { - ImGui::PushStyleColor(ImGuiCol_Text, label_color); - if (ImGui::TreeNode(j.key().c_str())) { - ImGui::PopStyleColor(); - TreeNodeJson(j.value()); - ImGui::TreePop(); - } else { - ImGui::PopStyleColor(); - } - } else { - ImGui::Bullet(); - ImGui::TextColored(label_color, "%s: ", j.key().c_str()); - ImGui::SameLine(); - if (j.value().is_number_float()) { - ImGui::Text("%g", j.value().get()); + void TreeNodeJson(const nlohmann::json json) { + static const ImVec4 label_color = +// ImVec4(241.f / 255.f, 196.f / 255.f, 15.f / 255.f, 1.0f); + ImVec4(0.9, 0.9, 0.9, 1.0f); + ImGui::Unindent(ImGui::GetTreeNodeToLabelSpacing() * 0.1f); + ImGui::PushStyleVar(ImGuiStyleVar_IndentSpacing, ImGui::GetFontSize() * 1); + for (auto &j: json.items()) { + if (j.value().is_object()) { + ImGui::PushStyleColor(ImGuiCol_Text, label_color); + if (ImGui::TreeNode(j.key().c_str())) { + ImGui::PopStyleColor(); + TreeNodeJson(j.value()); + ImGui::TreePop(); + } else { + ImGui::PopStyleColor(); + } } else { - ImGui::Text("%s", j.value().dump().c_str()); + ImGui::Bullet(); + ImGui::TextColored(label_color, "%s: ", j.key().c_str()); + ImGui::SameLine(); + if (j.value().is_number_float()) { + ImGui::Text("%g", j.value().get()); + } else if (j.value().is_array()) { + std::string the_arr; + char buffer[20]; + for (int i = 0; i < j.value().size(); ++i) { + double the_val = j.value()[i].get(); + if (the_val == 0) { + buffer[0] = '0'; + buffer[1] = '\0'; + } else { + sprintf(buffer, "%.2e", the_val); + } + the_arr += (i > 0 ? std::string(" ,") : std::string("")) + std::string(buffer); + } + ImGui::Text("%s", the_arr.c_str()); + } else { + spdlog::error("wrong json data!"); + } } } + ImGui::PopStyleVar(); + ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing() * 0.1f); } - ImGui::PopStyleVar(); - ImGui::Indent(ImGui::GetTreeNodeToLabelSpacing() * 0.1f); -} -void reload_font(int font_size) -{ - ImGuiIO& io = ImGui::GetIO(); - io.Fonts->Clear(); - io.Fonts->AddFontFromFileTTF("/home/oo/project/vscode/rigid_ipc/rigid-ipc/src/viewer/DroidSans.ttf", 14.0f, nullptr, - io.Fonts->GetGlyphRangesChineseFull()); -} + void reload_font(int font_size) { + ImGuiIO &io = ImGui::GetIO(); + io.Fonts->Clear(); + io.Fonts->AddFontFromFileTTF("/home/oo/project/vscode/rigid_ipc/rigid-ipc/src/viewer/DroidSans.ttf", 14.0f, + nullptr, + io.Fonts->GetGlyphRangesChineseFull()); + } } // namespace ImGui