diff --git a/src/main.cpp b/src/main.cpp index c642e75..46af4ca 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,15 +9,18 @@ #include // filesystem #include + #ifdef RIGID_IPC_WITH_OPENGL + #include #include "viewer/UIStaticSimState.h" + #endif + #include #include #include "path_config.h" -int main(int argc, char* argv[]) -{ +int main(int argc, char *argv[]) { using namespace ipc::rigid; set_logger_level(spdlog::level::info); @@ -29,46 +32,46 @@ int main(int argc, char* argv[]) bool with_viewer = false; #endif app.add_flag("--gui,!--ngui", with_viewer, "use the OpenGL GUI") - ->default_val(with_viewer); + ->default_val(with_viewer); std::string scene_path = ""; app.add_option( - "scene_path,-i,-s,--scene-path", scene_path, - "JSON file with input scene"); + "scene_path,-i,-s,--scene-path", scene_path, + "JSON file with input scene"); std::string output_dir = ""; app.add_option( - "output_dir,-o,--output-path", output_dir, - "directory for results (ngui only)"); + "output_dir,-o,--output-path", output_dir, + "directory for results (ngui only)"); std::string output_name = "sim.json"; app.add_option( - "-f,--output-name", output_name, - "name for simulation file (ngui only)") - ->default_val(output_name); + "-f,--output-name", output_name, + "name for simulation file (ngui only)") + ->default_val(output_name); int num_steps = -1; app.add_option( - "--num-steps", num_steps, "number of time-steps (ngui only)"); + "--num-steps", num_steps, "number of time-steps (ngui only)"); int checkpoint_freq = -1; app.add_option( - "--chkpt,--checkpoint-frequency", checkpoint_freq, - "number of time-steps between checkpoints (ngui only)"); + "--chkpt,--checkpoint-frequency", checkpoint_freq, + "number of time-steps between checkpoints (ngui only)"); spdlog::level::level_enum loglevel = spdlog::level::info; app.add_option("--log,--loglevel", loglevel, "log level") - ->default_val(loglevel) - ->transform(CLI::CheckedTransformer( - SPDLOG_LEVEL_NAMES_TO_LEVELS, CLI::ignore_case)); + ->default_val(loglevel) + ->transform(CLI::CheckedTransformer( + SPDLOG_LEVEL_NAMES_TO_LEVELS, CLI::ignore_case)); int nthreads = tbb::task_scheduler_init::default_num_threads(); app.add_option("--nthreads", nthreads, "maximum number of threads to use") - ->default_val(nthreads); + ->default_val(nthreads); std::string patch = ""; app.add_option("--patch", patch, "patch to input file (ngui only)") - ->default_val(patch); + ->default_val(patch); CLI11_PARSE(app, argc, argv); @@ -80,22 +83,45 @@ int main(int argc, char* argv[]) if (nthreads > tbb::task_scheduler_init::default_num_threads()) { spdlog::warn( - "Attempting to use more threads than available ({:d} > {:d})!", - nthreads, tbb::task_scheduler_init::default_num_threads()); + "Attempting to use more threads than available ({:d} > {:d})!", + nthreads, tbb::task_scheduler_init::default_num_threads()); } tbb::global_control thread_limiter( - tbb::global_control::max_allowed_parallelism, nthreads); + tbb::global_control::max_allowed_parallelism, nthreads); if (with_viewer) { #ifdef RIGID_IPC_WITH_OPENGL // UISimState ui; // ui.launch(scene_path); // Static Simulation + + + +// bool my_tool_active = true; +// bool switch_to_static; +// begin_viewer.callback_pre_draw = [&](igl::opengl::glfw::Viewer &viewer) { +// ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver); +// ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver); +//// ImGui::SetNextWindowSizeConstraints( +//// ImVec2(menu_width, -1.0f), ImVec2(menu_width, -1.0f)); +// bool _viewer_menu_visible = true; +// +// ImGui::Begin( +// "控制菜单", &_viewer_menu_visible, +// ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_AlwaysAutoResize); +// ImGui::End(); +// return false; +// }; +// begin_viewer.launch(); + + +// std::cout << "switch is: " << my_tool_active << std::endl; +// exit(1); ssim::SimTargetOption option; option.set_option(option.U_NORM); - std::string json_path=CMAKE_SOURCE_DIR "/sim-test/rigid-test/cube/config.json"; - std::shared_ptr sp_StaticSim = std::make_shared(option,json_path); + std::string json_path = CMAKE_SOURCE_DIR "/sim-test/rigid-test/cube/config.json"; + std::shared_ptr sp_StaticSim = std::make_shared(option, json_path); UIStaticSimState ui(sp_StaticSim); ui.launch(scene_path); @@ -107,18 +133,17 @@ int main(int argc, char* argv[]) } else { if (scene_path.empty()) { exit(app.exit(CLI::Error( - "scene_path", "Must provide a scene path in ngui mode!"))); + "scene_path", "Must provide a scene path in ngui mode!"))); } if (output_dir.empty()) { exit(app.exit(CLI::Error( - "output_dir", - "Must provide a output directory in ngui mode!"))); + "output_dir", + "Must provide a output directory in ngui mode!"))); } // Create the output directory if it does not exist - fs::create_directories(fs::path(output_dir)); - PROFILER_OUTDIR(output_dir); + fs::create_directories(fs::path(output_dir));PROFILER_OUTDIR(output_dir); std::string fout = fmt::format("{}/{}", output_dir, output_name); SimState sim; diff --git a/src/viewer/UIStaticMenu.cpp b/src/viewer/UIStaticMenu.cpp index 8008b0e..973c625 100644 --- a/src/viewer/UIStaticMenu.cpp +++ b/src/viewer/UIStaticMenu.cpp @@ -7,6 +7,7 @@ #include #include +#include "string" namespace ipc::rigid { @@ -147,34 +148,61 @@ namespace ipc::rigid { if (ImGui::Button("开始计算")) { sp_StaticSim_->simulation(); - gui_ctrl_.is_modified = true; gui_ctrl_.is_solved = true; } // ImGui::RadioButton("开始计算##SimPlayer", &player_state, PlayerState::Playing); // ImGui::RadioButton("暂停##SimPlayer", &player_state, PlayerState::Paused); - ImGui::Checkbox("边界条件", &gui_ctrl_.is_visible_BC); - ImGui::Checkbox("网格可视化",&gui_ctrl_.mesh_visible); + ImGui::Checkbox("网格可视化", &gui_ctrl_.mesh_visible); + // -------------------------------------------------------------------- if (ImGui::CollapsingHeader( - "边界条件设置##SimPlayer", ImGuiTreeNodeFlags_DefaultOpen)) { - ImGui::Checkbox("边界包围盒", &m_bkp_has_intersections); - // -------------------------------------------------------------------- - - for (int i = 0; i < sp_StaticSim_->DirichletBCs.size(); ++i) { - // each boundary - // ImGui::Checkbox("受力", &m_state.m_solve_collisions); - auto &i_DBC = sp_StaticSim_->DirichletBCs[i]; - std::vector v_min_point = {(float) i_DBC.relMinBBox.x(), (float) i_DBC.relMinBBox.y(), - (float) i_DBC.relMinBBox.z()}; - std::vector v_max_point = {(float) i_DBC.relMaxBBox.x(), (float) i_DBC.relMaxBBox.y(), - (float) i_DBC.relMaxBBox.z()}; - ImGui::SliderFloat3("最小值", v_min_point.data(), -50, 50, "%.3f"); - ImGui::SliderFloat3("最大值", v_max_point.data(), -50, 50, "%.3f"); - i_DBC.relMinBBox={v_min_point[0],v_min_point[1],v_min_point[2]}; - i_DBC.relMaxBBox={v_max_point[0],v_max_point[1],v_max_point[2]}; + "边界条件", ImGuiTreeNodeFlags_DefaultOpen)) { + ImGui::Checkbox("边界可视化", &gui_ctrl_.is_visible_BC); + if (ImGui::CollapsingHeader( + "Dirichlet边界", ImGuiTreeNodeFlags_DefaultOpen)) { + // -------------------------------------------------------------------- + + for (int i = 0; i < sp_StaticSim_->DirichletBCs.size(); ++i) { + // each boundary + // ImGui::Checkbox("受力", &m_state.m_solve_collisions); + auto &i_DBC = sp_StaticSim_->DirichletBCs[i]; + std::vector v_min_point = {(float) i_DBC.relMinBBox.x(), (float) i_DBC.relMinBBox.y(), + (float) i_DBC.relMinBBox.z()}; + std::vector v_max_point = {(float) i_DBC.relMaxBBox.x(), (float) i_DBC.relMaxBBox.y(), + (float) i_DBC.relMaxBBox.z()}; + ImGui::InputFloat3(("Dirichlet最小值 " + std::to_string(i + 1)).c_str(), v_min_point.data()); + ImGui::InputFloat3(("Dirichlet最大值 " + std::to_string(i + 1)).c_str(), v_min_point.data()); + i_DBC.relMinBBox = {v_min_point[0], v_min_point[1], v_min_point[2]}; + i_DBC.relMaxBBox = {v_max_point[0], v_max_point[1], v_max_point[2]}; + } + + } + + if (ImGui::CollapsingHeader( + "Neumann边界", ImGuiTreeNodeFlags_DefaultOpen)) { + // -------------------------------------------------------------------- + + for (int i = 0; i < sp_StaticSim_->NeumannBCs.size(); ++i) { + auto &i_NBC = sp_StaticSim_->NeumannBCs[i]; + std::vector v_min_point = {(float) i_NBC.relMinBBox.x(), (float) i_NBC.relMinBBox.y(), + (float) i_NBC.relMinBBox.z()}; + std::vector v_max_point = {(float) i_NBC.relMaxBBox.x(), (float) i_NBC.relMaxBBox.y(), + (float) i_NBC.relMaxBBox.z()}; + std::vector v_force = {(float) i_NBC.force.x(), (float) i_NBC.force.y(), + (float) i_NBC.force.z()}; + + ImGui::InputFloat3(("Neumann最小值 " + std::to_string(i + 1)).c_str(), v_min_point.data()); + ImGui::InputFloat3(("Neumann最大值 " + std::to_string(i + 1)).c_str(), v_min_point.data()); + ImGui::InputFloat3(("Neumann力 " + std::to_string(i + 1)).c_str(), v_force.data()); + i_NBC.relMinBBox = {v_min_point[0], v_min_point[1], v_min_point[2]}; + i_NBC.relMaxBBox = {v_max_point[0], v_max_point[1], v_max_point[2]}; + i_NBC.force={v_force[0],v_force[1],v_force[2]}; + } + } } + // ImGui::Checkbox("受力大小", &m_bkp_optimization_failed); // ImGui::SameLine(); // ImGui::HelpMarker("yes - stop playing if step optimization failed."); @@ -197,17 +225,10 @@ namespace ipc::rigid { // } // -------------------------------------------------------------------- if (ImGui::CollapsingHeader("材料设置", ImGuiTreeNodeFlags_DefaultOpen)) { - static float f0 = 0.001f; - static float f1 = 0.001f; - static float f2 = 0.001f; - ImGui::InputFloat("杨氏模量", &f0, 0.01f, 1.0f, "%.3f"); - ImGui::InputFloat("泊松比", &f1, 0.01f, 1.0f, "%.3f"); - ImGui::InputFloat("密度", &f2, 0.01f, 1.0f, "%.3f"); - } - if (ImGui::CollapsingHeader( - "其他设置", ImGuiTreeNodeFlags_DefaultOpen)) { - static float f3 = 0.01f; - ImGui::InputFloat("时间步", &f3, 0.01f, 1.0f, "%.2f"); + + ImGui::InputFloat("杨氏模量", &sp_StaticSim_->get_material_property().Youngs_Modulus, 1.0f, 1e10f, "%.3f"); + ImGui::InputFloat("泊松比", &sp_StaticSim_->get_material_property().Poisson_ratio, 0.01f, 1.0f, "%.3f"); + ImGui::InputFloat("密度", &sp_StaticSim_->get_material_property().density, 1.0f, 1000.0f, "%.3f"); } } @@ -231,7 +252,7 @@ namespace ipc::rigid { char *desc = "121.88"; // ImGui::Text("柔顺度(compliance)"); // sp_StaticSim_->EvaluateTarget(ssim::SimTargetOption::COMPLIANCE)(0,0); - ImGui::TextWrapped("柔顺度 (compliance): %.3f", 12222.2); + ImGui::TextWrapped("柔顺度 (compliance): %.3e", sp_StaticSim_->EvaluateTarget(ssim::SimTargetOption::COMPLIANCE)(0,0)); if (ImGui::IsItemHovered()) { // 显示工具的提示 ImGui::BeginTooltip(); diff --git a/src/viewer/UIStaticSimState.h b/src/viewer/UIStaticSimState.h index 812170c..2e8e0a9 100644 --- a/src/viewer/UIStaticSimState.h +++ b/src/viewer/UIStaticSimState.h @@ -190,7 +190,7 @@ namespace ipc { 5, 1, 2, 5, 2, 6, 4, 7, 3, - 5, 4, 3; + 4, 3, 0; Eigen::Vector3d transform = (v_max + v_min) / 2.0; Eigen::Vector3d scaled_factor = (v_max - v_min) / 2.0; V = V.array().rowwise() * scaled_factor.transpose().array(); diff --git a/static_sim/StaticSim.h b/static_sim/StaticSim.h index 834e6db..1d257f3 100644 --- a/static_sim/StaticSim.h +++ b/static_sim/StaticSim.h @@ -42,6 +42,12 @@ namespace ssim { }; }; + struct MaterialProperty{ + float Youngs_Modulus=1.0f; + float Poisson_ratio=0.3f; + float density=1.0f; + }; + class StaticSim { using MeshModel = Model; @@ -52,22 +58,11 @@ namespace ssim { StaticSim(const SimTargetOption &option, const std::string &jsonPath); - ~ - - StaticSim() {} + ~StaticSim() {} void simulation(); - Mesh GetMeshInDBC() { - // TODO: get mesh in DBC box - Mesh ret; - ret.V = get_mesh().V; - ret.F = get_mesh().F.topRows(100); - - return ret; - } - /** * Given query points Q, compute their displacements and stress * @param Q (nQ, 3), query points @@ -105,6 +100,11 @@ namespace ssim { void MapAppendTarget(int target); + MaterialProperty& get_material_property(){ + return material_property_; + } + + // Return: #mesh.V.rows() x 1 Eigen::MatrixXd EvaluateUNorm() const; @@ -137,9 +137,11 @@ namespace ssim { private: MeshModel mesh_; + MaterialProperty material_property_; SimTargetOption option_; std::vector map_target_to_evaluated_; + private: std::vector DirichletBCs; std::vector NeumannBCs;