mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	Refactoring of the G-code preview for lower memory allocation
and for separation of concerns: The final G-code preview no more uses ExtrusionPaths structure to hold the G-code path data extracted by parsing the G-code. Instead, the ExtrusionPath class has been trimmed down back to the original size before the G-code preview was introduced, and a new GCodePreviewData::Extrusion::Path class was created to hold the additional path data as the extruder ID, color change ID and fan speed.
This commit is contained in:
		
							parent
							
								
									b425ee50a9
								
							
						
					
					
						commit
						272479826f
					
				
					 7 changed files with 64 additions and 41 deletions
				
			
		| 
						 | 
				
			
			@ -14,7 +14,7 @@ class ExtrusionEntityCollection;
 | 
			
		|||
class Extruder;
 | 
			
		||||
 | 
			
		||||
// Each ExtrusionRole value identifies a distinct set of { extruder, speed }
 | 
			
		||||
enum ExtrusionRole {
 | 
			
		||||
enum ExtrusionRole : uint8_t {
 | 
			
		||||
    erNone,
 | 
			
		||||
    erPerimeter,
 | 
			
		||||
    erExternalPerimeter,
 | 
			
		||||
| 
						 | 
				
			
			@ -117,25 +117,16 @@ public:
 | 
			
		|||
    float width;
 | 
			
		||||
    // Height of the extrusion, used for visualization purposes.
 | 
			
		||||
    float height;
 | 
			
		||||
    // Feedrate of the extrusion, used for visualization purposes.
 | 
			
		||||
    float feedrate;
 | 
			
		||||
    // Id of the extruder, used for visualization purposes.
 | 
			
		||||
    unsigned int extruder_id;
 | 
			
		||||
    // Id of the color, used for visualization purposes in the color printing case.
 | 
			
		||||
    unsigned int cp_color_id;
 | 
			
		||||
    // Fan speed for the extrusion, used for visualization purposes.
 | 
			
		||||
    float fan_speed;
 | 
			
		||||
 | 
			
		||||
    ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), feedrate(0.0f), extruder_id(0), cp_color_id(0), fan_speed(0.0f), m_role(role) {};
 | 
			
