diff --git a/src/libslic3r/SLAPrint.cpp b/src/libslic3r/SLAPrint.cpp index e550cc80c..a40aebc45 100644 --- a/src/libslic3r/SLAPrint.cpp +++ b/src/libslic3r/SLAPrint.cpp @@ -40,7 +40,8 @@ const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS = 20, // slaposSupportPoints, 25, // slaposSupportTree, 25, // slaposBasePool, - 10 // slaposSliceSupports, + 5, // slaposSliceSupports, + 5 // slaposIndexSlices }; const std::array<std::string, slaposCount> OBJ_STEP_LABELS = @@ -50,7 +51,8 @@ const std::array<std::string, slaposCount> OBJ_STEP_LABELS = L("Scanning model structure"), // slaposSupportPoints, L("Generating support tree"), // slaposSupportTree, L("Generating base pool"), // slaposBasePool, - L("Slicing supports") // slaposSliceSupports, + L("Slicing supports"), // slaposSliceSupports, + L("Slicing supports") // slaposIndexSlices, }; // Should also add up to 100 (%) @@ -548,84 +550,88 @@ void SLAPrint::process() } }; - // Rasterizing the model objects, and their supports - auto rasterize = [this, ilh, ilhd, max_objstatus]() { - using Layer = sla::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)) {} - }; + using Layer = sla::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)) {} + }; - using LevelID = long long; - using LayerRefs = std::vector<LayerRef>; - - // layers according to quantized height levels - std::map<LevelID, LayerRefs> levels; + using LevelID = long long; + using LayerRefs = std::vector<LayerRef>; + // layers according to quantized height levels + std::map<LevelID, LayerRefs> levels; + auto index_slices = [this, ilh, ilhd, &levels](SLAPrintObject& po) { auto sih = LevelID(scale_(ilh)); // For all print objects, go through its initial layers and place them // into the layers hash - for(SLAPrintObject *o : m_objects) { - auto bb = o->transformed_mesh().bounding_box(); - double modelgnd = bb.min(Z); - double elevation = o->get_elevation(); - double lh = o->m_config.layer_height.getFloat(); - double minZ = modelgnd - elevation; + auto bb = po.transformed_mesh().bounding_box(); + double modelgnd = bb.min(Z); + double elevation = po.get_elevation(); + double lh = po.m_config.layer_height.getFloat(); + double minZ = modelgnd - elevation; - // scaled values: - auto sminZ = LevelID(scale_(minZ)); - auto smaxZ = LevelID(scale_(bb.max(Z))); - auto smodelgnd = LevelID(scale_(modelgnd)); - auto slh = LevelID(scale_(lh)); + // scaled values: + auto sminZ = LevelID(scale_(minZ)); + auto smaxZ = LevelID(scale_(bb.max(Z))); + auto smodelgnd = LevelID(scale_(modelgnd)); + auto slh = LevelID(scale_(lh)); - // It is important that the next levels math the levels in - // model_slice method. Only difference is that here it works with - // scaled coordinates - std::vector<LevelID> levelids; - if(sminZ >= smodelgnd) levelids.emplace_back(sminZ); - for(LevelID h = sminZ + sih; h < smaxZ; h += slh) - if(h >= smodelgnd) levelids.emplace_back(h); + // It is important that the next levels math the levels in + // model_slice method. Only difference is that here it works with + // scaled coordinates + std::vector<LevelID> levelids; + if(sminZ >= smodelgnd) levelids.emplace_back(sminZ); + for(LevelID h = sminZ + sih; h < smaxZ; h += slh) + if(h >= smodelgnd) levelids.emplace_back(h); - SlicedModel & oslices = o->m_model_slices; + SlicedModel & oslices = po.m_model_slices; - // If everything went well this code should not run at all, but - // let's be robust... - // assert(levelids.size() == oslices.size()); - if(levelids.size() < oslices.size()) { // extend the levels until... + // If everything went well this code should not run at all, but + // let's be robust... + // assert(levelids.size() == oslices.size()); + if(levelids.size() < oslices.size()) { // extend the levels until... - BOOST_LOG_TRIVIAL(warning) - << "Height level mismatch at rasterization!\n"; + BOOST_LOG_TRIVIAL(warning) + << "Height level mismatch at rasterization!\n"; - LevelID lastlvl = levelids.back(); - while(levelids.size() < oslices.size()) { - lastlvl += slh; - levelids.emplace_back(lastlvl); - } - } - - for(int i = 0; i < oslices.size(); ++i) { - LevelID h = levelids[i]; - auto& lyrs = levels[h]; // this initializes a new record - 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) { - int a = i == 0 ? 0 : 1; - int b = i == 0 ? 0 : i - 1; - LevelID h = sminZ + a * sih + b * slh; - - auto& lyrs = levels[h]; - lyrs.emplace_back(sslices[i], o->m_instances); - } + LevelID lastlvl = levelids.back(); + while(levelids.size() < oslices.size()) { + lastlvl += slh; + levelids.emplace_back(lastlvl); } } + for(int i = 0; i < oslices.size(); ++i) { + LevelID h = levelids[i]; + auto& lyrs = levels[h]; // this initializes a new record + lyrs.emplace_back(oslices[i], po.m_instances); + SLAPrintObject::SliceRecord& sr = po.m_slice_index[h]; + sr.model_slices_idx = i; + } + + if(po.m_supportdata) { // deal with the support slices if present + auto& sslices = po.m_supportdata->support_slices; + for(int i = 0; i < sslices.size(); ++i) { + int a = i == 0 ? 0 : 1; + int b = i == 0 ? 0 : i - 1; + LevelID h = sminZ + a * sih + b * slh; + + auto& lyrs = levels[h]; + lyrs.emplace_back(sslices[i], po.m_instances); + + SLAPrintObject::SliceRecord& sr = po.m_slice_index[h]; + sr.support_slices_idx = i; + } + } + }; + + // Rasterizing the model objects, and their supports + auto rasterize = [this, ilh, ilhd, max_objstatus, &levels]() { if(canceled()) return; // collect all the keys @@ -719,7 +725,8 @@ void SLAPrint::process() slaposSupportPoints, slaposSupportTree, slaposBasePool, - slaposSliceSupports + slaposSliceSupports, + slaposIndexSlices }; std::array<slaposFn, slaposCount> pobj_program = @@ -729,7 +736,8 @@ void SLAPrint::process() support_points, support_tree, base_pool, - slice_supports + slice_supports, + index_slices }; std::array<slapsFn, slapsCount> print_program = @@ -982,13 +990,20 @@ const TriangleMesh EMPTY_MESH; const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const { - if(!is_step_done(slaposSliceSupports) || !m_supportdata) return EMPTY_SLICES; + // assert(is_step_done(slaposSliceSupports)); + if(!!m_supportdata) return EMPTY_SLICES; return m_supportdata->support_slices; } +const SLAPrintObject::SliceIndex &SLAPrintObject::get_slice_index() const +{ + // assert(is_step_done(slaposIndexSlices)); + return m_slice_index; +} + const std::vector<ExPolygons> &SLAPrintObject::get_model_slices() const { - if(!is_step_done(slaposObjectSlice)) return EMPTY_SLICES; + // assert(is_step_done(slaposObjectSlice)); return m_model_slices; } diff --git a/src/libslic3r/SLAPrint.hpp b/src/libslic3r/SLAPrint.hpp index 704508278..1f6695dbf 100644 --- a/src/libslic3r/SLAPrint.hpp +++ b/src/libslic3r/SLAPrint.hpp @@ -23,6 +23,7 @@ enum SLAPrintObjectStep : unsigned int { slaposSupportTree, slaposBasePool, slaposSliceSupports, + slaposIndexSlices, slaposCount }; @@ -60,7 +61,7 @@ public: // Support mesh is only valid if this->is_step_done(slaposSupportTree) is true. const TriangleMesh& support_mesh() const; // Get a pad mesh centered around origin in XY, and with zero rotation around Z applied. - // Support mesh is only valid if this->is_step_done(slaposPad) is true. + // Support mesh is only valid if this->is_step_done(slaposBasePool) is true. const TriangleMesh& pad_mesh() const; // This will return the transformed mesh which is cached @@ -79,9 +80,29 @@ public: // pad is not, then without the pad, otherwise the full value is returned. double get_current_elevation() const; - // Should be obvious - const std::vector<ExPolygons>& get_support_slices() const; + // These two methods should be callable on the client side (e.g. UI thread) + // when the appropriate steps slaposObjectSlice and slaposSliceSupports + // are ready. All the print objects are processed before slapsRasterize so + // it is safe to call them during and/or after slapsRasterize. const std::vector<ExPolygons>& get_model_slices() const; + const std::vector<ExPolygons>& get_support_slices() const; + + struct SliceRecord { + using Key = long long; + inline static float scale_back(Key h) { return float(scale_(h)); } + + using Idx = size_t; + static const Idx NONE = ULONG_MAX; // std::numeric_limits<Idx>::max() // damn msvc 2013... ; + + Idx model_slices_idx = NONE; + Idx support_slices_idx = NONE; + }; + + using SliceIndex = std::map<SliceRecord::Key, SliceRecord>; + + // Retrieve the slice index which is readable only after slaposIndexSlices + // is done. + const SliceIndex& get_slice_index() const; // I refuse to grantee copying (Tamas) SLAPrintObject(const SLAPrintObject&) = delete; @@ -119,6 +140,7 @@ private: // Which steps have to be performed. Implicitly: all std::vector<bool> m_stepmask; std::vector<ExPolygons> m_model_slices; + SliceIndex m_slice_index; // Caching the transformed (m_trafo) raw mesh of the object mutable CachedObject<TriangleMesh> m_transformed_rmesh;