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:
bubnikv 2019-02-03 22:14:34 +01:00
parent bcab373a54
commit cd838561ee
4 changed files with 66 additions and 58 deletions

View File

@ -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); }
using ModelBase::set_new_unique_id;
protected:
friend class Print;
friend class SLAPrint;

View File

@ -2113,31 +2113,10 @@ void Plater::priv::fix_through_netfabb(const int obj_idx, const int vol_idx/* =
{
if (obj_idx < 0)
return;
const auto model_object = model.objects[obj_idx];
Model model_fixed;// = new Model();
fix_model_by_win10_sdk_gui(*model_object, this->fff_print, model_fixed);
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);
fix_model_by_win10_sdk_gui(*model.objects[obj_idx], vol_idx);
this->object_list_changed();
this->update();
this->schedule_background_process();
}
void Plater::priv::set_current_panel(wxPanel* panel)

View File

@ -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);
{
on_progress(L("Exporting the source model"), 20);
on_progress(L("Exporting source model"), 20);
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);
@ -239,7 +239,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
unsigned num_meshes = 0;
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;
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."));
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.
meshes.Reset();
@ -316,7 +316,7 @@ public:
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::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> 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.
wxProgressDialog progress_dialog(
_(L("Model fixing")),
@ -337,22 +343,27 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr
// 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).
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);
progress.message = msg;
progress.percent = prcnt;
progress.percent = (int)floor((float(prcnt) + float(ivolume) * 100.f) / float(volumes.size()));
progress.updated = true;
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 {
on_progress(L("Exporting the source model"), 0);
std::vector<TriangleMesh> meshes_repaired;
meshes_repaired.reserve(volumes.size());
for (; ivolume < volumes.size(); ++ ivolume) {
on_progress(L("Exporting source model"), 0);
boost::filesystem::path path_src = boost::filesystem::temp_directory_path() / boost::filesystem::unique_path();
path_src += ".3mf";
Model model;
DynamicPrintConfig config;
model.add_object(model_object);
if (! Slic3r::store_3mf(path_src.string().c_str(), &model, &config)) {
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"));
}
@ -364,15 +375,31 @@ void fix_model_by_win10_sdk_gui(const ModelObject &model_object, const Print &pr
[&canceled]() { if (canceled) throw RepairCanceledException(); });
boost::filesystem::remove(path_src);
// 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";
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));
}
for (size_t i = 0; i < volumes.size(); ++ i) {
volumes[i]->mesh = std::move(meshes_repaired[i]);
volumes[i]->set_new_unique_id();
}
model_object.invalidate_bounding_box();
-- ivolume;
on_progress(L("Model repair finished"), 100);
success = true;
finished = true;
on_progress(L("Model repair finished"), 100);
} catch (RepairCanceledException & /* ex */) {
canceled = true;
finished = true;

View File

@ -12,12 +12,12 @@ class Print;
#ifdef HAS_WIN10SDK
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 */
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 */