diff --git a/src/libslic3r/CSGMesh/VoxelizeCSGMesh.hpp b/src/libslic3r/CSGMesh/VoxelizeCSGMesh.hpp index 9d72e3ea8..003fc2ca0 100644 --- a/src/libslic3r/CSGMesh/VoxelizeCSGMesh.hpp +++ b/src/libslic3r/CSGMesh/VoxelizeCSGMesh.hpp @@ -1,52 +1,27 @@ #ifndef VOXELIZECSGMESH_HPP #define VOXELIZECSGMESH_HPP +#include + #include "CSGMesh.hpp" #include "libslic3r/OpenVDBUtils.hpp" namespace Slic3r { namespace csg { -class VoxelizeParams { - float m_voxel_scale = 1.f; - float m_exterior_bandwidth = 3.0f; - float m_interior_bandwidth = 3.0f; - -public: - float voxel_scale() const noexcept { return m_voxel_scale; } - float exterior_bandwidth() const noexcept { return m_exterior_bandwidth; } - float interior_bandwidth() const noexcept { return m_interior_bandwidth; } - - VoxelizeParams &voxel_scale(float val) noexcept - { - m_voxel_scale = val; - return *this; - } - VoxelizeParams &exterior_bandwidth(float val) noexcept - { - m_exterior_bandwidth = val; - return *this; - } - VoxelizeParams &interior_bandwidth(float val) noexcept - { - m_interior_bandwidth = val; - return *this; - } -}; +using VoxelizeParams = MeshToGridParams; // This method can be overriden when a specific CSGPart type supports caching // of the voxel grid template -VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, const VoxelizeParams ¶ms) +VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, VoxelizeParams params) { const indexed_triangle_set *its = csg::get_mesh(csgpart); VoxelGridPtr ret; + params.trafo(params.trafo() * csg::get_transform(csgpart)); + if (its) - ret = mesh_to_grid(*csg::get_mesh(csgpart), - csg::get_transform(csgpart), - params.voxel_scale(), - params.exterior_bandwidth(), - params.interior_bandwidth()); + ret = mesh_to_grid(*csg::get_mesh(csgpart), params); return ret; } @@ -58,6 +33,9 @@ VoxelGridPtr voxelize_csgmesh(const Range &csgrange, VoxelGridPtr ret; for (auto &csgpart : csgrange) { + if (params.statusfn() && params.statusfn()(-1)) + break; + VoxelGridPtr partgrid = get_voxelgrid(csgpart, params); if (!ret && get_operation(csgpart) == CSGType::Union) { diff --git a/src/libslic3r/OpenVDBUtils.cpp b/src/libslic3r/OpenVDBUtils.cpp index 8ea110000..2a94d38e0 100644 --- a/src/libslic3r/OpenVDBUtils.cpp +++ b/src/libslic3r/OpenVDBUtils.cpp @@ -74,11 +74,18 @@ public: : its{m}, trafo{tr} {} }; +struct Interrupter +{ + std::function statusfn; + + void start(const char* name = nullptr) { (void)name; } + void end() {} + + inline bool wasInterrupted(int percent = -1) { return statusfn(percent); } +}; + VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh, - const Transform3f &tr, - float voxel_scale, - float exteriorBandWidth, - float interiorBandWidth) + const MeshToGridParams ¶ms) { // Might not be needed but this is now proven to be working openvdb::initialize(); @@ -92,14 +99,22 @@ VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh, meshparts.erase(it, meshparts.end()); - Transform3d trafo = tr.cast(); - trafo.prescale(voxel_scale); + Transform3d trafo = params.trafo().cast(); + trafo.prescale(params.voxel_scale()); + + Interrupter interrupter{params.statusfn()}; openvdb::FloatGrid::Ptr grid; for (auto &m : meshparts) { auto subgrid = openvdb::tools::meshToVolume( - TriangleMeshDataAdapter{m, trafo}, {}, - exteriorBandWidth, interiorBandWidth); + interrupter, + TriangleMeshDataAdapter{m, trafo}, + openvdb::math::Transform{}, + params.exterior_bandwidth(), + params.interior_bandwidth()); + + if (interrupter.wasInterrupted()) + break; if (grid && subgrid) openvdb::tools::csgUnion(*grid, *subgrid); @@ -107,16 +122,24 @@ VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh, grid = std::move(subgrid); } + if (interrupter.wasInterrupted()) + return {}; + if (meshparts.empty()) { // Splitting failed, fall back to hollow the original mesh grid = openvdb::tools::meshToVolume( - TriangleMeshDataAdapter{mesh, trafo}, {}, exteriorBandWidth, - interiorBandWidth); + interrupter, + TriangleMeshDataAdapter{mesh, trafo}, + openvdb::math::Transform{}, + params.exterior_bandwidth(), + params.interior_bandwidth()); } + if (interrupter.wasInterrupted()) + return {}; - grid->transform().preScale(1./voxel_scale); - grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale)); + grid->transform().preScale(1./params.voxel_scale()); + grid->insertMeta("voxel_scale", openvdb::FloatMetadata(params.voxel_scale())); VoxelGridPtr ret = make_voxelgrid(std::move(*grid)); diff --git a/src/libslic3r/OpenVDBUtils.hpp b/src/libslic3r/OpenVDBUtils.hpp index 959cd854d..cb857020f 100644 --- a/src/libslic3r/OpenVDBUtils.hpp +++ b/src/libslic3r/OpenVDBUtils.hpp @@ -23,6 +23,28 @@ float get_voxel_scale(const VoxelGrid &grid); VoxelGridPtr clone(const VoxelGrid &grid); +class MeshToGridParams { + Transform3f m_tr = Transform3f::Identity(); + float m_voxel_scale = 1.f; + float m_exteriorBandWidth = 3.0f; + float m_interiorBandWidth = 3.0f; + + std::function m_statusfn; + +public: + MeshToGridParams & trafo(const Transform3f &v) { m_tr = v; return *this; } + MeshToGridParams & voxel_scale(float v) { m_voxel_scale = v; return *this; } + MeshToGridParams & exterior_bandwidth(float v) { m_exteriorBandWidth = v; return *this; } + MeshToGridParams & interior_bandwidth(float v) { m_interiorBandWidth = v; return *this; } + MeshToGridParams & statusfn(std::function fn) { m_statusfn = fn; return *this; } + + const Transform3f& trafo() const noexcept { return m_tr; } + float voxel_scale() const noexcept { return m_voxel_scale; } + float exterior_bandwidth() const noexcept { return m_exteriorBandWidth; } + float interior_bandwidth() const noexcept { return m_interiorBandWidth; } + const std::function& statusfn() const noexcept { return m_statusfn; } +}; + // Here voxel_scale defines the scaling of voxels which affects the voxel count. // 1.0 value means a voxel for every unit cube. 2 means the model is scaled to // be 2x larger and the voxel count is increased by the increment in the scaled @@ -31,10 +53,7 @@ VoxelGridPtr clone(const VoxelGrid &grid); // The resulting grid will contain the voxel_scale in its metadata under the // "voxel_scale" key to be used in grid_to_mesh function. VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh, - const Transform3f &tr = Transform3f::Identity(), - float voxel_scale = 1.f, - float exteriorBandWidth = 3.0f, - float interiorBandWidth = 3.0f); + const MeshToGridParams ¶ms = {}); indexed_triangle_set grid_to_mesh(const VoxelGrid &grid, double isovalue = 0.0, diff --git a/src/libslic3r/SLA/Hollowing.hpp b/src/libslic3r/SLA/Hollowing.hpp index 6ff4660ba..bcc26981e 100644 --- a/src/libslic3r/SLA/Hollowing.hpp +++ b/src/libslic3r/SLA/Hollowing.hpp @@ -84,16 +84,24 @@ InteriorPtr generate_interior(const VoxelGrid &mesh, const JobController &ctl = {}); inline InteriorPtr generate_interior(const indexed_triangle_set &mesh, - const HollowingConfig &hc = {}, - const JobController &ctl = {}) + const HollowingConfig &hc = {}, + const JobController &ctl = {}) { auto voxel_scale = get_voxel_scale(its_volume(mesh), hc); - auto grid = mesh_to_grid(mesh, Transform3f::Identity(), voxel_scale, 1.f, 1.f); + auto statusfn = [&ctl](int){ return ctl.stopcondition && ctl.stopcondition(); }; + auto grid = mesh_to_grid(mesh, MeshToGridParams{} + .voxel_scale(voxel_scale) + .exterior_bandwidth(1.f) + .interior_bandwidth(1.f) + .statusfn(statusfn)); + + if (!grid || (ctl.stopcondition && ctl.stopcondition())) + return {}; if (its_is_splittable(mesh)) grid = redistance_grid(*grid, 0.0f, 6.f / voxel_scale, 6.f / voxel_scale); - return generate_interior(*grid, hc, ctl); + return grid ? generate_interior(*grid, hc, ctl) : InteriorPtr{}; } template @@ -109,17 +117,21 @@ InteriorPtr generate_interior(const Range &csgparts, auto params = csg::VoxelizeParams{} .voxel_scale(get_voxel_scale(mesh_vol, hc)) .exterior_bandwidth(1.f) - .interior_bandwidth(1.f); + .interior_bandwidth(1.f) + .statusfn([&ctl](int){ return ctl.stopcondition && ctl.stopcondition(); }); auto ptr = csg::voxelize_csgmesh(csgparts, params); + if (!ptr || (ctl.stopcondition && ctl.stopcondition())) + return {}; + if (csgparts.size() > 1 || its_is_splittable(*csg::get_mesh(*csgparts.begin()))) ptr = redistance_grid(*ptr, 0.0f, 6.f / params.voxel_scale(), 6.f / params.voxel_scale()); - return generate_interior(*ptr, hc, ctl); + return ptr ? generate_interior(*ptr, hc, ctl) : InteriorPtr{}; } // Will do the hollowing diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index b8000f384..fdb264b5e 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -1160,19 +1160,16 @@ inline bool operator==(const VoxelizeParams &a, const VoxelizeParams &b) return h(a) == h(b); } -VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, const VoxelizeParams &p) +VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, VoxelizeParams p) { VoxelGridPtr &ret = part.gridcache[p]; if (!ret) { - ret = mesh_to_grid(*csg::get_mesh(part), - csg::get_transform(part), - p.voxel_scale(), - p.exterior_bandwidth(), - p.interior_bandwidth()); + p.trafo(csg::get_transform(part)); + ret = mesh_to_grid(*csg::get_mesh(part), p); } - return clone(*ret); + return ret ? clone(*ret) : nullptr; } } // namespace csg diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index ca74cb391..37aeb7b1c 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -13,6 +13,8 @@ #include "libslic3r/CSGMesh/CSGMesh.hpp" #include "libslic3r/OpenVDBUtils.hpp" +#include + namespace Slic3r { enum SLAPrintStep : unsigned int { @@ -51,11 +53,32 @@ namespace std { template<> struct hash { size_t operator() (const Slic3r::csg::VoxelizeParams &p) const { - std::string str = Slic3r::float_to_string_decimal_point(p.voxel_scale()); - str += Slic3r::float_to_string_decimal_point(p.exterior_bandwidth()); - str += Slic3r::float_to_string_decimal_point(p.interior_bandwidth()); + int64_t vs = Slic3r::scaled(p.voxel_scale()) >> 10; + int64_t eb = Slic3r::scaled(p.exterior_bandwidth()) >> 10; + int64_t ib = Slic3r::scaled(p.interior_bandwidth()) >> 10; - return std::hash{}(str); + size_t h = 0; + boost::hash_combine(h, vs); + boost::hash_combine(h, eb); + boost::hash_combine(h, ib); + + return h; + } +}; + +template<> struct equal_to { + size_t operator() (const Slic3r::csg::VoxelizeParams &p1, + const Slic3r::csg::VoxelizeParams &p2) const { + + int64_t vs1 = Slic3r::scaled(p1.voxel_scale()) >> 10; + int64_t eb1 = Slic3r::scaled(p1.exterior_bandwidth()) >> 10; + int64_t ib1 = Slic3r::scaled(p1.interior_bandwidth()) >> 10; + + int64_t vs2 = Slic3r::scaled(p2.voxel_scale()) >> 10; + int64_t eb2 = Slic3r::scaled(p2.exterior_bandwidth()) >> 10; + int64_t ib2 = Slic3r::scaled(p2.interior_bandwidth()) >> 10; + + return vs1 == vs2 && eb1 == eb2 && ib1 == ib2; } }; @@ -91,7 +114,7 @@ struct CSGPartForStep : public csg::CSGPart namespace csg { -VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, const VoxelizeParams &p); +VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, VoxelizeParams p); } // namespace csg diff --git a/src/libslic3r/SLAPrintSteps.cpp b/src/libslic3r/SLAPrintSteps.cpp index 7989e9044..6c26c6f7b 100644 --- a/src/libslic3r/SLAPrintSteps.cpp +++ b/src/libslic3r/SLAPrintSteps.cpp @@ -41,14 +41,14 @@ namespace Slic3r { namespace { const std::array OBJ_STEP_LEVELS = { - 5, // slaposAssembly - 5, // slaposHollowing, - 10, // slaposDrillHoles - 10, // slaposObjectSlice, - 20, // slaposSupportPoints, - 10, // slaposSupportTree, - 10, // slaposPad, - 30, // slaposSliceSupports, + 13, // slaposAssembly + 13, // slaposHollowing, + 13, // slaposDrillHoles + 13, // slaposObjectSlice, + 13, // slaposSupportPoints, + 13, // slaposSupportTree, + 11, // slaposPad, + 11, // slaposSliceSupports, }; std::string OBJ_STEP_LABELS(size_t idx) @@ -144,13 +144,20 @@ indexed_triangle_set SLAPrint::Steps::generate_preview_vdb( .exterior_bandwidth(1.f) .interior_bandwidth(1.f); + voxparams.statusfn([&po](int){ + return po.m_print->cancel_status() != CancelStatus::NOT_CANCELED; + }); + auto grid = csg::voxelize_csgmesh(range(po.m_mesh_to_slice), voxparams); - indexed_triangle_set m = grid_to_mesh(*grid); + auto m = grid ? grid_to_mesh(*grid) : indexed_triangle_set{}; bench.stop(); - BOOST_LOG_TRIVIAL(trace) << "Preview gen took: " << bench.getElapsedSec(); + if (!m.empty()) + BOOST_LOG_TRIVIAL(trace) << "Preview gen took: " << bench.getElapsedSec(); + else + BOOST_LOG_TRIVIAL(error) << "Preview failed!"; return m; } diff --git a/src/libslic3r/SLAPrintSteps.hpp b/src/libslic3r/SLAPrintSteps.hpp index 3d63cbbad..a1b3ef42d 100644 --- a/src/libslic3r/SLAPrintSteps.hpp +++ b/src/libslic3r/SLAPrintSteps.hpp @@ -15,34 +15,34 @@ class SLAPrint::Steps private: SLAPrint *m_print = nullptr; std::mt19937 m_rng; - -public: + +public: // where the per object operations start and end - static const constexpr unsigned min_objstatus = 0; - static const constexpr unsigned max_objstatus = 50; - + static const constexpr unsigned min_objstatus = 0; + static const constexpr unsigned max_objstatus = 70; + private: const size_t objcount; - + // shortcut to initial layer height const double ilhd; const float ilh; const coord_t ilhs; - + // the coefficient that multiplies the per object status values which // are set up for <0, 100>. They need to be scaled into the whole process const double objectstep_scale; - + template void report_status(Args&&...args) { m_print->m_report_status(*m_print, std::forward(args)...); } - + double current_status() const { return m_print->m_report_status.status(); } void throw_if_canceled() const { m_print->throw_if_canceled(); } bool canceled() const { return m_print->canceled(); } void initialize_printer_input(); - + void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o); void generate_preview(SLAPrintObject &po, SLAPrintObjectStep step); @@ -50,7 +50,7 @@ private: public: explicit Steps(SLAPrint *print); - + void mesh_assembly(SLAPrintObject &po); void hollow_model(SLAPrintObject &po); void drill_holes (SLAPrintObject &po); @@ -59,20 +59,20 @@ public: void support_tree(SLAPrintObject& po); void generate_pad(SLAPrintObject& po); void slice_supports(SLAPrintObject& po); - + void merge_slices_and_eval_stats(); void rasterize(); - + void execute(SLAPrintObjectStep step, SLAPrintObject &obj); void execute(SLAPrintStep step); - + static std::string label(SLAPrintObjectStep step); static std::string label(SLAPrintStep step); - + double progressrange(SLAPrintObjectStep step) const; double progressrange(SLAPrintStep step) const; }; -} +} // namespace Slic3r #endif // SLAPRINTSTEPS_HPP