Improve cancellation of new sla backend
This commit is contained in:
parent
8511a17ad0
commit
a141a4c0bc
@ -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 ¶ms)
|
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) {
|
||||||
|
@ -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 ¶ms)
|
||||||
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));
|
||||||
|
|
||||||
|
@ -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 ¶ms = {});
|
||||||
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,
|
||||||
|
@ -88,12 +88,20 @@ inline InteriorPtr generate_interior(const indexed_triangle_set &mesh,
|
|||||||
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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
|
||||||
|
if (!m.empty())
|
||||||
BOOST_LOG_TRIVIAL(trace) << "Preview gen took: " << bench.getElapsedSec();
|
BOOST_LOG_TRIVIAL(trace) << "Preview gen took: " << bench.getElapsedSec();
|
||||||
|
else
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Preview failed!";
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ private:
|
|||||||
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;
|
||||||
@ -73,6 +73,6 @@ public:
|
|||||||
double progressrange(SLAPrintStep step) const;
|
double progressrange(SLAPrintStep step) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif // SLAPRINTSTEPS_HPP
|
#endif // SLAPRINTSTEPS_HPP
|
||||||
|
Loading…
Reference in New Issue
Block a user