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
#define VOXELIZECSGMESH_HPP
#include <functional>
#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<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);
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<It> &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) {

View File

@ -74,11 +74,18 @@ public:
: 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,
const Transform3f &tr,
float voxel_scale,
float exteriorBandWidth,
float interiorBandWidth)
const MeshToGridParams &params)
{
// 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<double>();
trafo.prescale(voxel_scale);
Transform3d trafo = params.trafo().cast<double>();
trafo.prescale(params.voxel_scale());
Interrupter interrupter{params.statusfn()};
openvdb::FloatGrid::Ptr grid;
for (auto &m : meshparts) {
auto subgrid = openvdb::tools::meshToVolume<openvdb::FloatGrid>(
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<openvdb::FloatGrid>(
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));

View File

@ -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<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.
// 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 &params = {});
indexed_triangle_set grid_to_mesh(const VoxelGrid &grid,
double isovalue = 0.0,

View File

@ -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<class It>
@ -109,17 +117,21 @@ InteriorPtr generate_interior(const Range<It> &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

View File

@ -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

View File

@ -13,6 +13,8 @@
#include "libslic3r/CSGMesh/CSGMesh.hpp"
#include "libslic3r/OpenVDBUtils.hpp"
#include <boost/functional/hash.hpp>
namespace Slic3r {
enum SLAPrintStep : unsigned int {
@ -51,11 +53,32 @@ namespace std {
template<> struct hash<Slic3r::csg::VoxelizeParams> {
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<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 {
VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, const VoxelizeParams &p);
VoxelGridPtr get_voxelgrid(const CSGPartForStep &part, VoxelizeParams p);
} // namespace csg

View File

@ -41,14 +41,14 @@ namespace Slic3r {
namespace {
const std::array<unsigned, slaposCount> 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;
}

View File

@ -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<class...Args> void report_status(Args&&...args)
{
m_print->m_report_status(*m_print, std::forward<Args>(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