diff --git a/engine/engine.json.in b/engine/engine.json.in index 8ccf73e..d5c098d 100644 --- a/engine/engine.json.in +++ b/engine/engine.json.in @@ -1,9 +1,7 @@ { - "scene_type": "distance_barrier_rb_problem", "timestep": 0.01, "max_time": 10.0, "rigid_body_problem": { - "coefficient_restitution": -1, "gravity": [0, 9.8, 0], "rigid_bodies": [{ "mesh": "@LOCAL_DIR_PATH@/stl/crank.stl", diff --git a/sim-test/rigid-test/cube/config.json b/sim-test/rigid-test/cube/config.json new file mode 100644 index 0000000..9bf68fb --- /dev/null +++ b/sim-test/rigid-test/cube/config.json @@ -0,0 +1,19 @@ +{ + "material": [1e5, 0.3, 1e3], + "mshFilePath": "/home/cflin/Documents/CppField/source/RigidElasticSim/sim-test/rigid-test/cube/cube_9743.msh", + + "DBC": [ + { + "min": [-0.001, -0.001, -0.001], + "max": [1.001, 0.001, 1.001] + } + ], + + "NBC": [ + { + "min": [-0.001, 0.999, -0.001], + "max": [1.001, 1.001, 1.001], + "force": [-10, 0, 0] + } + ] +} diff --git a/sim-test/rigid-test/rearAxle-mod/config.json b/sim-test/rigid-test/rearAxle-mod/config.json new file mode 100644 index 0000000..9b39242 --- /dev/null +++ b/sim-test/rigid-test/rearAxle-mod/config.json @@ -0,0 +1,24 @@ +{ + "material": [1e5, 0.3, 1e3], + "mshFilePath": "/home/cflin/Documents/CppField/source/RigidElasticSim/sim-test/rigid-test/rearAxle-mod/rearAxle-mod_.msh", + + "DBC": [ + { + "min": [-0.1, 0.4, -0.1], + "max": [0.6, 0.6, 1.1] + } + ], + + "NBC": [ + { + "min": [-0.1, 0.8, -0.1], + "max": [1.1, 1.1, 1.1], + "force": [1, 0, 0] + }, + { + "min": [-0.1, -0.1, -0.1], + "max": [1.1, 0.2, 1.1], + "force": [1, 0, 0] + } + ] +} diff --git a/sim-test/rigid-test/rocker-arm/config.json b/sim-test/rigid-test/rocker-arm/config.json new file mode 100644 index 0000000..b90f702 --- /dev/null +++ b/sim-test/rigid-test/rocker-arm/config.json @@ -0,0 +1,19 @@ +{ + "material": [1e5, 0.3, 1e3], + "mshFilePath": "/home/cflin/Documents/CppField/source/RigidElasticSim/sim-test/rigid-test/rocker-arm/rocker-arm_.msh", + + "DBC": [ + { + "min": [-0.001, 0.8, 0.8], + "max": [1.001, 1.1, 1.1] + } + ], + + "NBC": [ + { + "min": [-0.001, 0.25, -0.001], + "max": [1.001, 0.4, 0.1], + "force": [0, -10, 0] + } + ] +} diff --git a/src/SimState.cpp b/src/SimState.cpp index c8296cb..45d9b31 100644 --- a/src/SimState.cpp +++ b/src/SimState.cpp @@ -455,7 +455,6 @@ bool SimState::save_obj_sequence(const std::string& dir_name) { // Create the output directory if it does not exist fs::path dir_path(dir_name); - fs::create_directories(dir_path); bool success = true; for (int i = 0; i < state_sequence.size(); i++) { diff --git a/src/viewer/UIMenu.cpp b/src/viewer/UIMenu.cpp index 644920a..e6019e3 100644 --- a/src/viewer/UIMenu.cpp +++ b/src/viewer/UIMenu.cpp @@ -7,7 +7,7 @@ #include #include - +#include "Util.h" namespace ipc::rigid { void UISimState::draw_menu() { @@ -99,12 +99,7 @@ namespace ipc::rigid { - // if (ImGui::Button("Save OBJ sequence", ImVec2(-1, 0))) { - // std::string dir_name = igl::file_dialog_save(); - // if (dir_name != "") { - // save_obj_sequence(dir_name); - // } - // } + // if (ImGui::Button("Save gltf", ImVec2(-1, 0))) { // std::string filename = igl::file_dialog_save(); @@ -200,6 +195,12 @@ namespace ipc::rigid { std::string fname = igl::file_dialog_save(); save(fname); } + if (ImGui::Button("导出 OBJ 文件", ImVec2(-1, 0))) { + std::string dir_name = ssim::directory_dialog_save(); + if (dir_name != "") { + save_obj_sequence(dir_name); + } + } ImGui::EndChild(); } diff --git a/src/viewer/Util.h b/src/viewer/Util.h new file mode 100644 index 0000000..08226e8 --- /dev/null +++ b/src/viewer/Util.h @@ -0,0 +1,116 @@ +// +// Created by cflin on 4/14/23. +// + +#ifndef EXAMPLE_UTIL_H +#define EXAMPLE_UTIL_H +#include +#include +#include + +#ifdef _WIN32 +#include + #include +#endif +namespace ssim { + + inline std::string directory_dialog_save(){ + const int FILE_DIALOG_MAX_BUFFER = 1024; + char buffer[FILE_DIALOG_MAX_BUFFER]; + buffer[0] = '\0'; + buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0' + +#ifdef __APPLE__ + // For apple use applescript hack + // There is currently a bug in Applescript that strips extensions off + // of chosen existing files in the "choose file name" dialog + // I'm assuming that will be fixed soon + FILE * output = popen( + "osascript -e \"" + " tell application \\\"System Events\\\"\n" + " activate\n" + " set existing_file to choose file name\n" + " end tell\n" + " set existing_file_path to (POSIX path of (existing_file))\n" + "\" 2>/dev/null | tr -d '\n' ","r"); + if (output) + { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } + } +#elif defined _WIN32 + + // Use native windows file dialog box + // (code contributed by Tino Weinkauf) + + OPENFILENAME ofn; // common dialog box structure + char szFile[260]; // buffer for file name + + // Initialize OPENFILENAME + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hwndOwner = NULL;//hwnd; + ofn.lpstrFile = szDir; + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // use the contents of szFile to initialize itself. + ofn.lpstrFile[0] = '\0'; + ofn.nMaxFile = sizeof(szDir); + ofn.lpstrFilter = ""; + ofn.nFilterIndex = 1; + ofn.lpstrFileTitle = NULL; + ofn.nMaxFileTitle = 0; + ofn.lpstrInitialDir = NULL; + ofn.Flags = OFN_PATHMUSTEXIST; + + // Display the Open dialog box. + int pos = 0; + if (GetSaveFileName(&ofn)==TRUE) + { + while(ofn.lpstrFile[pos] != '\0') + { + buffer[pos] = (char)ofn.lpstrFile[pos]; + pos++; + } + buffer[pos] = 0; + } + +#else + // For every other machine type use zenity + FILE * output = popen("/usr/bin/zenity --directory --file-selection --save","r"); + if (output) + { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } + } + + // Replace last '\n' by '\0' + if(strlen(buffer) > 0) + { + buffer[strlen(buffer)-1] = '\0'; + } + +#endif + return std::string(buffer); + } + +} // ssim + +#endif //EXAMPLE_UTIL_H