mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Fix for empty or broken png output.
Fix for instance transformation order error and state invalidation issues with rasterization.
This commit is contained in:
		
							parent
							
								
									bf94751a94
								
							
						
					
					
						commit
						55d62b8295
					
				
					 5 changed files with 54 additions and 161 deletions
				
			
		| 
						 | 
				
			
			@ -218,8 +218,10 @@ public:
 | 
			
		|||
                    std::sprintf(lyrnum, "%.5d", i);
 | 
			
		||||
                    auto zfilename = project + lyrnum + ".png";
 | 
			
		||||
                    writer.next_entry(zfilename);
 | 
			
		||||
                    writer << m_layers_rst[i].second.rdbuf();
 | 
			
		||||
                    m_layers_rst[i].second.str("");
 | 
			
		||||
                    writer << m_layers_rst[i].second.str();
 | 
			
		||||
                    // writer << m_layers_rst[i].second.rdbuf();
 | 
			
		||||
                    // we can keep the date for later calls of this method
 | 
			
		||||
                    //m_layers_rst[i].second.str("");
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -250,146 +252,6 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
//// Let's shadow this eigen interface
 | 
			
		||||
//inline coord_t  px(const Point& p) { return p(0); }
 | 
			
		||||
//inline coord_t  py(const Point& p) { return p(1); }
 | 
			
		||||
//inline coordf_t px(const Vec2d& p) { return p(0); }
 | 
			
		||||
//inline coordf_t py(const Vec2d& p) { return p(1); }
 | 
			
		||||
 | 
			
		||||
//template<FilePrinterFormat format, class LayerFormat, class...Args>
 | 
			
		||||
//void print_to(Print& print,
 | 
			
		||||
//              std::string dirpath,
 | 
			
		||||
//              double width_mm,
 | 
			
		||||
//              double height_mm,
 | 
			
		||||
//              Args&&...args)
 | 
			
		||||
//{
 | 
			
		||||
 | 
			
		||||
//    std::string& dir = dirpath;
 | 
			
		||||
 | 
			
		||||
//    // This map will hold the layers sorted by z coordinate. Layers on the
 | 
			
		||||
//    // same height (from different objects) will be mapped to the same key and
 | 
			
		||||
//    // rasterized to the same image.
 | 
			
		||||
//    std::map<long long, LayerPtrs> layers;
 | 
			
		||||
 | 
			
		||||
//    auto& objects = print.objects();
 | 
			
		||||
 | 
			
		||||
//    // Merge the sliced layers with the support layers
 | 
			
		||||
//    std::for_each(objects.cbegin(), objects.cend(),
 | 
			
		||||
//                  [&layers](const PrintObject *o)
 | 
			
		||||
//    {
 | 
			
		||||
//        for(const auto l : o->layers()) {
 | 
			
		||||
//            auto& lyrs = layers[static_cast<long long>(scale_(l->print_z))];
 | 
			
		||||
