Generation of preview paths moved to c++
This commit is contained in:
parent
f262ec9094
commit
a8254e0053
@ -2199,56 +2199,36 @@ sub load_object {
|
|||||||
return @{$volume_indices};
|
return @{$volume_indices};
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create 3D thick extrusion lines for a skirt and brim.
|
|
||||||
# Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes.
|
|
||||||
sub load_print_toolpaths {
|
|
||||||
my ($self, $print, $colors) = @_;
|
|
||||||
|
|
||||||
#==============================================================================================================================
|
#==============================================================================================================================
|
||||||
my $useVBOs = Slic3r::GUI::_3DScene::use_VBOs();
|
## Create 3D thick extrusion lines for a skirt and brim.
|
||||||
$self->SetCurrent($self->GetContext) if $useVBOs;
|
## Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes.
|
||||||
Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $colors, $useVBOs)
|
#sub load_print_toolpaths {
|
||||||
if ($print->step_done(STEP_SKIRT) && $print->step_done(STEP_BRIM));
|
# my ($self, $print, $colors) = @_;
|
||||||
|
#
|
||||||
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||||
# Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $colors, $self->UseVBOs)
|
# Slic3r::GUI::_3DScene::_load_print_toolpaths($print, $self->volumes, $colors, $self->UseVBOs)
|
||||||
# if ($print->step_done(STEP_SKIRT) && $print->step_done(STEP_BRIM));
|
# if ($print->step_done(STEP_SKIRT) && $print->step_done(STEP_BRIM));
|
||||||
#==============================================================================================================================
|
#}
|
||||||
}
|
#
|
||||||
|
## Create 3D thick extrusion lines for object forming extrusions.
|
||||||
# Create 3D thick extrusion lines for object forming extrusions.
|
## Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||||
# Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
## one for perimeters, one for infill and one for supports.
|
||||||
# one for perimeters, one for infill and one for supports.
|
#sub load_print_object_toolpaths {
|
||||||
sub load_print_object_toolpaths {
|
# my ($self, $object, $colors) = @_;
|
||||||
my ($self, $object, $colors) = @_;
|
#
|
||||||
|
|
||||||
#==============================================================================================================================
|
|
||||||
my $useVBOs = Slic3r::GUI::_3DScene::use_VBOs();
|
|
||||||
$self->SetCurrent($self->GetContext) if $useVBOs;
|
|
||||||
Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $colors, $useVBOs);
|
|
||||||
|
|
||||||
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||||
# Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $colors, $self->UseVBOs);
|
# Slic3r::GUI::_3DScene::_load_print_object_toolpaths($object, $self->volumes, $colors, $self->UseVBOs);
|
||||||
#==============================================================================================================================
|
#}
|
||||||
}
|
#
|
||||||
|
## Create 3D thick extrusion lines for wipe tower extrusions.
|
||||||
# Create 3D thick extrusion lines for wipe tower extrusions.
|
#sub load_wipe_tower_toolpaths {
|
||||||
sub load_wipe_tower_toolpaths {
|
# my ($self, $print, $colors) = @_;
|
||||||
my ($self, $print, $colors) = @_;
|
#
|
||||||
|
|
||||||
#==============================================================================================================================
|
|
||||||
my $useVBOs = Slic3r::GUI::_3DScene::use_VBOs();
|
|
||||||
$self->SetCurrent($self->GetContext) if $useVBOs;
|
|
||||||
Slic3r::GUI::_3DScene::_load_wipe_tower_toolpaths($print, $self->volumes, $colors, $useVBOs)
|
|
||||||
if ($print->step_done(STEP_WIPE_TOWER));
|
|
||||||
|
|
||||||
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
# $self->SetCurrent($self->GetContext) if $self->UseVBOs;
|
||||||
# Slic3r::GUI::_3DScene::_load_wipe_tower_toolpaths($print, $self->volumes, $colors, $self->UseVBOs)
|
# Slic3r::GUI::_3DScene::_load_wipe_tower_toolpaths($print, $self->volumes, $colors, $self->UseVBOs)
|
||||||
# if ($print->step_done(STEP_WIPE_TOWER));
|
# if ($print->step_done(STEP_WIPE_TOWER));
|
||||||
#==============================================================================================================================
|
#}
|
||||||
}
|
#
|
||||||
|
|
||||||
#==============================================================================================================================
|
|
||||||
#sub load_gcode_preview {
|
#sub load_gcode_preview {
|
||||||
# my ($self, $print, $gcode_preview_data, $colors) = @_;
|
# my ($self, $print, $gcode_preview_data, $colors) = @_;
|
||||||
#
|
#
|
||||||
|
@ -376,10 +376,18 @@ sub load_print {
|
|||||||
|
|
||||||
if ($self->gcode_preview_data->empty) {
|
if ($self->gcode_preview_data->empty) {
|
||||||
# load skirt and brim
|
# load skirt and brim
|
||||||
$self->canvas->load_print_toolpaths($self->print, \@colors);
|
#==============================================================================================================================
|
||||||
$self->canvas->load_wipe_tower_toolpaths($self->print, \@colors);
|
Slic3r::GUI::_3DScene::set_print($self->canvas, $self->print);
|
||||||
|
Slic3r::GUI::_3DScene::load_print_toolpaths($self->canvas);
|
||||||
|
Slic3r::GUI::_3DScene::load_wipe_tower_toolpaths($self->canvas, \@colors);
|
||||||
|
# $self->canvas->load_print_toolpaths($self->print, \@colors);
|
||||||
|
# $self->canvas->load_wipe_tower_toolpaths($self->print, \@colors);
|
||||||
|
#==============================================================================================================================
|
||||||
foreach my $object (@{$self->print->objects}) {
|
foreach my $object (@{$self->print->objects}) {
|
||||||
$self->canvas->load_print_object_toolpaths($object, \@colors);
|
#==============================================================================================================================
|
||||||
|
Slic3r::GUI::_3DScene::load_print_object_toolpaths($self->canvas, $object, \@colors);
|
||||||
|
# $self->canvas->load_print_object_toolpaths($object, \@colors);
|
||||||
|
#==============================================================================================================================
|
||||||
# Show the objects in very transparent color.
|
# Show the objects in very transparent color.
|
||||||
#my @volume_ids = $self->canvas->load_object($object->model_object);
|
#my @volume_ids = $self->canvas->load_object($object->model_object);
|
||||||
#$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
|
#$self->canvas->volumes->[$_]->color->[3] = 0.2 for @volume_ids;
|
||||||
|
@ -1348,7 +1348,10 @@ static void point_to_indexed_vertex_array(const Point3& point,
|
|||||||
volume.push_triangle(idxs[0], idxs[3], idxs[4]);
|
volume.push_triangle(idxs[0], idxs[3], idxs[4]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thick_lines_to_verts(
|
//##################################################################################################################
|
||||||
|
void _3DScene::thick_lines_to_verts(
|
||||||
|
//static void thick_lines_to_verts(
|
||||||
|
//##################################################################################################################
|
||||||
const Lines &lines,
|
const Lines &lines,
|
||||||
const std::vector<double> &widths,
|
const std::vector<double> &widths,
|
||||||
const std::vector<double> &heights,
|
const std::vector<double> &heights,
|
||||||
@ -1359,7 +1362,10 @@ static void thick_lines_to_verts(
|
|||||||
thick_lines_to_indexed_vertex_array(lines, widths, heights, closed, top_z, volume.indexed_vertex_array);
|
thick_lines_to_indexed_vertex_array(lines, widths, heights, closed, top_z, volume.indexed_vertex_array);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void thick_lines_to_verts(const Lines3& lines,
|
//##################################################################################################################
|
||||||
|
void _3DScene::thick_lines_to_verts(const Lines3& lines,
|
||||||
|
//static void thick_lines_to_verts(const Lines3& lines,
|
||||||
|
//##################################################################################################################
|
||||||
const std::vector<double>& widths,
|
const std::vector<double>& widths,
|
||||||
const std::vector<double>& heights,
|
const std::vector<double>& heights,
|
||||||
bool closed,
|
bool closed,
|
||||||
@ -2010,6 +2016,21 @@ static inline std::vector<float> parse_colors(const std::vector<std::string> &sc
|
|||||||
}
|
}
|
||||||
|
|
||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
|
void _3DScene::load_print_toolpaths(wxGLCanvas* canvas)
|
||||||
|
{
|
||||||
|
s_canvas_mgr.load_print_toolpaths(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _3DScene::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors)
|
||||||
|
{
|
||||||
|
s_canvas_mgr.load_print_object_toolpaths(canvas, print_object, str_tool_colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _3DScene::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||||
|
{
|
||||||
|
s_canvas_mgr.load_wipe_tower_toolpaths(canvas, str_tool_colors);
|
||||||
|
}
|
||||||
|
|
||||||
void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
void _3DScene::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
||||||
{
|
{
|
||||||
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
s_canvas_mgr.load_gcode_preview(canvas, preview_data, str_tool_colors);
|
||||||
@ -2102,366 +2123,366 @@ unsigned int _3DScene::finalize_warning_texture()
|
|||||||
return s_warning_texture.finalize();
|
return s_warning_texture.finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create 3D thick extrusion lines for a skirt and brim.
|
|
||||||
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
|
||||||
void _3DScene::_load_print_toolpaths(
|
|
||||||
const Print *print,
|
|
||||||
GLVolumeCollection *volumes,
|
|
||||||
const std::vector<std::string> &tool_colors,
|
|
||||||
bool use_VBOs)
|
|
||||||
{
|
|
||||||
if (!print->has_skirt() && print->config.brim_width.value == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
|
||||||
|
|
||||||
// number of skirt layers
|
|
||||||
size_t total_layer_count = 0;
|
|
||||||
for (const PrintObject *print_object : print->objects)
|
|
||||||
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
|
||||||
size_t skirt_height = print->has_infinite_skirt() ?
|
|
||||||
total_layer_count :
|
|
||||||
std::min<size_t>(print->config.skirt_height.value, total_layer_count);
|
|
||||||
if (skirt_height == 0 && print->config.brim_width.value > 0)
|
|
||||||
skirt_height = 1;
|
|
||||||
|
|
||||||
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
|
||||||
const PrintObject *object0 = print->objects.front();
|
|
||||||
std::vector<float> print_zs;
|
|
||||||
print_zs.reserve(skirt_height * 2);
|
|
||||||
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++ i)
|
|
||||||
print_zs.push_back(float(object0->layers[i]->print_z));
|
|
||||||
//FIXME why there are support layers?
|
|
||||||
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++ i)
|
|
||||||
print_zs.push_back(float(object0->support_layers[i]->print_z));
|
|
||||||
sort_remove_duplicates(print_zs);
|
|
||||||
if (print_zs.size() > skirt_height)
|
|
||||||
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
|
||||||
|
|
||||||
volumes->volumes.emplace_back(new GLVolume(color));
|
|
||||||
GLVolume &volume = *volumes->volumes.back();
|
|
||||||
for (size_t i = 0; i < skirt_height; ++ i) {
|
|
||||||
volume.print_zs.push_back(print_zs[i]);
|
|
||||||
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
|
||||||
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
|
||||||
if (i == 0)
|
|
||||||
extrusionentity_to_verts(print->brim, print_zs[i], Point(0, 0), volume);
|
|
||||||
extrusionentity_to_verts(print->skirt, print_zs[i], Point(0, 0), volume);
|
|
||||||
}
|
|
||||||
volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
|
||||||
volume.indexed_vertex_array.finalize_geometry(use_VBOs);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create 3D thick extrusion lines for object forming extrusions.
|
|
||||||
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
|
||||||
// one for perimeters, one for infill and one for supports.
|
|
||||||
void _3DScene::_load_print_object_toolpaths(
|
|
||||||
const PrintObject *print_object,
|
|
||||||
GLVolumeCollection *volumes,
|
|
||||||
const std::vector<std::string> &tool_colors_str,
|
|
||||||
bool use_VBOs)
|
|
||||||
{
|
|
||||||
std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
|
||||||
|
|
||||||
struct Ctxt
|
|
||||||
{
|
|
||||||
const Points *shifted_copies;
|
|
||||||
std::vector<const Layer*> layers;
|
|
||||||
bool has_perimeters;
|
|
||||||
bool has_infill;
|
|
||||||
bool has_support;
|
|
||||||
const std::vector<float>* tool_colors;
|
|
||||||
|
|
||||||
// Number of vertices (each vertex is 6x4=24 bytes long)
|
|
||||||
static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
|
||||||
// static const size_t alloc_size_max () { return 65536; } // 1.57MB
|
|
||||||
// static const size_t alloc_size_max () { return 32768; } // 786kB
|
|
||||||
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
|
||||||
|
|
||||||
static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
|
||||||
static const float* color_infill () { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
|
||||||
static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
|
||||||
|
|
||||||
// For cloring by a tool, return a parsed color.
|
|
||||||
bool color_by_tool() const { return tool_colors != nullptr; }
|
|
||||||
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
|
||||||
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
|
||||||
int volume_idx(int extruder, int feature) const
|
|
||||||
{ return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature; }
|
|
||||||
} ctxt;
|
|
||||||
|
|
||||||
ctxt.shifted_copies = &print_object->_shifted_copies;
|
|
||||||
|
|
||||||
// order layers by print_z
|
|
||||||
ctxt.layers.reserve(print_object->layers.size() + print_object->support_layers.size());
|
|
||||||
for (const Layer *layer : print_object->layers)
|
|
||||||
ctxt.layers.push_back(layer);
|
|
||||||
for (const Layer *layer : print_object->support_layers)
|
|
||||||
ctxt.layers.push_back(layer);
|
|
||||||
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
|
||||||
|
|
||||||
// Maximum size of an allocation block: 32MB / sizeof(float)
|
|
||||||
ctxt.has_perimeters = print_object->state.is_done(posPerimeters);
|
|
||||||
ctxt.has_infill = print_object->state.is_done(posInfill);
|
|
||||||
ctxt.has_support = print_object->state.is_done(posSupportMaterial);
|
|
||||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
|
||||||
|
|
||||||
//FIXME Improve the heuristics for a grain size.
|
|
||||||
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
|
||||||
tbb::spin_mutex new_volume_mutex;
|
|
||||||
auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
|
||||||
auto *volume = new GLVolume(color);
|
|
||||||
new_volume_mutex.lock();
|
|
||||||
volume->outside_printer_detection_enabled = false;
|
|
||||||
volumes->volumes.emplace_back(volume);
|
|
||||||
new_volume_mutex.unlock();
|
|
||||||
return volume;
|
|
||||||
};
|
|
||||||
const size_t volumes_cnt_initial = volumes->volumes.size();
|
|
||||||
std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
|
||||||
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
|
||||||
std::vector<GLVolume*> vols;
|
|
||||||
if (ctxt.color_by_tool()) {
|
|
||||||
for (size_t i = 0; i < ctxt.number_tools(); ++ i)
|
|
||||||
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
|
||||||
} else
|
|
||||||
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
|
||||||
for (GLVolume *vol : vols)
|
|
||||||
vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
|
||||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
|
||||||
const Layer *layer = ctxt.layers[idx_layer];
|
|
||||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
|
||||||
GLVolume &vol = *vols[i];
|
|
||||||
if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
|
|
||||||
vol.print_zs.push_back(layer->print_z);
|
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const Point ©: *ctxt.shifted_copies) {
|
|
||||||
for (const LayerRegion *layerm : layer->regions) {
|
|
||||||
if (ctxt.has_perimeters)
|
|
||||||
extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
|
||||||
*vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
|
|
||||||
if (ctxt.has_infill) {
|
|
||||||
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
|
||||||
// fill represents infill extrusions of a single island.
|
|
||||||
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
|
||||||
if (! fill->entities.empty())
|
|
||||||
extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
|
||||||
*vols[ctxt.volume_idx(
|
|
||||||
is_solid_infill(fill->entities.front()->role()) ?
|
|
||||||
layerm->region()->config.solid_infill_extruder :
|
|
||||||
layerm->region()->config.infill_extruder,
|
|
||||||
1)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ctxt.has_support) {
|
|
||||||
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
|
||||||
if (support_layer) {
|
|
||||||
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
|
||||||
extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
|
||||||
*vols[ctxt.volume_idx(
|
|
||||||
(extrusion_entity->role() == erSupportMaterial) ?
|
|
||||||
support_layer->object()->config.support_material_extruder :
|
|
||||||
support_layer->object()->config.support_material_interface_extruder,
|
|
||||||
2)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
|
||||||
GLVolume &vol = *vols[i];
|
|
||||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
|
||||||
// Store the vertex arrays and restart their containers,
|
|
||||||
vols[i] = new_volume(vol.color);
|
|
||||||
GLVolume &vol_new = *vols[i];
|
|
||||||
// Assign the large pre-allocated buffers to the new GLVolume.
|
|
||||||
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
|
||||||
// Copy the content back to the old GLVolume.
|
|
||||||
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
|
||||||
// Finalize a bounding box of the old GLVolume.
|
|
||||||
vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
|
||||||
// Clear the buffers, but keep them pre-allocated.
|
|
||||||
vol_new.indexed_vertex_array.clear();
|
|
||||||
// Just make sure that clear did not clear the reserved memory.
|
|
||||||
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (GLVolume *vol : vols) {
|
|
||||||
vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
|
||||||
vol->indexed_vertex_array.shrink_to_fit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
|
|
||||||
// Remove empty volumes from the newly added volumes.
|
|
||||||
volumes->volumes.erase(
|
|
||||||
std::remove_if(volumes->volumes.begin() + volumes_cnt_initial, volumes->volumes.end(),
|
|
||||||
[](const GLVolume *volume) { return volume->empty(); }),
|
|
||||||
volumes->volumes.end());
|
|
||||||
for (size_t i = volumes_cnt_initial; i < volumes->volumes.size(); ++ i)
|
|
||||||
volumes->volumes[i]->indexed_vertex_array.finalize_geometry(use_VBOs);
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
|
||||||
}
|
|
||||||
|
|
||||||
void _3DScene::_load_wipe_tower_toolpaths(
|
|
||||||
const Print *print,
|
|
||||||
GLVolumeCollection *volumes,
|
|
||||||
const std::vector<std::string> &tool_colors_str,
|
|
||||||
bool use_VBOs)
|
|
||||||
{
|
|
||||||
if (print->m_wipe_tower_tool_changes.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
|
||||||
|
|
||||||
struct Ctxt
|
|
||||||
{
|
|
||||||
const Print *print;
|
|
||||||
const std::vector<float> *tool_colors;
|
|
||||||
|
|
||||||
// Number of vertices (each vertex is 6x4=24 bytes long)
|
|
||||||
static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
|
||||||
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
|
||||||
|
|
||||||
static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
|
||||||
|
|
||||||
// For cloring by a tool, return a parsed color.
|
|
||||||
bool color_by_tool() const { return tool_colors != nullptr; }
|
|
||||||
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
|
||||||
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
|
||||||
int volume_idx(int tool, int feature) const
|
|
||||||
{ return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature; }
|
|
||||||
|
|
||||||
const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
|
||||||
return priming.empty() ?
|
|
||||||
((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
|
|
||||||
((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
|
|
||||||
}
|
|
||||||
std::vector<WipeTower::ToolChangeResult> priming;
|
|
||||||
std::vector<WipeTower::ToolChangeResult> final;
|
|
||||||
} ctxt;
|
|
||||||
|
|
||||||
ctxt.print = print;
|
|
||||||
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
|
||||||
if (print->m_wipe_tower_priming)
|
|
||||||
ctxt.priming.emplace_back(*print->m_wipe_tower_priming.get());
|
|
||||||
if (print->m_wipe_tower_final_purge)
|
|
||||||
ctxt.final.emplace_back(*print->m_wipe_tower_final_purge.get());
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
|
||||||
|
|
||||||
//FIXME Improve the heuristics for a grain size.
|
|
||||||
size_t n_items = print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
|
||||||
size_t grain_size = std::max(n_items / 128, size_t(1));
|
|
||||||
tbb::spin_mutex new_volume_mutex;
|
|
||||||
auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
|
||||||
auto *volume = new GLVolume(color);
|
|
||||||
new_volume_mutex.lock();
|
|
||||||
volume->outside_printer_detection_enabled = false;
|
|
||||||
volumes->volumes.emplace_back(volume);
|
|
||||||
new_volume_mutex.unlock();
|
|
||||||
return volume;
|
|
||||||
};
|
|
||||||
const size_t volumes_cnt_initial = volumes->volumes.size();
|
|
||||||
std::vector<GLVolumeCollection> volumes_per_thread(n_items);
|
|
||||||
tbb::parallel_for(
|
|
||||||
tbb::blocked_range<size_t>(0, n_items, grain_size),
|
|
||||||
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
|
||||||
// Bounding box of this slab of a wipe tower.
|
|
||||||
std::vector<GLVolume*> vols;
|
|
||||||
if (ctxt.color_by_tool()) {
|
|
||||||
for (size_t i = 0; i < ctxt.number_tools(); ++ i)
|
|
||||||
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
|
||||||
} else
|
|
||||||
vols = { new_volume(ctxt.color_support()) };
|
|
||||||
for (GLVolume *volume : vols)
|
|
||||||
volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
|
||||||
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
|
||||||
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
|
|
||||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
|
||||||
GLVolume &vol = *vols[i];
|
|
||||||
if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
|
|
||||||
vol.print_zs.push_back(layer.front().print_z);
|
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
|
||||||
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const WipeTower::ToolChangeResult &extrusions : layer) {
|
|
||||||
for (size_t i = 1; i < extrusions.extrusions.size();) {
|
|
||||||
const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
|
||||||
if (e.width == 0.) {
|
|
||||||
++ i;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
size_t j = i + 1;
|
|
||||||
if (ctxt.color_by_tool())
|
|
||||||
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.f; ++ j) ;
|
|
||||||
else
|
|
||||||
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.f; ++ j) ;
|
|
||||||
size_t n_lines = j - i;
|
|
||||||
Lines lines;
|
|
||||||
std::vector<double> widths;
|
|
||||||
std::vector<double> heights;
|
|
||||||
lines.reserve(n_lines);
|
|
||||||
widths.reserve(n_lines);
|
|
||||||
heights.assign(n_lines, extrusions.layer_height);
|
|
||||||
for (; i < j; ++ i) {
|
|
||||||
const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
|
||||||
assert(e.width > 0.f);
|
|
||||||
const WipeTower::Extrusion &e_prev = *(&e - 1);
|
|
||||||
lines.emplace_back(Point::new_scale(e_prev.pos.x, e_prev.pos.y), Point::new_scale(e.pos.x, e.pos.y));
|
|
||||||
widths.emplace_back(e.width);
|
|
||||||
}
|
|
||||||
thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
|
|
||||||
*vols[ctxt.volume_idx(e.tool, 0)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t i = 0; i < vols.size(); ++ i) {
|
|
||||||
GLVolume &vol = *vols[i];
|
|
||||||
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
|
||||||
// Store the vertex arrays and restart their containers,
|
|
||||||
vols[i] = new_volume(vol.color);
|
|
||||||
GLVolume &vol_new = *vols[i];
|
|
||||||
// Assign the large pre-allocated buffers to the new GLVolume.
|
|
||||||
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
|
||||||
// Copy the content back to the old GLVolume.
|
|
||||||
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
|
||||||
// Finalize a bounding box of the old GLVolume.
|
|
||||||
vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
|
||||||
// Clear the buffers, but keep them pre-allocated.
|
|
||||||
vol_new.indexed_vertex_array.clear();
|
|
||||||
// Just make sure that clear did not clear the reserved memory.
|
|
||||||
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (GLVolume *vol : vols) {
|
|
||||||
vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
|
||||||
vol->indexed_vertex_array.shrink_to_fit();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
|
|
||||||
// Remove empty volumes from the newly added volumes.
|
|
||||||
volumes->volumes.erase(
|
|
||||||
std::remove_if(volumes->volumes.begin() + volumes_cnt_initial, volumes->volumes.end(),
|
|
||||||
[](const GLVolume *volume) { return volume->empty(); }),
|
|
||||||
volumes->volumes.end());
|
|
||||||
for (size_t i = volumes_cnt_initial; i < volumes->volumes.size(); ++ i)
|
|
||||||
volumes->volumes[i]->indexed_vertex_array.finalize_geometry(use_VBOs);
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
|
|
||||||
}
|
|
||||||
|
|
||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
|
//// Create 3D thick extrusion lines for a skirt and brim.
|
||||||
|
//// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||||
|
//void _3DScene::_load_print_toolpaths(
|
||||||
|
// const Print *print,
|
||||||
|
// GLVolumeCollection *volumes,
|
||||||
|
// const std::vector<std::string> &tool_colors,
|
||||||
|
// bool use_VBOs)
|
||||||
|
//{
|
||||||
|
// if (!print->has_skirt() && print->config.brim_width.value == 0)
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// const float color[] = { 0.5f, 1.0f, 0.5f, 1.f }; // greenish
|
||||||
|
//
|
||||||
|
// // number of skirt layers
|
||||||
|
// size_t total_layer_count = 0;
|
||||||
|
// for (const PrintObject *print_object : print->objects)
|
||||||
|
// total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||||
|
// size_t skirt_height = print->has_infinite_skirt() ?
|
||||||
|
// total_layer_count :
|
||||||
|
// std::min<size_t>(print->config.skirt_height.value, total_layer_count);
|
||||||
|
// if (skirt_height == 0 && print->config.brim_width.value > 0)
|
||||||
|
// skirt_height = 1;
|
||||||
|
//
|
||||||
|
// // get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
||||||
|
// const PrintObject *object0 = print->objects.front();
|
||||||
|
// std::vector<float> print_zs;
|
||||||
|
// print_zs.reserve(skirt_height * 2);
|
||||||
|
// for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++ i)
|
||||||
|
// print_zs.push_back(float(object0->layers[i]->print_z));
|
||||||
|
// //FIXME why there are support layers?
|
||||||
|
// for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++ i)
|
||||||
|
// print_zs.push_back(float(object0->support_layers[i]->print_z));
|
||||||
|
// sort_remove_duplicates(print_zs);
|
||||||
|
// if (print_zs.size() > skirt_height)
|
||||||
|
// print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
||||||
|
//
|
||||||
|
// volumes->volumes.emplace_back(new GLVolume(color));
|
||||||
|
// GLVolume &volume = *volumes->volumes.back();
|
||||||
|
// for (size_t i = 0; i < skirt_height; ++ i) {
|
||||||
|
// volume.print_zs.push_back(print_zs[i]);
|
||||||
|
// volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
||||||
|
// volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
||||||
|
// if (i == 0)
|
||||||
|
// extrusionentity_to_verts(print->brim, print_zs[i], Point(0, 0), volume);
|
||||||
|
// extrusionentity_to_verts(print->skirt, print_zs[i], Point(0, 0), volume);
|
||||||
|
// }
|
||||||
|
// volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
||||||
|
// volume.indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//// Create 3D thick extrusion lines for object forming extrusions.
|
||||||
|
//// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||||
|
//// one for perimeters, one for infill and one for supports.
|
||||||
|
//void _3DScene::_load_print_object_toolpaths(
|
||||||
|
// const PrintObject *print_object,
|
||||||
|
// GLVolumeCollection *volumes,
|
||||||
|
// const std::vector<std::string> &tool_colors_str,
|
||||||
|
// bool use_VBOs)
|
||||||
|
//{
|
||||||
|
// std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
||||||
|
//
|
||||||
|
// struct Ctxt
|
||||||
|
// {
|
||||||
|
// const Points *shifted_copies;
|
||||||
|
// std::vector<const Layer*> layers;
|
||||||
|
// bool has_perimeters;
|
||||||
|
// bool has_infill;
|
||||||
|
// bool has_support;
|
||||||
|
// const std::vector<float>* tool_colors;
|
||||||
|
//
|
||||||
|
// // Number of vertices (each vertex is 6x4=24 bytes long)
|
||||||
|
// static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
||||||
|
//// static const size_t alloc_size_max () { return 65536; } // 1.57MB
|
||||||
|
//// static const size_t alloc_size_max () { return 32768; } // 786kB
|
||||||
|
// static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||||
|
//
|
||||||
|
// static const float* color_perimeters () { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
||||||
|
// static const float* color_infill () { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
||||||
|
// static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||||
|
//
|
||||||
|
// // For cloring by a tool, return a parsed color.
|
||||||
|
// bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
|
// size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
||||||
|
// const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
||||||
|
// int volume_idx(int extruder, int feature) const
|
||||||
|
// { return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature; }
|
||||||
|
// } ctxt;
|
||||||
|
//
|
||||||
|
// ctxt.shifted_copies = &print_object->_shifted_copies;
|
||||||
|
//
|
||||||
|
// // order layers by print_z
|
||||||
|
// ctxt.layers.reserve(print_object->layers.size() + print_object->support_layers.size());
|
||||||
|
// for (const Layer *layer : print_object->layers)
|
||||||
|
// ctxt.layers.push_back(layer);
|
||||||
|
// for (const Layer *layer : print_object->support_layers)
|
||||||
|
// ctxt.layers.push_back(layer);
|
||||||
|
// std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||||
|
//
|
||||||
|
// // Maximum size of an allocation block: 32MB / sizeof(float)
|
||||||
|
// ctxt.has_perimeters = print_object->state.is_done(posPerimeters);
|
||||||
|
// ctxt.has_infill = print_object->state.is_done(posInfill);
|
||||||
|
// ctxt.has_support = print_object->state.is_done(posSupportMaterial);
|
||||||
|
// ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
||||||
|
//
|
||||||
|
// //FIXME Improve the heuristics for a grain size.
|
||||||
|
// size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
||||||
|
// tbb::spin_mutex new_volume_mutex;
|
||||||
|
// auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||||
|
// auto *volume = new GLVolume(color);
|
||||||
|
// new_volume_mutex.lock();
|
||||||
|
// volume->outside_printer_detection_enabled = false;
|
||||||
|
// volumes->volumes.emplace_back(volume);
|
||||||
|
// new_volume_mutex.unlock();
|
||||||
|
// return volume;
|
||||||
|
// };
|
||||||
|
// const size_t volumes_cnt_initial = volumes->volumes.size();
|
||||||
|
// std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
|
||||||
|
// tbb::parallel_for(
|
||||||
|
// tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||||
|
// [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||||
|
// std::vector<GLVolume*> vols;
|
||||||
|
// if (ctxt.color_by_tool()) {
|
||||||
|
// for (size_t i = 0; i < ctxt.number_tools(); ++ i)
|
||||||
|
// vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
// } else
|
||||||
|
// vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
||||||
|
// for (GLVolume *vol : vols)
|
||||||
|
// vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
// for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||||
|
// const Layer *layer = ctxt.layers[idx_layer];
|
||||||
|
// for (size_t i = 0; i < vols.size(); ++ i) {
|
||||||
|
// GLVolume &vol = *vols[i];
|
||||||
|
// if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
|
||||||
|
// vol.print_zs.push_back(layer->print_z);
|
||||||
|
// vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
||||||
|
// vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (const Point ©: *ctxt.shifted_copies) {
|
||||||
|
// for (const LayerRegion *layerm : layer->regions) {
|
||||||
|
// if (ctxt.has_perimeters)
|
||||||
|
// extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
||||||
|
// *vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
|
||||||
|
// if (ctxt.has_infill) {
|
||||||
|
// for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||||
|
// // fill represents infill extrusions of a single island.
|
||||||
|
// const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||||
|
// if (! fill->entities.empty())
|
||||||
|
// extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
||||||
|
// *vols[ctxt.volume_idx(
|
||||||
|
// is_solid_infill(fill->entities.front()->role()) ?
|
||||||
|
// layerm->region()->config.solid_infill_extruder :
|
||||||
|
// layerm->region()->config.infill_extruder,
|
||||||
|
// 1)]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if (ctxt.has_support) {
|
||||||
|
// const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
||||||
|
// if (support_layer) {
|
||||||
|
// for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
||||||
|
// extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||||
|
// *vols[ctxt.volume_idx(
|
||||||
|
// (extrusion_entity->role() == erSupportMaterial) ?
|
||||||
|
// support_layer->object()->config.support_material_extruder :
|
||||||
|
// support_layer->object()->config.support_material_interface_extruder,
|
||||||
|
// 2)]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (size_t i = 0; i < vols.size(); ++ i) {
|
||||||
|
// GLVolume &vol = *vols[i];
|
||||||
|
// if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||||
|
// // Store the vertex arrays and restart their containers,
|
||||||
|
// vols[i] = new_volume(vol.color);
|
||||||
|
// GLVolume &vol_new = *vols[i];
|
||||||
|
// // Assign the large pre-allocated buffers to the new GLVolume.
|
||||||
|
// vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
||||||
|
// // Copy the content back to the old GLVolume.
|
||||||
|
// vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
||||||
|
// // Finalize a bounding box of the old GLVolume.
|
||||||
|
// vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
||||||
|
// // Clear the buffers, but keep them pre-allocated.
|
||||||
|
// vol_new.indexed_vertex_array.clear();
|
||||||
|
// // Just make sure that clear did not clear the reserved memory.
|
||||||
|
// vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (GLVolume *vol : vols) {
|
||||||
|
// vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
||||||
|
// vol->indexed_vertex_array.shrink_to_fit();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
|
||||||
|
// // Remove empty volumes from the newly added volumes.
|
||||||
|
// volumes->volumes.erase(
|
||||||
|
// std::remove_if(volumes->volumes.begin() + volumes_cnt_initial, volumes->volumes.end(),
|
||||||
|
// [](const GLVolume *volume) { return volume->empty(); }),
|
||||||
|
// volumes->volumes.end());
|
||||||
|
// for (size_t i = volumes_cnt_initial; i < volumes->volumes.size(); ++ i)
|
||||||
|
// volumes->volumes[i]->indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//void _3DScene::_load_wipe_tower_toolpaths(
|
||||||
|
// const Print *print,
|
||||||
|
// GLVolumeCollection *volumes,
|
||||||
|
// const std::vector<std::string> &tool_colors_str,
|
||||||
|
// bool use_VBOs)
|
||||||
|
//{
|
||||||
|
// if (print->m_wipe_tower_tool_changes.empty())
|
||||||
|
// return;
|
||||||
|
//
|
||||||
|
// std::vector<float> tool_colors = parse_colors(tool_colors_str);
|
||||||
|
//
|
||||||
|
// struct Ctxt
|
||||||
|
// {
|
||||||
|
// const Print *print;
|
||||||
|
// const std::vector<float> *tool_colors;
|
||||||
|
//
|
||||||
|
// // Number of vertices (each vertex is 6x4=24 bytes long)
|
||||||
|
// static const size_t alloc_size_max () { return 131072; } // 3.15MB
|
||||||
|
// static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||||
|
//
|
||||||
|
// static const float* color_support () { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||||
|
//
|
||||||
|
// // For cloring by a tool, return a parsed color.
|
||||||
|
// bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
|
// size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
||||||
|
// const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
||||||
|
// int volume_idx(int tool, int feature) const
|
||||||
|
// { return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature; }
|
||||||
|
//
|
||||||
|
// const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
||||||
|
// return priming.empty() ?
|
||||||
|
// ((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
|
||||||
|
// ((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
|
||||||
|
// }
|
||||||
|
// std::vector<WipeTower::ToolChangeResult> priming;
|
||||||
|
// std::vector<WipeTower::ToolChangeResult> final;
|
||||||
|
// } ctxt;
|
||||||
|
//
|
||||||
|
// ctxt.print = print;
|
||||||
|
// ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||||
|
// if (print->m_wipe_tower_priming)
|
||||||
|
// ctxt.priming.emplace_back(*print->m_wipe_tower_priming.get());
|
||||||
|
// if (print->m_wipe_tower_final_purge)
|
||||||
|
// ctxt.final.emplace_back(*print->m_wipe_tower_final_purge.get());
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
||||||
|
//
|
||||||
|
// //FIXME Improve the heuristics for a grain size.
|
||||||
|
// size_t n_items = print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||||
|
// size_t grain_size = std::max(n_items / 128, size_t(1));
|
||||||
|
// tbb::spin_mutex new_volume_mutex;
|
||||||
|
// auto new_volume = [volumes, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||||
|
// auto *volume = new GLVolume(color);
|
||||||
|
// new_volume_mutex.lock();
|
||||||
|
// volume->outside_printer_detection_enabled = false;
|
||||||
|
// volumes->volumes.emplace_back(volume);
|
||||||
|
// new_volume_mutex.unlock();
|
||||||
|
// return volume;
|
||||||
|
// };
|
||||||
|
// const size_t volumes_cnt_initial = volumes->volumes.size();
|
||||||
|
// std::vector<GLVolumeCollection> volumes_per_thread(n_items);
|
||||||
|
// tbb::parallel_for(
|
||||||
|
// tbb::blocked_range<size_t>(0, n_items, grain_size),
|
||||||
|
// [&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||||
|
// // Bounding box of this slab of a wipe tower.
|
||||||
|
// std::vector<GLVolume*> vols;
|
||||||
|
// if (ctxt.color_by_tool()) {
|
||||||
|
// for (size_t i = 0; i < ctxt.number_tools(); ++ i)
|
||||||
|
// vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
// } else
|
||||||
|
// vols = { new_volume(ctxt.color_support()) };
|
||||||
|
// for (GLVolume *volume : vols)
|
||||||
|
// volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
// for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++ idx_layer) {
|
||||||
|
// const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
|
||||||
|
// for (size_t i = 0; i < vols.size(); ++ i) {
|
||||||
|
// GLVolume &vol = *vols[i];
|
||||||
|
// if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
|
||||||
|
// vol.print_zs.push_back(layer.front().print_z);
|
||||||
|
// vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
||||||
|
// vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (const WipeTower::ToolChangeResult &extrusions : layer) {
|
||||||
|
// for (size_t i = 1; i < extrusions.extrusions.size();) {
|
||||||
|
// const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
||||||
|
// if (e.width == 0.) {
|
||||||
|
// ++ i;
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// size_t j = i + 1;
|
||||||
|
// if (ctxt.color_by_tool())
|
||||||
|
// for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.f; ++ j) ;
|
||||||
|
// else
|
||||||
|
// for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.f; ++ j) ;
|
||||||
|
// size_t n_lines = j - i;
|
||||||
|
// Lines lines;
|
||||||
|
// std::vector<double> widths;
|
||||||
|
// std::vector<double> heights;
|
||||||
|
// lines.reserve(n_lines);
|
||||||
|
// widths.reserve(n_lines);
|
||||||
|
// heights.assign(n_lines, extrusions.layer_height);
|
||||||
|
// for (; i < j; ++ i) {
|
||||||
|
// const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
||||||
|
// assert(e.width > 0.f);
|
||||||
|
// const WipeTower::Extrusion &e_prev = *(&e - 1);
|
||||||
|
// lines.emplace_back(Point::new_scale(e_prev.pos.x, e_prev.pos.y), Point::new_scale(e.pos.x, e.pos.y));
|
||||||
|
// widths.emplace_back(e.width);
|
||||||
|
// }
|
||||||
|
// thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
|
||||||
|
// *vols[ctxt.volume_idx(e.tool, 0)]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (size_t i = 0; i < vols.size(); ++ i) {
|
||||||
|
// GLVolume &vol = *vols[i];
|
||||||
|
// if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||||
|
// // Store the vertex arrays and restart their containers,
|
||||||
|
// vols[i] = new_volume(vol.color);
|
||||||
|
// GLVolume &vol_new = *vols[i];
|
||||||
|
// // Assign the large pre-allocated buffers to the new GLVolume.
|
||||||
|
// vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
||||||
|
// // Copy the content back to the old GLVolume.
|
||||||
|
// vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
||||||
|
// // Finalize a bounding box of the old GLVolume.
|
||||||
|
// vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
||||||
|
// // Clear the buffers, but keep them pre-allocated.
|
||||||
|
// vol_new.indexed_vertex_array.clear();
|
||||||
|
// // Just make sure that clear did not clear the reserved memory.
|
||||||
|
// vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (GLVolume *vol : vols) {
|
||||||
|
// vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
||||||
|
// vol->indexed_vertex_array.shrink_to_fit();
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
|
||||||
|
// // Remove empty volumes from the newly added volumes.
|
||||||
|
// volumes->volumes.erase(
|
||||||
|
// std::remove_if(volumes->volumes.begin() + volumes_cnt_initial, volumes->volumes.end(),
|
||||||
|
// [](const GLVolume *volume) { return volume->empty(); }),
|
||||||
|
// volumes->volumes.end());
|
||||||
|
// for (size_t i = volumes_cnt_initial; i < volumes->volumes.size(); ++ i)
|
||||||
|
// volumes->volumes[i]->indexed_vertex_array.finalize_geometry(use_VBOs);
|
||||||
|
//
|
||||||
|
// BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
|
||||||
|
//}
|
||||||
|
//
|
||||||
//void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs)
|
//void _3DScene::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, GLVolumeCollection& volumes, const std::vector<float>& tool_colors, bool use_VBOs)
|
||||||
//{
|
//{
|
||||||
// // helper functions to select data in dependence of the extrusion view type
|
// // helper functions to select data in dependence of the extrusion view type
|
||||||
|
@ -611,6 +611,9 @@ public:
|
|||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
|
|
||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
|
static void load_print_toolpaths(wxGLCanvas* canvas);
|
||||||
|
static void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& str_tool_colors);
|
||||||
|
static void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||||
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
static void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
// static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs);
|
// static void load_gcode_preview(const Print* print, const GCodePreviewData* preview_data, GLVolumeCollection* volumes, const std::vector<std::string>& str_tool_colors, bool use_VBOs);
|
||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
@ -633,25 +636,29 @@ public:
|
|||||||
static void reset_warning_texture();
|
static void reset_warning_texture();
|
||||||
static unsigned int finalize_warning_texture();
|
static unsigned int finalize_warning_texture();
|
||||||
|
|
||||||
static void _load_print_toolpaths(
|
//##################################################################################################################
|
||||||
const Print *print,
|
// static void _load_print_toolpaths(
|
||||||
GLVolumeCollection *volumes,
|
// const Print *print,
|
||||||
const std::vector<std::string> &tool_colors,
|
// GLVolumeCollection *volumes,
|
||||||
bool use_VBOs);
|
// const std::vector<std::string> &tool_colors,
|
||||||
|
// bool use_VBOs);
|
||||||
static void _load_print_object_toolpaths(
|
//
|
||||||
const PrintObject *print_object,
|
// static void _load_print_object_toolpaths(
|
||||||
GLVolumeCollection *volumes,
|
// const PrintObject *print_object,
|
||||||
const std::vector<std::string> &tool_colors,
|
// GLVolumeCollection *volumes,
|
||||||
bool use_VBOs);
|
// const std::vector<std::string> &tool_colors,
|
||||||
|
// bool use_VBOs);
|
||||||
static void _load_wipe_tower_toolpaths(
|
//
|
||||||
const Print *print,
|
// static void _load_wipe_tower_toolpaths(
|
||||||
GLVolumeCollection *volumes,
|
// const Print *print,
|
||||||
const std::vector<std::string> &tool_colors_str,
|
// GLVolumeCollection *volumes,
|
||||||
bool use_VBOs);
|
// const std::vector<std::string> &tool_colors_str,
|
||||||
|
// bool use_VBOs);
|
||||||
|
//##################################################################################################################
|
||||||
|
|
||||||
//##################################################################################################################
|
//##################################################################################################################
|
||||||
|
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 ExtrusionPath& extrusion_path, 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 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);
|
static void extrusionentity_to_verts(const ExtrusionLoop& extrusion_loop, float print_z, const Point& copy, GLVolume& volume);
|
||||||
|
@ -13,6 +13,11 @@
|
|||||||
#include <wx/image.h>
|
#include <wx/image.h>
|
||||||
#include <wx/timer.h>
|
#include <wx/timer.h>
|
||||||
|
|
||||||
|
#include <tbb/parallel_for.h>
|
||||||
|
#include <tbb/spin_mutex.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
|
|
||||||
@ -1346,6 +1351,371 @@ void GLCanvas3D::set_toolpaths_range(double low, double high)
|
|||||||
m_volumes->set_range(low, high);
|
m_volumes->set_range(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::load_print_toolpaths()
|
||||||
|
{
|
||||||
|
if ((m_print == nullptr) || (m_volumes == nullptr))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_print->state.is_done(psSkirt) || !m_print->state.is_done(psBrim))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_print->has_skirt() && (m_print->config.brim_width.value == 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const float color[] = { 0.5f, 1.0f, 0.5f, 1.0f }; // greenish
|
||||||
|
|
||||||
|
// number of skirt layers
|
||||||
|
size_t total_layer_count = 0;
|
||||||
|
for (const PrintObject* print_object : m_print->objects)
|
||||||
|
{
|
||||||
|
total_layer_count = std::max(total_layer_count, print_object->total_layer_count());
|
||||||
|
}
|
||||||
|
size_t skirt_height = m_print->has_infinite_skirt() ? total_layer_count : std::min<size_t>(m_print->config.skirt_height.value, total_layer_count);
|
||||||
|
if ((skirt_height == 0) && (m_print->config.brim_width.value > 0))
|
||||||
|
skirt_height = 1;
|
||||||
|
|
||||||
|
// get first skirt_height layers (maybe this should be moved to a PrintObject method?)
|
||||||
|
const PrintObject* object0 = m_print->objects.front();
|
||||||
|
std::vector<float> print_zs;
|
||||||
|
print_zs.reserve(skirt_height * 2);
|
||||||
|
for (size_t i = 0; i < std::min(skirt_height, object0->layers.size()); ++i)
|
||||||
|
{
|
||||||
|
print_zs.push_back(float(object0->layers[i]->print_z));
|
||||||
|
}
|
||||||
|
//FIXME why there are support layers?
|
||||||
|
for (size_t i = 0; i < std::min(skirt_height, object0->support_layers.size()); ++i)
|
||||||
|
{
|
||||||
|
print_zs.push_back(float(object0->support_layers[i]->print_z));
|
||||||
|
}
|
||||||
|
sort_remove_duplicates(print_zs);
|
||||||
|
if (print_zs.size() > skirt_height)
|
||||||
|
print_zs.erase(print_zs.begin() + skirt_height, print_zs.end());
|
||||||
|
|
||||||
|
m_volumes->volumes.emplace_back(new GLVolume(color));
|
||||||
|
GLVolume& volume = *m_volumes->volumes.back();
|
||||||
|
for (size_t i = 0; i < skirt_height; ++i) {
|
||||||
|
volume.print_zs.push_back(print_zs[i]);
|
||||||
|
volume.offsets.push_back(volume.indexed_vertex_array.quad_indices.size());
|
||||||
|
volume.offsets.push_back(volume.indexed_vertex_array.triangle_indices.size());
|
||||||
|
if (i == 0)
|
||||||
|
_3DScene::extrusionentity_to_verts(m_print->brim, print_zs[i], Point(0, 0), volume);
|
||||||
|
|
||||||
|
_3DScene::extrusionentity_to_verts(m_print->skirt, print_zs[i], Point(0, 0), volume);
|
||||||
|
}
|
||||||
|
volume.bounding_box = volume.indexed_vertex_array.bounding_box();
|
||||||
|
volume.indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors)
|
||||||
|
{
|
||||||
|
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
|
||||||
|
|
||||||
|
struct Ctxt
|
||||||
|
{
|
||||||
|
const Points *shifted_copies;
|
||||||
|
std::vector<const Layer*> layers;
|
||||||
|
bool has_perimeters;
|
||||||
|
bool has_infill;
|
||||||
|
bool has_support;
|
||||||
|
const std::vector<float>* tool_colors;
|
||||||
|
|
||||||
|
// Number of vertices (each vertex is 6x4=24 bytes long)
|
||||||
|
static const size_t alloc_size_max() { return 131072; } // 3.15MB
|
||||||
|
// static const size_t alloc_size_max () { return 65536; } // 1.57MB
|
||||||
|
// static const size_t alloc_size_max () { return 32768; } // 786kB
|
||||||
|
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||||
|
|
||||||
|
static const float* color_perimeters() { static float color[4] = { 1.0f, 1.0f, 0.0f, 1.f }; return color; } // yellow
|
||||||
|
static const float* color_infill() { static float color[4] = { 1.0f, 0.5f, 0.5f, 1.f }; return color; } // redish
|
||||||
|
static const float* color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||||
|
|
||||||
|
// For cloring by a tool, return a parsed color.
|
||||||
|
bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
|
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
||||||
|
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
||||||
|
int volume_idx(int extruder, int feature) const
|
||||||
|
{
|
||||||
|
return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(extruder - 1, 0)) : feature;
|
||||||
|
}
|
||||||
|
} ctxt;
|
||||||
|
|
||||||
|
if (m_volumes == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ctxt.shifted_copies = &print_object._shifted_copies;
|
||||||
|
|
||||||
|
// order layers by print_z
|
||||||
|
ctxt.layers.reserve(print_object.layers.size() + print_object.support_layers.size());
|
||||||
|
for (const Layer *layer : print_object.layers)
|
||||||
|
ctxt.layers.push_back(layer);
|
||||||
|
for (const Layer *layer : print_object.support_layers)
|
||||||
|
ctxt.layers.push_back(layer);
|
||||||
|
std::sort(ctxt.layers.begin(), ctxt.layers.end(), [](const Layer *l1, const Layer *l2) { return l1->print_z < l2->print_z; });
|
||||||
|
|
||||||
|
// Maximum size of an allocation block: 32MB / sizeof(float)
|
||||||
|
ctxt.has_perimeters = print_object.state.is_done(posPerimeters);
|
||||||
|
ctxt.has_infill = print_object.state.is_done(posInfill);
|
||||||
|
ctxt.has_support = print_object.state.is_done(posSupportMaterial);
|
||||||
|
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - start";
|
||||||
|
|
||||||
|
//FIXME Improve the heuristics for a grain size.
|
||||||
|
size_t grain_size = std::max(ctxt.layers.size() / 16, size_t(1));
|
||||||
|
tbb::spin_mutex new_volume_mutex;
|
||||||
|
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||||
|
auto *volume = new GLVolume(color);
|
||||||
|
new_volume_mutex.lock();
|
||||||
|
volume->outside_printer_detection_enabled = false;
|
||||||
|
m_volumes->volumes.emplace_back(volume);
|
||||||
|
new_volume_mutex.unlock();
|
||||||
|
return volume;
|
||||||
|
};
|
||||||
|
const size_t volumes_cnt_initial = m_volumes->volumes.size();
|
||||||
|
std::vector<GLVolumeCollection> volumes_per_thread(ctxt.layers.size());
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, ctxt.layers.size(), grain_size),
|
||||||
|
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||||
|
std::vector<GLVolume*> vols;
|
||||||
|
if (ctxt.color_by_tool()) {
|
||||||
|
for (size_t i = 0; i < ctxt.number_tools(); ++i)
|
||||||
|
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vols = { new_volume(ctxt.color_perimeters()), new_volume(ctxt.color_infill()), new_volume(ctxt.color_support()) };
|
||||||
|
for (GLVolume *vol : vols)
|
||||||
|
vol->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
|
||||||
|
const Layer *layer = ctxt.layers[idx_layer];
|
||||||
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
|
GLVolume &vol = *vols[i];
|
||||||
|
if (vol.print_zs.empty() || vol.print_zs.back() != layer->print_z) {
|
||||||
|
vol.print_zs.push_back(layer->print_z);
|
||||||
|
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
||||||
|
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const Point © : *ctxt.shifted_copies) {
|
||||||
|
for (const LayerRegion *layerm : layer->regions) {
|
||||||
|
if (ctxt.has_perimeters)
|
||||||
|
_3DScene::extrusionentity_to_verts(layerm->perimeters, float(layer->print_z), copy,
|
||||||
|
*vols[ctxt.volume_idx(layerm->region()->config.perimeter_extruder.value, 0)]);
|
||||||
|
if (ctxt.has_infill) {
|
||||||
|
for (const ExtrusionEntity *ee : layerm->fills.entities) {
|
||||||
|
// fill represents infill extrusions of a single island.
|
||||||
|
const auto *fill = dynamic_cast<const ExtrusionEntityCollection*>(ee);
|
||||||
|
if (!fill->entities.empty())
|
||||||
|
_3DScene::extrusionentity_to_verts(*fill, float(layer->print_z), copy,
|
||||||
|
*vols[ctxt.volume_idx(
|
||||||
|
is_solid_infill(fill->entities.front()->role()) ?
|
||||||
|
layerm->region()->config.solid_infill_extruder :
|
||||||
|
layerm->region()->config.infill_extruder,
|
||||||
|
1)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ctxt.has_support) {
|
||||||
|
const SupportLayer *support_layer = dynamic_cast<const SupportLayer*>(layer);
|
||||||
|
if (support_layer) {
|
||||||
|
for (const ExtrusionEntity *extrusion_entity : support_layer->support_fills.entities)
|
||||||
|
_3DScene::extrusionentity_to_verts(extrusion_entity, float(layer->print_z), copy,
|
||||||
|
*vols[ctxt.volume_idx(
|
||||||
|
(extrusion_entity->role() == erSupportMaterial) ?
|
||||||
|
support_layer->object()->config.support_material_extruder :
|
||||||
|
support_layer->object()->config.support_material_interface_extruder,
|
||||||
|
2)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
|
GLVolume &vol = *vols[i];
|
||||||
|
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||||
|
// Store the vertex arrays and restart their containers,
|
||||||
|
vols[i] = new_volume(vol.color);
|
||||||
|
GLVolume &vol_new = *vols[i];
|
||||||
|
// Assign the large pre-allocated buffers to the new GLVolume.
|
||||||
|
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
||||||
|
// Copy the content back to the old GLVolume.
|
||||||
|
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
||||||
|
// Finalize a bounding box of the old GLVolume.
|
||||||
|
vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
||||||
|
// Clear the buffers, but keep them pre-allocated.
|
||||||
|
vol_new.indexed_vertex_array.clear();
|
||||||
|
// Just make sure that clear did not clear the reserved memory.
|
||||||
|
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (GLVolume *vol : vols) {
|
||||||
|
vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
||||||
|
vol->indexed_vertex_array.shrink_to_fit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - finalizing results";
|
||||||
|
// Remove empty volumes from the newly added volumes.
|
||||||
|
m_volumes->volumes.erase(
|
||||||
|
std::remove_if(m_volumes->volumes.begin() + volumes_cnt_initial, m_volumes->volumes.end(),
|
||||||
|
[](const GLVolume *volume) { return volume->empty(); }),
|
||||||
|
m_volumes->volumes.end());
|
||||||
|
for (size_t i = volumes_cnt_initial; i < m_volumes->volumes.size(); ++i)
|
||||||
|
m_volumes->volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading print object toolpaths in parallel - end";
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3D::load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors)
|
||||||
|
{
|
||||||
|
if ((m_volumes == nullptr) || (m_print == nullptr) || m_print->m_wipe_tower_tool_changes.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!m_print->state.is_done(psWipeTower))
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<float> tool_colors = _parse_colors(str_tool_colors);
|
||||||
|
|
||||||
|
struct Ctxt
|
||||||
|
{
|
||||||
|
const Print *print;
|
||||||
|
const std::vector<float> *tool_colors;
|
||||||
|
|
||||||
|
// Number of vertices (each vertex is 6x4=24 bytes long)
|
||||||
|
static const size_t alloc_size_max() { return 131072; } // 3.15MB
|
||||||
|
static const size_t alloc_size_reserve() { return alloc_size_max() * 2; }
|
||||||
|
|
||||||
|
static const float* color_support() { static float color[4] = { 0.5f, 1.0f, 0.5f, 1.f }; return color; } // greenish
|
||||||
|
|
||||||
|
// For cloring by a tool, return a parsed color.
|
||||||
|
bool color_by_tool() const { return tool_colors != nullptr; }
|
||||||
|
size_t number_tools() const { return this->color_by_tool() ? tool_colors->size() / 4 : 0; }
|
||||||
|
const float* color_tool(size_t tool) const { return tool_colors->data() + tool * 4; }
|
||||||
|
int volume_idx(int tool, int feature) const
|
||||||
|
{
|
||||||
|
return this->color_by_tool() ? std::min<int>(this->number_tools() - 1, std::max<int>(tool, 0)) : feature;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<WipeTower::ToolChangeResult>& tool_change(size_t idx) {
|
||||||
|
return priming.empty() ?
|
||||||
|
((idx == print->m_wipe_tower_tool_changes.size()) ? final : print->m_wipe_tower_tool_changes[idx]) :
|
||||||
|
((idx == 0) ? priming : (idx == print->m_wipe_tower_tool_changes.size() + 1) ? final : print->m_wipe_tower_tool_changes[idx - 1]);
|
||||||
|
}
|
||||||
|
std::vector<WipeTower::ToolChangeResult> priming;
|
||||||
|
std::vector<WipeTower::ToolChangeResult> final;
|
||||||
|
} ctxt;
|
||||||
|
|
||||||
|
ctxt.print = m_print;
|
||||||
|
ctxt.tool_colors = tool_colors.empty() ? nullptr : &tool_colors;
|
||||||
|
if (m_print->m_wipe_tower_priming)
|
||||||
|
ctxt.priming.emplace_back(*m_print->m_wipe_tower_priming.get());
|
||||||
|
if (m_print->m_wipe_tower_final_purge)
|
||||||
|
ctxt.final.emplace_back(*m_print->m_wipe_tower_final_purge.get());
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - start";
|
||||||
|
|
||||||
|
//FIXME Improve the heuristics for a grain size.
|
||||||
|
size_t n_items = m_print->m_wipe_tower_tool_changes.size() + (ctxt.priming.empty() ? 0 : 1);
|
||||||
|
size_t grain_size = std::max(n_items / 128, size_t(1));
|
||||||
|
tbb::spin_mutex new_volume_mutex;
|
||||||
|
auto new_volume = [this, &new_volume_mutex](const float *color) -> GLVolume* {
|
||||||
|
auto *volume = new GLVolume(color);
|
||||||
|
new_volume_mutex.lock();
|
||||||
|
volume->outside_printer_detection_enabled = false;
|
||||||
|
m_volumes->volumes.emplace_back(volume);
|
||||||
|
new_volume_mutex.unlock();
|
||||||
|
return volume;
|
||||||
|
};
|
||||||
|
const size_t volumes_cnt_initial = m_volumes->volumes.size();
|
||||||
|
std::vector<GLVolumeCollection> volumes_per_thread(n_items);
|
||||||
|
tbb::parallel_for(
|
||||||
|
tbb::blocked_range<size_t>(0, n_items, grain_size),
|
||||||
|
[&ctxt, &new_volume](const tbb::blocked_range<size_t>& range) {
|
||||||
|
// Bounding box of this slab of a wipe tower.
|
||||||
|
std::vector<GLVolume*> vols;
|
||||||
|
if (ctxt.color_by_tool()) {
|
||||||
|
for (size_t i = 0; i < ctxt.number_tools(); ++i)
|
||||||
|
vols.emplace_back(new_volume(ctxt.color_tool(i)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
vols = { new_volume(ctxt.color_support()) };
|
||||||
|
for (GLVolume *volume : vols)
|
||||||
|
volume->indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
for (size_t idx_layer = range.begin(); idx_layer < range.end(); ++idx_layer) {
|
||||||
|
const std::vector<WipeTower::ToolChangeResult> &layer = ctxt.tool_change(idx_layer);
|
||||||
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
|
GLVolume &vol = *vols[i];
|
||||||
|
if (vol.print_zs.empty() || vol.print_zs.back() != layer.front().print_z) {
|
||||||
|
vol.print_zs.push_back(layer.front().print_z);
|
||||||
|
vol.offsets.push_back(vol.indexed_vertex_array.quad_indices.size());
|
||||||
|
vol.offsets.push_back(vol.indexed_vertex_array.triangle_indices.size());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const WipeTower::ToolChangeResult &extrusions : layer) {
|
||||||
|
for (size_t i = 1; i < extrusions.extrusions.size();) {
|
||||||
|
const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
||||||
|
if (e.width == 0.) {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
size_t j = i + 1;
|
||||||
|
if (ctxt.color_by_tool())
|
||||||
|
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].tool == e.tool && extrusions.extrusions[j].width > 0.f; ++j);
|
||||||
|
else
|
||||||
|
for (; j < extrusions.extrusions.size() && extrusions.extrusions[j].width > 0.f; ++j);
|
||||||
|
size_t n_lines = j - i;
|
||||||
|
Lines lines;
|
||||||
|
std::vector<double> widths;
|
||||||
|
std::vector<double> heights;
|
||||||
|
lines.reserve(n_lines);
|
||||||
|
widths.reserve(n_lines);
|
||||||
|
heights.assign(n_lines, extrusions.layer_height);
|
||||||
|
for (; i < j; ++i) {
|
||||||
|
const WipeTower::Extrusion &e = extrusions.extrusions[i];
|
||||||
|
assert(e.width > 0.f);
|
||||||
|
const WipeTower::Extrusion &e_prev = *(&e - 1);
|
||||||
|
lines.emplace_back(Point::new_scale(e_prev.pos.x, e_prev.pos.y), Point::new_scale(e.pos.x, e.pos.y));
|
||||||
|
widths.emplace_back(e.width);
|
||||||
|
}
|
||||||
|
_3DScene::thick_lines_to_verts(lines, widths, heights, lines.front().a == lines.back().b, extrusions.print_z,
|
||||||
|
*vols[ctxt.volume_idx(e.tool, 0)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < vols.size(); ++i) {
|
||||||
|
GLVolume &vol = *vols[i];
|
||||||
|
if (vol.indexed_vertex_array.vertices_and_normals_interleaved.size() / 6 > ctxt.alloc_size_max()) {
|
||||||
|
// Store the vertex arrays and restart their containers,
|
||||||
|
vols[i] = new_volume(vol.color);
|
||||||
|
GLVolume &vol_new = *vols[i];
|
||||||
|
// Assign the large pre-allocated buffers to the new GLVolume.
|
||||||
|
vol_new.indexed_vertex_array = std::move(vol.indexed_vertex_array);
|
||||||
|
// Copy the content back to the old GLVolume.
|
||||||
|
vol.indexed_vertex_array = vol_new.indexed_vertex_array;
|
||||||
|
// Finalize a bounding box of the old GLVolume.
|
||||||
|
vol.bounding_box = vol.indexed_vertex_array.bounding_box();
|
||||||
|
// Clear the buffers, but keep them pre-allocated.
|
||||||
|
vol_new.indexed_vertex_array.clear();
|
||||||
|
// Just make sure that clear did not clear the reserved memory.
|
||||||
|
vol_new.indexed_vertex_array.reserve(ctxt.alloc_size_reserve());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (GLVolume *vol : vols) {
|
||||||
|
vol->bounding_box = vol->indexed_vertex_array.bounding_box();
|
||||||
|
vol->indexed_vertex_array.shrink_to_fit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - finalizing results";
|
||||||
|
// Remove empty volumes from the newly added volumes.
|
||||||
|
m_volumes->volumes.erase(
|
||||||
|
std::remove_if(m_volumes->volumes.begin() + volumes_cnt_initial, m_volumes->volumes.end(),
|
||||||
|
[](const GLVolume *volume) { return volume->empty(); }),
|
||||||
|
m_volumes->volumes.end());
|
||||||
|
for (size_t i = volumes_cnt_initial; i < m_volumes->volumes.size(); ++i)
|
||||||
|
m_volumes->volumes[i]->indexed_vertex_array.finalize_geometry(m_use_VBOs && m_initialized);
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Loading wipe tower toolpaths in parallel - end";
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
|
void GLCanvas3D::load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors)
|
||||||
{
|
{
|
||||||
if ((m_canvas != nullptr) && (m_volumes != nullptr) && (m_print != nullptr))
|
if ((m_canvas != nullptr) && (m_volumes != nullptr) && (m_print != nullptr))
|
||||||
@ -2416,28 +2786,6 @@ static inline int hex_digit_to_int(const char c)
|
|||||||
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
(c >= 'a' && c <= 'f') ? int(c - 'a') + 10 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
|
|
||||||
{
|
|
||||||
std::vector<float> output(colors.size() * 4, 1.0f);
|
|
||||||
for (size_t i = 0; i < colors.size(); ++i) {
|
|
||||||
const std::string& color = colors[i];
|
|
||||||
const char* c = color.data() + 1;
|
|
||||||
if ((color.size() == 7) && (color.front() == '#'))
|
|
||||||
{
|
|
||||||
for (size_t j = 0; j < 3; ++j)
|
|
||||||
{
|
|
||||||
int digit1 = hex_digit_to_int(*c++);
|
|
||||||
int digit2 = hex_digit_to_int(*c++);
|
|
||||||
if ((digit1 == -1) || (digit2 == -1))
|
|
||||||
break;
|
|
||||||
|
|
||||||
output[i * 4 + j] = float(digit1 * 16 + digit2) / 255.0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
void GLCanvas3D::_load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors)
|
||||||
{
|
{
|
||||||
// helper functions to select data in dependence of the extrusion view type
|
// helper functions to select data in dependence of the extrusion view type
|
||||||
@ -3008,5 +3356,27 @@ void GLCanvas3D::_update_gcode_volumes_visibility(const GCodePreviewData& previe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<float> GLCanvas3D::_parse_colors(const std::vector<std::string>& colors)
|
||||||
|
{
|
||||||
|
std::vector<float> output(colors.size() * 4, 1.0f);
|
||||||
|
for (size_t i = 0; i < colors.size(); ++i) {
|
||||||
|
const std::string& color = colors[i];
|
||||||
|
const char* c = color.data() + 1;
|
||||||
|
if ((color.size() == 7) && (color.front() == '#'))
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < 3; ++j)
|
||||||
|
{
|
||||||
|
int digit1 = hex_digit_to_int(*c++);
|
||||||
|
int digit2 = hex_digit_to_int(*c++);
|
||||||
|
if ((digit1 == -1) || (digit2 == -1))
|
||||||
|
break;
|
||||||
|
|
||||||
|
output[i * 4 + j] = float(digit1 * 16 + digit2) / 255.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
} // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
@ -411,6 +411,15 @@ public:
|
|||||||
std::vector<double> get_current_print_zs(bool active_only) const;
|
std::vector<double> get_current_print_zs(bool active_only) const;
|
||||||
void set_toolpaths_range(double low, double high);
|
void set_toolpaths_range(double low, double high);
|
||||||
|
|
||||||
|
// Create 3D thick extrusion lines for a skirt and brim.
|
||||||
|
// Adds a new Slic3r::GUI::3DScene::Volume to volumes.
|
||||||
|
void load_print_toolpaths();
|
||||||
|
// Create 3D thick extrusion lines for object forming extrusions.
|
||||||
|
// Adds a new Slic3r::GUI::3DScene::Volume to $self->volumes,
|
||||||
|
// one for perimeters, one for infill and one for supports.
|
||||||
|
void load_print_object_toolpaths(const PrintObject& print_object, const std::vector<std::string>& str_tool_colors);
|
||||||
|
// Create 3D thick extrusion lines for wipe tower extrusions
|
||||||
|
void load_wipe_tower_toolpaths(const std::vector<std::string>& str_tool_colors);
|
||||||
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
void load_gcode_preview(const GCodePreviewData& preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
|
|
||||||
void register_on_viewport_changed_callback(void* callback);
|
void register_on_viewport_changed_callback(void* callback);
|
||||||
@ -472,8 +481,6 @@ private:
|
|||||||
void _start_timer();
|
void _start_timer();
|
||||||
void _stop_timer();
|
void _stop_timer();
|
||||||
|
|
||||||
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
|
||||||
|
|
||||||
// generates gcode extrusion paths geometry
|
// generates gcode extrusion paths geometry
|
||||||
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
void _load_gcode_extrusion_paths(const GCodePreviewData& preview_data, const std::vector<float>& tool_colors);
|
||||||
// generates gcode travel paths geometry
|
// generates gcode travel paths geometry
|
||||||
@ -489,6 +496,8 @@ private:
|
|||||||
void _load_shells();
|
void _load_shells();
|
||||||
// sets gcode geometry visibility according to user selection
|
// sets gcode geometry visibility according to user selection
|
||||||
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
void _update_gcode_volumes_visibility(const GCodePreviewData& preview_data);
|
||||||
|
|
||||||
|
static std::vector<float> _parse_colors(const std::vector<std::string>& colors);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
@ -450,6 +450,30 @@ void GLCanvas3DManager::set_toolpaths_range(wxGLCanvas* canvas, double low, doub
|
|||||||
it->second->set_toolpaths_range(low, high);
|
it->second->set_toolpaths_range(low, high);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GLCanvas3DManager::load_print_toolpaths(wxGLCanvas* canvas)
|
||||||
|
{
|
||||||
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
if (it != m_canvases.end())
|
||||||
|
it->second->load_print_toolpaths();
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3DManager::load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors)
|
||||||
|
{
|
||||||
|
if (print_object == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
if (it != m_canvases.end())
|
||||||
|
it->second->load_print_object_toolpaths(*print_object, tool_colors);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GLCanvas3DManager::load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors)
|
||||||
|
{
|
||||||
|
CanvasesMap::iterator it = _get_canvas(canvas);
|
||||||
|
if (it != m_canvases.end())
|
||||||
|
it->second->load_wipe_tower_toolpaths(str_tool_colors);
|
||||||
|
}
|
||||||
|
|
||||||
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
void GLCanvas3DManager::load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors)
|
||||||
{
|
{
|
||||||
if (preview_data == nullptr)
|
if (preview_data == nullptr)
|
||||||
|
@ -95,6 +95,9 @@ public:
|
|||||||
std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const;
|
std::vector<double> get_current_print_zs(wxGLCanvas* canvas, bool active_only) const;
|
||||||
void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
|
void set_toolpaths_range(wxGLCanvas* canvas, double low, double high);
|
||||||
|
|
||||||
|
void load_print_toolpaths(wxGLCanvas* canvas);
|
||||||
|
void load_print_object_toolpaths(wxGLCanvas* canvas, const PrintObject* print_object, const std::vector<std::string>& tool_colors);
|
||||||
|
void load_wipe_tower_toolpaths(wxGLCanvas* canvas, const std::vector<std::string>& str_tool_colors);
|
||||||
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
void load_gcode_preview(wxGLCanvas* canvas, const GCodePreviewData* preview_data, const std::vector<std::string>& str_tool_colors);
|
||||||
|
|
||||||
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
void register_on_viewport_changed_callback(wxGLCanvas* canvas, void* callback);
|
||||||
|
@ -511,31 +511,25 @@ reset_warning_texture()
|
|||||||
_3DScene::reset_warning_texture();
|
_3DScene::reset_warning_texture();
|
||||||
|
|
||||||
void
|
void
|
||||||
_load_print_toolpaths(print, volumes, tool_colors, use_VBOs)
|
load_print_toolpaths(canvas)
|
||||||
Print *print;
|
SV *canvas;
|
||||||
GLVolumeCollection *volumes;
|
|
||||||
std::vector<std::string> tool_colors;
|
|
||||||
int use_VBOs;
|
|
||||||
CODE:
|
CODE:
|
||||||
_3DScene::_load_print_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
_3DScene::load_print_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"));
|
||||||
|
|
||||||
void
|
void
|
||||||
_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs)
|
load_print_object_toolpaths(canvas, print_object, tool_colors)
|
||||||
PrintObject *print_object;
|
SV *canvas;
|
||||||
GLVolumeCollection *volumes;
|
PrintObject *print_object;
|
||||||
std::vector<std::string> tool_colors;
|
std::vector<std::string> tool_colors;
|
||||||
int use_VBOs;
|
|
||||||
CODE:
|
CODE:
|
||||||
_3DScene::_load_print_object_toolpaths(print_object, volumes, tool_colors, use_VBOs != 0);
|
_3DScene::load_print_object_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), print_object, tool_colors);
|
||||||
|
|
||||||
void
|
void
|
||||||
_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs)
|
load_wipe_tower_toolpaths(canvas, tool_colors)
|
||||||
Print *print;
|
SV *canvas;
|
||||||
GLVolumeCollection *volumes;
|
|
||||||
std::vector<std::string> tool_colors;
|
std::vector<std::string> tool_colors;
|
||||||
int use_VBOs;
|
|
||||||
CODE:
|
CODE:
|
||||||
_3DScene::_load_wipe_tower_toolpaths(print, volumes, tool_colors, use_VBOs != 0);
|
_3DScene::load_wipe_tower_toolpaths((wxGLCanvas*)wxPli_sv_2_object(aTHX_ canvas, "Wx::GLCanvas"), tool_colors);
|
||||||
|
|
||||||
void
|
void
|
||||||
load_gcode_preview(canvas, preview_data, str_tool_colors)
|
load_gcode_preview(canvas, preview_data, str_tool_colors)
|
||||||
|
Loading…
Reference in New Issue
Block a user