Improve cancellation of new sla backend
This commit is contained in:
parent
8511a17ad0
commit
a141a4c0bc
@ -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 ¶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<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) {
|
||||
|
@ -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 ¶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<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));
|
||||
|
||||
|
@ -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 ¶ms = {});
|
||||
|
||||
indexed_triangle_set grid_to_mesh(const VoxelGrid &grid,
|
||||
double isovalue = 0.0,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user