//            lyrs.push_back(l);
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        for(const auto l : o->support_layers()) {
 | 
			
		||||
//            auto& lyrs = layers[static_cast<long long>(scale_(l->print_z))];
 | 
			
		||||
//            lyrs.push_back(l);
 | 
			
		||||
//        }
 | 
			
		||||
//    });
 | 
			
		||||
 | 
			
		||||
//    auto print_bb = print.bounding_box();
 | 
			
		||||
//    Vec2d punsc = unscale(print_bb.size());
 | 
			
		||||
 | 
			
		||||
//    // If the print does not fit into the print area we should cry about it.
 | 
			
		||||
//    if(px(punsc) > width_mm || py(punsc) > height_mm) {
 | 
			
		||||
//        BOOST_LOG_TRIVIAL(warning) << "Warning: Print will not fit!" << "\n"
 | 
			
		||||
//            << "Width needed: " << px(punsc) << "\n"
 | 
			
		||||
//            << "Height needed: " << py(punsc) << "\n";
 | 
			
		||||
//    }
 | 
			
		||||
 | 
			
		||||
//    // Offset for centering the print onto the print area
 | 
			
		||||
//    auto cx = scale_(width_mm)/2 - (px(print_bb.center()) - px(print_bb.min));
 | 
			
		||||
//    auto cy = scale_(height_mm)/2 - (py(print_bb.center()) - py(print_bb.min));
 | 
			
		||||
 | 
			
		||||
//    // Create the actual printer, forward any additional arguments to it.
 | 
			
		||||
//    FilePrinter<format, LayerFormat> printer(width_mm, height_mm,
 | 
			
		||||
//                                             std::forward<Args>(args)...);
 | 
			
		||||
 | 
			
		||||
//    printer.print_config(print);
 | 
			
		||||
 | 
			
		||||
//    printer.layers(layers.size());  // Allocate space for all the layers
 | 
			
		||||
 | 
			
		||||
//    int st_prev = 0;
 | 
			
		||||
//    const std::string jobdesc = "Rasterizing and compressing sliced layers";
 | 
			
		||||
//    tbb::spin_mutex m;
 | 
			
		||||
 | 
			
		||||
//    std::vector<long long> keys;
 | 
			
		||||
//    keys.reserve(layers.size());
 | 
			
		||||
//    for(auto& e : layers) keys.push_back(e.first);
 | 
			
		||||
 | 
			
		||||
//    print.set_status(0, jobdesc);
 | 
			
		||||
 | 
			
		||||
//    // Method that prints one layer
 | 
			
		||||
//    auto process_layer = [&layers, &keys, &printer, &st_prev, &m,
 | 
			
		||||
//            &jobdesc, print_bb, dir, cx, cy, &print]
 | 
			
		||||
//            (unsigned layer_id)
 | 
			
		||||
//    {
 | 
			
		||||
//        LayerPtrs lrange = layers[keys[layer_id]];
 | 
			
		||||
 | 
			
		||||
//        printer.begin_layer(layer_id);   // Switch to the appropriate layer
 | 
			
		||||
 | 
			
		||||
//        for(Layer *lp : lrange) {
 | 
			
		||||
//            Layer& l = *lp;
 | 
			
		||||
 | 
			
		||||
//            ExPolygonCollection slices = l.slices;  // Copy the layer slices
 | 
			
		||||
 | 
			
		||||
//            // Sort the polygons in the layer
 | 
			
		||||
//            std::stable_sort(slices.expolygons.begin(), slices.expolygons.end(),
 | 
			
		||||
//                             [](const ExPolygon& a, const ExPolygon& b) {
 | 
			
		||||
//                return a.contour.contains(b.contour.first_point()) ? false :
 | 
			
		||||
//                                                                     true;
 | 
			
		||||
//            });
 | 
			
		||||
 | 
			
		||||
//            // Draw all the polygons in the slice to the actual layer.
 | 
			
		||||
//            for (const Point &d : l.object()->copies())
 | 
			
		||||
//                for (ExPolygon slice : slices.expolygons) {
 | 
			
		||||
//                    slice.translate(px(d), py(d));
 | 
			
		||||
//                    slice.translate(-px(print_bb.min) + cx,
 | 
			
		||||
//                                    -py(print_bb.min) + cy);
 | 
			
		||||
 | 
			
		||||
//                    printer.draw_polygon(slice, layer_id);
 | 
			
		||||
//                }
 | 
			
		||||
 | 
			
		||||
//            /*if(print.has_support_material() && layer_id > 0) {
 | 
			
		||||
//                BOOST_LOG_TRIVIAL(warning) << "support material for layer "
 | 
			
		||||
//                                           << layer_id
 | 
			
		||||
//                                           << " defined but export is "
 | 
			
		||||
//                                              "not yet implemented.";
 | 
			
		||||
 | 
			
		||||
//            }*/
 | 
			
		||||
 | 
			
		||||
//        }
 | 
			
		||||
 | 
			
		||||
//        printer.finish_layer(layer_id);  // Finish the layer for later saving it.
 | 
			
		||||
 | 
			
		||||
//        auto st = static_cast<int>(layer_id*80.0/layers.size());
 | 
			
		||||
//        m.lock();
 | 
			
		||||
//        if( st - st_prev > 10) {
 | 
			
		||||
//            print.set_status(st, jobdesc);
 | 
			
		||||
//            st_prev = st;
 | 
			
		||||
//        }
 | 
			
		||||
//        m.unlock();
 | 
			
		||||
 | 
			
		||||
//        // printer.saveLayer(layer_id, dir); We could save the layer immediately
 | 
			
		||||
//    };
 | 
			
		||||
 | 
			
		||||
//    // Print all the layers in parallel
 | 
			
		||||
//    tbb::parallel_for<size_t, decltype(process_layer)>(0,
 | 
			
		||||
//                                                       layers.size(),
 | 
			
		||||
//                                                       process_layer);
 | 
			
		||||
 | 
			
		||||
//    // Sequential version (for testing)
 | 
			
		||||
//    // for(unsigned l = 0; l < layers.size(); ++l) process_layer(l);
 | 
			
		||||
 | 
			
		||||
////    print.set_status(100, jobdesc);
 | 
			
		||||
 | 
			
		||||
//    // Save the print into the file system.
 | 
			
		||||
//    print.set_status(90, "Writing layers to disk");
 | 
			
		||||
//    printer.save(dir);
 | 
			
		||||
//    print.set_status(100, "Writing layers completed");
 | 
			
		||||
//}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif // PRINTEXPORT_HPP
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,7 @@ public:
 | 
			
		|||
    sla::PointSet    support_points;     // all the support points (manual/auto)
 | 
			
		||||
    SupportTreePtr   support_tree_ptr;   // the supports
 | 
			
		||||
    SlicedSupports   support_slices;     // sliced supports
 | 
			
		||||
    std::vector<LevelID>    level_ids;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace {
 | 
			
		||||
| 
						 | 
				
			
			@ -567,11 +568,10 @@ void SLAPrint::process()
 | 
			
		|||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    auto& levels = m_printer_input;
 | 
			
		||||
 | 
			
		||||
    // We have the layer polygon collection but we need to unite them into
 | 
			
		||||
    // an index where the key is the height level in discrete levels (clipper)
 | 
			
		||||
    auto index_slices = [this, ilh, ilhd, &levels](SLAPrintObject& po) {
 | 
			
		||||
    auto index_slices = [this, ilh, ilhd](SLAPrintObject& po) {
 | 
			
		||||
        po.m_slice_index.clear();
 | 
			
		||||
        auto sih = LevelID(scale_(ilh));
 | 
			
		||||
 | 
			
		||||
        // For all print objects, go through its initial layers and place them
 | 
			
		||||
| 
						 | 
				
			
			@ -591,7 +591,7 @@ void SLAPrint::process()
 | 
			
		|||
        // It is important that the next levels match the levels in
 | 
			
		||||
        // model_slice method. Only difference is that here it works with
 | 
			
		||||
        // scaled coordinates
 | 
			
		||||
        std::vector<LevelID> levelids;
 | 
			
		||||
        auto& levelids = po.m_level_ids; levelids.clear();
 | 
			
		||||
        if(sminZ >= smodelgnd) levelids.emplace_back(sminZ);
 | 
			
		||||
        for(LevelID h = sminZ + sih; h < smaxZ; h += slh)
 | 
			
		||||
            if(h >= smodelgnd) levelids.emplace_back(h);
 | 
			
		||||
| 
						 | 
				
			
			@ -615,11 +615,9 @@ void SLAPrint::process()
 | 
			
		|||
 | 
			
		||||
        // shortcut for empty index into the slice vectors
 | 
			
		||||
        static const auto EMPTY_SLICE = SLAPrintObject::SliceRecord::NONE;
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        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);
 | 
			
		||||
 | 
			
		||||
            float fh = float(double(h) * SCALING_FACTOR);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -632,13 +630,14 @@ void SLAPrint::process()
 | 
			
		|||
 | 
			
		||||
        if(po.m_supportdata) { // deal with the support slices if present
 | 
			
		||||
            auto& sslices = po.m_supportdata->support_slices;
 | 
			
		||||
            po.m_supportdata->level_ids.clear();
 | 
			
		||||
            po.m_supportdata->level_ids.reserve(sslices.size());
 | 
			
		||||
 | 
			
		||||
            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);
 | 
			
		||||
                po.m_supportdata->level_ids.emplace_back(h);
 | 
			
		||||
 | 
			
		||||
                float fh = float(double(h) * SCALING_FACTOR);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -649,10 +648,40 @@ void SLAPrint::process()
 | 
			
		|||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    auto& levels = m_printer_input;
 | 
			
		||||
 | 
			
		||||
    // Rasterizing the model objects, and their supports
 | 
			
		||||
    auto rasterize = [this, ilh, ilhd, max_objstatus, &levels]() {
 | 
			
		||||
        if(canceled()) return;
 | 
			
		||||
 | 
			
		||||
        // clear the rasterizer input
 | 
			
		||||
        m_printer_input.clear();
 | 
			
		||||
 | 
			
		||||
        for(SLAPrintObject * o : m_objects) {
 | 
			
		||||
            auto& po = *o;
 | 
			
		||||
            SlicedModel & oslices = po.m_model_slices;
 | 
			
		||||
 | 
			
		||||
            // We need to adjust the min Z level of the slices to be zero
 | 
			
		||||
            LevelID smfirst = po.m_supportdata? po.m_supportdata->level_ids.front() : 0;
 | 
			
		||||
            LevelID mfirst = po.m_level_ids.front();
 | 
			
		||||
            LevelID gndlvl = -(std::min(smfirst, mfirst));
 | 
			
		||||
 | 
			
		||||
            // now merge this object's support and object slices with the rest
 | 
			
		||||
            // of the print object slices
 | 
			
		||||
 | 
			
		||||
            for(int i = 0; i < oslices.size(); ++i) {
 | 
			
		||||
                auto& lyrs = levels[gndlvl + po.m_level_ids[i]];
 | 
			
		||||
                lyrs.emplace_back(oslices[i], po.m_instances);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if(!po.m_supportdata) continue;
 | 
			
		||||
            auto& sslices = po.m_supportdata->support_slices;
 | 
			
		||||
            for(int i = 0; i < sslices.size(); ++i) {
 | 
			
		||||
                auto& lyrs = levels[gndlvl + po.m_supportdata->level_ids[i]];
 | 
			
		||||
                lyrs.emplace_back(sslices[i], po.m_instances);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // collect all the keys
 | 
			
		||||
        std::vector<long long> keys; keys.reserve(levels.size());
 | 
			
		||||
        for(auto& e : levels) keys.emplace_back(e.first);
 | 
			
		||||
| 
						 | 
				
			
			@ -704,8 +733,10 @@ void SLAPrint::process()
 | 
			
		|||
                // Draw all the polygons in the slice to the actual layer.
 | 
			
		||||
                for(auto& cp : copies) {
 | 
			
		||||
                    for(ExPolygon slice : sl) {
 | 
			
		||||
                        slice.translate(cp.shift(X), cp.shift(Y));
 | 
			
		||||
                        // The order is important here:
 | 
			
		||||
                        // apply rotation before translation...
 | 
			
		||||
                        slice.rotate(cp.rotation);
 | 
			
		||||
                        slice.translate(cp.shift(X), cp.shift(Y));
 | 
			
		||||
                        printer.draw_polygon(slice, level_id);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,10 @@ class GLCanvas;
 | 
			
		|||
using _SLAPrintObjectBase =
 | 
			
		||||
    PrintObjectBaseWithState<SLAPrint, SLAPrintObjectStep, slaposCount>;
 | 
			
		||||
 | 
			
		||||
// Layers according to quantized height levels. This will be consumed by
 | 
			
		||||
// the printer (rasterizer) in the SLAPrint class.
 | 
			
		||||
using LevelID = long long;
 | 
			
		||||
 | 
			
		||||
class SLAPrintObject : public _SLAPrintObjectBase
 | 
			
		||||
{
 | 
			
		||||
private: // Prevents erroneous use by other classes.
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +97,6 @@ public:
 | 
			
		|||
    // to the z coordinate of the object coordinate system.
 | 
			
		||||
    struct SliceRecord {
 | 
			
		||||
        using Key = float;
 | 
			
		||||
//        inline static float scale_back(Key h) { return float(h * SCALING_FACTOR); }
 | 
			
		||||
 | 
			
		||||
        using Idx = size_t;
 | 
			
		||||
        static const Idx NONE = Idx(-1); // this will be the max limit of size_t
 | 
			
		||||
| 
						 | 
				
			
			@ -145,6 +148,7 @@ private:
 | 
			
		|||
    std::vector<bool>                       m_stepmask;
 | 
			
		||||
    std::vector<ExPolygons>                 m_model_slices;
 | 
			
		||||
    SliceIndex                              m_slice_index;
 | 
			
		||||
    std::vector<LevelID>                    m_level_ids;
 | 
			
		||||
 | 
			
		||||
    // Caching the transformed (m_trafo) raw mesh of the object
 | 
			
		||||
    mutable CachedObject<TriangleMesh>      m_transformed_rmesh;
 | 
			
		||||
| 
						 | 
				
			
			@ -214,10 +218,6 @@ private:
 | 
			
		|||
            lref(std::cref(lyr)), copies(std::cref(cp)) {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // Layers according to quantized height levels. This will be consumed by
 | 
			
		||||
    // the printer (rasterizer) in the SLAPrint class.
 | 
			
		||||
    using LevelID = long long;
 | 
			
		||||
 | 
			
		||||
    // One level may contain multiple slices from multiple objects and their
 | 
			
		||||
    // supports
 | 
			
		||||
    using LayerRefs = std::vector<LayerRef>;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,14 +71,12 @@ int ProgressStatusBar::get_progress() const
 | 
			
		|||
void ProgressStatusBar::set_progress(int val)
 | 
			
		||||
{
 | 
			
		||||
    if(!m_prog->IsShown()) show_progress(true);
 | 
			
		||||
    if(val < 0) return;
 | 
			
		||||
 | 
			
		||||
    if(val == m_prog->GetRange()) {
 | 
			
		||||
        m_prog->SetValue(0);
 | 
			
		||||
        show_progress(false);
 | 
			
		||||
    }
 | 
			
		||||
    else if(val < 0) {
 | 
			
		||||
        m_prog->Pulse();
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        m_prog->SetValue(val);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,6 +35,8 @@ public:
 | 
			
		|||
    ~ProgressStatusBar();
 | 
			
		||||
 | 
			
		||||
    int         get_progress() const;
 | 
			
		||||
    // if the argument is less than 0 it shows the last state or
 | 
			
		||||
    // pulses if no state was set before.
 | 
			
		||||
    void        set_progress(int);
 | 
			
		||||
    int         get_range() const;
 | 
			
		||||
    void        set_range(int = 100);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue