mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-08-31 05:47:02 +00:00
Add read support for Google's Draco (.drc) format.
This commit is contained in:
26
cmake/modules/FindDraco.cmake
Normal file
26
cmake/modules/FindDraco.cmake
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
set(_q "")
|
||||||
|
if(${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
|
||||||
|
set(_q QUIET)
|
||||||
|
set(_quietly TRUE)
|
||||||
|
endif()
|
||||||
|
find_package(${CMAKE_FIND_PACKAGE_NAME} ${${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION} CONFIG ${_q})
|
||||||
|
|
||||||
|
if (NOT ${CMAKE_FIND_PACKAGE_NAME}_FOUND)
|
||||||
|
include(CheckIncludeFileCXX)
|
||||||
|
add_library(draco INTERFACE)
|
||||||
|
target_include_directories(draco INTERFACE include)
|
||||||
|
|
||||||
|
if (_quietly)
|
||||||
|
set(CMAKE_REQUIRED_QUIET ON)
|
||||||
|
endif()
|
||||||
|
CHECK_INCLUDE_FILE_CXX("draco/draco_features.h" HAVE_DRACO_H)
|
||||||
|
|
||||||
|
if (NOT HAVE_DRACO_H)
|
||||||
|
if (${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
|
||||||
|
message(FATAL_ERROR "Draco library not found. Please install the dependency.")
|
||||||
|
elseif(NOT _quietly)
|
||||||
|
message(WARNING "Draco library not found.")
|
||||||
|
endif()
|
||||||
|
endif ()
|
||||||
|
endif()
|
||||||
|
|
||||||
3
deps/CMakeLists.txt
vendored
3
deps/CMakeLists.txt
vendored
@@ -294,6 +294,8 @@ include(CGAL/CGAL.cmake)
|
|||||||
include(NLopt/NLopt.cmake)
|
include(NLopt/NLopt.cmake)
|
||||||
include(libnoise/libnoise.cmake)
|
include(libnoise/libnoise.cmake)
|
||||||
|
|
||||||
|
include(Draco/Draco.cmake)
|
||||||
|
|
||||||
|
|
||||||
# I *think* 1.1 is used for *just* md5 hashing?
|
# I *think* 1.1 is used for *just* md5 hashing?
|
||||||
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
# 3.1 has everything in the right place, but the md5 funcs used are deprecated
|
||||||
@@ -357,6 +359,7 @@ set(_dep_list
|
|||||||
${CURL_PKG}
|
${CURL_PKG}
|
||||||
${WXWIDGETS_PKG}
|
${WXWIDGETS_PKG}
|
||||||
dep_Cereal
|
dep_Cereal
|
||||||
|
dep_Draco
|
||||||
dep_NLopt
|
dep_NLopt
|
||||||
dep_OpenVDB
|
dep_OpenVDB
|
||||||
dep_OpenCSG
|
dep_OpenCSG
|
||||||
|
|||||||
4
deps/Draco/Draco.cmake
vendored
Normal file
4
deps/Draco/Draco.cmake
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
orcaslicer_add_cmake_project(Draco
|
||||||
|
URL https://github.com/google/draco/archive/refs/tags/1.5.7.zip
|
||||||
|
URL_HASH SHA256=27b72ba2d5ff3d0a9814ad40d4cb88f8dc89a35491c0866d952473f8f9416b77
|
||||||
|
)
|
||||||
@@ -133,6 +133,8 @@ set(lisbslic3r_sources
|
|||||||
Format/bbs_3mf.hpp
|
Format/bbs_3mf.hpp
|
||||||
Format/AMF.cpp
|
Format/AMF.cpp
|
||||||
Format/AMF.hpp
|
Format/AMF.hpp
|
||||||
|
Format/DRC.cpp
|
||||||
|
Format/DRC.hpp
|
||||||
Format/OBJ.cpp
|
Format/OBJ.cpp
|
||||||
Format/OBJ.hpp
|
Format/OBJ.hpp
|
||||||
Format/objparser.cpp
|
Format/objparser.cpp
|
||||||
@@ -522,6 +524,7 @@ find_package(OpenCASCADE REQUIRED)
|
|||||||
target_include_directories(libslic3r PUBLIC ${OpenCASCADE_INCLUDE_DIR})
|
target_include_directories(libslic3r PUBLIC ${OpenCASCADE_INCLUDE_DIR})
|
||||||
|
|
||||||
find_package(JPEG REQUIRED)
|
find_package(JPEG REQUIRED)
|
||||||
|
find_package(draco REQUIRED)
|
||||||
|
|
||||||
set(OCCT_LIBS
|
set(OCCT_LIBS
|
||||||
TKXDESTEP
|
TKXDESTEP
|
||||||
@@ -578,6 +581,7 @@ target_link_libraries(libslic3r
|
|||||||
qoi
|
qoi
|
||||||
opencv_world
|
opencv_world
|
||||||
noise::noise
|
noise::noise
|
||||||
|
draco::draco
|
||||||
)
|
)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
|
|||||||
126
src/libslic3r/Format/DRC.cpp
Normal file
126
src/libslic3r/Format/DRC.cpp
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include <draco/compression/decode.h>
|
||||||
|
#include <draco/io/mesh_io.h>
|
||||||
|
#include <draco/mesh/mesh.h>
|
||||||
|
using namespace draco;
|
||||||
|
|
||||||
|
#include "libslic3r/Model.hpp"
|
||||||
|
#include "libslic3r/TriangleMesh.hpp"
|
||||||
|
#include "DRC.hpp"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define DIR_SEPARATOR '\\'
|
||||||
|
#else
|
||||||
|
#define DIR_SEPARATOR '/'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
bool load_drc(const char *path, TriangleMesh *meshptr)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (stat(path, &st)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE *fp = fopen(path, "rb");
|
||||||
|
if (fp == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *data = new char[st.st_size];
|
||||||
|
if (fread(data, 1, st.st_size, fp) != st.st_size) {
|
||||||
|
fclose(fp);
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
DecoderBuffer buffer;
|
||||||
|
buffer.Init(data, st.st_size);
|
||||||
|
|
||||||
|
auto geotype = Decoder::GetEncodedGeometryType(&buffer);
|
||||||
|
if ((!geotype.ok()) || geotype.value() != TRIANGULAR_MESH) {
|
||||||
|
delete[] data;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Decoder decoder;
|
||||||
|
Mesh dracoMesh;
|
||||||
|
Status status = decoder.DecodeBufferToGeometry(&buffer, &dracoMesh);
|
||||||
|
delete[] data;
|
||||||
|
if (!status.ok()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
indexed_triangle_set its;
|
||||||
|
|
||||||
|
const PointAttribute *const positions = dracoMesh.GetNamedAttribute(GeometryAttribute::POSITION);
|
||||||
|
size_t num_vertices = positions->size();
|
||||||
|
its.vertices.reserve(num_vertices);
|
||||||
|
for (AttributeValueIndex i(0); i < num_vertices; ++ i) {
|
||||||
|
float pos[3];
|
||||||
|
positions->ConvertValue<float>(i, 3, pos);
|
||||||
|
its.vertices.emplace_back(pos[0], pos[1], pos[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t num_faces = dracoMesh.num_faces();
|
||||||
|
its.indices.reserve(num_faces);
|
||||||
|
for (FaceIndex i(0); i < num_faces; ++ i) {
|
||||||
|
Mesh::Face face = dracoMesh.face(i);
|
||||||
|
|
||||||
|
its.indices.emplace_back(
|
||||||
|
positions->mapped_index(face[0]).value(),
|
||||||
|
positions->mapped_index(face[1]).value(),
|
||||||
|
positions->mapped_index(face[2]).value()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
*meshptr = TriangleMesh(std::move(its));
|
||||||
|
if (meshptr->volume() < 0)
|
||||||
|
meshptr->flip_triangles();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool load_drc(const char *path, Model *model, const char *object_name_in)
|
||||||
|
{
|
||||||
|
TriangleMesh mesh;
|
||||||
|
|
||||||
|
bool ret = load_drc(path, &mesh);
|
||||||
|
|
||||||
|
if (ret) {
|
||||||
|
std::string object_name;
|
||||||
|
if (object_name_in == nullptr) {
|
||||||
|
const char *last_slash = strrchr(path, DIR_SEPARATOR);
|
||||||
|
object_name.assign((last_slash == nullptr) ? path : last_slash + 1);
|
||||||
|
} else
|
||||||
|
object_name.assign(object_name_in);
|
||||||
|
|
||||||
|
model->add_object(object_name.c_str(), path, std::move(mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool store_drc(const char *path, TriangleMesh *mesh, bool binary)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool store_drc(const char *path, ModelObject *model_object, bool binary)
|
||||||
|
{
|
||||||
|
TriangleMesh mesh = model_object->mesh();
|
||||||
|
return store_drc(path, &mesh, binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool store_drc(const char *path, Model *model, bool binary)
|
||||||
|
{
|
||||||
|
TriangleMesh mesh = model->mesh();
|
||||||
|
return store_drc(path, &mesh, binary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
||||||
20
src/libslic3r/Format/DRC.hpp
Normal file
20
src/libslic3r/Format/DRC.hpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#ifndef slic3r_Format_DRC_hpp_
|
||||||
|
#define slic3r_Format_DRC_hpp_
|
||||||
|
|
||||||
|
namespace Slic3r {
|
||||||
|
|
||||||
|
class TriangleMesh;
|
||||||
|
class ModelObject;
|
||||||
|
class Model;
|
||||||
|
|
||||||
|
// Load a Draco file into a provided model.
|
||||||
|
extern bool load_drc(const char *path, TriangleMesh *meshptr);
|
||||||
|
extern bool load_drc(const char *path, Model *model, const char *object_name = nullptr);
|
||||||
|
|
||||||
|
extern bool store_drc(const char *path, TriangleMesh *mesh, bool binary);
|
||||||
|
extern bool store_drc(const char *path, ModelObject *model_object, bool binary);
|
||||||
|
extern bool store_drc(const char *path, Model *model, bool binary);
|
||||||
|
|
||||||
|
}; // namespace Slic3r
|
||||||
|
|
||||||
|
#endif /* slic3r_Format_DRC_hpp_ */
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "Format/AMF.hpp"
|
#include "Format/AMF.hpp"
|
||||||
#include "Format/svg.hpp"
|
#include "Format/svg.hpp"
|
||||||
|
#include "Format/DRC.hpp"
|
||||||
// BBS
|
// BBS
|
||||||
#include "FaceDetector.hpp"
|
#include "FaceDetector.hpp"
|
||||||
|
|
||||||
@@ -300,6 +301,8 @@ Model Model::read_from_file(const std::string&
|
|||||||
result = load_svg(input_file.c_str(), &model, message);
|
result = load_svg(input_file.c_str(), &model, message);
|
||||||
//BBS: remove the old .amf.xml files
|
//BBS: remove the old .amf.xml files
|
||||||
//else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
//else if (boost::algorithm::iends_with(input_file, ".amf") || boost::algorithm::iends_with(input_file, ".amf.xml"))
|
||||||
|
else if (boost::algorithm::iends_with(input_file, ".drc"))
|
||||||
|
result = load_drc(input_file.c_str(), &model);
|
||||||
else if (boost::algorithm::iends_with(input_file, ".amf"))
|
else if (boost::algorithm::iends_with(input_file, ".amf"))
|
||||||
//BBS: is_xxx is used for is_inches when load amf
|
//BBS: is_xxx is used for is_inches when load amf
|
||||||
result = load_amf(input_file.c_str(), config, config_substitutions, &model, is_xxx);
|
result = load_amf(input_file.c_str(), config, config_substitutions, &model, is_xxx);
|
||||||
|
|||||||
@@ -516,10 +516,10 @@ static const FileWildcards file_wildcards_by_type[FT_SIZE] = {
|
|||||||
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv} },
|
/* FT_GCODE */ { "G-code files"sv, { ".gcode"sv} },
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
/* FT_MODEL */
|
/* FT_MODEL */
|
||||||
{"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv, ".usd"sv, ".usda"sv, ".usdc"sv, ".usdz"sv, ".abc"sv, ".ply"sv}},
|
{"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv, ".usd"sv, ".usda"sv, ".usdc"sv, ".usdz"sv, ".abc"sv, ".ply"sv, ".drc"sv}},
|
||||||
#else
|
#else
|
||||||
/* FT_MODEL */
|
/* FT_MODEL */
|
||||||
{"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv}},
|
{"Supported files"sv, {".3mf"sv, ".stl"sv, ".oltp"sv, ".stp"sv, ".step"sv, ".svg"sv, ".amf"sv, ".obj"sv, ".drc"sv}},
|
||||||
#endif
|
#endif
|
||||||
/* FT_ZIP */ { "ZIP files"sv, { ".zip"sv } },
|
/* FT_ZIP */ { "ZIP files"sv, { ".zip"sv } },
|
||||||
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
|
/* FT_PROJECT */ { "Project files"sv, { ".3mf"sv} },
|
||||||
|
|||||||
@@ -10946,7 +10946,7 @@ void ProjectDropDialog::on_dpi_changed(const wxRect& suggested_rect)
|
|||||||
//BBS: remove GCodeViewer as seperate APP logic
|
//BBS: remove GCodeViewer as seperate APP logic
|
||||||
bool Plater::load_files(const wxArrayString& filenames)
|
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);
|
const std::regex pattern_gcode_drop(".*[.](gcode|g)", std::regex::icase);
|
||||||
|
|
||||||
std::vector<fs::path> normal_paths;
|
std::vector<fs::path> normal_paths;
|
||||||
|
|||||||
Reference in New Issue
Block a user