mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-07-11 00:37:51 -06:00
WIP:
* slicing supports * adding the pad geometry * rasterizing the support and pad slices
This commit is contained in:
parent
3613a54e03
commit
e98c83a025
6 changed files with 268 additions and 144 deletions
|
@ -425,6 +425,8 @@ void base_plate(const TriangleMesh &mesh, ExPolygons &output, float h)
|
||||||
|
|
||||||
TriangleMesh upper, lower;
|
TriangleMesh upper, lower;
|
||||||
slicer.cut(h, &upper, &lower);
|
slicer.cut(h, &upper, &lower);
|
||||||
|
|
||||||
|
// TODO: this might be slow
|
||||||
output = lower.horizontal_projection();
|
output = lower.horizontal_projection();
|
||||||
|
|
||||||
for(auto& o : output) o = o.simplify(0.1/SCALING_FACTOR).front();
|
for(auto& o : output) o = o.simplify(0.1/SCALING_FACTOR).front();
|
||||||
|
|
|
@ -168,9 +168,10 @@ Contour3D sphere(double rho, Portion portion = make_portion(0.0, 2.0*PI),
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Contour3D cylinder(double r, double h, size_t steps) {
|
Contour3D cylinder(double r, double h, size_t ssteps) {
|
||||||
Contour3D ret;
|
Contour3D ret;
|
||||||
|
|
||||||
|
auto steps = int(ssteps);
|
||||||
auto& points = ret.points;
|
auto& points = ret.points;
|
||||||
auto& indices = ret.indices;
|
auto& indices = ret.indices;
|
||||||
points.reserve(2*steps);
|
points.reserve(2*steps);
|
||||||
|
@ -275,10 +276,10 @@ struct Head {
|
||||||
mesh.indices.emplace_back(i1s1, i2s2, i1s2);
|
mesh.indices.emplace_back(i1s1, i2s2, i1s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto i1s1 = coord_t(s1.points.size()) - steps;
|
auto i1s1 = coord_t(s1.points.size()) - coord_t(steps);
|
||||||
auto i2s1 = coord_t(s1.points.size()) - 1;
|
auto i2s1 = coord_t(s1.points.size()) - 1;
|
||||||
auto i1s2 = coord_t(s1.points.size());
|
auto i1s2 = coord_t(s1.points.size());
|
||||||
auto i2s2 = coord_t(s1.points.size()) + steps - 1;
|
auto i2s2 = coord_t(s1.points.size()) + coord_t(steps) - 1;
|
||||||
|
|
||||||
mesh.indices.emplace_back(i2s2, i2s1, i1s1);
|
mesh.indices.emplace_back(i2s2, i2s1, i1s1);
|
||||||
mesh.indices.emplace_back(i1s2, i2s2, i1s1);
|
mesh.indices.emplace_back(i1s2, i2s2, i1s1);
|
||||||
|
@ -368,13 +369,13 @@ struct Pillar {
|
||||||
}
|
}
|
||||||
|
|
||||||
indices.reserve(2*steps);
|
indices.reserve(2*steps);
|
||||||
auto offs = steps;
|
int offs = int(steps);
|
||||||
for(int i = 0; i < steps - 1; ++i) {
|
for(int i = 0; i < steps - 1; ++i) {
|
||||||
indices.emplace_back(i, i + offs, offs + i + 1);
|
indices.emplace_back(i, i + offs, offs + i + 1);
|
||||||
indices.emplace_back(i, offs + i + 1, i + 1);
|
indices.emplace_back(i, offs + i + 1, i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto last = steps - 1;
|
int last = int(steps) - 1;
|
||||||
indices.emplace_back(0, last, offs);
|
indices.emplace_back(0, last, offs);
|
||||||
indices.emplace_back(last, offs + last, offs);
|
indices.emplace_back(last, offs + last, offs);
|
||||||
}
|
}
|
||||||
|
@ -499,6 +500,27 @@ struct CompactBridge {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// A wrapper struct around the base pool (pad)
|
||||||
|
struct Pad {
|
||||||
|
// Contour3D mesh;
|
||||||
|
TriangleMesh tmesh;
|
||||||
|
PoolConfig cfg;
|
||||||
|
double zlevel;
|
||||||
|
|
||||||
|
Pad() {}
|
||||||
|
|
||||||
|
Pad(const TriangleMesh& object_support_mesh,
|
||||||
|
double ground_level,
|
||||||
|
const PoolConfig& cfg) : zlevel(ground_level)
|
||||||
|
{
|
||||||
|
ExPolygons basep;
|
||||||
|
base_plate(object_support_mesh, basep);
|
||||||
|
create_base_pool(basep, tmesh, cfg);
|
||||||
|
tmesh.translate(0, 0, float(zlevel));
|
||||||
|
std::cout << "pad ground level " << zlevel << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
EigenMesh3D to_eigenmesh(const Contour3D& cntr) {
|
EigenMesh3D to_eigenmesh(const Contour3D& cntr) {
|
||||||
EigenMesh3D emesh;
|
EigenMesh3D emesh;
|
||||||
|
|
||||||
|
@ -564,7 +586,11 @@ EigenMesh3D to_eigenmesh(const TriangleMesh& tmesh) {
|
||||||
}
|
}
|
||||||
|
|
||||||
EigenMesh3D to_eigenmesh(const ModelObject& modelobj) {
|
EigenMesh3D to_eigenmesh(const ModelObject& modelobj) {
|
||||||
return to_eigenmesh(modelobj.raw_mesh());
|
auto&& rmesh = modelobj.raw_mesh();
|
||||||
|
auto&& ret = to_eigenmesh(rmesh);
|
||||||
|
auto&& bb = rmesh.bounding_box();
|
||||||
|
ret.ground_level = bb.min(Z);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
EigenMesh3D to_eigenmesh(const Model& model) {
|
EigenMesh3D to_eigenmesh(const Model& model) {
|
||||||
|
@ -606,13 +632,12 @@ PointSet support_points(const Model& model) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
PointSet support_points(const ModelObject& modelobject, std::size_t instance_id)
|
PointSet support_points(const ModelObject& modelobject)
|
||||||
{
|
{
|
||||||
PointSet ret(modelobject.sla_support_points.size(), 3);
|
PointSet ret(modelobject.sla_support_points.size(), 3);
|
||||||
long i = 0;
|
long i = 0;
|
||||||
ModelInstance *inst = modelobject.instances[instance_id];
|
|
||||||
for(const Vec3f& msource : modelobject.sla_support_points) {
|
for(const Vec3f& msource : modelobject.sla_support_points) {
|
||||||
ret.row(i++) = model_coord(*inst, msource);
|
ret.row(i++) = msource.cast<double>();
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -643,12 +668,16 @@ class SLASupportTree::Impl {
|
||||||
std::vector<Junction> m_junctions;
|
std::vector<Junction> m_junctions;
|
||||||
std::vector<Bridge> m_bridges;
|
std::vector<Bridge> m_bridges;
|
||||||
std::vector<CompactBridge> m_compact_bridges;
|
std::vector<CompactBridge> m_compact_bridges;
|
||||||
|
Pad m_pad;
|
||||||
|
mutable TriangleMesh meshcache; mutable bool meshcache_valid;
|
||||||
|
mutable double model_height = 0; // the full height of the model
|
||||||
public:
|
public:
|
||||||
float model_height = 0; // the full height of the model
|
double ground_level = 0;
|
||||||
|
|
||||||
template<class...Args> Head& add_head(Args&&... args) {
|
template<class...Args> Head& add_head(Args&&... args) {
|
||||||
m_heads.emplace_back(std::forward<Args>(args)...);
|
m_heads.emplace_back(std::forward<Args>(args)...);
|
||||||
m_heads.back().id = long(m_heads.size() - 1);
|
m_heads.back().id = long(m_heads.size() - 1);
|
||||||
|
meshcache_valid = false;
|
||||||
return m_heads.back();
|
return m_heads.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -661,6 +690,7 @@ public:
|
||||||
head.pillar_id = pillar.id;
|
head.pillar_id = pillar.id;
|
||||||
pillar.start_junction_id = head.id;
|
pillar.start_junction_id = head.id;
|
||||||
pillar.starts_from_head = true;
|
pillar.starts_from_head = true;
|
||||||
|
meshcache_valid = false;
|
||||||
return m_pillars.back();
|
return m_pillars.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -669,6 +699,7 @@ public:
|
||||||
Pillar& p = m_pillars[pillar_id];
|
Pillar& p = m_pillars[pillar_id];
|
||||||
assert(p.starts_from_head && p.start_junction_id > 0 &&
|
assert(p.starts_from_head && p.start_junction_id > 0 &&
|
||||||
p.start_junction_id < m_heads.size() );
|
p.start_junction_id < m_heads.size() );
|
||||||
|
meshcache_valid = false;
|
||||||
return m_heads[p.start_junction_id];
|
return m_heads[p.start_junction_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,18 +707,21 @@ public:
|
||||||
assert(headid >= 0 && headid < m_heads.size());
|
assert(headid >= 0 && headid < m_heads.size());
|
||||||
Head& h = m_heads[headid];
|
Head& h = m_heads[headid];
|
||||||
assert(h.pillar_id > 0 && h.pillar_id < m_pillars.size());
|
assert(h.pillar_id > 0 && h.pillar_id < m_pillars.size());
|
||||||
|
meshcache_valid = false;
|
||||||
return m_pillars[h.pillar_id];
|
return m_pillars[h.pillar_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class...Args> const Junction& add_junction(Args&&... args) {
|
template<class...Args> const Junction& add_junction(Args&&... args) {
|
||||||
m_junctions.emplace_back(std::forward<Args>(args)...);
|
m_junctions.emplace_back(std::forward<Args>(args)...);
|
||||||
m_junctions.back().id = long(m_junctions.size() - 1);
|
m_junctions.back().id = long(m_junctions.size() - 1);
|
||||||
|
meshcache_valid = false;
|
||||||
return m_junctions.back();
|
return m_junctions.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class...Args> const Bridge& add_bridge(Args&&... args) {
|
template<class...Args> const Bridge& add_bridge(Args&&... args) {
|
||||||
m_bridges.emplace_back(std::forward<Args>(args)...);
|
m_bridges.emplace_back(std::forward<Args>(args)...);
|
||||||
m_bridges.back().id = long(m_bridges.size() - 1);
|
m_bridges.back().id = long(m_bridges.size() - 1);
|
||||||
|
meshcache_valid = false;
|
||||||
return m_bridges.back();
|
return m_bridges.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,17 +729,64 @@ public:
|
||||||
const CompactBridge& add_compact_bridge(Args&&...args) {
|
const CompactBridge& add_compact_bridge(Args&&...args) {
|
||||||
m_compact_bridges.emplace_back(std::forward<Args>(args)...);
|
m_compact_bridges.emplace_back(std::forward<Args>(args)...);
|
||||||
m_compact_bridges.back().id = long(m_compact_bridges.size() - 1);
|
m_compact_bridges.back().id = long(m_compact_bridges.size() - 1);
|
||||||
|
meshcache_valid = false;
|
||||||
return m_compact_bridges.back();
|
return m_compact_bridges.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<Head>& heads() const { return m_heads; }
|
const std::vector<Head>& heads() const { return m_heads; }
|
||||||
Head& head(size_t idx) { return m_heads[idx]; }
|
Head& head(size_t idx) { meshcache_valid = false; return m_heads[idx]; }
|
||||||
const std::vector<Pillar>& pillars() const { return m_pillars; }
|
const std::vector<Pillar>& pillars() const { return m_pillars; }
|
||||||
const std::vector<Bridge>& bridges() const { return m_bridges; }
|
const std::vector<Bridge>& bridges() const { return m_bridges; }
|
||||||
const std::vector<Junction>& junctions() const { return m_junctions; }
|
const std::vector<Junction>& junctions() const { return m_junctions; }
|
||||||
const std::vector<CompactBridge>& compact_bridges() const {
|
const std::vector<CompactBridge>& compact_bridges() const {
|
||||||
return m_compact_bridges;
|
return m_compact_bridges;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Pad& create_pad(const TriangleMesh& object_supports,
|
||||||
|
const PoolConfig& cfg) {
|
||||||
|
m_pad = Pad(object_supports, ground_level, cfg);
|
||||||
|
return m_pad;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Pad& pad() const { return m_pad; }
|
||||||
|
|
||||||
|
// WITHOUT THE PAD!!!
|
||||||
|
const TriangleMesh& merged_mesh() const {
|
||||||
|
if(meshcache_valid) return meshcache;
|
||||||
|
|
||||||
|
meshcache = TriangleMesh();
|
||||||
|
|
||||||
|
for(auto& head : heads()) {
|
||||||
|
meshcache.merge(mesh(head.mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& stick : pillars()) {
|
||||||
|
meshcache.merge(mesh(stick.mesh));
|
||||||
|
meshcache.merge(mesh(stick.base));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& j : junctions()) {
|
||||||
|
meshcache.merge(mesh(j.mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& cb : compact_bridges()) {
|
||||||
|
meshcache.merge(mesh(cb.mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto& bs : bridges()) {
|
||||||
|
meshcache.merge(mesh(bs.mesh));
|
||||||
|
}
|
||||||
|
|
||||||
|
BoundingBoxf3&& bb = meshcache.bounding_box();
|
||||||
|
model_height = bb.max(Z);
|
||||||
|
|
||||||
|
meshcache_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double full_height() const {
|
||||||
|
if(!meshcache_valid) merged_mesh();
|
||||||
|
return model_height;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class DistFn>
|
template<class DistFn>
|
||||||
|
@ -908,6 +989,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
using Result = SLASupportTree::Impl;
|
using Result = SLASupportTree::Impl;
|
||||||
|
|
||||||
Result& result = *m_impl;
|
Result& result = *m_impl;
|
||||||
|
result.ground_level = mesh.ground_level;
|
||||||
|
|
||||||
enum Steps {
|
enum Steps {
|
||||||
BEGIN,
|
BEGIN,
|
||||||
|
@ -925,9 +1007,9 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Debug:
|
// Debug:
|
||||||
for(int pn = 0; pn < points.rows(); ++pn) {
|
// for(int pn = 0; pn < points.rows(); ++pn) {
|
||||||
std::cout << "p " << pn << " " << points.row(pn) << std::endl;
|
// std::cout << "p " << pn << " " << points.row(pn) << std::endl;
|
||||||
}
|
// }
|
||||||
|
|
||||||
auto filterfn = [] (
|
auto filterfn = [] (
|
||||||
const SupportConfig& cfg,
|
const SupportConfig& cfg,
|
||||||
|
@ -1119,8 +1201,8 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
const Head& phead = result.pillar_head(pillar.id);
|
const Head& phead = result.pillar_head(pillar.id);
|
||||||
const Head& nextphead = result.pillar_head(nextpillar.id);
|
const Head& nextphead = result.pillar_head(nextpillar.id);
|
||||||
|
|
||||||
double d = 2*pillar.r;
|
// double d = 2*pillar.r;
|
||||||
const Vec3d& pp = pillar.endpoint.cwiseProduct(Vec3d{1, 1, 0});
|
// const Vec3d& pp = pillar.endpoint.cwiseProduct(Vec3d{1, 1, 0});
|
||||||
|
|
||||||
Vec3d sj = phead.junction_point();
|
Vec3d sj = phead.junction_point();
|
||||||
sj(Z) = std::min(sj(Z), nextphead.junction_point()(Z));
|
sj(Z) = std::min(sj(Z), nextphead.junction_point()(Z));
|
||||||
|
@ -1176,10 +1258,13 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
const double hbr = cfg.head_back_radius_mm;
|
const double hbr = cfg.head_back_radius_mm;
|
||||||
const double pradius = cfg.pillar_radius_mm;
|
const double pradius = cfg.pillar_radius_mm;
|
||||||
const double maxbridgelen = cfg.max_bridge_length_mm;
|
const double maxbridgelen = cfg.max_bridge_length_mm;
|
||||||
|
const double gndlvl = emesh.ground_level - cfg.object_elevation_mm;
|
||||||
|
|
||||||
ClusterEl cl_centroids;
|
ClusterEl cl_centroids;
|
||||||
cl_centroids.reserve(gnd_clusters.size());
|
cl_centroids.reserve(gnd_clusters.size());
|
||||||
|
|
||||||
|
std::cout << "gnd_clusters size: " << gnd_clusters.size() << std::endl;
|
||||||
|
|
||||||
SpatIndex pheadindex; // spatial index for the junctions
|
SpatIndex pheadindex; // spatial index for the junctions
|
||||||
for(auto cl : gnd_clusters) {
|
for(auto cl : gnd_clusters) {
|
||||||
// place all the centroid head positions into the index. We will
|
// place all the centroid head positions into the index. We will
|
||||||
|
@ -1201,7 +1286,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
unsigned hid = gndidx[cl[cid]]; // Head index
|
unsigned hid = gndidx[cl[cid]]; // Head index
|
||||||
Head& h = result.head(hid);
|
Head& h = result.head(hid);
|
||||||
h.transform();
|
h.transform();
|
||||||
Vec3d p = h.junction_point(); p(Z) = 0;
|
Vec3d p = h.junction_point(); p(Z) = gndlvl;
|
||||||
|
|
||||||
pheadindex.insert(p, hid);
|
pheadindex.insert(p, hid);
|
||||||
}
|
}
|
||||||
|
@ -1218,7 +1303,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
auto& head = result.head(index_to_heads);
|
auto& head = result.head(index_to_heads);
|
||||||
|
|
||||||
Vec3d startpoint = head.junction_point();
|
Vec3d startpoint = head.junction_point();
|
||||||
auto endpoint = startpoint; endpoint(Z) = 0;
|
auto endpoint = startpoint; endpoint(Z) = gndlvl;
|
||||||
|
|
||||||
// Create the central pillar of the cluster with its base on the
|
// Create the central pillar of the cluster with its base on the
|
||||||
// ground
|
// ground
|
||||||
|
@ -1233,7 +1318,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
// is distributed more effectively on the pillar.
|
// is distributed more effectively on the pillar.
|
||||||
|
|
||||||
auto search_nearest =
|
auto search_nearest =
|
||||||
[&cfg, &result, &emesh, maxbridgelen]
|
[&cfg, &result, &emesh, maxbridgelen, gndlvl]
|
||||||
(SpatIndex& spindex, const Vec3d& jsh)
|
(SpatIndex& spindex, const Vec3d& jsh)
|
||||||
{
|
{
|
||||||
long nearest_id = -1;
|
long nearest_id = -1;
|
||||||
|
@ -1244,7 +1329,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
// (this may happen as the clustering is not perfect)
|
// (this may happen as the clustering is not perfect)
|
||||||
// than we will bridge to this closer pillar
|
// than we will bridge to this closer pillar
|
||||||
|
|
||||||
Vec3d qp(jsh(X), jsh(Y), 0);
|
Vec3d qp(jsh(X), jsh(Y), gndlvl);
|
||||||
auto ne = spindex.nearest(qp, 1).front();
|
auto ne = spindex.nearest(qp, 1).front();
|
||||||
const Head& nearhead = result.heads()[ne.second];
|
const Head& nearhead = result.heads()[ne.second];
|
||||||
|
|
||||||
|
@ -1263,7 +1348,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
}
|
}
|
||||||
|
|
||||||
double d = distance(jp, jn);
|
double d = distance(jp, jn);
|
||||||
if(jn(Z) <= 0 || d > max_len) break;
|
if(jn(Z) <= gndlvl || d > max_len) break;
|
||||||
|
|
||||||
double chkd = ray_mesh_intersect(jp, dirv(jp, jn), emesh);
|
double chkd = ray_mesh_intersect(jp, dirv(jp, jn), emesh);
|
||||||
if(chkd >= d) nearest_id = ne.second;
|
if(chkd >= d) nearest_id = ne.second;
|
||||||
|
@ -1278,7 +1363,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
sidehead.transform();
|
sidehead.transform();
|
||||||
|
|
||||||
Vec3d jsh = sidehead.junction_point();
|
Vec3d jsh = sidehead.junction_point();
|
||||||
Vec3d jp2d = {jsh(X), jsh(Y), 0};
|
// Vec3d jp2d = {jsh(X), jsh(Y), gndlvl};
|
||||||
SpatIndex spindex = pheadindex;
|
SpatIndex spindex = pheadindex;
|
||||||
long nearest_id = search_nearest(spindex, jsh);
|
long nearest_id = search_nearest(spindex, jsh);
|
||||||
|
|
||||||
|
@ -1286,7 +1371,7 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
// to connect the sidehead to the ground
|
// to connect the sidehead to the ground
|
||||||
if(nearest_id < 0) {
|
if(nearest_id < 0) {
|
||||||
// Could not find a pillar, create one
|
// Could not find a pillar, create one
|
||||||
Vec3d jp = jsh; jp(Z) = 0;
|
Vec3d jp = jsh; jp(Z) = gndlvl;
|
||||||
result.add_pillar(sidehead.id, jp, pradius).
|
result.add_pillar(sidehead.id, jp, pradius).
|
||||||
add_base(cfg.base_height_mm, cfg.base_radius_mm);
|
add_base(cfg.base_height_mm, cfg.base_radius_mm);
|
||||||
|
|
||||||
|
@ -1571,28 +1656,12 @@ bool SLASupportTree::generate(const PointSet &points,
|
||||||
|
|
||||||
void SLASupportTree::merged_mesh(TriangleMesh &outmesh) const
|
void SLASupportTree::merged_mesh(TriangleMesh &outmesh) const
|
||||||
{
|
{
|
||||||
const SLASupportTree::Impl& stree = get();
|
outmesh.merge(get().merged_mesh());
|
||||||
|
|
||||||
for(auto& head : stree.heads()) {
|
|
||||||
outmesh.merge(mesh(head.mesh));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& stick : stree.pillars()) {
|
void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const {
|
||||||
outmesh.merge(mesh(stick.mesh));
|
merged_mesh(outmesh);
|
||||||
outmesh.merge(mesh(stick.base));
|
outmesh.merge(get_pad());
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& j : stree.junctions()) {
|
|
||||||
outmesh.merge(mesh(j.mesh));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& cb : stree.compact_bridges()) {
|
|
||||||
outmesh.merge(mesh(cb.mesh));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& bs : stree.bridges()) {
|
|
||||||
outmesh.merge(mesh(bs.mesh));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> void slice_part(const T& inp,
|
template<class T> void slice_part(const T& inp,
|
||||||
|
@ -1616,7 +1685,7 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
|
||||||
{
|
{
|
||||||
if(init_layerh < 0) init_layerh = layerh;
|
if(init_layerh < 0) init_layerh = layerh;
|
||||||
auto& stree = get();
|
auto& stree = get();
|
||||||
const float modelh = stree.model_height;
|
const float modelh = stree.full_height();
|
||||||
|
|
||||||
std::vector<float> heights; heights.reserve(size_t(modelh/layerh) + 1);
|
std::vector<float> heights; heights.reserve(size_t(modelh/layerh) + 1);
|
||||||
for(float h = init_layerh; h <= modelh; h += layerh) {
|
for(float h = init_layerh; h <= modelh; h += layerh) {
|
||||||
|
@ -1640,10 +1709,24 @@ SlicedSupports SLASupportTree::slice(float layerh, float init_layerh) const
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here we should implement the support editing
|
const TriangleMesh &SLASupportTree::add_pad(double min_wall_thickness_mm,
|
||||||
void SLASupportTree::mouse_event(const MouseEvent &)
|
double min_wall_height_mm,
|
||||||
|
double max_merge_distance_mm,
|
||||||
|
double edge_radius_mm) const
|
||||||
{
|
{
|
||||||
|
TriangleMesh mm;
|
||||||
|
merged_mesh(mm);
|
||||||
|
PoolConfig pcfg;
|
||||||
|
// pcfg.min_wall_thickness_mm = min_wall_thickness_mm;
|
||||||
|
// pcfg.min_wall_height_mm = min_wall_height_mm;
|
||||||
|
// pcfg.max_merge_distance_mm = max_merge_distance_mm;
|
||||||
|
// pcfg.edge_radius_mm = edge_radius_mm;
|
||||||
|
return m_impl->create_pad(mm, pcfg).tmesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
const TriangleMesh &SLASupportTree::get_pad() const
|
||||||
|
{
|
||||||
|
return m_impl->pad().tmesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
SLASupportTree::SLASupportTree(const Model& model,
|
SLASupportTree::SLASupportTree(const Model& model,
|
||||||
|
|
|
@ -60,6 +60,10 @@ struct SupportConfig {
|
||||||
|
|
||||||
// The max length of a bridge in mm
|
// The max length of a bridge in mm
|
||||||
double max_bridge_length_mm = 15.0;
|
double max_bridge_length_mm = 15.0;
|
||||||
|
|
||||||
|
// The elevation in Z direction upwards. This is the space between the pad
|
||||||
|
// and the model object's bounding box bottom.
|
||||||
|
double object_elevation_mm = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A Control structure for the support calculation. Consists of the status
|
/// A Control structure for the support calculation. Consists of the status
|
||||||
|
@ -76,6 +80,7 @@ struct Controller {
|
||||||
struct EigenMesh3D {
|
struct EigenMesh3D {
|
||||||
Eigen::MatrixXd V;
|
Eigen::MatrixXd V;
|
||||||
Eigen::MatrixXi F;
|
Eigen::MatrixXi F;
|
||||||
|
double ground_level = 0;
|
||||||
|
|
||||||
// igl crashes with the following data types:
|
// igl crashes with the following data types:
|
||||||
// Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> V;
|
// Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::DontAlign> V;
|
||||||
|
@ -100,7 +105,7 @@ EigenMesh3D to_eigenmesh(const Model& model);
|
||||||
EigenMesh3D to_eigenmesh(const ModelObject& model);
|
EigenMesh3D to_eigenmesh(const ModelObject& model);
|
||||||
|
|
||||||
PointSet support_points(const Model& model);
|
PointSet support_points(const Model& model);
|
||||||
PointSet support_points(const ModelObject& modelobject, size_t instance_id = 0);
|
PointSet support_points(const ModelObject& modelobject);
|
||||||
|
|
||||||
/* ************************************************************************** */
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
@ -111,24 +116,10 @@ public:
|
||||||
SLASupportsStoppedException(): std::runtime_error("") {}
|
SLASupportsStoppedException(): std::runtime_error("") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A simple type carrying mouse event info. For support editing purposes
|
|
||||||
struct MouseEvent {
|
|
||||||
enum Buttons {
|
|
||||||
M_RIGHT, M_LEFT, M_MIDDLE
|
|
||||||
} button;
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
ENGAGE, RELEASE, MOVE
|
|
||||||
} type;
|
|
||||||
|
|
||||||
Vec3d coords;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// The class containing mesh data for the generated supports.
|
/// The class containing mesh data for the generated supports.
|
||||||
class SLASupportTree {
|
class SLASupportTree {
|
||||||
class Impl;
|
class Impl;
|
||||||
std::unique_ptr<Impl> m_impl;
|
std::unique_ptr<Impl> m_impl;
|
||||||
std::function<void()> m_vcallback;
|
|
||||||
|
|
||||||
Impl& get() { return *m_impl; }
|
Impl& get() { return *m_impl; }
|
||||||
const Impl& get() const { return *m_impl; }
|
const Impl& get() const { return *m_impl; }
|
||||||
|
@ -160,20 +151,23 @@ public:
|
||||||
~SLASupportTree();
|
~SLASupportTree();
|
||||||
|
|
||||||
/// Get the whole mesh united into the output TriangleMesh
|
/// Get the whole mesh united into the output TriangleMesh
|
||||||
|
/// WITHOUT THE PAD
|
||||||
void merged_mesh(TriangleMesh& outmesh) const;
|
void merged_mesh(TriangleMesh& outmesh) const;
|
||||||
|
|
||||||
|
void merged_mesh_with_pad(TriangleMesh&) const;
|
||||||
|
|
||||||
/// Get the sliced 2d layers of the support geometry.
|
/// Get the sliced 2d layers of the support geometry.
|
||||||
SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
|
SlicedSupports slice(float layerh, float init_layerh = -1.0) const;
|
||||||
|
|
||||||
/// The function to call when mouse events should be propagated to the
|
/// Adding the "pad" (base pool) under the supports
|
||||||
/// supports for editing
|
const TriangleMesh& add_pad(double min_wall_thickness_mm,
|
||||||
void mouse_event(const MouseEvent&);
|
double min_wall_height_mm,
|
||||||
|
double max_merge_distance_mm,
|
||||||
|
double edge_radius_mm) const;
|
||||||
|
|
||||||
|
/// Get the pad geometry
|
||||||
|
const TriangleMesh& get_pad() const;
|
||||||
|
|
||||||
/// The provided callback will be called if the supports change their shape
|
|
||||||
/// or need to be repainted
|
|
||||||
inline void on_supports_changed(std::function<void()> callback) {
|
|
||||||
m_vcallback = callback;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ void SLAPrint::clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
||||||
const DynamicPrintConfig &config)
|
const DynamicPrintConfig &config_in)
|
||||||
{
|
{
|
||||||
// if (m_objects.empty())
|
// if (m_objects.empty())
|
||||||
// return APPLY_STATUS_UNCHANGED;
|
// return APPLY_STATUS_UNCHANGED;
|
||||||
|
@ -80,6 +80,11 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
||||||
if(m_objects.empty() && model.objects.empty())
|
if(m_objects.empty() && model.objects.empty())
|
||||||
return APPLY_STATUS_UNCHANGED;
|
return APPLY_STATUS_UNCHANGED;
|
||||||
|
|
||||||
|
// Temporary: just to have to correct layer height for the rasterization
|
||||||
|
DynamicPrintConfig config(config_in);
|
||||||
|
config.normalize();
|
||||||
|
auto lh = config.opt<ConfigOptionFloat>("layer_height");
|
||||||
|
|
||||||
// Temporary quick fix, just invalidate everything.
|
// Temporary quick fix, just invalidate everything.
|
||||||
{
|
{
|
||||||
for (SLAPrintObject *print_object : m_objects) {
|
for (SLAPrintObject *print_object : m_objects) {
|
||||||
|
@ -95,6 +100,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model,
|
||||||
// Generate new SLAPrintObjects.
|
// Generate new SLAPrintObjects.
|
||||||
for (ModelObject *model_object : m_model.objects) {
|
for (ModelObject *model_object : m_model.objects) {
|
||||||
auto po = new SLAPrintObject(this, model_object);
|
auto po = new SLAPrintObject(this, model_object);
|
||||||
|
po->m_config.layer_height.set(lh);
|
||||||
m_objects.emplace_back(po);
|
m_objects.emplace_back(po);
|
||||||
for (ModelInstance *oinst : model_object->instances) {
|
for (ModelInstance *oinst : model_object->instances) {
|
||||||
Point tr = Point::new_scale(oinst->get_offset()(X),
|
Point tr = Point::new_scale(oinst->get_offset()(X),
|
||||||
|
@ -138,7 +144,17 @@ void SLAPrint::process()
|
||||||
slicer.slice(heights, &layers, [](){});
|
slicer.slice(heights, &layers, [](){});
|
||||||
};
|
};
|
||||||
|
|
||||||
auto support_points = [](SLAPrintObject&) {
|
auto support_points = [](SLAPrintObject& po) {
|
||||||
|
ModelObject& mo = *po.m_model_object;
|
||||||
|
if(!mo.sla_support_points.empty()) {
|
||||||
|
po.m_supportdata.reset(new SLAPrintObject::SupportData());
|
||||||
|
po.m_supportdata->emesh = sla::to_eigenmesh(mo);
|
||||||
|
po.m_supportdata->support_points = sla::support_points(mo);
|
||||||
|
|
||||||
|
std::cout << "support points copied "
|
||||||
|
<< po.m_supportdata->support_points.rows() << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
// for(SLAPrintObject *po : pobjects) {
|
// for(SLAPrintObject *po : pobjects) {
|
||||||
// TODO: calculate automatic support points
|
// TODO: calculate automatic support points
|
||||||
// po->m_supportdata->slice_cache contains the slices at this point
|
// po->m_supportdata->slice_cache contains the slices at this point
|
||||||
|
@ -149,7 +165,6 @@ void SLAPrint::process()
|
||||||
auto support_tree = [this](SLAPrintObject& po) {
|
auto support_tree = [this](SLAPrintObject& po) {
|
||||||
auto& emesh = po.m_supportdata->emesh;
|
auto& emesh = po.m_supportdata->emesh;
|
||||||
auto& pts = po.m_supportdata->support_points; // nowhere filled yet
|
auto& pts = po.m_supportdata->support_points; // nowhere filled yet
|
||||||
auto& supportd = *po.m_supportdata;
|
|
||||||
try {
|
try {
|
||||||
SupportConfig scfg; // TODO fill or replace with po.m_config
|
SupportConfig scfg; // TODO fill or replace with po.m_config
|
||||||
|
|
||||||
|
@ -161,7 +176,7 @@ void SLAPrint::process()
|
||||||
};
|
};
|
||||||
ctl.stopcondition = [this](){ return canceled(); };
|
ctl.stopcondition = [this](){ return canceled(); };
|
||||||
|
|
||||||
supportd.support_tree_ptr.reset(
|
po.m_supportdata->support_tree_ptr.reset(
|
||||||
new SLASupportTree(pts, emesh, scfg, ctl));
|
new SLASupportTree(pts, emesh, scfg, ctl));
|
||||||
|
|
||||||
} catch(sla::SLASupportsStoppedException&) {
|
} catch(sla::SLASupportsStoppedException&) {
|
||||||
|
@ -171,13 +186,32 @@ void SLAPrint::process()
|
||||||
};
|
};
|
||||||
|
|
||||||
// This step generates the sla base pad
|
// This step generates the sla base pad
|
||||||
auto base_pool = [](SLAPrintObject&) {
|
auto base_pool = [](SLAPrintObject& po) {
|
||||||
|
// this step can only go after the support tree has been created
|
||||||
|
// and before the supports had been sliced. (or the slicing has to be
|
||||||
|
// repeated)
|
||||||
|
if(po.is_step_done(slaposSupportTree) &&
|
||||||
|
po.m_supportdata &&
|
||||||
|
po.m_supportdata->support_tree_ptr)
|
||||||
|
{
|
||||||
|
double wt = po.m_config.pad_wall_thickness.getFloat();
|
||||||
|
double h = po.m_config.pad_wall_height.getFloat();
|
||||||
|
double md = po.m_config.pad_max_merge_distance.getFloat();
|
||||||
|
double er = po.m_config.pad_edge_radius.getFloat();
|
||||||
|
|
||||||
|
po.m_supportdata->support_tree_ptr->add_pad(wt, h, md, er);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Slicing the support geometries similarly to the model slicing procedure
|
// Slicing the support geometries similarly to the model slicing procedure.
|
||||||
auto slice_supports = [](SLAPrintObject&) {
|
// If the pad had been added previously (see step "base_pool" than it will
|
||||||
|
// be part of the slices)
|
||||||
|
auto slice_supports = [ilh](SLAPrintObject& po) {
|
||||||
|
auto& sd = po.m_supportdata;
|
||||||
|
if(sd && sd->support_tree_ptr) {
|
||||||
|
auto lh = float(po.m_config.layer_height.getFloat());
|
||||||
|
sd->support_slices = sd->support_tree_ptr->slice(lh, ilh);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Rasterizing the model objects, and their supports
|
// Rasterizing the model objects, and their supports
|
||||||
|
@ -198,29 +232,49 @@ void SLAPrint::process()
|
||||||
|
|
||||||
// For all print objects, go through its initial layers and place them
|
// For all print objects, go through its initial layers and place them
|
||||||
// into the layers hash
|
// into the layers hash
|
||||||
long long initlyridx = static_cast<long long>(scale_(ilh));
|
// long long initlyridx = static_cast<long long>(scale_(ilh));
|
||||||
for(SLAPrintObject *o : m_objects) {
|
for(SLAPrintObject *o : m_objects) {
|
||||||
auto& oslices = o->m_model_slices;
|
|
||||||
auto& firstlyr = oslices.front();
|
|
||||||
auto& initlevel = levels[initlyridx];
|
|
||||||
initlevel.emplace_back(firstlyr, o->m_instances);
|
|
||||||
|
|
||||||
// now push the support slices as well
|
|
||||||
// TODO
|
|
||||||
|
|
||||||
double lh = o->m_config.layer_height.getFloat();
|
double lh = o->m_config.layer_height.getFloat();
|
||||||
size_t li = 1;
|
std::vector<ExPolygons> & oslices = o->m_model_slices;
|
||||||
for(auto lit = std::next(oslices.begin());
|
for(int i = 0; i < oslices.size(); ++i) {
|
||||||
lit != oslices.end();
|
double h = ilh + i * lh;
|
||||||
++lit)
|
long long lyridx = static_cast<long long>(scale_(h));
|
||||||
{
|
auto& lyrs = levels[lyridx]; // this initializes a new record
|
||||||
double h = ilh + li++ * lh;
|
lyrs.emplace_back(oslices[i], o->m_instances);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(o->m_supportdata) { // deal with the support slices if present
|
||||||
|
auto& sslices = o->m_supportdata->support_slices;
|
||||||
|
|
||||||
|
for(int i = 0; i < sslices.size(); ++i) {
|
||||||
|
double h = ilh + i * lh;
|
||||||
long long lyridx = static_cast<long long>(scale_(h));
|
long long lyridx = static_cast<long long>(scale_(h));
|
||||||
auto& lyrs = levels[lyridx];
|
auto& lyrs = levels[lyridx];
|
||||||
lyrs.emplace_back(*lit, o->m_instances);
|
lyrs.emplace_back(sslices[i], o->m_instances);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// auto& oslices = o->m_model_slices;
|
||||||
|
// auto& firstlyr = oslices.front();
|
||||||
|
// auto& initlevel = levels[initlyridx];
|
||||||
|
// initlevel.emplace_back(firstlyr, o->m_instances);
|
||||||
|
|
||||||
|
// // now push the support slices as well
|
||||||
|
// // TODO
|
||||||
|
|
||||||
|
// double lh = o->m_config.layer_height.getFloat();
|
||||||
|
// size_t li = 1;
|
||||||
|
// for(auto lit = std::next(oslices.begin());
|
||||||
|
// lit != oslices.end();
|
||||||
|
// ++lit)
|
||||||
|
// {
|
||||||
|
// double h = ilh + li++ * lh;
|
||||||
|
// long long lyridx = static_cast<long long>(scale_(h));
|
||||||
|
// auto& lyrs = levels[lyridx];
|
||||||
|
// lyrs.emplace_back(*lit, o->m_instances);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
// collect all the keys
|
// collect all the keys
|
||||||
std::vector<long long> keys; keys.reserve(levels.size());
|
std::vector<long long> keys; keys.reserve(levels.size());
|
||||||
for(auto& e : levels) keys.emplace_back(e.first);
|
for(auto& e : levels) keys.emplace_back(e.first);
|
||||||
|
@ -244,10 +298,11 @@ void SLAPrint::process()
|
||||||
|
|
||||||
// Allocate space for all the layers
|
// Allocate space for all the layers
|
||||||
SLAPrinter& printer = *m_printer;
|
SLAPrinter& printer = *m_printer;
|
||||||
printer.layers(unsigned(levels.size()));
|
auto lvlcnt = unsigned(levels.size());
|
||||||
|
printer.layers(lvlcnt);
|
||||||
|
|
||||||
// procedure to process one height level. This will run in parallel
|
// procedure to process one height level. This will run in parallel
|
||||||
auto process_level = [&keys, &levels, &printer](unsigned level_id) {
|
auto lvlfn = [&keys, &levels, &printer](unsigned level_id) {
|
||||||
LayerRefs& lrange = levels[keys[level_id]];
|
LayerRefs& lrange = levels[keys[level_id]];
|
||||||
|
|
||||||
for(auto& lyrref : lrange) { // for all layers in the current level
|
for(auto& lyrref : lrange) { // for all layers in the current level
|
||||||
|
@ -273,12 +328,10 @@ void SLAPrint::process()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sequential version (for testing)
|
// Sequential version (for testing)
|
||||||
// for(unsigned l = 0; l < levels.size(); ++l) process_level(l);
|
// for(unsigned l = 0; l < lvlcnt; ++l) process_level(l);
|
||||||
|
|
||||||
// Print all the layers in parallel
|
// Print all the layers in parallel
|
||||||
tbb::parallel_for<size_t, decltype(process_level)>(0,
|
tbb::parallel_for<unsigned, decltype(lvlfn)>(0, lvlcnt, lvlfn);
|
||||||
levels.size(),
|
|
||||||
process_level);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
using slaposFn = std::function<void(SLAPrintObject&)>;
|
using slaposFn = std::function<void(SLAPrintObject&)>;
|
||||||
|
@ -333,6 +386,9 @@ void SLAPrint::process()
|
||||||
slapsRasterize, slapsValidate
|
slapsRasterize, slapsValidate
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: enable rasterizing
|
||||||
|
m_stepmask[slapsRasterize] = false;
|
||||||
|
|
||||||
for(size_t s = 0; s < print_program.size(); ++s) {
|
for(size_t s = 0; s < print_program.size(); ++s) {
|
||||||
auto currentstep = printsteps[s];
|
auto currentstep = printsteps[s];
|
||||||
|
|
||||||
|
@ -352,33 +408,39 @@ void SLAPrint::process()
|
||||||
set_status(100, L("Slicing done"));
|
set_status(100, L("Slicing done"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SLAPrint::render_supports(SLASupportRenderer &renderer)
|
|
||||||
{
|
|
||||||
std::cout << "Would show the SLA supports" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
|
SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
|
||||||
Inherited(print),
|
Inherited(print),
|
||||||
m_model_object(model_object),
|
m_model_object(model_object),
|
||||||
m_supportdata(new SupportData()),
|
|
||||||
m_stepmask(slaposCount, true)
|
m_stepmask(slaposCount, true)
|
||||||
{
|
{
|
||||||
m_supportdata->emesh = sla::to_eigenmesh(*m_model_object);
|
|
||||||
m_supportdata->support_points = sla::support_points(*m_model_object);
|
|
||||||
|
|
||||||
std::cout << "support points copied " << m_supportdata->support_points.rows() << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SLAPrintObject::~SLAPrintObject() {}
|
SLAPrintObject::~SLAPrintObject() {}
|
||||||
|
|
||||||
TriangleMesh SLAPrintObject::support_mesh() const
|
TriangleMesh SLAPrintObject::support_mesh() const
|
||||||
{
|
{
|
||||||
return make_cube(10., 10., 10.);
|
TriangleMesh trm;
|
||||||
|
|
||||||
|
if(m_supportdata && m_supportdata->support_tree_ptr)
|
||||||
|
m_supportdata->support_tree_ptr->merged_mesh(trm);
|
||||||
|
|
||||||
|
trm.repair();
|
||||||
|
|
||||||
|
std::cout << "support mesh united and returned" << std::endl;
|
||||||
|
return trm;
|
||||||
|
// return make_cube(10., 10., 10.);
|
||||||
}
|
}
|
||||||
|
|
||||||
TriangleMesh SLAPrintObject::pad_mesh() const
|
TriangleMesh SLAPrintObject::pad_mesh() const
|
||||||
{
|
{
|
||||||
return make_cube(10., 10., 10.);
|
if(!m_supportdata || !m_supportdata->support_tree_ptr) {
|
||||||
|
std::cout << "Empty pad mesh returned.." << std::endl;
|
||||||
|
return TriangleMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: pad mesh is empty here for some reason.
|
||||||
|
return m_supportdata->support_tree_ptr->get_pad();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
|
@ -98,33 +98,6 @@ using PrintObjects = std::vector<SLAPrintObject*>;
|
||||||
|
|
||||||
class TriangleMesh;
|
class TriangleMesh;
|
||||||
|
|
||||||
class SLASupportRenderer {
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~SLASupportRenderer() {}
|
|
||||||
|
|
||||||
enum Buttons {
|
|
||||||
LEFT, RIGHT, MIDDLE
|
|
||||||
};
|
|
||||||
|
|
||||||
enum MType {
|
|
||||||
ENGAGE, RELEASE, HOVER
|
|
||||||
};
|
|
||||||
|
|
||||||
struct MouseEvt {
|
|
||||||
Buttons button; MType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ClickCb = std::function<void(MouseEvt)>;
|
|
||||||
using Mesh = TriangleMesh;
|
|
||||||
|
|
||||||
virtual void add_pillar(const Mesh&, ClickCb on_mouse_evt) = 0;
|
|
||||||
virtual void add_head(const Mesh&, ClickCb on_mouse_evt) = 0;
|
|
||||||
virtual void add_bridge(const Mesh&, ClickCb on_mouse_evt) = 0;
|
|
||||||
virtual void add_junction(const Mesh&, ClickCb on_mouse_evt) = 0;
|
|
||||||
virtual void add_pad(const Mesh&, ClickCb on_mouse_evt) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief This class is the high level FSM for the SLA printing process.
|
* @brief This class is the high level FSM for the SLA printing process.
|
||||||
*
|
*
|
||||||
|
@ -156,11 +129,8 @@ public:
|
||||||
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
ApplyStatus apply(const Model &model, const DynamicPrintConfig &config) override;
|
||||||
void process() override;
|
void process() override;
|
||||||
|
|
||||||
void render_supports(SLASupportRenderer& renderer);
|
|
||||||
|
|
||||||
template<class Fmt> void export_raster(const std::string& fname) {
|
template<class Fmt> void export_raster(const std::string& fname) {
|
||||||
if(m_printer) m_printer->save<Fmt>(fname);
|
if(m_printer) m_printer->save<Fmt>(fname);
|
||||||
std::cout << "Would export the SLA raster" << std::endl;
|
|
||||||
}
|
}
|
||||||
const PrintObjects& objects() const { return m_objects; }
|
const PrintObjects& objects() const { return m_objects; }
|
||||||
|
|
||||||
|
|
|
@ -1871,8 +1871,21 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
||||||
case ptSLA:
|
case ptSLA:
|
||||||
// Update the SLAPrint from the current Model, so that the reload_scene()
|
// Update the SLAPrint from the current Model, so that the reload_scene()
|
||||||
// pulls the correct data.
|
// pulls the correct data.
|
||||||
if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART)
|
// if (this->update_background_process() & UPDATE_BACKGROUND_PROCESS_RESTART)
|
||||||
this->schedule_background_process();
|
// this->schedule_background_process();
|
||||||
|
|
||||||
|
{
|
||||||
|
// for(SLAPrintObject * po: sla_print.objects()) {
|
||||||
|
// TriangleMesh&& suppmesh = po->support_mesh();
|
||||||
|
// if(suppmesh.facets_count() > 0) {
|
||||||
|
// ModelObject* mo = model.add_object();
|
||||||
|
// for(const SLAPrintObject::Instance& inst : po->instances() ) {
|
||||||
|
// mo->add_instance(*(mo->instances[inst.instance_id.id]));
|
||||||
|
// mo->add_volume(suppmesh);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
_3DScene::reload_scene(canvas3D, true);
|
_3DScene::reload_scene(canvas3D, true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue