Add support for Draco (.drc) format (#10681)

* Add read support for Google's Draco (.drc) format.

* Fix build on Linux

* Use boost instead of fstat.

* Switch to boost memory-mapped file to save RAM and potentially improve performance.

* Trim trailing whitespace.

* Initial Draco write support.

Currently always exports with 16-bit precision and speed 0 (best compression).
The back-end function does have arguments to specify them, it's just not hooked into the GUI.

* Add Draco to the About dialogue.

* Fix Linux compile (hopefully)

* Add an option to associate DRC files on Windows.

* Implement a Preferences option to set Draco position quantization bits

* Update src/slic3r/GUI/Preferences.cpp

Co-authored-by: Ian Bassi <ian.bassi@outlook.com>

* Some slight changes to ianalexis's suggestion.

* Implement a create_item_spinctrl() function for numeric inputs, and use that instead of create_item_input().

* Move "bits" to inside the spinctrl box.

* Refactor following yw4z's feedback

* Update src/slic3r/GUI/Preferences.cpp

Co-authored-by: Ian Bassi <ian.bassi@outlook.com>

* Change to 0 bits as the default setting for Draco export precision.

* Change to a lossy checkbox and a bits field with a range of 8-30.

* Proper SpinInput code from yw4z

* Revert "Proper SpinInput code from yw4z"

This reverts commit 7e9c85f31a.

* Revert "Change to a lossy checkbox and a bits field with a range of 8-30."

This reverts commit d642c9bcc0.

* Redo preferences based on SoftFever's feedback

* Refactor to minimize code duplication

* Fix padding

* Improve Draco export quality level tooltip clarity

Clarify that 0 means lossless compression (not uncompressed),
document the valid lossy range (8-30), and better explain the
tradeoff between file size and geometric detail.

---------

Co-authored-by: SoftFever <softfeverever@gmail.com>
Co-authored-by: Noisyfox <timemanager.rick@gmail.com>
Co-authored-by: Ian Bassi <ian.bassi@outlook.com>
This commit is contained in:
Maeyanie
2026-02-06 05:27:17 -05:00
committed by GitHub
parent dffaa5c0a9
commit bb30999673
18 changed files with 396 additions and 12 deletions

View File

@@ -49,6 +49,7 @@
#include "libslic3r/libslic3r.h"
#include "libslic3r/Format/STL.hpp"
#include "libslic3r/Format/DRC.hpp"
#include "libslic3r/Format/STEP.hpp"
#include "libslic3r/Format/AMF.hpp"
//#include "libslic3r/Format/3mf.hpp"
@@ -6967,6 +6968,7 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
wxString wildcard;
switch (file_type) {
case FT_STL:
case FT_DRC:
case FT_AMF:
case FT_3MF:
case FT_GCODE:
@@ -6988,6 +6990,12 @@ wxString Plater::priv::get_export_file(GUI::FileType file_type)
dlg_title = _L("Export STL file:");
break;
}
case FT_DRC:
{
output_file.replace_extension("drc");
dlg_title = _L("Export Draco file:");
break;
}
case FT_AMF:
{
// XXX: Problem on OS X with double extension?
@@ -13685,7 +13693,7 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect)
//BBS: remove GCodeViewer as seperate APP logic
bool Plater::load_files(const wxArrayString& filenames)
{
const std::regex pattern_drop(".*[.](stp|step|stl|oltp|obj|amf|3mf|svg|zip)", std::regex::icase);
const std::regex pattern_drop(".*[.](stp|step|stl|oltp|obj|amf|3mf|svg|zip|drc)", std::regex::icase);
const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase);
std::vector<fs::path> normal_paths;
@@ -14722,10 +14730,22 @@ TriangleMesh Plater::combine_mesh_fff(const ModelObject& mo, int instance_id, st
// BBS export with/without boolean, however, stil merge mesh
#define EXPORT_WITH_BOOLEAN 0
void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
void Plater::export_stl(bool extended, bool selection_only, bool multi_stls, FileType file_type)
{
if (p->model.objects.empty()) { return; }
int quality = 0;
switch (file_type) {
case FT_DRC:
AppConfig* app_config = wxGetApp().app_config;
if (app_config)
quality = stoi(app_config->get("drc_bits"));
else
quality = DRC_BITS_DEFAULT;
break;
}
wxString path;
if (multi_stls) {
wxDirDialog dlg(this, _L("Choose a directory"), from_u8(wxGetApp().app_config->get_last_dir()),
@@ -14734,7 +14754,7 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
path = dlg.GetPath() + "/";
}
} else {
path = p->get_export_file(FT_STL);
path = p->get_export_file(file_type);
}
if (path.empty()) { return; }
const std::string path_u8 = into_u8(path);
@@ -14881,11 +14901,17 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
else
mesh_to_export = mesh_to_export_sla;
auto get_save_file = [](std::string const & dir, std::string const & name) {
auto path = dir + name + ".stl";
auto get_save_file = [file_type](std::string const & dir, std::string const & name) {
std::string ext = "";
switch (file_type) {
case FT_STL: ext = ".stl"; break;
case FT_DRC: ext = ".drc"; break;
}
auto path = dir + name + ext;
int n = 1;
while (boost::filesystem::exists(path))
path = dir + name + "(" + std::to_string(n++) + ").stl";
path = dir + name + "(" + std::to_string(n++) + ")"+ext;
return path;
};
@@ -14918,7 +14944,10 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
auto mesh = mesh_to_export(*object, i.second);
mesh.translate(-object->origin_translation.cast<float>());
Slic3r::store_stl(get_save_file(path_u8, object->name).c_str(), &mesh, true);
switch (file_type) {
case FT_STL: Slic3r::store_stl(get_save_file(path_u8, object->name).c_str(), &mesh, true); break;
case FT_DRC: Slic3r::store_drc(get_save_file(path_u8, object->name).c_str(), &mesh, quality); break;
}
}
return;
}
@@ -14931,12 +14960,19 @@ void Plater::export_stl(bool extended, bool selection_only, bool multi_stls)
for (const ModelObject* o : p->model.objects) {
auto mesh = mesh_to_export(*o, -1);
mesh.translate(-o->origin_translation.cast<float>());
Slic3r::store_stl(get_save_file(path_u8, o->name).c_str(), &mesh, true);
switch (file_type) {
case FT_STL: Slic3r::store_stl(get_save_file(path_u8, o->name).c_str(), &mesh, true); break;
case FT_DRC: Slic3r::store_drc(get_save_file(path_u8, o->name).c_str(), &mesh, quality); break;
}
}
return;
}
Slic3r::store_stl(path_u8.c_str(), &mesh, true);
switch (file_type) {
case FT_STL: Slic3r::store_stl(path_u8.c_str(), &mesh, true); break;
case FT_DRC: Slic3r::store_drc(path_u8.c_str(), &mesh, quality); break;
}
}
//BBS: remove amf export