Make sure prime tower uses correct line width and filament for outer wall

This commit is contained in:
sentientstardust
2026-05-06 13:33:39 +01:00
parent 7580532c6a
commit 6960168c07
7 changed files with 328 additions and 53 deletions

View File

@@ -269,6 +269,14 @@ void ToolOrdering::handle_dontcare_extruder(const std::vector<unsigned int>& too
assert(extruder_id > 0);
--extruder_id;
}
for (unsigned int &extruder_id : lt.texture_mapping_extruders) {
assert(extruder_id > 0);
--extruder_id;
}
for (unsigned int &extruder_id : lt.texture_mapping_component_extruders) {
assert(extruder_id > 0);
--extruder_id;
}
}
}
@@ -339,6 +347,14 @@ void ToolOrdering::handle_dontcare_extruder(unsigned int last_extruder_id)
assert(extruder_id > 0);
-- extruder_id;
}
for (unsigned int &extruder_id : lt.texture_mapping_extruders) {
assert(extruder_id > 0);
-- extruder_id;
}
for (unsigned int &extruder_id : lt.texture_mapping_component_extruders) {
assert(extruder_id > 0);
-- extruder_id;
}
}
}
@@ -720,10 +736,35 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
// Store the current extruder override (set to zero if no overriden), so that layer_tools.wiping_extrusions().is_overridable_and_mark() will use it.
layer_tools.extruder_override = extruder_override;
auto append_layer_filament = [&layer_tools](unsigned int filament_id) {
if (layer_tools.texture_mapping_manager != nullptr && layer_tools.texture_mapping_manager->is_texture_mapping_zone_id(filament_id))
auto append_layer_filament = [&layer_tools, &object](unsigned int filament_id) {
const bool is_texture_mapping_zone = layer_tools.texture_mapping_manager != nullptr &&
layer_tools.texture_mapping_manager->is_texture_mapping_zone_id(filament_id);
const unsigned int resolved_filament_id = layer_tools.resolve_filament_id(filament_id);
if (is_texture_mapping_zone) {
layer_tools.has_texture_mapping_zone = true;
layer_tools.extruders.emplace_back(layer_tools.resolve_filament_id(filament_id));
if (resolved_filament_id > 0)
layer_tools.texture_mapping_extruders.emplace_back(resolved_filament_id);
const TextureMappingZone *zone = layer_tools.texture_mapping_manager->zone_from_id(filament_id);
bool added_texture_component = false;
if (zone != nullptr && zone->enabled && !zone->deleted) {
std::vector<std::string> filament_colours = object.print()->config().filament_colour.values;
filament_colours.resize(layer_tools.num_physical_filaments, "#FFFFFF");
std::vector<unsigned int> component_ids =
zone->is_image_texture() ?
TextureMappingManager::effective_texture_component_ids(*zone,
layer_tools.num_physical_filaments,
filament_colours) :
TextureMappingManager::selected_component_ids(*zone, layer_tools.num_physical_filaments);
for (const unsigned int component_id : component_ids)
if (component_id >= 1 && component_id <= layer_tools.num_physical_filaments) {
layer_tools.texture_mapping_component_extruders.emplace_back(component_id);
added_texture_component = true;
}
}
if (!added_texture_component && resolved_filament_id > 0)
layer_tools.texture_mapping_component_extruders.emplace_back(resolved_filament_id);
}
layer_tools.extruders.emplace_back(resolved_filament_id);
};
// What extruders are required to print this object layer?
@@ -841,6 +882,8 @@ void ToolOrdering::collect_extruders(const PrintObject &object, const std::vecto
for (auto& layer : m_layer_tools) {
// Sort and remove duplicates
sort_remove_duplicates(layer.extruders);
sort_remove_duplicates(layer.texture_mapping_extruders);
sort_remove_duplicates(layer.texture_mapping_component_extruders);
// make sure that there are some tools for each object layer (e.g. tall wiping object will result in empty extruders vector)
if (layer.extruders.empty() && layer.has_object)

View File

@@ -156,6 +156,8 @@ public:
bool has_support = false;
// Zero based extruder IDs, ordered to minimize tool switches.
std::vector<unsigned int> extruders;
std::vector<unsigned int> texture_mapping_extruders;
std::vector<unsigned int> texture_mapping_component_extruders;
// If per layer extruder switches are inserted by the G-code preview slider, this value contains the new (1 based) extruder, with which the whole object layer is being printed with.
// If not overriden, it is set to 0.
unsigned int extruder_override = 0;

View File

@@ -630,7 +630,7 @@ public:
if (! m_preview_suppressed && e > 0.f && len > 0.f) {
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
// This is left zero if it is a travel move.
float width = e * m_filpar[0].filament_area / (len * m_layer_height);
float width = e * m_filpar[m_current_tool].filament_area / (len * m_layer_height);
// Correct for the roundings of a squished extrusion.
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
@@ -688,7 +688,7 @@ public:
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
// This is left zero if it is a travel move.
float width = e * m_filpar[0].filament_area / (len * m_layer_height);
float width = e * m_filpar[m_current_tool].filament_area / (len * m_layer_height);
// Correct for the roundings of a squished extrusion.
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos) m_extrusions.emplace_back(WipeTower::Extrusion(rotated_current_pos, 0, m_current_tool));
@@ -1447,7 +1447,8 @@ static void prime_tower_textured_path(WipeTowerWriter &writer,
float width_range = (base_width - min_width) * std::clamp(texture.global_strength, 0.f, 1.f);
if (texture.sagging_ratio > EPSILON)
width_range = std::min(width_range, layer_height * texture.sagging_ratio);
const float sample_step = std::max(0.35f, reference_width);
const float base_extrusion_flow = extrusion_flow * prime_tower_flow_scale_for_width(reference_width, base_width, layer_height);
const float sample_step = std::max(0.35f, base_width);
float travelled = 0.f;
bool have_shifted_pos = false;
@@ -1476,7 +1477,7 @@ static void prime_tower_textured_path(WipeTowerWriter &writer,
const float u = (mid_distance - texture_path.anchor_distance) / total_length;
const float visibility = texture.sample_tool_visibility(current_tool, u, v, normalization_tools);
const float target_width = base_width - (1.f - visibility) * width_range;
const float flow_scale = prime_tower_flow_scale_for_width(reference_width, target_width, layer_height);
const float flow_scale = prime_tower_flow_scale_for_width(base_width, target_width, layer_height);
const float centerline_shift = 0.5f * (base_width - reference_width) + 0.5f * (base_width - target_width);
const Vec2f p0 = a + delta * t0 - outward * centerline_shift;
const Vec2f p1 = a + delta * t1 - outward * centerline_shift;
@@ -1485,12 +1486,11 @@ static void prime_tower_textured_path(WipeTowerWriter &writer,
shifted_pos = p0;
have_shifted_pos = true;
}
writer.extrude_explicit(p1, (p1 - p0).norm() * extrusion_flow * flow_scale, feedrate, true);
writer.extrude_explicit(p1, (p1 - p0).norm() * base_extrusion_flow * flow_scale, feedrate, true);
shifted_pos = p1;
}
travelled += sample_len;
}
writer.change_analyzer_line_width(reference_width);
}
static void prime_tower_textured_closed_path(WipeTowerWriter &writer,
@@ -2748,12 +2748,17 @@ WipeTower::ToolChangeResult WipeTower::finish_layer(bool extrude_perimeter, bool
std::vector<size_t> texture_normalization_tools;
if (m_prime_tower_texture.valid()) {
const size_t texture_tool_count = m_prime_tower_texture.filament_colours.size();
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
if (m_layer_info != m_plan.end()) {
if (m_layer_info != m_plan.end() && !m_layer_info->texture_mapping_layer_tools.empty()) {
for (const size_t tool : m_layer_info->texture_mapping_layer_tools)
prime_tower_append_texture_tool(texture_normalization_tools, tool, texture_tool_count);
} else if (m_layer_info != m_plan.end()) {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
for (const WipeTowerInfo::ToolChange &tool_change : m_layer_info->tool_changes) {
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.old_tool, texture_tool_count);
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.new_tool, texture_tool_count);
}
} else {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
}
}
if (extrude_perimeter) {
@@ -2835,13 +2840,23 @@ void WipeTower::plan_toolchange(float z_par,
unsigned int new_tool,
float wipe_volume,
float purge_volume,
bool texture_mapping_single_component_layer)
bool texture_mapping_single_component_layer,
const std::vector<unsigned int> &texture_mapping_layer_tools,
int texture_mapping_wall_tool)
{
assert(m_plan.empty() || m_plan.back().z <= z_par + WT_EPSILON); // refuses to add a layer below the last one
if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan first
m_plan.push_back(WipeTowerInfo(z_par, layer_height_par));
m_plan.back().texture_mapping_single_component_layer |= texture_mapping_single_component_layer;
if (texture_mapping_wall_tool >= 0)
m_plan.back().texture_mapping_wall_tool = size_t(texture_mapping_wall_tool);
std::vector<size_t> &layer_texture_tools = m_plan.back().texture_mapping_layer_tools;
for (const unsigned int tool : texture_mapping_layer_tools) {
const size_t tool_id = size_t(tool);
if (std::find(layer_texture_tools.begin(), layer_texture_tools.end(), tool_id) == layer_texture_tools.end())
layer_texture_tools.emplace_back(tool_id);
}
if (m_first_layer_idx == size_t(-1) && (! m_no_sparse_layers || old_tool != new_tool))
m_first_layer_idx = m_plan.size() - 1;
@@ -4299,10 +4314,28 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
ToolChangeResult timelapse_wall;
auto get_wall_filament_for_this_layer = [this, &layer, &wall_filament]() -> int {
if (layer.tool_changes.size() == 0)
auto texture_wall_tool_for_this_layer = [this, &layer]() -> int {
if (!m_prime_tower_texture.valid() || layer.texture_mapping_wall_tool == size_t(-1))
return -1;
const int texture_wall_tool = int(layer.texture_mapping_wall_tool);
if (layer.tool_changes.empty())
return texture_wall_tool == int(m_current_tool) ? texture_wall_tool : -1;
if (int(layer.tool_changes.front().old_tool) == texture_wall_tool)
return texture_wall_tool;
for (const WipeTowerInfo::ToolChange &tool_change : layer.tool_changes)
if (int(tool_change.new_tool) == texture_wall_tool)
return texture_wall_tool;
return -1;
if (m_prime_tower_texture.valid() && layer.texture_mapping_single_component_layer && layer.tool_changes.size() == 1)
return layer.tool_changes.front().new_tool;
};
if (const int texture_wall_tool = texture_wall_tool_for_this_layer(); texture_wall_tool != -1)
return texture_wall_tool;
if (layer.tool_changes.size() == 0) {
return -1;
}
if (m_prime_tower_texture.valid()) {
if (layer.texture_mapping_single_component_layer && layer.tool_changes.size() == 1)
return layer.tool_changes.front().new_tool;
}
int candidate_id = -1;
for (size_t idx = 0; idx < layer.tool_changes.size(); ++idx) {
@@ -4713,12 +4746,17 @@ Polygon WipeTower::generate_support_wall_new(WipeTowerWriter &writer, const box_
if (m_prime_tower_texture.valid() && result_wall.size() == 1 && !result_wall.front().points.empty()) {
std::vector<size_t> texture_normalization_tools;
const size_t texture_tool_count = m_prime_tower_texture.filament_colours.size();
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
if (m_layer_info != m_plan.end()) {
if (m_layer_info != m_plan.end() && !m_layer_info->texture_mapping_layer_tools.empty()) {
for (const size_t tool : m_layer_info->texture_mapping_layer_tools)
prime_tower_append_texture_tool(texture_normalization_tools, tool, texture_tool_count);
} else if (m_layer_info != m_plan.end()) {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
for (const WipeTowerInfo::ToolChange &tool_change : m_layer_info->tool_changes) {
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.old_tool, texture_tool_count);
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.new_tool, texture_tool_count);
}
} else {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
}
const bool closed_texture_path = !rib_wall && !skip_points;
std::vector<Vec2f> points;

View File

@@ -76,8 +76,8 @@ struct PrimeTowerTextureRenderSettings
float sample_tool_visibility(size_t tool, float u, float v) const
{
const float raw_visibility = sample_tool_visibility_raw(tool, u, v);
if (settings_zone_enabled || !compact_offset_mode)
return raw_visibility;
if (!compact_offset_mode)
return adjusted_tool_visibility(tool, raw_visibility);
float max_visibility = std::clamp(raw_visibility, 0.f, 1.f);
if (!tool_indices.empty()) {
@@ -91,27 +91,126 @@ struct PrimeTowerTextureRenderSettings
max_visibility = std::max(max_visibility, std::clamp(sample_tool_visibility_raw(candidate_tool, u, v), 0.f, 1.f));
}
}
return max_visibility > 1e-6f ?
std::clamp(raw_visibility / max_visibility, 0.f, 1.f) :
std::clamp(raw_visibility, 0.f, 1.f);
return max_visibility > 1e-6f ? adjusted_tool_visibility(tool, raw_visibility / max_visibility) :
adjusted_tool_visibility(tool, raw_visibility);
}
float sample_tool_visibility(size_t tool, float u, float v, const std::vector<size_t> &normalization_tools) const
{
const float raw_visibility = sample_tool_visibility_raw(tool, u, v);
if (settings_zone_enabled || !compact_offset_mode || normalization_tools.empty())
return raw_visibility;
if (!compact_offset_mode || normalization_tools.empty())
return adjusted_tool_visibility(tool, raw_visibility);
float max_visibility = std::clamp(raw_visibility, 0.f, 1.f);
for (const size_t normalization_tool : normalization_tools)
max_visibility = std::max(max_visibility, std::clamp(sample_tool_visibility_raw(normalization_tool, u, v), 0.f, 1.f));
return max_visibility > 1e-6f ?
std::clamp(raw_visibility / max_visibility, 0.f, 1.f) :
std::clamp(raw_visibility, 0.f, 1.f);
return max_visibility > 1e-6f ? adjusted_tool_visibility(tool, raw_visibility / max_visibility) :
adjusted_tool_visibility(tool, raw_visibility);
}
std::vector<size_t> component_tools_for_layer_sequence() const
{
std::vector<size_t> tools;
if (!valid())
return tools;
if (settings_zone_enabled && !component_ids.empty()) {
tools.reserve(component_ids.size());
for (const unsigned int physical_id : component_ids) {
if (physical_id >= 1 && physical_id <= filament_colours.size()) {
const size_t tool = size_t(physical_id - 1);
if (std::find(tools.begin(), tools.end(), tool) == tools.end())
tools.emplace_back(tool);
}
}
if (!tools.empty())
return tools;
}
const std::vector<std::array<float, 3>> ideals = color_mode_ideals(color_mode);
if (ideals.empty())
return tools;
std::vector<size_t> candidates;
if (!tool_indices.empty()) {
for (const size_t tool : tool_indices)
if (tool < filament_colours.size() && std::find(candidates.begin(), candidates.end(), tool) == candidates.end())
candidates.emplace_back(tool);
} else {
candidates.reserve(filament_colours.size());
for (size_t tool = 0; tool < filament_colours.size(); ++tool)
candidates.emplace_back(tool);
}
if (candidates.empty())
return tools;
std::vector<char> used(filament_colours.size(), 0);
tools.reserve(ideals.size());
for (const std::array<float, 3> &ideal : ideals) {
size_t best_tool = size_t(-1);
float best_distance = std::numeric_limits<float>::max();
for (const size_t candidate : candidates) {
if (candidate >= used.size() || used[candidate])
continue;
const float distance = color_distance2(tool_color(candidate), ideal);
if (distance < best_distance) {
best_distance = distance;
best_tool = candidate;
}
}
if (best_tool != size_t(-1)) {
used[best_tool] = 1;
tools.emplace_back(best_tool);
}
}
return tools;
}
size_t tool_for_layer_sequence(int layer_index) const
{
const std::vector<size_t> tools = component_tools_for_layer_sequence();
if (tools.empty())
return size_t(-1);
const int tool_count = int(tools.size());
const int index = ((layer_index % tool_count) + tool_count) % tool_count;
return tools[size_t(index)];
}
private:
static std::vector<std::array<float, 3>> color_mode_ideals(int mode)
{
switch (mode) {
case CMY:
return {std::array<float, 3>{0.f, 1.f, 1.f}, std::array<float, 3>{1.f, 0.f, 1.f}, std::array<float, 3>{1.f, 1.f, 0.f}};
case CMYK:
return {std::array<float, 3>{0.f, 1.f, 1.f},
std::array<float, 3>{1.f, 0.f, 1.f},
std::array<float, 3>{1.f, 1.f, 0.f},
std::array<float, 3>{0.f, 0.f, 0.f}};
case CMYW:
return {std::array<float, 3>{0.f, 1.f, 1.f},
std::array<float, 3>{1.f, 0.f, 1.f},
std::array<float, 3>{1.f, 1.f, 0.f},
std::array<float, 3>{1.f, 1.f, 1.f}};
case RGB:
return {std::array<float, 3>{1.f, 0.f, 0.f}, std::array<float, 3>{0.f, 1.f, 0.f}, std::array<float, 3>{0.f, 0.f, 1.f}};
case RGBK:
return {std::array<float, 3>{1.f, 0.f, 0.f},
std::array<float, 3>{0.f, 1.f, 0.f},
std::array<float, 3>{0.f, 0.f, 1.f},
std::array<float, 3>{0.f, 0.f, 0.f}};
case RGBW:
return {std::array<float, 3>{1.f, 0.f, 0.f},
std::array<float, 3>{0.f, 1.f, 0.f},
std::array<float, 3>{0.f, 0.f, 1.f},
std::array<float, 3>{1.f, 1.f, 1.f}};
case BW:
return {std::array<float, 3>{0.f, 0.f, 0.f}, std::array<float, 3>{1.f, 1.f, 1.f}};
default: return {};
}
}
float sample_tool_visibility_raw(size_t tool, float u, float v) const
{
if (!valid())
@@ -321,6 +420,14 @@ private:
return std::clamp(minimum + std::clamp(value, 0.f, 1.f) * strength * (1.f - minimum), 0.f, 1.f);
}
float adjusted_tool_visibility(size_t tool, float value) const
{
const unsigned int physical_id = unsigned(tool + 1);
return settings_zone_enabled && std::find(component_ids.begin(), component_ids.end(), physical_id) != component_ids.end() ?
adjusted_visibility_factor(physical_id, value) :
std::clamp(value, 0.f, 1.f);
}
float sample_settings_zone_tool_visibility(size_t tool, float u, float v, bool back) const
{
const unsigned int physical_id = unsigned(tool + 1);
@@ -350,15 +457,7 @@ private:
return sample_image_tool_visibility(tool, u, v, back);
apply_contrast(weights, std::clamp(contrast_pct, 25.f, 300.f) / 100.f, mapped_count);
if (compact_offset_mode) {
float max_weight = 0.f;
for (const float weight : weights)
max_weight = std::max(max_weight, std::clamp(weight, 0.f, 1.f));
if (max_weight > 1e-6f)
for (float &weight : weights)
weight = std::clamp(weight / max_weight, 0.f, 1.f);
}
return adjusted_visibility_factor(physical_id, weights[component_idx]);
return std::clamp(weights[component_idx], 0.f, 1.f);
}
float fixed_mode_visibility(size_t tool, float r, float g, float b) const
@@ -626,7 +725,9 @@ public:
unsigned int new_tool,
float wipe_volume = 0.f,
float prime_volume = 0.f,
bool texture_mapping_single_component_layer = false);
bool texture_mapping_single_component_layer = false,
const std::vector<unsigned int> &texture_mapping_layer_tools = {},
int texture_mapping_wall_tool = -1);
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
void generate(std::vector<std::vector<ToolChangeResult>> &result);
@@ -986,9 +1087,11 @@ private:
float z; // z position of the layer
float height; // layer height
float depth; // depth of the layer based on all layers above
float extra_spacing;
float extra_spacing;
bool extruder_fill{true};
bool texture_mapping_single_component_layer{false};
std::vector<size_t> texture_mapping_layer_tools;
size_t texture_mapping_wall_tool{size_t(-1)};
float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; }
std::vector<ToolChange> tool_changes;

View File

@@ -683,7 +683,7 @@ public:
if (! m_preview_suppressed && e > 0.f && len > 0.f) {
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
// This is left zero if it is a travel move.
float width = e * m_filpar[0].filament_area / (len * m_layer_height);
float width = e * m_filpar[m_current_tool].filament_area / (len * m_layer_height);
// Correct for the roundings of a squished extrusion.
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
@@ -1019,7 +1019,7 @@ public:
#endif // ENABLE_GCODE_VIEWER_DATA_CHECKING
// Width of a squished extrusion, corrected for the roundings of the squished extrusions.
// This is left zero if it is a travel move.
float width = e * m_filpar[0].filament_area / (len * m_layer_height);
float width = e * m_filpar[m_current_tool].filament_area / (len * m_layer_height);
// Correct for the roundings of a squished extrusion.
width += m_layer_height * float(1. - M_PI / 4.);
if (m_extrusions.empty() || m_extrusions.back().pos != rotated_current_pos)
@@ -1426,7 +1426,8 @@ static void prime_tower_textured_path(WipeTowerWriter2& writer,
float width_range = (base_width - min_width) * std::clamp(texture.global_strength, 0.f, 1.f);
if (texture.sagging_ratio > EPSILON)
width_range = std::min(width_range, layer_height * texture.sagging_ratio);
const float sample_step = std::max(0.35f, reference_width);
const float base_extrusion_flow = extrusion_flow * prime_tower_flow_scale_for_width(reference_width, base_width, layer_height);
const float sample_step = std::max(0.35f, base_width);
float travelled = 0.f;
bool have_shifted_pos = false;
@@ -1455,7 +1456,7 @@ static void prime_tower_textured_path(WipeTowerWriter2& writer,
const float u = (mid_distance - texture_path.anchor_distance) / total_length;
const float visibility = texture.sample_tool_visibility(current_tool, u, v, normalization_tools);
const float target_width = base_width - (1.f - visibility) * width_range;
const float flow_scale = prime_tower_flow_scale_for_width(reference_width, target_width, layer_height);
const float flow_scale = prime_tower_flow_scale_for_width(base_width, target_width, layer_height);
const float centerline_shift = 0.5f * (base_width - reference_width) + 0.5f * (base_width - target_width);
const Vec2f p0 = a + delta * t0 - outward * centerline_shift;
const Vec2f p1 = a + delta * t1 - outward * centerline_shift;
@@ -1464,12 +1465,11 @@ static void prime_tower_textured_path(WipeTowerWriter2& writer,
shifted_pos = p0;
have_shifted_pos = true;
}
writer.extrude_explicit(p1, (p1 - p0).norm() * extrusion_flow * flow_scale, feedrate, true);
writer.extrude_explicit(p1, (p1 - p0).norm() * base_extrusion_flow * flow_scale, feedrate, true);
shifted_pos = p1;
}
travelled += sample_len;
}
writer.change_analyzer_line_width(reference_width);
}
static void prime_tower_textured_closed_path(WipeTowerWriter2& writer,
@@ -2521,13 +2521,26 @@ static float get_wipe_depth(float volume, float layer_height, float perimeter_wi
}
// Appends a toolchange into m_plan and calculates neccessary depth of the corresponding box
void WipeTower2::plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool,
unsigned int new_tool, float wipe_volume)
void WipeTower2::plan_toolchange(float z_par,
float layer_height_par,
unsigned int old_tool,
unsigned int new_tool,
float wipe_volume,
const std::vector<unsigned int> &texture_mapping_layer_tools,
int texture_mapping_wall_tool)
{
assert(m_plan.empty() || m_plan.back().z <= z_par + WT_EPSILON); // refuses to add a layer below the last one
if (m_plan.empty() || m_plan.back().z + WT_EPSILON < z_par) // if we moved to a new layer, we'll add it to m_plan first
m_plan.push_back(WipeTowerInfo(z_par, layer_height_par));
if (texture_mapping_wall_tool >= 0)
m_plan.back().texture_mapping_wall_tool = size_t(texture_mapping_wall_tool);
std::vector<size_t> &layer_texture_tools = m_plan.back().texture_mapping_layer_tools;
for (const unsigned int tool : texture_mapping_layer_tools) {
const size_t tool_id = size_t(tool);
if (std::find(layer_texture_tools.begin(), layer_texture_tools.end(), tool_id) == layer_texture_tools.end())
layer_texture_tools.emplace_back(tool_id);
}
if (m_first_layer_idx == size_t(-1) && (! m_no_sparse_layers || old_tool != new_tool || m_plan.size() == 1))
m_first_layer_idx = m_plan.size() - 1;
@@ -2719,6 +2732,21 @@ void WipeTower2::generate(std::vector<std::vector<WipeTower::ToolChangeResult>>
m_y_shift = (m_wipe_tower_depth-m_layer_info->depth-m_perimeter_width)/2.f;
int idx = first_toolchange_to_nonsoluble(layer.tool_changes);
auto texture_wall_finish_idx = [this, &layer]() -> int {
if (!m_prime_tower_texture.valid() || layer.texture_mapping_wall_tool == size_t(-1))
return std::numeric_limits<int>::min();
const int texture_wall_tool = int(layer.texture_mapping_wall_tool);
if (layer.tool_changes.empty())
return texture_wall_tool == int(m_current_tool) ? -1 : std::numeric_limits<int>::min();
if (int(layer.tool_changes.front().old_tool) == texture_wall_tool)
return -1;
for (int i = 0; i < int(layer.tool_changes.size()); ++i)
if (int(layer.tool_changes[i].new_tool) == texture_wall_tool)
return i;
return std::numeric_limits<int>::min();
};
if (const int texture_idx = texture_wall_finish_idx(); texture_idx != std::numeric_limits<int>::min())
idx = texture_idx;
WipeTower::ToolChangeResult finish_layer_tcr;
if (idx == -1) {
@@ -2843,12 +2871,17 @@ Polygon WipeTower2::generate_support_rib_wall(WipeTowerWriter2&
if (m_prime_tower_texture.valid() && result_wall.size() == 1 && !result_wall.front().points.empty()) {
std::vector<size_t> texture_normalization_tools;
const size_t texture_tool_count = m_prime_tower_texture.filament_colours.size();
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
if (m_layer_info != m_plan.end()) {
if (m_layer_info != m_plan.end() && !m_layer_info->texture_mapping_layer_tools.empty()) {
for (const size_t tool : m_layer_info->texture_mapping_layer_tools)
prime_tower_append_texture_tool(texture_normalization_tools, tool, texture_tool_count);
} else if (m_layer_info != m_plan.end()) {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
for (const WipeTowerInfo::ToolChange &tool_change : m_layer_info->tool_changes) {
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.old_tool, texture_tool_count);
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.new_tool, texture_tool_count);
}
} else {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
}
const bool closed_texture_path = !rib_wall && !skip_points;
std::vector<Vec2f> points;
@@ -2983,12 +3016,17 @@ Polygon WipeTower2::generate_support_cone_wall(
if (m_prime_tower_texture.valid() && polylines.empty()) {
std::vector<size_t> texture_normalization_tools;
const size_t texture_tool_count = m_prime_tower_texture.filament_colours.size();
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
if (m_layer_info != m_plan.end()) {
if (m_layer_info != m_plan.end() && !m_layer_info->texture_mapping_layer_tools.empty()) {
for (const size_t tool : m_layer_info->texture_mapping_layer_tools)
prime_tower_append_texture_tool(texture_normalization_tools, tool, texture_tool_count);
} else if (m_layer_info != m_plan.end()) {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
for (const WipeTowerInfo::ToolChange &tool_change : m_layer_info->tool_changes) {
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.old_tool, texture_tool_count);
prime_tower_append_texture_tool(texture_normalization_tools, tool_change.new_tool, texture_tool_count);
}
} else {
prime_tower_append_texture_tool(texture_normalization_tools, m_current_tool, texture_tool_count);
}
std::vector<Vec2f> ordered;
ordered.reserve(pts.size());

View File

@@ -50,7 +50,13 @@ public:
// Appends into internal structure m_plan containing info about the future wipe tower
// to be used before building begins. The entries must be added ordered in z.
void plan_toolchange(float z_par, float layer_height_par, unsigned int old_tool, unsigned int new_tool, float wipe_volume = 0.f);
void plan_toolchange(float z_par,
float layer_height_par,
unsigned int old_tool,
unsigned int new_tool,
float wipe_volume = 0.f,
const std::vector<unsigned int> &texture_mapping_layer_tools = {},
int texture_mapping_wall_tool = -1);
// Iterates through prepared m_plan, generates ToolChangeResults and appends them to "result"
void generate(std::vector<std::vector<WipeTower::ToolChangeResult>> &result);
@@ -310,6 +316,8 @@ private:
float z; // z position of the layer
float height; // layer height
float depth; // depth of the layer based on all layers above
std::vector<size_t> texture_mapping_layer_tools;
size_t texture_mapping_wall_tool{size_t(-1)};
float toolchanges_depth() const { float sum = 0.f; for (const auto &a : tool_changes) sum += a.required_depth; return sum; }
std::vector<ToolChange> tool_changes;

View File

@@ -3538,6 +3538,43 @@ void Print::_make_wipe_tower()
return texture;
};
const PrimeTowerTextureRenderSettings prime_tower_texture = build_prime_tower_texture();
const std::vector<size_t> prime_tower_texture_component_tools = prime_tower_texture.component_tools_for_layer_sequence();
auto prime_tower_texture_layer_tools = [&prime_tower_texture, &prime_tower_texture_component_tools](const LayerTools &layer_tools) {
std::vector<unsigned int> tools;
if (!prime_tower_texture.valid())
return tools;
if (layer_tools.has_texture_mapping_zone && !layer_tools.texture_mapping_component_extruders.empty()) {
tools = layer_tools.texture_mapping_component_extruders;
return tools;
}
if (layer_tools.has_texture_mapping_zone && !layer_tools.texture_mapping_extruders.empty()) {
tools = layer_tools.texture_mapping_extruders;
return tools;
}
if (!prime_tower_texture_component_tools.empty()) {
tools.reserve(prime_tower_texture_component_tools.size());
for (const size_t tool : prime_tower_texture_component_tools)
tools.emplace_back(unsigned(tool));
return tools;
}
return tools;
};
auto prime_tower_texture_wall_tool = [&prime_tower_texture](const LayerTools &layer_tools) -> int {
if (!prime_tower_texture.valid())
return -1;
if (layer_tools.has_texture_mapping_zone && !layer_tools.texture_mapping_extruders.empty()) {
const size_t sequence_tool = prime_tower_texture.tool_for_layer_sequence(layer_tools.layer_index);
if (sequence_tool != size_t(-1) && std::find(layer_tools.texture_mapping_extruders.begin(),
layer_tools.texture_mapping_extruders.end(),
unsigned(sequence_tool)) != layer_tools.texture_mapping_extruders.end())
return int(sequence_tool);
return int(layer_tools.texture_mapping_extruders.front());
}
const size_t tool = prime_tower_texture.tool_for_layer_sequence(layer_tools.layer_index);
if (tool != size_t(-1))
return int(tool);
return -1;
};
if (!is_wipe_tower_type2) {
// in BBL machine, wipe tower is only use to prime extruder. So just use a global wipe volume.
@@ -3584,13 +3621,17 @@ void Print::_make_wipe_tower()
for (auto& layer_tools : m_wipe_tower_data.tool_ordering.layer_tools()) { // for all layers
if (!layer_tools.has_wipe_tower) continue;
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
std::vector<unsigned int> texture_mapping_layer_tools = prime_tower_texture_layer_tools(layer_tools);
const int texture_mapping_wall_tool = prime_tower_texture_wall_tool(layer_tools);
wipe_tower.plan_toolchange((float) layer_tools.print_z,
(float) layer_tools.wipe_tower_layer_height,
current_filament_id,
current_filament_id,
0.f,
0.f,
layer_tools.has_texture_mapping_zone && layer_tools.extruders.size() == 1);
layer_tools.has_texture_mapping_zone && layer_tools.extruders.size() == 1,
texture_mapping_layer_tools,
texture_mapping_wall_tool);
used_filament_ids.insert(layer_tools.extruders.begin(), layer_tools.extruders.end());
@@ -3718,8 +3759,10 @@ void Print::_make_wipe_tower()
if (!layer_tools.has_wipe_tower)
continue;
bool first_layer = &layer_tools == &m_wipe_tower_data.tool_ordering.front();
std::vector<unsigned int> texture_mapping_layer_tools = prime_tower_texture_layer_tools(layer_tools);
const int texture_mapping_wall_tool = prime_tower_texture_wall_tool(layer_tools);
wipe_tower.plan_toolchange((float) layer_tools.print_z, (float) layer_tools.wipe_tower_layer_height, current_extruder_id,
current_extruder_id, false);
current_extruder_id, false, texture_mapping_layer_tools, texture_mapping_wall_tool);
for (const auto extruder_id : layer_tools.extruders) {
if ((first_layer && extruder_id == m_wipe_tower_data.tool_ordering.all_extruders().back()) || extruder_id !=
current_extruder_id) {