From e8d4291e02c6c4320a0f3f9e90853715fff28d8c Mon Sep 17 00:00:00 2001 From: Arthur Date: Wed, 13 Sep 2023 21:00:04 +0800 Subject: [PATCH] FIX: adaptive layer height may mess up support layers We must ensure when independent support layer height is enabled, the support layers are strictly synced with object layers. Otherwise, the wipe tower toolchange may be messed up. Jira: STUDIO-4097 Change-Id: I6208653f9665b15d028940d5e130c9e895629fc2 (cherry picked from commit 41d35c8af152c91cb356a68d88a879a115b44778) (cherry picked from commit 2b593ce378e7294c52f4d96b2403004972ed2a18) --- src/libslic3r/Support/SupportMaterial.cpp | 84 +++++++++++++++++++---- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/src/libslic3r/Support/SupportMaterial.cpp b/src/libslic3r/Support/SupportMaterial.cpp index 85c461b02b..b64862f60e 100644 --- a/src/libslic3r/Support/SupportMaterial.cpp +++ b/src/libslic3r/Support/SupportMaterial.cpp @@ -1685,6 +1685,48 @@ static inline std::tuple detect_contacts( return std::make_tuple(std::move(contact_polygons), std::move(enforcer_polygons), no_interface_offset); } +// find the object layer that is closest to the {layer.bottom_z-gap_support_object} for top contact, +// or {layer.print_z+gap_object_support} for bottom contact +Layer* sync_gap_with_object_layer(const Layer& layer, const coordf_t gap_support_object, bool is_top_contact) +{ + // sync gap with the object layer height + float gap_synced = 0; + if (is_top_contact) { + Layer* lower_layer = layer.lower_layer, * last_valid_gap_layer = layer.lower_layer; + while (lower_layer && gap_synced < gap_support_object) { + last_valid_gap_layer = lower_layer; + gap_synced += lower_layer->height; + lower_layer = lower_layer->lower_layer; + + } + // maybe gap_synced is too large, find the nearest object layer (one layer above may be better) + if (std::abs(gap_synced - last_valid_gap_layer->height - gap_support_object) < std::abs(gap_synced - gap_support_object)) { + gap_synced -= last_valid_gap_layer->height; + last_valid_gap_layer = last_valid_gap_layer->upper_layer; + } + lower_layer = last_valid_gap_layer; // layer just below the last valid gap layer + if (last_valid_gap_layer->lower_layer) + lower_layer = last_valid_gap_layer->lower_layer; + return lower_layer; + }else{ + Layer* upper_layer = layer.upper_layer, * last_valid_gap_layer = layer.upper_layer; + while (upper_layer && gap_synced < gap_support_object) { + last_valid_gap_layer = upper_layer; + gap_synced += upper_layer->height; + upper_layer = upper_layer->upper_layer; + } + // maybe gap_synced is too large, find the nearest object layer (one layer above may be better) + if (std::abs(gap_synced - last_valid_gap_layer->height - gap_support_object) < std::abs(gap_synced - gap_support_object)) { + gap_synced -= last_valid_gap_layer->height; + last_valid_gap_layer = last_valid_gap_layer->lower_layer; + } + upper_layer = last_valid_gap_layer; // layer just above the last valid gap layer + if (last_valid_gap_layer->upper_layer) + upper_layer = last_valid_gap_layer->upper_layer; + return upper_layer; + } +} + // Allocate one, possibly two support contact layers. // For "thick" overhangs, one support layer will be generated to support normal extrusions, the other to support the "thick" extrusions. static inline std::pair new_contact_layer( @@ -1712,9 +1754,18 @@ static inline std::pair new_cont print_z = layer.bottom_z(); height = layer.lower_layer->height; bottom_z = (layer_id == 1) ? slicing_params.object_print_z_min : layer.lower_layer->lower_layer->print_z; - } else { - print_z = layer.bottom_z() - slicing_params.gap_support_object; - height = print_config.independent_support_layer_height ? 0. : layer.lower_layer->height/*object_config.layer_height*/; // BBS: need to consider adaptive layer heights + } + else { + // BBS: need to consider adaptive layer heights + if (print_config.independent_support_layer_height) { + print_z = layer.bottom_z() - slicing_params.gap_support_object; + height = 0; + } + else { + Layer* synced_layer = sync_gap_with_object_layer(layer, slicing_params.gap_support_object, true); + print_z = synced_layer->print_z; + height = synced_layer->height; + } bottom_z = print_z - height; // Ignore this contact area if it's too low. // Don't want to print a layer below the first layer height as it may not stick well. @@ -1739,7 +1790,7 @@ static inline std::pair new_cont // Contact layer will be printed with a normal flow, but // it will support layers printed with a bridging flow. - if (object_config.thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer)) { + if (object_config.thick_bridges && SupportMaterialInternal::has_bridging_extrusions(layer) && print_config.independent_support_layer_height) { coordf_t bridging_height = 0.; for (const LayerRegion* region : layer.regions()) bridging_height += region->region().bridging_height_avg(print_config); @@ -2373,15 +2424,22 @@ static inline SupportGeneratorLayer* detect_bottom_contacts( // Grow top surfaces so that interface and support generation are generated // with some spacing from object - it looks we don't need the actual // top shapes so this can be done here - //FIXME calculate layer height based on the actual thickness of the layer: - // If the layer is extruded with no bridging flow, support just the normal extrusions. - layer_new.height = slicing_params.soluble_interface || !object.print()->config().independent_support_layer_height ? - // Align the interface layer with the object's layer height. - layer.upper_layer->height : - // Place a bridge flow interface layer or the normal flow interface layer over the top surface. - support_params.support_material_bottom_interface_flow.height(); - layer_new.print_z = slicing_params.soluble_interface ? layer.upper_layer->print_z : - layer.print_z + layer_new.height + slicing_params.gap_object_support; + if (object.print()->config().independent_support_layer_height) { + // If the layer is extruded with no bridging flow, support just the normal extrusions. + layer_new.height = slicing_params.soluble_interface? + // Align the interface layer with the object's layer height. + layer.upper_layer->height : + // Place a bridge flow interface layer or the normal flow interface layer over the top surface. + support_params.support_material_bottom_interface_flow.height(); + layer_new.print_z = slicing_params.soluble_interface ? layer.upper_layer->print_z : + layer.print_z + layer_new.height + slicing_params.gap_object_support; + } + else { + Layer* synced_layer = sync_gap_with_object_layer(layer, slicing_params.gap_object_support, false); + // If the layer is extruded with no bridging flow, support just the normal extrusions. + layer_new.height = synced_layer->height; + layer_new.print_z = synced_layer->print_z; + } layer_new.bottom_z = layer.print_z; layer_new.idx_object_layer_below = layer_id; layer_new.bridging = !slicing_params.soluble_interface && object.config().thick_bridges;