Improve cancellation of new sla backend

This commit is contained in:
tamasmeszaros 2022-12-07 16:35:07 +01:00
parent 8511a17ad0
commit a141a4c0bc
8 changed files with 151 additions and 92 deletions

View File

@ -1,52 +1,27 @@
#ifndef VOXELIZECSGMESH_HPP #ifndef VOXELIZECSGMESH_HPP
#define VOXELIZECSGMESH_HPP #define VOXELIZECSGMESH_HPP
#include <functional>
#include "CSGMesh.hpp" #include "CSGMesh.hpp"
#include "libslic3r/OpenVDBUtils.hpp" #include "libslic3r/OpenVDBUtils.hpp"
namespace Slic3r { namespace csg { namespace Slic3r { namespace csg {
class VoxelizeParams { using VoxelizeParams = MeshToGridParams;
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;
}
};
// This method can be overriden when a specific CSGPart type supports caching // This method can be overriden when a specific CSGPart type supports caching
// of the voxel grid // of the voxel grid
template<class CSGPartT> template<class CSGPartT>
VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, const VoxelizeParams &params) VoxelGridPtr get_voxelgrid(const CSGPartT &csgpart, VoxelizeParams params)
{ {
const indexed_triangle_set *its = csg::get_mesh(csgpart); const indexed_triangle_set *its = csg::get_mesh(csgpart);
VoxelGridPtr ret; VoxelGridPtr ret;
params.trafo(params.trafo() * csg::get_transform(csgpart));
if (its) if (its)
ret = mesh_to_grid(*csg::get_mesh(csgpart), ret = mesh_to_grid(*csg::get_mesh(csgpart), params);
csg::get_transform(csgpart),
params.voxel_scale(),
params.exterior_bandwidth(),
params.interior_bandwidth());
return ret; return ret;
} }
@ -58,6 +33,9 @@ VoxelGridPtr voxelize_csgmesh(const Range<It> &csgrange,
VoxelGridPtr ret; VoxelGridPtr ret;
for (auto &csgpart : csgrange) { for (auto &csgpart : csgrange) {
if (params.statusfn() && params.statusfn()(-1))
break;
VoxelGridPtr partgrid = get_voxelgrid(csgpart, params); VoxelGridPtr partgrid = get_voxelgrid(csgpart, params);
if (!ret && get_operation(csgpart) == CSGType::Union) { if (!ret && get_operation(csgpart) == CSGType::Union) {

View File

@ -74,11 +74,18 @@ public:
: its{m}, trafo{tr} {} : its{m}, trafo{tr} {}
}; };
struct Interrupter
{
std::function<bool(int)> 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, VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh,
const Transform3f &tr, const MeshToGridParams &params)
float voxel_scale,
float exteriorBandWidth,
float interiorBandWidth)
{ {
// Might not be needed but this is now proven to be working // Might not be needed but this is now proven to be working
openvdb::initialize(); openvdb::initialize();
@ -92,14 +99,22 @@ VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh,
meshparts.erase(it, meshparts.end()); meshparts.erase(it, meshparts.end());
Transform3d trafo = tr.cast<double>(); Transform3d trafo = params.trafo().cast<double>();
trafo.prescale(voxel_scale); trafo.prescale(params.voxel_scale());
Interrupter interrupter{params.statusfn()};
openvdb::FloatGrid::Ptr grid; openvdb::FloatGrid::Ptr grid;
for (auto &m : meshparts) { for (auto &m : meshparts) {
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>( auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
TriangleMeshDataAdapter{m, trafo}, {}, interrupter,
exteriorBandWidth, interiorBandWidth); TriangleMeshDataAdapter{m, trafo},
openvdb::math::Transform{},
params.exterior_bandwidth(),
params.interior_bandwidth());
if (interrupter.wasInterrupted())
break;
if (grid && subgrid) if (grid && subgrid)
openvdb::tools::csgUnion(*grid, *subgrid); openvdb::tools::csgUnion(*grid, *subgrid);
@ -107,16 +122,24 @@ VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh,
grid = std::move(subgrid); grid = std::move(subgrid);
} }
if (interrupter.wasInterrupted())
return {};
if (meshparts.empty()) { if (meshparts.empty()) {
// Splitting failed, fall back to hollow the original mesh // Splitting failed, fall back to hollow the original mesh
grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>( grid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
TriangleMeshDataAdapter{mesh, trafo}, {}, exteriorBandWidth, interrupter,
interiorBandWidth); TriangleMeshDataAdapter{mesh, trafo},
openvdb::math::Transform{},
params.exterior_bandwidth(),
params.interior_bandwidth());
} }
if (interrupter.wasInterrupted())
return {};
grid->transform().preScale(1./voxel_scale); grid->transform().preScale(1./params.voxel_scale());
grid->insertMeta("voxel_scale", openvdb::FloatMetadata(voxel_scale)); grid->insertMeta("voxel_scale", openvdb::FloatMetadata(params.voxel_scale()));
VoxelGridPtr ret = make_voxelgrid(std::move(*grid)); VoxelGridPtr ret = make_voxelgrid(std::move(*grid));

View File

@ -23,6 +23,28 @@ float get_voxel_scale(const VoxelGrid &grid);
VoxelGridPtr clone(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<bool(int)> 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<bool(int)> 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<bool(int)>& statusfn() const noexcept { return m_statusfn; }
};
// Here voxel_scale defines the scaling of voxels which affects the voxel count. // 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 // 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 // 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 // The resulting grid will contain the voxel_scale in its metadata under the
// "voxel_scale" key to be used in grid_to_mesh function. // "voxel_scale" key to be used in grid_to_mesh function.
VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh, VoxelGridPtr mesh_to_grid(const indexed_triangle_set &mesh,
const Transform3f &tr = Transform3f::Identity(), const MeshToGridParams &params = {});
float voxel_scale = 1.f,
float exteriorBandWidth = 3.0f,
float interiorBandWidth = 3.0f);
indexed_triangle_set grid_to_mesh(const VoxelGrid &grid, indexed_triangle_set grid_to_mesh(const VoxelGrid &grid,
double isovalue = 0.0, double isovalue = 0.0,

View File

@ -84,16 +84,24 @@ InteriorPtr generate_interior(const VoxelGrid &mesh,
const JobController &ctl = {}); const JobController &ctl = {});
inline InteriorPtr generate_interior(const indexed_triangle_set &mesh, inline InteriorPtr generate_interior(const indexed_triangle_set &mesh,
const HollowingConfig &hc = {}, const HollowingConfig &hc = {},
const JobController &ctl = {}) const JobController &ctl = {})
{ {
auto voxel_scale = get_voxel_scale(its_volume(mesh), hc); 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)) if (its_is_splittable(mesh))
grid = redistance_grid(*grid, 0.0f, 6.f / voxel_scale, 6.f / voxel_scale); 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<class It> template<class It>
@ -109,17 +117,21 @@ InteriorPtr generate_interior(const Range<It> &csgparts,
auto params = csg::VoxelizeParams{} auto params = csg::VoxelizeParams{}
.voxel_scale(get_voxel_scale(mesh_vol, hc)) .voxel_scale(get_voxel_scale(mesh_vol, hc))
.exterior_bandwidth(1.f) .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); 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()))) if (csgparts.size() > 1 || its_is_splittable(*csg::get_mesh(*csgparts.begin())))
ptr = redistance_grid(*ptr, ptr = redistance_grid(*ptr,
0.0f, 0.0f,
6.f / params.voxel_scale(), 6.f / params.voxel_scale(),
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 // Will do the hollowing

View File

@ -1160,19 +1160,16 @@ inline bool operator==(const VoxelizeParams &a, const VoxelizeParams &b)
return h(a) == h(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]; VoxelGridPtr &ret = part.gridcache[p];
if (!ret) { if (!ret) {
ret = mesh_to_grid(*csg::get_mesh(part), p.trafo(csg::get_transform(part));
csg::get_transform(part), ret = mesh_to_grid(*csg::get_mesh(part), p);
p.voxel_scale(),
p.exterior_bandwidth(),
p.interior_bandwidth());
} }
return clone(*ret); return ret ? clone(*ret) : nullptr;
} }
} // namespace csg } // namespace csg