		||||
    ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), feedrate(0.0f), extruder_id(0), cp_color_id(0), fan_speed(0.0f), m_role(role) {};
 | 
			
		||||
    ExtrusionPath(const ExtrusionPath& rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), fan_speed(rhs.fan_speed), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(ExtrusionPath&& rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), fan_speed(rhs.fan_speed), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) : polyline(polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), fan_speed(rhs.fan_speed), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) : polyline(std::move(polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), feedrate(rhs.feedrate), extruder_id(rhs.extruder_id), cp_color_id(rhs.cp_color_id), fan_speed(rhs.fan_speed), m_role(rhs.m_role) {}
 | 
			
		||||
//    ExtrusionPath(ExtrusionRole role, const Flow &flow) : m_role(role), mm3_per_mm(flow.mm3_per_mm()), width(flow.width), height(flow.height), feedrate(0.0f), extruder_id(0) {};
 | 
			
		||||
    ExtrusionPath(ExtrusionRole role) : mm3_per_mm(-1), width(-1), height(-1), m_role(role) {};
 | 
			
		||||
    ExtrusionPath(ExtrusionRole role, double mm3_per_mm, float width, float height) : mm3_per_mm(mm3_per_mm), width(width), height(height), m_role(role) {};
 | 
			
		||||
    ExtrusionPath(const ExtrusionPath& rhs) : polyline(rhs.polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(ExtrusionPath&& rhs) : polyline(std::move(rhs.polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(const Polyline &polyline, const ExtrusionPath &rhs) : polyline(polyline), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
 | 
			
		||||
    ExtrusionPath(Polyline &&polyline, const ExtrusionPath &rhs) : polyline(std::move(polyline)), mm3_per_mm(rhs.mm3_per_mm), width(rhs.width), height(rhs.height), m_role(rhs.m_role) {}
 | 
			
		||||
 | 
			
		||||
    ExtrusionPath& operator=(const ExtrusionPath& rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->fan_speed = rhs.fan_speed, this->polyline = rhs.polyline; return *this; }
 | 
			
		||||
    ExtrusionPath& operator=(ExtrusionPath&& rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->feedrate = rhs.feedrate, this->extruder_id = rhs.extruder_id, this->cp_color_id = rhs.cp_color_id, this->fan_speed = rhs.fan_speed, this->polyline = std::move(rhs.polyline); return *this; }
 | 
			
		||||
    ExtrusionPath& operator=(const ExtrusionPath& rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->polyline = rhs.polyline; return *this; }
 | 
			
		||||
    ExtrusionPath& operator=(ExtrusionPath&& rhs) { m_role = rhs.m_role; this->mm3_per_mm = rhs.mm3_per_mm; this->width = rhs.width; this->height = rhs.height; this->polyline = std::move(rhs.polyline); return *this; }
 | 
			
		||||
 | 
			
		||||
	ExtrusionEntity* clone() const override { return new ExtrusionPath(*this); }
 | 
			
		||||
    // Create a new object, initialize it with this object using the move semantics.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -866,7 +866,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            // if layer not found, create and return it
 | 
			
		||||
            layers.emplace_back(z, ExtrusionPaths());
 | 
			
		||||
            layers.emplace_back(z, GCodePreviewData::Extrusion::Paths());
 | 
			
		||||
            return layers.back();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -875,14 +875,18 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(GCodePreviewData& previ
 | 
			
		|||
            // if the polyline is valid, create the extrusion path from it and store it
 | 
			
		||||
            if (polyline.is_valid())
 | 
			
		||||
            {
 | 
			
		||||
                ExtrusionPath path(data.extrusion_role, data.mm3_per_mm, data.width, data.height);
 | 
			
		||||
				auto& paths = get_layer_at_z(preview_data.extrusion.layers, z).paths;
 | 
			
		||||
				paths.emplace_back(GCodePreviewData::Extrusion::Path());
 | 
			
		||||
				GCodePreviewData::Extrusion::Path &path = paths.back();
 | 
			
		||||
                path.polyline = polyline;
 | 
			
		||||
				path.extrusion_role = data.extrusion_role;
 | 
			
		||||
				path.mm3_per_mm = data.mm3_per_mm;
 | 
			
		||||
				path.width = data.width;
 | 
			
		||||
				path.height = data.height;
 | 
			
		||||
                path.feedrate = data.feedrate;
 | 
			
		||||
                path.extruder_id = data.extruder_id;
 | 
			
		||||
                path.fan_speed = data.fan_speed;
 | 
			
		||||
                path.cp_color_id = data.cp_color_id;
 | 
			
		||||
 | 
			
		||||
                get_layer_at_z(preview_data.extrusion.layers, z).paths.push_back(path);
 | 
			
		||||
                path.fan_speed = data.fan_speed;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,7 @@ std::vector<unsigned char> GCodePreviewData::Color::as_bytes() const
 | 
			
		|||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GCodePreviewData::Extrusion::Layer::Layer(float z, const ExtrusionPaths& paths)
 | 
			
		||||
GCodePreviewData::Extrusion::Layer::Layer(float z, const Paths& paths)
 | 
			
		||||
    : z(z)
 | 
			
		||||
    , paths(paths)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -171,8 +171,8 @@ size_t GCodePreviewData::Extrusion::memory_used() const
 | 
			
		|||
    size_t out = sizeof(*this);
 | 
			
		||||
    out += SLIC3R_STDVEC_MEMSIZE(this->layers, Layer);
 | 
			
		||||
    for (const Layer &layer : this->layers) {
 | 
			
		||||
        out += SLIC3R_STDVEC_MEMSIZE(layer.paths, ExtrusionPath);
 | 
			
		||||
        for (const ExtrusionPath &path : layer.paths)
 | 
			
		||||
        out += SLIC3R_STDVEC_MEMSIZE(layer.paths, Path);
 | 
			
		||||
        for (const Path &path : layer.paths)
 | 
			
		||||
			out += SLIC3R_STDVEC_MEMSIZE(path.polyline.points, Point);
 | 
			
		||||
    }
 | 
			
		||||
	return out;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,12 +87,34 @@ public:
 | 
			
		|||
        static const std::string Default_Extrusion_Role_Names[erCount];
 | 
			
		||||
        static const EViewType Default_View_Type;
 | 
			
		||||
 | 
			
		||||
		class Path
 | 
			
		||||
		{
 | 
			
		||||
		public:
 | 
			
		||||
		    Polyline 		polyline;
 | 
			
		||||
		    ExtrusionRole 	extrusion_role;
 | 
			
		||||
		    // Volumetric velocity. mm^3 of plastic per mm of linear head motion. Used by the G-code generator.
 | 
			
		||||
		    float			mm3_per_mm;
 | 
			
		||||
		    // Width of the extrusion, used for visualization purposes.
 | 
			
		||||
		    float 			width;
 | 
			
		||||
		    // Height of the extrusion, used for visualization purposes.
 | 
			
		||||
		    float 			height;
 | 
			
		||||
		    // Feedrate of the extrusion, used for visualization purposes.
 | 
			
		||||
		    float 			feedrate;
 | 
			
		||||
		    // Id of the extruder, used for visualization purposes.
 | 
			
		||||
		    uint32_t		extruder_id;
 | 
			
		||||
		    // Id of the color, used for visualization purposes in the color printing case.
 | 
			
		||||
		    uint32_t	 	cp_color_id;
 | 
			
		||||
		    // Fan speed for the extrusion, used for visualization purposes.
 | 
			
		||||
		    float 			fan_speed;
 | 
			
		||||
		};
 | 
			
		||||
		using Paths = std::vector<Path>;
 | 
			
		||||
 | 
			
		||||
        struct Layer
 | 
			
		||||
        {
 | 
			
		||||
            float z;
 | 
			
		||||
            ExtrusionPaths paths;
 | 
			
		||||
            Paths paths;
 | 
			
		||||
 | 
			
		||||
            Layer(float z, const ExtrusionPaths& paths);
 | 
			
		||||
            Layer(float z, const Paths& paths);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        typedef std::vector<Layer> LayersList;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1717,13 +1717,18 @@ static void thick_point_to_verts(const Vec3crd& point,
 | 
			
		|||
    point_to_indexed_vertex_array(point, width, height, volume.indexed_vertex_array);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void _3DScene::extrusionentity_to_verts(const Polyline &polyline, float width, float height, float print_z, GLVolume& volume)
 | 
			
		||||
{
 | 
			
		||||
	if (polyline.size() >= 2) {
 | 
			
		||||
		size_t num_segments = polyline.size() - 1;
 | 
			
		||||
		thick_lines_to_verts(polyline.lines(), std::vector<double>(num_segments, width), std::vector<double>(num_segments, height), false, print_z, volume);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fill in the qverts and tverts with quads and triangles for the extrusion_path.
 | 
			
		||||
void _3DScene::extrusionentity_to_verts(const ExtrusionPath &extrusion_path, float print_z, GLVolume &volume)
 | 
			
		||||
{
 | 
			
		||||
    Lines               lines = extrusion_path.polyline.lines();
 | 
			
		||||
    std::vector<double> widths(lines.size(), extrusion_path.width);
 | 
			
		||||
    std::vector<double> heights(lines.size(), extrusion_path.height);
 | 
			
		||||
    thick_lines_to_verts(lines, widths, heights, false, print_z, volume);
 | 
			
		||||
	extrusionentity_to_verts(extrusion_path.polyline, extrusion_path.width, extrusion_path.height, print_z, volume);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Fill in the qverts and tverts with quads and triangles for the extrusion_path.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -656,6 +656,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    static void thick_lines_to_verts(const Lines& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, double top_z, GLVolume& volume);
 | 
			
		||||
    static void thick_lines_to_verts(const Lines3& lines, const std::vector<double>& widths, const std::vector<double>& heights, bool closed, GLVolume& volume);
 | 
			
		||||
	static void extrusionentity_to_verts(const Polyline &polyline, float width, float height, float print_z, GLVolume& volume);
 | 
			
		||||
    static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, GLVolume& volume);
 | 
			
		||||
    static void extrusionentity_to_verts(const ExtrusionPath& extrusion_path, float print_z, const Point& copy, GLVolume& volume);
 | 
			
		||||
    static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4987,13 +4987,13 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
 | 
			
		|||
    // helper functions to select data in dependence of the extrusion view type
 | 
			
		||||
    struct Helper
 | 
			
		||||
    {
 | 
			
		||||
        static float path_filter(GCodePreviewData::Extrusion::EViewType type, const ExtrusionPath& path)
 | 
			
		||||
        static float path_filter(GCodePreviewData::Extrusion::EViewType type, const GCodePreviewData::Extrusion::Path& path)
 | 
			
		||||
        {
 | 
			
		||||
            switch (type)
 | 
			
		||||
            {
 | 
			
		||||
            case GCodePreviewData::Extrusion::FeatureType:
 | 
			
		||||
            	// The role here is used for coloring.
 | 
			
		||||
                return (float)path.role();
 | 
			
		||||
                return (float)path.extrusion_role;
 | 
			
		||||
            case GCodePreviewData::Extrusion::Height:
 | 
			
		||||
                return path.height;
 | 
			
		||||
            case GCodePreviewData::Extrusion::Width:
 | 
			
		||||
| 
						 | 
				
			
			@ -5071,15 +5071,15 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
 | 
			
		|||
	    {
 | 
			
		||||
		    std::vector<size_t> num_paths_per_role(size_t(erCount), 0);
 | 
			
		||||
		    for (const GCodePreviewData::Extrusion::Layer &layer : preview_data.extrusion.layers)
 | 
			
		||||
		        for (const ExtrusionPath &path : layer.paths)
 | 
			
		||||
		        	++ num_paths_per_role[size_t(path.role())];
 | 
			
		||||
		        for (const GCodePreviewData::Extrusion::Path &path : layer.paths)
 | 
			
		||||
		        	++ num_paths_per_role[size_t(path.extrusion_role)];
 | 
			
		||||
            std::vector<std::vector<float>> roles_values;
 | 
			
		||||
			roles_values.assign(size_t(erCount), std::vector<float>());
 | 
			
		||||
		    for (size_t i = 0; i < roles_values.size(); ++ i)
 | 
			
		||||
		    	roles_values[i].reserve(num_paths_per_role[i]);
 | 
			
		||||
            for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
 | 
			
		||||
		        for (const ExtrusionPath& path : layer.paths)
 | 
			
		||||
		        	roles_values[size_t(path.role())].emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path));
 | 
			
		||||
		        for (const GCodePreviewData::Extrusion::Path &path : layer.paths)
 | 
			
		||||
		        	roles_values[size_t(path.extrusion_role)].emplace_back(Helper::path_filter(preview_data.extrusion.view_type, path));
 | 
			
		||||
            roles_filters.reserve(size_t(erCount));
 | 
			
		||||
			size_t num_buffers = 0;
 | 
			
		||||
		    for (std::vector<float> &values : roles_values) {
 | 
			
		||||
| 
						 | 
				
			
			@ -5107,9 +5107,9 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
 | 
			
		|||
	    // populates volumes
 | 
			
		||||
		for (const GCodePreviewData::Extrusion::Layer& layer : preview_data.extrusion.layers)
 | 
			
		||||
		{
 | 
			
		||||
			for (const ExtrusionPath& path : layer.paths)
 | 
			
		||||
			for (const GCodePreviewData::Extrusion::Path& path : layer.paths)
 | 
			
		||||
			{
 | 
			
		||||
				std::vector<std::pair<float, GLVolume*>> &filters = roles_filters[size_t(path.role())];
 | 
			
		||||
				std::vector<std::pair<float, GLVolume*>> &filters = roles_filters[size_t(path.extrusion_role)];
 | 
			
		||||
				auto key = std::make_pair<float, GLVolume*>(Helper::path_filter(preview_data.extrusion.view_type, path), nullptr);
 | 
			
		||||
				auto it_filter = std::lower_bound(filters.begin(), filters.end(), key);
 | 
			
		||||
				assert(it_filter != filters.end() && key.first == it_filter->first);
 | 
			
		||||
| 
						 | 
				
			
			@ -5119,7 +5119,7 @@ void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_dat
 | 
			
		|||
				vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
 | 
			
		||||
				vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
 | 
			
		||||
 | 
			
		||||
				_3DScene::extrusionentity_to_verts(path, layer.z, vol);
 | 
			
		||||
				_3DScene::extrusionentity_to_verts(path.polyline, path.width, path.height, layer.z, vol);
 | 
			
		||||
			}
 | 
			
		||||
			// Ensure that no volume grows over the limits. If the volume is too large, allocate a new one.
 | 
			
		||||
		    for (std::vector<std::pair<float, GLVolume*>> &filters : roles_filters) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue