diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index a047d1db48..d869a93350 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -2211,48 +2211,12 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const unsigned int ModelObject::update_instances_print_volume_state(const BuildVolume &build_volume) { unsigned int num_printable = 0; - enum { - INSIDE = 1, - OUTSIDE = 2 - }; - //BBS: add logs for build_volume //const BoundingBoxf3& print_volume = build_volume.bounding_volume(); //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", print_volume {%1%, %2%, %3%} to {%4%, %5%, %6%}")\ // %print_volume.min.x() %print_volume.min.y() %print_volume.min.z()%print_volume.max.x() %print_volume.max.y() %print_volume.max.z(); for (ModelInstance* model_instance : this->instances) { - unsigned int inside_outside = 0; - for (const ModelVolume *vol : this->volumes) { - if (vol->is_model_part()) { - //BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object) - BoundingBoxf3 bb = vol->get_convex_hull().bounding_box(); - Vec3d size = bb.size(); - if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) { - BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->name %vol->name\ - %bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z(); - continue; - } - - const Transform3d matrix = model_instance->get_matrix() * vol->get_matrix(); - BuildVolume::ObjectState 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; - else if (state == BuildVolume::ObjectState::Outside) - // Volume is completely outside. - inside_outside |= OUTSIDE; - else if (state == BuildVolume::ObjectState::Below) { - // Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable - // if some of its volumes are still inside the build volume. - } else - // Volume colliding with the build volume. - inside_outside |= INSIDE | OUTSIDE; - } - } - model_instance->print_volume_state = - inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside : - inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside; - if (inside_outside == INSIDE) { + if (model_instance->update_print_volume_state(build_volume) == ModelInstancePVS_Inside) { //BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s instance inside print volum")%this->name; ++num_printable; } @@ -3280,6 +3244,46 @@ void ModelInstance::get_arrange_polygon(void *ap, const Slic3r::DynamicPrintConf ret.extrude_ids.push_back(1); } +ModelInstanceEPrintVolumeState ModelInstance::calc_print_volume_state(const BuildVolume& build_volume) const +{ + enum { + INSIDE = 1, + OUTSIDE = 2 + }; + + unsigned int inside_outside = 0; + for (const ModelVolume* vol : this->object->volumes) { + if (vol->is_model_part()) { + //BBS: add bounding box empty check logic, for some volume is empty before split(it will be removed after split to object) + BoundingBoxf3 bb = vol->get_convex_hull().bounding_box(); + Vec3d size = bb.size(); + if ((size.x() == 0.f) || (size.y() == 0.f) || (size.z() == 0.f)) { + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", object %1%'s vol %2% is empty, skip it, box: {%3%, %4%, %5%} to {%6%, %7%, %8%}")%this->object->name %vol->name\ + %bb.min.x() %bb.min.y() %bb.min.z()%bb.max.x() %bb.max.y() %bb.max.z(); + continue; + } + + 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 */); + if (state == BuildVolume::ObjectState::Inside) + // Volume is completely inside. + inside_outside |= INSIDE; + else if (state == BuildVolume::ObjectState::Outside) + // Volume is completely outside. + inside_outside |= OUTSIDE; + else if (state == BuildVolume::ObjectState::Below) { + // Volume below the print bed, thus it is completely outside, however this does not prevent the object to be printable + // if some of its volumes are still inside the build volume. + } else + // Volume colliding with the build volume. + inside_outside |= INSIDE | OUTSIDE; + } + } + + return inside_outside == (INSIDE | OUTSIDE) ? ModelInstancePVS_Partly_Outside : + inside_outside == INSIDE ? ModelInstancePVS_Inside : ModelInstancePVS_Fully_Outside; +} + indexed_triangle_set FacetsAnnotation::get_facets(const ModelVolume& mv, EnforcerBlockerType type) const { TriangleSelector selector(mv.mesh()); diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index f3000d9628..015a8b929f 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -1325,6 +1325,8 @@ public: this->object->invalidate_bounding_box(); } + ModelInstanceEPrintVolumeState calc_print_volume_state(const BuildVolume& build_volume) const; + protected: friend class Print; friend class SLAPrint; @@ -1334,6 +1336,12 @@ protected: explicit ModelInstance(const ModelInstance &rhs) = default; void set_model_object(ModelObject *model_object) { object = model_object; } + ModelInstanceEPrintVolumeState update_print_volume_state(const BuildVolume& build_volume) + { + print_volume_state = calc_print_volume_state(build_volume); + return print_volume_state; + } + private: // Parent object, owning this instance. ModelObject* object; diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 9070887052..598351fb89 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -1077,14 +1077,15 @@ bool GLVolumeCollection::check_outside_state(const BuildVolume &build_volume, Mo { if (! volume->is_modifier && (volume->shader_outside_printer_detection_enabled || (! volume->is_wipe_tower && volume->composite_id.volume_id >= 0))) { BuildVolume::ObjectState state; - const BoundingBoxf3& bb = volume_bbox(*volume); if (volume_below(*volume)) state = BuildVolume::ObjectState::Below; else { switch (plate_build_volume.type()) { - case BuildVolume_Type::Rectangle: - //FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects. + case BuildVolume_Type::Rectangle: { + //FIXME this test does not evaluate collision of a build volume bounding box with non-convex objects. + const BoundingBoxf3& bb = volume_bbox(*volume); state = plate_build_volume.volume_state_bbox(bb); + } break; case BuildVolume_Type::Circle: case BuildVolume_Type::Convex: diff --git a/src/slic3r/GUI/PartPlate.cpp b/src/slic3r/GUI/PartPlate.cpp index e5f2a190f0..3a07a42810 100644 --- a/src/slic3r/GUI/PartPlate.cpp +++ b/src/slic3r/GUI/PartPlate.cpp @@ -2074,6 +2074,16 @@ bool PartPlate::check_outside(int obj_id, int instance_id, BoundingBoxf3* boundi if (instance_box.max.z() > plate_box.min.z()) plate_box.min.z() += instance_box.min.z(); // not considering outsize if sinking + if (instance_box.min.z() < SINKING_Z_THRESHOLD) { + // Orca: For sinking object, we use a more expensive algorithm so part below build plate won't be considered + if (plate_box.intersects(instance_box)) { + // TODO: FIXME: this does not take exclusion area into account + const BuildVolume build_volume(get_shape(), m_plater->build_volume().printable_height()); + const auto state = instance->calc_print_volume_state(build_volume); + outside = state == ModelInstancePVS_Partly_Outside; + } + } + else if (plate_box.contains(instance_box)) { if (m_exclude_bounding_box.size() > 0)