View File

@ -13,6 +13,8 @@
#include "libslic3r/CSGMesh/CSGMesh.hpp" #include "libslic3r/CSGMesh/CSGMesh.hpp"
#include "libslic3r/OpenVDBUtils.hpp" #include "libslic3r/OpenVDBUtils.hpp"
#include <boost/functional/hash.hpp>
namespace Slic3r { namespace Slic3r {
enum SLAPrintStep : unsigned int { enum SLAPrintStep : unsigned int {
@ -51,11 +53,32 @@ namespace std {
template<> struct hash<Slic3r::csg::VoxelizeParams> { template<> struct hash<Slic3r::csg::VoxelizeParams> {
size_t operator() (const Slic3r::csg::VoxelizeParams &p) const { size_t operator() (const Slic3r::csg::VoxelizeParams &p) const {
std::string str = Slic3r::float_to_string_decimal_point(p.voxel_scale()); int64_t vs = Slic3r::scaled(p.voxel_scale()) >> 10;
str += Slic3r::float_to_string_decimal_point(p.exterior_bandwidth()); int64_t eb = Slic3r::scaled(p.exterior_bandwidth()) >> 10;
str += Slic3r::float_to_string_decimal_point(p.interior_bandwidth()); int64_t ib = Slic3r::scaled(p.interior_bandwidth()) >> 10;
return std::hash<std::string>{}(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<Slic3r::csg::VoxelizeParams> {
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 { namespace csg {
VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, const VoxelizeParams &p); VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, VoxelizeParams p);
} // namespace csg } // namespace csg

View File

@ -41,14 +41,14 @@ namespace Slic3r {
namespace { namespace {
const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS = { const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS = {
5, // slaposAssembly 13, // slaposAssembly
5, // slaposHollowing, 13, // slaposHollowing,
10, // slaposDrillHoles 13, // slaposDrillHoles
10, // slaposObjectSlice, 13, // slaposObjectSlice,
20, // slaposSupportPoints, 13, // slaposSupportPoints,
10, // slaposSupportTree, 13, // slaposSupportTree,
10, // slaposPad, 11, // slaposPad,
30, // slaposSliceSupports, 11, // slaposSliceSupports,
}; };
std::string OBJ_STEP_LABELS(size_t idx) std::string OBJ_STEP_LABELS(size_t idx)
@ -144,13 +144,20 @@ indexed_triangle_set SLAPrint::Steps::generate_preview_vdb(
.exterior_bandwidth(1.f) .exterior_bandwidth(1.f)
.interior_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); 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(); 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; return m;
} }

View File

@ -15,34 +15,34 @@ class SLAPrint::Steps
private: private:
SLAPrint *m_print = nullptr; SLAPrint *m_print = nullptr;
std::mt19937 m_rng; std::mt19937 m_rng;
public: public:
// where the per object operations start and end // where the per object operations start and end
static const constexpr unsigned min_objstatus = 0; static const constexpr unsigned min_objstatus = 0;
static const constexpr unsigned max_objstatus = 50; static const constexpr unsigned max_objstatus = 70;
private: private:
const size_t objcount; const size_t objcount;
// shortcut to initial layer height // shortcut to initial layer height
const double ilhd; const double ilhd;
const float ilh; const float ilh;
const coord_t ilhs; const coord_t ilhs;
// the coefficient that multiplies the per object status values which // 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 // are set up for <0, 100>. They need to be scaled into the whole process
const double objectstep_scale; const double objectstep_scale;
template<class...Args> void report_status(Args&&...args) template<class...Args> void report_status(Args&&...args)
{ {
m_print->m_report_status(*m_print, std::forward<Args>(args)...); m_print->m_report_status(*m_print, std::forward<Args>(args)...);
} }
double current_status() const { return m_print->m_report_status.status(); } double current_status() const { return m_print->m_report_status.status(); }
void throw_if_canceled() const { m_print->throw_if_canceled(); } void throw_if_canceled() const { m_print->throw_if_canceled(); }
bool canceled() const { return m_print->canceled(); } bool canceled() const { return m_print->canceled(); }
void initialize_printer_input(); void initialize_printer_input();
void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o); void apply_printer_corrections(SLAPrintObject &po, SliceOrigin o);
void generate_preview(SLAPrintObject &po, SLAPrintObjectStep step); void generate_preview(SLAPrintObject &po, SLAPrintObjectStep step);
@ -50,7 +50,7 @@ private:
public: public:
explicit Steps(SLAPrint *print); explicit Steps(SLAPrint *print);
void mesh_assembly(SLAPrintObject &po); void mesh_assembly(SLAPrintObject &po);
void hollow_model(SLAPrintObject &po); void hollow_model(SLAPrintObject &po);
void drill_holes (SLAPrintObject &po); void drill_holes (SLAPrintObject &po);
@ -59,20 +59,20 @@ public:
void support_tree(SLAPrintObject& po); void support_tree(SLAPrintObject& po);
void generate_pad(SLAPrintObject& po); void generate_pad(SLAPrintObject& po);
void slice_supports(SLAPrintObject& po); void slice_supports(SLAPrintObject& po);
void merge_slices_and_eval_stats(); void merge_slices_and_eval_stats();
void rasterize(); void rasterize();
void execute(SLAPrintObjectStep step, SLAPrintObject &obj); void execute(SLAPrintObjectStep step, SLAPrintObject &obj);
void execute(SLAPrintStep step); void execute(SLAPrintStep step);
static std::string label(SLAPrintObjectStep step); static std::string label(SLAPrintObjectStep step);
static std::string label(SLAPrintStep step); static std::string label(SLAPrintStep step);
double progressrange(SLAPrintObjectStep step) const; double progressrange(SLAPrintObjectStep step) const;
double progressrange(SLAPrintStep step) const; double progressrange(SLAPrintStep step) const;
}; };
} } // namespace Slic3r
#endif // SLAPRINTSTEPS_HPP #endif // SLAPRINTSTEPS_HPP