diff --git a/src/libslic3r/BoundingBox.hpp b/src/libslic3r/BoundingBox.hpp index 64f9725218..2218a7b116 100644 --- a/src/libslic3r/BoundingBox.hpp +++ b/src/libslic3r/BoundingBox.hpp @@ -268,7 +268,7 @@ inline BoundingBoxf3 unscaled(const BoundingBox3 &bb) { return {unscaled(bb.min) template auto cast(const BoundingBoxBase &b) { - return BoundingBoxBase>{b.min.template cast(), + return BoundingBoxBase>{b.min.template cast(), b.max.template cast()}; } diff --git a/src/libslic3r/BuildVolume.cpp b/src/libslic3r/BuildVolume.cpp index 010a330e26..147a556aa3 100644 --- a/src/libslic3r/BuildVolume.cpp +++ b/src/libslic3r/BuildVolume.cpp @@ -188,7 +188,7 @@ static inline BuildVolume::ObjectState rectangle_test(const indexed_triangle_set // Trim the input transformed triangle mesh with print bed and test the remaining vertices with is_inside callback. // Return inside / colliding / outside state. template -BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed, InsideFn is_inside) +BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, const Transform3f &trafo, bool may_be_below_bed, bool convex, InsideFn is_inside) { size_t num_inside = 0; size_t num_above = 0; @@ -205,8 +205,10 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con const auto sign = [](const stl_vertex& pt) { return pt.z() > world_min_z ? 1 : pt.z() < world_min_z ? -1 : 0; }; + bool below_outside = false; + for (const stl_vertex &v : its.vertices) { - const stl_vertex pt = trafo * v; + stl_vertex pt = trafo * v; const int s = sign(pt); sides.emplace_back(s); if (s >= 0) { @@ -214,6 +216,10 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con ++ num_above; if (is_inside(pt)) ++ num_inside; + } else if (convex && !below_outside) { + pt.z() = 0; + if (!is_inside(pt)) + below_outside = true; } } @@ -225,7 +231,8 @@ BuildVolume::ObjectState object_state_templ(const indexed_triangle_set &its, con // 2) Calculate intersections of triangle edges with the build surface. inside = num_inside > 0; outside = num_inside < num_above; - if (num_above < its.vertices.size() && ! (inside && outside)) { + // Orca: for convex shape, if everything inside then don't bother check intersection + if (num_above < its.vertices.size() && !(inside && outside) && (!(inside && !below_outside) || !convex)) { // Not completely above the build surface and status may still change by testing edges intersecting the build platform. for (const stl_triangle_vertex_indices &tri : its.indices) { const int s[3] = { sides[tri(0)], sides[tri(1)], sides[tri(2)] }; @@ -284,21 +291,21 @@ BuildVolume::ObjectState BuildVolume::object_state(const indexed_triangle_set& i // The following test correctly interprets intersection of a non-convex object with a rectangular build volume. //return rectangle_test(its, trafo, to_2d(build_volume.min), to_2d(build_volume.max), build_volume.max.z()); //FIXME This test does NOT correctly interprets intersection of a non-convex object with a rectangular build volume. - return object_state_templ(its, trafo, may_be_below_bed, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); }); + return object_state_templ(its, trafo, may_be_below_bed, true, [build_volumef](const Vec3f &pt) { return build_volumef.contains(pt); }); } case BuildVolume_Type::Circle: { Geometry::Circlef circle { unscaled(m_circle.center), unscaled(m_circle.radius + SceneEpsilon) }; return m_max_print_height == 0.0 ? - object_state_templ(its, trafo, may_be_below_bed, [circle](const Vec3f &pt) { return circle.contains(to_2d(pt)); }) : - object_state_templ(its, trafo, may_be_below_bed, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); }); + object_state_templ(its, trafo, may_be_below_bed, true, [circle](const Vec3f& pt) { return circle.contains(to_2d(pt)); }) : + object_state_templ(its, trafo, may_be_below_bed, true, [circle, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && circle.contains(to_2d(pt)); }); } case BuildVolume_Type::Convex: //FIXME doing test on convex hull until we learn to do test on non-convex polygons efficiently. case BuildVolume_Type::Custom: return m_max_print_height == 0.0 ? - object_state_templ(its, trafo, may_be_below_bed, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }) : - object_state_templ(its, trafo, may_be_below_bed, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }); + object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this](const Vec3f &pt) { return Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }) : + object_state_templ(its, trafo, may_be_below_bed, m_type == BuildVolume_Type::Convex, [this, z = m_max_print_height + SceneEpsilon](const Vec3f &pt) { return pt.z() < z && Geometry::inside_convex_polygon(m_top_bottom_convex_hull_decomposition_scene, to_2d(pt).cast()); }); case BuildVolume_Type::Invalid: default: return ObjectState::Inside; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 34e1949b98..a6b4f2bb87 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -3317,7 +3317,14 @@ ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const Buil } const Transform3d matrix = this->get_matrix() * vol->get_matrix(); - BuildVolume::ObjectState state = build_volume.object_state(vol->mesh().its, matrix.cast(), true /* may be below print bed */); + + const auto bboxt = bb.transformed(matrix); + const BoundingBoxf bbox2d{to_2d(bboxt.min), to_2d(bboxt.max)}; + BuildVolume::ObjectState state; + if (!build_volume.bounding_volume2d().inflated(BuildVolume::SceneEpsilon).overlap(bbox2d)) + state = BuildVolume::ObjectState::Outside; + else + state = build_volume.object_state(vol->mesh().its, matrix.cast(), true /* may be below print bed */); if (state == BuildVolume::ObjectState::Inside) // Volume is completely inside. inside_outside |= INSIDE; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 4319935fa4..9c006fc5d1 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5286,8 +5286,6 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(": enter, force_validation=%1% postpone_error_messages=%2%, switch_print=%3%, was_running=%4%")%force_validation %postpone_error_messages %switch_print %was_running; if (switch_print) { - // Update the "out of print bed" state of ModelInstances. - this->update_print_volume_state(); //BBS: update the current print to the current plate this->partplate_list.update_slice_context_to_current_plate(background_process); this->preview->update_gcode_result(partplate_list.get_current_slice_result());