Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/xs
diff options
context:
space:
mode:
authorEnrico Turri <enricoturri@seznam.cz>2018-01-10 15:43:00 +0300
committerEnrico Turri <enricoturri@seznam.cz>2018-01-10 15:43:00 +0300
commitbbc9a0abe6a318a27ff3b18b23f4ae18f845946d (patch)
treef4bae7f9350e910252f6eaea736a255beb1598c4 /xs
parent6a744238b9a4d266b1028d1b86998553c0f61df8 (diff)
Parallelization of extrude path render geometry generation
Diffstat (limited to 'xs')
-rw-r--r--xs/src/libslic3r/GCode/Analyzer.cpp4
-rw-r--r--xs/src/slic3r/GUI/3DScene.cpp239
2 files changed, 157 insertions, 86 deletions
diff --git a/xs/src/libslic3r/GCode/Analyzer.cpp b/xs/src/libslic3r/GCode/Analyzer.cpp
index e00bd5daf..b7d1e742f 100644
--- a/xs/src/libslic3r/GCode/Analyzer.cpp
+++ b/xs/src/libslic3r/GCode/Analyzer.cpp
@@ -1181,6 +1181,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(Print& print)
if ((data != move.data) || (data.feedrate != move.data.feedrate) || (z != move.start_position.z) || (position != move.start_position))
{
// store current polyline
+ polyline.remove_duplicate_points();
Helper::store_polyline(polyline, data, z, print);
// reset current polyline
@@ -1206,6 +1207,7 @@ void GCodeAnalyzer::_calc_gcode_preview_extrusion_layers(Print& print)
}
// store last polyline
+ polyline.remove_duplicate_points();
Helper::store_polyline(polyline, data, z, print);
// updates preview ranges data
@@ -1244,6 +1246,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print)
if ((type != move_type) || (direction != move_direction) || (position != move.start_position))
{
// store current polyline
+ polyline.remove_duplicate_points();
Helper::store_polyline(polyline, type, direction, print);
// reset current polyline
@@ -1263,6 +1266,7 @@ void GCodeAnalyzer::_calc_gcode_preview_travel(Print& print)
}
// store last polyline
+ polyline.remove_duplicate_points();
Helper::store_polyline(polyline, type, direction, print);
}
diff --git a/xs/src/slic3r/GUI/3DScene.cpp b/xs/src/slic3r/GUI/3DScene.cpp
index 4429d7449..8af45e6b2 100644
--- a/xs/src/slic3r/GUI/3DScene.cpp
+++ b/xs/src/slic3r/GUI/3DScene.cpp
@@ -658,11 +658,7 @@ static void thick_lines_to_indexed_vertex_array(const Lines3& lines,
Vectorf3 n_right;
Vectorf3 unit_positive_z(0.0, 0.0, 1.0);
-// float dot_z = dot(unit_v, unit_positive_z);
-// bool is_vertical = ::fabs(dot_z) > 0.99999;
-
if ((line.a.x == line.b.x) && (line.a.y == line.b.y))
-// if (is_vertical)
{
// vertical segment
n_right = (line.a.z < line.b.z) ? Vectorf3(-1.0, 0.0, 0.0) : Vectorf3(1.0, 0.0, 0.0);
@@ -955,13 +951,22 @@ static void thick_lines_to_verts(const Lines3& lines,
thick_lines_to_indexed_vertex_array(lines, widths, heights, closed, volume.indexed_vertex_array);
}
-static void point_to_verts(const Point3& point,
+static void thick_point_to_verts(const Point3& point,
double width,
double height,
GLVolume& volume)
{
point_to_indexed_vertex_array(point, width, height, volume.indexed_vertex_array);
}
+
+// Fill in the qverts and tverts with quads and triangles for the extrusion_path.
+static inline void 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);
+}
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
@@ -1050,22 +1055,17 @@ static void extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity, fl
//############################################################################################################
#if ENRICO_GCODE_PREVIEW
-static void polyline3_to_verts(const Polyline3& polyline, double width, double height, const Point& copy, GLVolume& volume)
+static void polyline3_to_verts(const Polyline3& polyline, double width, double height, GLVolume& volume)
{
- Polyline3 p = polyline;
- p.remove_duplicate_points();
- p.translate(copy);
Lines3 lines = polyline.lines();
std::vector<double> widths(lines.size(), width);
std::vector<double> heights(lines.size(), height);
thick_lines_to_verts(lines, widths, heights, false, volume);
}
-static void point3_to_verts(const Point3& point, double width, double height, const Point& copy, GLVolume& volume)
+static void point3_to_verts(const Point3& point, double width, double height, GLVolume& volume)
{
- Point3 p = point;
- p.translate(copy);
- point_to_verts(p, width, height, volume);
+ thick_point_to_verts(point, width, height, volume);
}
#endif // ENRICO_GCODE_PREVIEW
//############################################################################################################
@@ -1513,58 +1513,92 @@ void _3DScene::_load_gcode_extrusion_paths(const Print& print, GLVolumeCollectio
}
};
- Point origin(0, 0);
- for (const GCodeAnalyzer::PreviewData::Extrusion::Layer& layer : print.gcode_preview.extrusion.layers)
+ // temporary structure to contain data needed for parallelization
+ struct Ctxt
{
- float filter = FLT_MAX;
- GLVolume* volume = nullptr;
+ const Print* print;
+ const GCodeAnalyzer::PreviewData::Extrusion::LayersList* layers;
+ } ctxt;
- for (const ExtrusionPath& path : layer.paths)
+ // fills data in temporary variable
+ ctxt.print = &print;
+ ctxt.layers = &print.gcode_preview.extrusion.layers;
+
+ // lambda for creating new volumes in a thread-safe way
+ tbb::spin_mutex new_volume_mutex;
+ auto new_volume = [&volumes, &new_volume_mutex](const float* color) -> GLVolume*
+ {
+ // allocate a new volume
+ GLVolume* volume = new GLVolume(color);
+ if (volume != nullptr)
{
- if (print.gcode_preview.extrusion.is_role_flag_set(path.role()))
+ // adds the new volume to the collection
+ new_volume_mutex.lock();
+ volumes.volumes.emplace_back(volume);
+ new_volume_mutex.unlock();
+ }
+ return volume;
+ };
+
+ size_t initial_volumes_count = volumes.volumes.size();
+
+ // generates volumes using parallelization
+ tbb::parallel_for(tbb::blocked_range<size_t>(0, ctxt.layers->size()), [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range)
+ {
+ for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer)
+ {
+ const GCodeAnalyzer::PreviewData::Extrusion::Layer& layer = ctxt.layers->operator[](idx_layer);
+ float filter = FLT_MAX;
+ GLVolume* volume = nullptr;
+
+ for (const ExtrusionPath& path : layer.paths)
{
- float path_filter = PathHelper::path_filter(print.gcode_preview.extrusion.view_type, path);
- if (filter == path_filter)
+ if (ctxt.print->gcode_preview.extrusion.is_role_flag_set(path.role()))
{
- // adds path to current volume
- if (volume != nullptr)
- extrusionentity_to_verts(path, layer.z, origin, *volume);
- }
- else
- {
- if (volume != nullptr)
+ float path_filter = PathHelper::path_filter(ctxt.print->gcode_preview.extrusion.view_type, path);
+ if (filter == path_filter)
{
- // finalizes current volume
- volume->bounding_box = volume->indexed_vertex_array.bounding_box();
- volume->indexed_vertex_array.finalize_geometry(use_VBOs);
- volume = nullptr;
+ // adds path to current volume
+ if (volume != nullptr)
+ extrusionentity_to_verts(path, layer.z, *volume);
}
-
- // adds new volume
- volumes.volumes.emplace_back(new GLVolume(PathHelper::path_color(print.gcode_preview, path).rgba));
- volume = volumes.volumes.back();
- if (volume != nullptr)
+ else
{
- volume->print_zs.push_back(layer.z);
- volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
- volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
+ if (volume != nullptr)
+ {
+ // finalizes current volume
+ volume->bounding_box = volume->indexed_vertex_array.bounding_box();
+ volume = nullptr;
+ }
- // adds path to current volume
- extrusionentity_to_verts(path, layer.z, origin, *volume);
- }
+ // adds new volume
+ volume = new_volume(PathHelper::path_color(ctxt.print->gcode_preview, path).rgba);
+ if (volume != nullptr)
+ {
+ volume->print_zs.push_back(layer.z);
+ volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
+ volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
+
+ // adds path to current volume
+ extrusionentity_to_verts(path, layer.z, *volume);
+ }
- // updates current filter
- filter = path_filter;
+ // updates current filter
+ filter = path_filter;
+ }
}
}
- }
- if (volume != nullptr)
- {
- // finalizes last volume on layer
- volume->bounding_box = volume->indexed_vertex_array.bounding_box();
- volume->indexed_vertex_array.finalize_geometry(use_VBOs);
+ if (volume != nullptr)
+ // finalizes last volume on layer
+ volume->bounding_box = volume->indexed_vertex_array.bounding_box();
}
+ });
+
+ // sends geometry to gpu
+ for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i)
+ {
+ volumes.volumes[i]->indexed_vertex_array.finalize_geometry(use_VBOs);
}
}
@@ -1587,36 +1621,71 @@ void _3DScene::_load_gcode_travel_paths(const Print& print, GLVolumeCollection&
if (print.gcode_preview.travel.is_visible)
{
- Point origin(0, 0);
- for (unsigned int i = (unsigned int)GCodeAnalyzer::PreviewData::Travel::Move; i < (unsigned int)GCodeAnalyzer::PreviewData::Travel::Num_Types; ++i)
+ size_t initial_volumes_count = volumes.volumes.size();
+ unsigned int types_count = (unsigned int)GCodeAnalyzer::PreviewData::Travel::Num_Types;
+
+ // creates a new volume for each travel type
+ for (unsigned int i = 0; i < types_count; ++i)
{
- GCodeAnalyzer::PreviewData::Travel::EType type = (GCodeAnalyzer::PreviewData::Travel::EType)i;
- if (std::count_if(print.gcode_preview.travel.polylines.begin(), print.gcode_preview.travel.polylines.end(), TypeMatch(type)) > 0)
+ GLVolume* volume = new GLVolume(print.gcode_preview.travel.type_colors[i].rgba);
+ if (volume != nullptr)
+ volumes.volumes.emplace_back(volume);
+ else
{
- volumes.volumes.emplace_back(new GLVolume(print.gcode_preview.travel.type_colors[i].rgba));
- GLVolume* volume = volumes.volumes.back();
-
- if (volume != nullptr)
+ // an error occourred - restore to previous state and return
+ std::vector<GLVolume*>::iterator begin = volumes.volumes.begin() + initial_volumes_count;
+ std::vector<GLVolume*>::iterator end = volumes.volumes.end();
+ for (std::vector<GLVolume*>::iterator it = begin; it < end; ++it)
{
- for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines)
- {
- if (polyline.type == type)
- {
- const BoundingBox3& bbox = polyline.polyline.bounding_box();
- coordf_t print_z = unscale(bbox.max.z);
- volume->print_zs.push_back(print_z);
- volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
- volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
+ GLVolume* volume = *it;
+ delete volume;
+ }
+ volumes.volumes.erase(begin, end);
+ return;
+ }
+ }
- // adds polyline to volume
- polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, origin, *volume);
- }
- }
+ for (const GCodeAnalyzer::PreviewData::Travel::Polyline& polyline : print.gcode_preview.travel.polylines)
+ {
+ unsigned int type = (unsigned int)polyline.type;
+ if (type < types_count)
+ {
+ const BoundingBox3& bbox = polyline.polyline.bounding_box();
+ coordf_t print_z = unscale(bbox.max.z);
- // finalizes volume
- volume->bounding_box = volume->indexed_vertex_array.bounding_box();
- volume->indexed_vertex_array.finalize_geometry(use_VBOs);
- }
+ // selects volume from polyline type
+ GLVolume* volume = volumes.volumes[initial_volumes_count + type];
+ volume->print_zs.push_back(print_z);
+ volume->offsets.push_back(volume->indexed_vertex_array.quad_indices.size());
+ volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
+
+ // adds polyline to volume
+ polyline3_to_verts(polyline.polyline, print.gcode_preview.travel.width, print.gcode_preview.travel.height, *volume);
+ }
+ }
+
+ // removes empty volumes
+ std::vector<GLVolume*>::iterator it = volumes.volumes.begin() + initial_volumes_count;
+ while (it != volumes.volumes.end())
+ {
+ GLVolume* volume = *it;
+ if (volume->print_zs.empty())
+ {
+ delete volume;
+ it = volumes.volumes.erase(it);
+ }
+ else
+ ++it;
+ }
+
+ // finalize volumes and sends geometry to gpu
+ if (volumes.volumes.size() > initial_volumes_count)
+ {
+ for (size_t i = initial_volumes_count; i < volumes.volumes.size(); ++i)
+ {
+ GLVolume* volume = volumes.volumes[i];
+ volume->bounding_box = volume->indexed_vertex_array.bounding_box();
+ volume->indexed_vertex_array.finalize_geometry(use_VBOs);
}
}
}
@@ -1626,12 +1695,11 @@ void _3DScene::_load_gcode_retractions(const Print& print, GLVolumeCollection& v
{
if (print.gcode_preview.retraction.is_visible)
{
- volumes.volumes.emplace_back(new GLVolume(print.gcode_preview.retraction.color.rgba));
- GLVolume* volume = volumes.volumes.back();
-
+ GLVolume* volume = new GLVolume(print.gcode_preview.retraction.color.rgba);
if (volume != nullptr)
{
- Point origin(0, 0);
+ volumes.volumes.emplace_back(volume);
+
for (const GCodeAnalyzer::PreviewData::Retraction::Position& position : print.gcode_preview.retraction.positions)
{
coordf_t print_z = unscale(position.position.z);
@@ -1640,7 +1708,7 @@ void _3DScene::_load_gcode_retractions(const Print& print, GLVolumeCollection& v
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
// adds point to volume
- point3_to_verts(position.position, position.width, position.height, origin, *volume);
+ point3_to_verts(position.position, position.width, position.height, *volume);
}
// finalizes volume
@@ -1654,12 +1722,11 @@ void _3DScene::_load_gcode_unretractions(const Print& print, GLVolumeCollection&
{
if (print.gcode_preview.unretraction.is_visible)
{
- volumes.volumes.emplace_back(new GLVolume(print.gcode_preview.unretraction.color.rgba));
- GLVolume* volume = volumes.volumes.back();
-
+ GLVolume* volume = new GLVolume(print.gcode_preview.unretraction.color.rgba);
if (volume != nullptr)
{
- Point origin(0, 0);
+ volumes.volumes.emplace_back(volume);
+
for (const GCodeAnalyzer::PreviewData::Retraction::Position& position : print.gcode_preview.unretraction.positions)
{
coordf_t print_z = unscale(position.position.z);
@@ -1668,7 +1735,7 @@ void _3DScene::_load_gcode_unretractions(const Print& print, GLVolumeCollection&
volume->offsets.push_back(volume->indexed_vertex_array.triangle_indices.size());
// adds point to volume
- point3_to_verts(position.position, position.width, position.height, origin, *volume);
+ point3_to_verts(position.position, position.width, position.height, *volume);
}
// finalizes volume