mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-08 07:39:10 +08:00
Model fixing through Netfabb service (Windows only):
Model volumes are now fixed one by one, instances & parameters are maintained, it is now possible to fix just a single volume of a multi-part object.
This commit is contained in:
parent
bcab373a54
commit
cd838561ee
@ -385,6 +385,8 @@ public:
|
|||||||
|
|
||||||
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
const Transform3d& get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const { return m_transformation.get_matrix(dont_translate, dont_rotate, dont_scale, dont_mirror); }
|
||||||
|
|
||||||
|
using ModelBase::set_new_unique_id;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Print;
|
friend class Print;
|
||||||
friend class SLAPrint;
|
friend class SLAPrint;
|
||||||
|
@ -2113,31 +2113,10 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
|
|||||||
{
|
{
|
||||||
if (obj_idx < 0)
|
if (obj_idx < 0)
|
||||||
return;
|
return;
|
||||||
|
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
|
||||||
const auto model_object = model.objects[obj_idx];
|
this->object_list_changed();
|
||||||
Model model_fixed;// = new Model();
|
this->update();
|
||||||
fix_model_by_win10_sdk_gui(*model_object, this->fff_print, model_fixed);
|
this->schedule_background_process();
|
||||||
|
|
||||||
auto new_obj_idxs = load_model_objects(model_fixed.objects);
|
|
||||||
if (new_obj_idxs.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(auto new_obj_idx : new_obj_idxs) {
|
|
||||||
auto o = model.objects[new_obj_idx];
|
|
||||||
o->clear_instances();
|
|
||||||
for (auto instance: model_object->instances)
|
|
||||||
o->add_instance(*instance);
|
|
||||||
o->invalidate_bounding_box();
|
|
||||||
|
|
||||||
if (o->volumes.size() == model_object->volumes.size()) {
|
|
||||||
for (int i = 0; i < o->volumes.size(); i++) {
|
|
||||||
o->volumes[i]->config.apply(model_object->volumes[i]->config);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// FIXME restore volumes and their configs, layer_height_ranges, layer_height_profile
|
|
||||||
}
|
|
||||||
|
|
||||||
remove(obj_idx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Plater::priv::set_current_panel(wxPanel* panel)
|
void Plater::priv::set_current_panel(wxPanel* panel)
|
||||||
|
@ -216,7 +216,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
|
|||||||
|
|
||||||
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
|
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
|
||||||
{
|
{
|
||||||
on_progress(L("Exporting the source model"), 20);
|
on_progress(L("Exporting source model"), 20);
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> fileStream;
|
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> fileStream;
|
||||||
hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel);
|
hr = winrt_open_file_stream(boost::nowide::widen(path_src), ABI::Windows::Storage::FileAccessMode::FileAccessMode_Read, fileStream.GetAddressOf(), throw_on_cancel);
|
||||||
@ -239,7 +239,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
|
|||||||
unsigned num_meshes = 0;
|
unsigned num_meshes = 0;
|
||||||
hr = meshes->get_Size(&num_meshes);
|
hr = meshes->get_Size(&num_meshes);
|
||||||
|
|
||||||
on_progress(L("Repairing the model by the Netfabb service"), 40);
|
on_progress(L("Repairing model by the Netfabb service"), 40);
|
||||||
|
|
||||||
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> repairAsync;
|
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncAction> repairAsync;
|
||||||
hr = model->RepairAsync(repairAsync.GetAddressOf());
|
hr = model->RepairAsync(repairAsync.GetAddressOf());
|
||||||
@ -248,7 +248,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
|
|||||||
throw std::runtime_error(L("Mesh repair failed."));
|
throw std::runtime_error(L("Mesh repair failed."));
|
||||||
repairAsync->GetResults();
|
repairAsync->GetResults();
|
||||||
|
|
||||||
on_progress(L("Loading the repaired model"), 60);
|
on_progress(L("Loading repaired model"), 60);
|
||||||
|
|
||||||
// Verify the number of meshes returned after the repair action.
|
// Verify the number of meshes returned after the repair action.
|
||||||
meshes.Reset();
|
meshes.Reset();
|
||||||
@ -316,7 +316,7 @@ public:
|
|||||||
const char* what() const throw() { return "Model repair has been canceled"; }
|
const char* what() const throw() { return "Model repair has been canceled"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result)
|
void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
|
||||||
{
|
{
|
||||||
std::mutex mutex;
|
std::mutex mutex;
|
||||||
std::condition_variable condition;
|
std::condition_variable condition;
|
||||||
@ -329,6 +329,12 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr
|
|||||||
std::atomic<bool> canceled = false;
|
std::atomic<bool> canceled = false;
|
||||||
std::atomic<bool> finished = false;
|
std::atomic<bool> finished = false;
|
||||||
|
|
||||||
|
std::vector<ModelVolume*> volumes;
|
||||||
|
if (volume_idx == -1)
|
||||||
|
volumes = model_object.volumes;
|
||||||
|
else
|
||||||
|
volumes.emplace_back(model_object.volumes[volume_idx]);
|
||||||
|
|
||||||
// Open a progress dialog.
|
// Open a progress dialog.
|
||||||
wxProgressDialog progress_dialog(
|
wxProgressDialog progress_dialog(
|
||||||
_(L("Model fixing")),
|
_(L("Model fixing")),
|
||||||
@ -336,43 +342,64 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr
|
|||||||
100, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
|
100, nullptr, wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
|
||||||
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
|
// Executing the calculation in a background thread, so that the COM context could be created with its own threading model.
|
||||||
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
|
// (It seems like wxWidgets initialize the COM contex as single threaded and we need a multi-threaded context).
|
||||||
bool success = false;
|
bool success = false;
|
||||||
auto on_progress = [&mutex, &condition, &progress](const char *msg, unsigned prcnt) {
|
size_t ivolume = 0;
|
||||||
|
auto on_progress = [&mutex, &condition, &ivolume, &volumes, &progress](const char *msg, unsigned prcnt) {
|
||||||
std::lock_guard<std::mutex> lk(mutex);
|
std::lock_guard<std::mutex> lk(mutex);
|
||||||
progress.message = msg;
|
progress.message = msg;
|
||||||
progress.percent = prcnt;
|
progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
|
||||||
progress.updated = true;
|
progress.updated = true;
|
||||||
condition.notify_all();
|
condition.notify_all();
|
||||||
};
|
};
|
||||||
auto worker_thread = boost::thread([&model_object, &print, &result, on_progress, &success, &canceled, &finished]() {
|
auto worker_thread = boost::thread([&model_object, &volumes, &ivolume, on_progress, &success, &canceled, &finished]() {
|
||||||
try {
|
try {
|
||||||
on_progress(L("Exporting the source model"), 0);
|
std::vector<TriangleMesh> meshes_repaired;
|
||||||
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
meshes_repaired.reserve(volumes.size());
|
||||||
path_src += ".3mf";
|
for (; ivolume < volumes.size(); ++ ivolume) {
|
||||||
Model model;
|
on_progress(L("Exporting source model"), 0);
|
||||||
DynamicPrintConfig config;
|
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||||
model.add_object(model_object);
|
path_src += ".3mf";
|
||||||
if (! Slic3r::store_3mf(path_src.string().c_str(), &model, &config)) {
|
Model model;
|
||||||
|
ModelObject *model_object = model.add_object();
|
||||||
|
model_object->add_volume(*volumes[ivolume]);
|
||||||
|
model_object->add_instance();
|
||||||
|
if (! Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr)) {
|
||||||
|
boost::filesystem::remove(path_src);
|
||||||
|
throw std::runtime_error(L("Export of a temporary 3mf file failed"));
|
||||||
|
}
|
||||||
|
model.clear_objects();
|
||||||
|
model.clear_materials();
|
||||||
|
boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
||||||
|
path_dst += ".3mf";
|
||||||
|
fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress,
|
||||||
|
[&canceled]() { if (canceled) throw RepairCanceledException(); });
|
||||||
boost::filesystem::remove(path_src);
|
boost::filesystem::remove(path_src);
|
||||||
throw std::runtime_error(L("Export of a temporary 3mf file failed"));
|
// PresetBundle bundle;
|
||||||
|
on_progress(L("Loading repaired model"), 80);
|
||||||
|
DynamicPrintConfig config;
|
||||||
|
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &model);
|
||||||
|
boost::filesystem::remove(path_dst);
|
||||||
|
if (! loaded)
|
||||||
|
throw std::runtime_error(L("Import of the repaired 3mf file failed"));
|
||||||
|
if (model.objects.size() == 0)
|
||||||
|
throw std::runtime_error(L("Repaired 3MF file does not contain any object"));
|
||||||
|
if (model.objects.size() > 1)
|
||||||
|
throw std::runtime_error(L("Repaired 3MF file contains more than one object"));
|
||||||
|
if (model.objects.front()->volumes.size() == 0)
|
||||||
|
throw std::runtime_error(L("Repaired 3MF file does not contain any volume"));
|
||||||
|
if (model.objects.front()->volumes.size() > 1)
|
||||||
|
throw std::runtime_error(L("Repaired 3MF file contains more than one volume"));
|
||||||
|
meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh));
|
||||||
}
|
}
|
||||||
model.clear_objects();
|
for (size_t i = 0; i < volumes.size(); ++ i) {
|
||||||
model.clear_materials();
|
volumes[i]->mesh = std::move(meshes_repaired[i]);
|
||||||
boost::filesystem::path path_dst = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
|
volumes[i]->set_new_unique_id();
|
||||||
path_dst += ".3mf";
|
}
|
||||||
fix_model_by_win10_sdk(path_src.string().c_str(), path_dst.string(), on_progress,
|
model_object.invalidate_bounding_box();
|
||||||
[&canceled]() { if (canceled) throw RepairCanceledException(); });
|
-- ivolume;
|
||||||
boost::filesystem::remove(path_src);
|
on_progress(L("Model repair finished"), 100);
|
||||||
// PresetBundle bundle;
|
|
||||||
on_progress(L("Loading the repaired model"), 80);
|
|
||||||
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &result);
|
|
||||||
result.objects[0]->name = boost::filesystem::path(model_object.name).filename().stem().string() + "_fixed";
|
|
||||||
boost::filesystem::remove(path_dst);
|
|
||||||
if (! loaded)
|
|
||||||
throw std::runtime_error(L("Import of the repaired 3mf file failed"));
|
|
||||||
success = true;
|
success = true;
|
||||||
finished = true;
|
finished = true;
|
||||||
on_progress(L("Model repair finished"), 100);
|
|
||||||
} catch (RepairCanceledException & /* ex */) {
|
} catch (RepairCanceledException & /* ex */) {
|
||||||
canceled = true;
|
canceled = true;
|
||||||
finished = true;
|
finished = true;
|
||||||
|
@ -12,12 +12,12 @@ class Print;
|
|||||||
#ifdef HAS_WIN10SDK
|
#ifdef HAS_WIN10SDK
|
||||||
|
|
||||||
extern bool is_windows10();
|
extern bool is_windows10();
|
||||||
extern void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &print, Model &result);
|
extern void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx);
|
||||||
|
|
||||||
#else /* HAS_WIN10SDK */
|
#else /* HAS_WIN10SDK */
|
||||||
|
|
||||||
inline bool is_windows10() { return false; }
|
inline bool is_windows10() { return false; }
|
||||||
inline void fix_model_by_win10_sdk_gui(const ModelObject &, const Print &, Model &) {}
|
inline void fix_model_by_win10_sdk_gui(ModelObject &, int) {}
|
||||||
|
|
||||||
#endif /* HAS_WIN10SDK */
|
#endif /* HAS_WIN10SDK */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user