From 57e28b53f24670e5867958ff95ea9e1ba0cd6d4e Mon Sep 17 00:00:00 2001 From: tamasmeszaros <meszaros.q@gmail.com> Date: Tue, 26 Mar 2019 10:57:45 +0100 Subject: [PATCH] Further refactor and simplification of slice index and print data. --- src/libslic3r/SLAPrint.cpp | 85 ++++++++++++++------------ src/libslic3r/SLAPrint.hpp | 108 +++++++++++++++++----------------- src/slic3r/GUI/GLCanvas3D.cpp | 8 +-- 3 files changed, 105 insertions(+), 96 deletions(-) diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index 03dd6045c..e4b45d9a4 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -698,7 +698,7 @@ void SLAPrint::process() id < po.m_model_slices.size() && mit != po.m_slice_index.end(); id++) { - mit->set_model_slice_idx(id); ++mit; + mit->set_model_slice_idx(po, id); ++mit; } }; @@ -894,7 +894,7 @@ void SLAPrint::process() i < sd->support_slices.size() && i < po.m_slice_index.size(); ++i) { - po.m_slice_index[i].set_support_slice_idx(i); + po.m_slice_index[i].set_support_slice_idx(po, i); } }; @@ -924,7 +924,7 @@ void SLAPrint::process() for(SLAPrintObject * o : m_objects) { coord_t gndlvl = o->get_slice_index().front().print_level() - ilhs; - for(auto& slicerecord : o->get_slice_index()) { + for(const SliceRecord& slicerecord : o->get_slice_index()) { coord_t lvlid = slicerecord.print_level() - gndlvl; // Neat trick to round the layer levels to the grid. @@ -932,21 +932,13 @@ void SLAPrint::process() auto it = std::lower_bound(m_printer_input.begin(), m_printer_input.end(), - LayerRefs(lvlid)); + PrintLayer(lvlid)); if(it == m_printer_input.end() || it->level != lvlid) - it = m_printer_input.insert(it, LayerRefs(lvlid)); + it = m_printer_input.insert(it, PrintLayer(lvlid)); - auto& lyrs = *it; - const ExPolygons& objslices = o->get_slices_from_record(slicerecord, soModel); - const ExPolygons& supslices = o->get_slices_from_record(slicerecord, soSupport); - - if(!objslices.empty()) - lyrs.refs.emplace_back(objslices, o->instances()); - - if(!supslices.empty()) - lyrs.refs.emplace_back(supslices, o->instances()); + it->slices.emplace_back(std::cref(slicerecord)); } } @@ -998,25 +990,40 @@ void SLAPrint::process() { if(canceled()) return; - LayerRefs& lrange = m_printer_input[level_id]; + PrintLayer& lrange = m_printer_input[level_id]; // Switch to the appropriate layer in the printer printer.begin_layer(level_id); - for(auto& lyrref : lrange.refs) { // for all layers in the current level + for(const SliceRecord& slrecord : lrange.slices) + { // for all layers in the current level + if(canceled()) break; - const Layer& sl = lyrref.lref; // get the layer reference - const LayerCopies& copies = lyrref.copies; + + // get the layer reference + const ExPolygons& objslice = slrecord.get_slice(soModel); + const ExPolygons& supslice = slrecord.get_slice(soModel); + const SLAPrintObject *po = slrecord.print_obj(); + assert(po != nullptr); // Draw all the polygons in the slice to the actual layer. - for(auto& cp : copies) { - for(ExPolygon slice : sl) { + for(const SLAPrintObject::Instance& tr : po->instances()) { + for(ExPolygon poly : objslice) { // The order is important here: // apply rotation before translation... - slice.rotate(double(cp.rotation)); - slice.translate(cp.shift(X), cp.shift(Y)); - if(flpXY) swapXY(slice); - printer.draw_polygon(slice, level_id); + poly.rotate(double(tr.rotation)); + poly.translate(tr.shift(X), tr.shift(Y)); + if(flpXY) swapXY(poly); + printer.draw_polygon(poly, level_id); + } + + for(ExPolygon poly : supslice) { + // The order is important here: + // apply rotation before translation... + poly.rotate(double(tr.rotation)); + poly.translate(tr.shift(X), tr.shift(Y)); + if(flpXY) swapXY(poly); + printer.draw_polygon(poly, level_id); } } } @@ -1026,11 +1033,13 @@ void SLAPrint::process() // Status indication guarded with the spinlock auto st = ist + unsigned(sd*level_id*slot/m_printer_input.size()); - { std::lock_guard<SpinMutex> lck(slck); - if( st > pst) { - report_status(*this, int(st), PRINT_STEP_LABELS[slapsRasterize]); - pst = st; - } + { + std::lock_guard<SpinMutex> lck(slck); + if( st > pst) { + report_status(*this, int(st), + PRINT_STEP_LABELS[slapsRasterize]); + pst = st; + } } }; @@ -1290,11 +1299,11 @@ void SLAPrint::fill_statistics() record = &slr; } - const ExPolygons &modelslices = po->get_slices_from_record(*record, soModel); + const ExPolygons &modelslices = record->get_slice(soModel); if (!modelslices.empty()) append(model_polygons, get_all_polygons(modelslices, po->instances())); - const ExPolygons &supportslices = po->get_slices_from_record(*record, soSupport); + const ExPolygons &supportslices = record->get_slice(soSupport); if (!supportslices.empty()) append(supports_polygons, get_all_polygons(supportslices, po->instances())); } @@ -1515,15 +1524,15 @@ const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const return m_supportdata->support_slices; } -const ExPolygons &SLAPrintObject::get_slices_from_record( - const SliceRecord &rec, - SliceOrigin o) const +const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const { - size_t idx = o == soModel ? rec.get_model_slice_idx() : - rec.get_support_slice_idx(); + size_t idx = o == soModel ? m_model_slices_idx : + m_support_slices_idx; - const std::vector<ExPolygons>& v = o == soModel? get_model_slices() : - get_support_slices(); + if(m_po == nullptr) return EMPTY_SLICE; + + const std::vector<ExPolygons>& v = o == soModel? m_po->get_model_slices() : + m_po->get_support_slices(); if(idx >= v.size()) return EMPTY_SLICE; diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 42317aa2e..6947cc80d 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -38,8 +38,9 @@ using _SLAPrintObjectBase = enum SliceOrigin { soSupport, soModel }; +class SLAPrintObject; + // The public Slice record structure. It corresponds to one printable layer. -// To get the sliced polygons, use SLAPrintObject::get_slices_from_record class SliceRecord { public: // this will be the max limit of size_t @@ -54,6 +55,7 @@ private: size_t m_model_slices_idx = NONE; size_t m_support_slices_idx = NONE; + const SLAPrintObject *m_po = nullptr; public: @@ -61,38 +63,28 @@ public: m_print_z(key), m_slice_z(slicez), m_height(height) {} // The key will be the integer height level of the top of the layer. - inline coord_t print_level() const { return m_print_z; } + coord_t print_level() const { return m_print_z; } // Returns the exact floating point Z coordinate of the slice - inline float slice_level() const { return m_slice_z; } + float slice_level() const { return m_slice_z; } // Returns the current layer height - inline float layer_height() const { return m_height; } + float layer_height() const { return m_height; } bool is_valid() const { return std::isnan(m_slice_z); } - template <class T> inline T level() const { - static_assert(std::is_integral<T>::value || - std::is_floating_point<T>::value, - "Slice record level is only valid for numeric types!"); - if (std::is_integral<T>::value) return T(print_level()); - else return T(slice_level()); - } - - template <class T> inline static SliceRecord create(T val) { - static_assert(std::is_integral<T>::value || - std::is_floating_point<T>::value, - "Slice record level is only valid for numeric types!"); - if (std::is_integral<T>::value) return { coord_t(val), 0.f, 0.f }; - else return { 0, float(val), 0.f }; - } + const SLAPrintObject* print_obj() const { return m_po; } // Methods for setting the indices into the slice vectors. - void set_model_slice_idx(size_t id) { m_model_slices_idx = id; } - void set_support_slice_idx(size_t id) { m_support_slices_idx = id; } + void set_model_slice_idx(const SLAPrintObject &po, size_t id) { + m_po = &po; m_model_slices_idx = id; + } - inline size_t get_model_slice_idx() const { return m_model_slices_idx; } - inline size_t get_support_slice_idx() const { return m_support_slices_idx; } + void set_support_slice_idx(const SLAPrintObject& po, size_t id) { + m_po = &po; m_support_slices_idx = id; + } + + const ExPolygons& get_slice(SliceOrigin o) const; }; @@ -153,6 +145,16 @@ public: private: + template <class T> inline static T level(const SliceRecord& sr) { + static_assert(std::is_arithmetic<T>::value, "Arithmetic only!"); + return std::is_integral<T>::value ? T(sr.print_level()) : T(sr.slice_level()); + } + + template <class T> inline static SliceRecord create_slice_record(T val) { + static_assert(std::is_arithmetic<T>::value, "Arithmetic only!"); + return std::is_integral<T>::value ? SliceRecord{ coord_t(val), 0.f, 0.f } : SliceRecord{ 0, float(val), 0.f }; + } + // This is a template method for searching the slice index either by // an integer key: print_level or a floating point key: slice_level. // The eps parameter gives the max deviation in + or - direction. @@ -162,23 +164,23 @@ private: static auto closest_slice_record(Container& cont, T lvl, T eps) -> decltype (cont.begin()) { if(cont.empty()) return cont.end(); - if(cont.size() == 1 && std::abs(cont.front().template level<T>() - lvl) > eps) + if(cont.size() == 1 && std::abs(level<T>(cont.front()) - lvl) > eps) return cont.end(); - SliceRecord query = SliceRecord::create(lvl); + SliceRecord query = create_slice_record(lvl); auto it = std::lower_bound(cont.begin(), cont.end(), query, [](const SliceRecord& r1, const SliceRecord& r2) { - return r1.level<T>() < r2.level<T>(); + return level<T>(r1) < level<T>(r2); }); - T diff = std::abs(it->template level<T>() - lvl); + T diff = std::abs(level<T>(*it) - lvl); if(it != cont.begin()) { auto it_prev = std::prev(it); - T diff_prev = std::abs(it_prev->template level<T>() - lvl); + T diff_prev = std::abs(level<T>(*it_prev) - lvl); if(diff_prev < diff) { diff = diff_prev; it = it_prev; } } @@ -226,9 +228,6 @@ public: return *it; } - // Get the actual slice polygons using a valid slice record. - const ExPolygons& get_slices_from_record( - const SliceRecord& rec, SliceOrigin o) const; protected: // to be called from SLAPrint only. friend class SLAPrint; @@ -327,6 +326,24 @@ private: // Prevents erroneous use by other classes. typedef PrintBaseWithState<SLAPrintStep, slapsCount> Inherited; public: + + // An aggregation of SliceRecord-s from all the print objects for each + // occupied layer. Slice record levels dont have to match exactly. + // They are unified if the level difference is within +/- SCALED_EPSILON + struct PrintLayer { + coord_t level; + + // The collection of slice records for the current level. + std::vector<std::reference_wrapper<const SliceRecord>> slices; + + explicit PrintLayer(coord_t lvl) : level(lvl) {} + + // for being sorted in their container (see m_printer_input) + bool operator<(const PrintLayer& other) const { + return level < other.level; + } + }; + SLAPrint(): m_stepmask(slapsCount, true) {} virtual ~SLAPrint() override { this->clear(); } @@ -360,6 +377,10 @@ public: std::string validate() const override; + // The aggregated and leveled print records from various objects. + // TODO: use this structure for the preview in the future. + const std::vector<PrintLayer>& print_layers() const { return m_printer_input; } + private: using SLAPrinter = FilePrinter<FilePrinterFormat::SLA_PNGZIP>; using SLAPrinterPtr = std::unique_ptr<SLAPrinter>; @@ -377,29 +398,8 @@ private: PrintObjects m_objects; std::vector<bool> m_stepmask; - // Definition of the print input map. It consists of the slices indexed - // with scaled (clipper) Z coordinates. Also contains the instance - // transformations in scaled and filtered version. This is enough for the - // rasterizer to be able to draw every layer in the right position - using Layer = ExPolygons; - using LayerCopies = std::vector<SLAPrintObject::Instance>; - struct LayerRef { - std::reference_wrapper<const Layer> lref; - std::reference_wrapper<const LayerCopies> copies; - LayerRef(const Layer& lyr, const LayerCopies& cp) : - lref(std::cref(lyr)), copies(std::cref(cp)) {} - }; - - // One level may contain multiple slices from multiple objects and their - // supports - struct LayerRefs { - coord_t level; - std::vector<LayerRef> refs; - bool operator<(const LayerRefs& other) const { return level < other.level; } - explicit LayerRefs(coord_t lvl) : level(lvl) {} - }; - - std::vector<LayerRefs> m_printer_input; + // Ready-made data for rasterization. + std::vector<PrintLayer> m_printer_input; // The printer itself SLAPrinterPtr m_printer; diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index c6a90a8cc..4bda48bcd 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5021,8 +5021,8 @@ void GLCanvas3D::_render_sla_slices() const SliceRecord slice_high = obj->closest_slice_to_print_level(key_high, coord_t(SCALED_EPSILON)); if (! slice_low.is_valid()) { - const ExPolygons& obj_bottom = obj->get_slices_from_record(slice_low, soModel); - const ExPolygons& sup_bottom = obj->get_slices_from_record(slice_low, soSupport); + const ExPolygons& obj_bottom = slice_low.get_slice(soModel); + const ExPolygons& sup_bottom = slice_low.get_slice(soSupport); // calculate model bottom cap if (bottom_obj_triangles.empty() && !obj_bottom.empty()) bottom_obj_triangles = triangulate_expolygons_3d(obj_bottom, clip_min_z, true); @@ -5032,8 +5032,8 @@ void GLCanvas3D::_render_sla_slices() const } if (! slice_high.is_valid()) { - const ExPolygons& obj_top = obj->get_slices_from_record(slice_high, soModel); - const ExPolygons& sup_top = obj->get_slices_from_record(slice_high, soSupport); + const ExPolygons& obj_top = slice_high.get_slice(soModel); + const ExPolygons& sup_top = slice_high.get_slice(soSupport); // calculate model top cap if (top_obj_triangles.empty() && !obj_top.empty()) top_obj_triangles = triangulate_expolygons_3d(obj_top, clip_max_z, false);