diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index d48443181..208cf9b66 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -1430,11 +1430,9 @@ double ModelObject::get_min_z() const { if (instances.empty()) return 0.0; - else - { + else { double min_z = DBL_MAX; - for (size_t i = 0; i < instances.size(); ++i) - { + for (size_t i = 0; i < instances.size(); ++i) { min_z = std::min(min_z, get_instance_min_z(i)); } return min_z; @@ -1445,15 +1443,14 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const { double min_z = DBL_MAX; - ModelInstance* inst = instances[instance_idx]; + const ModelInstance* inst = instances[instance_idx]; const Transform3d& mi = inst->get_matrix(true); - for (const ModelVolume* v : volumes) - { + for (const ModelVolume* v : volumes) { if (!v->is_model_part()) continue; - Transform3d mv = mi * v->get_matrix(); + const Transform3d mv = mi * v->get_matrix(); const TriangleMesh& hull = v->get_convex_hull(); for (const stl_facet &facet : hull.stl.facet_start) for (int i = 0; i < 3; ++ i) diff --git a/src/slic3r/GUI/3DScene.cpp b/src/slic3r/GUI/3DScene.cpp index 57ec1e0d9..c64c36ea8 100644 --- a/src/slic3r/GUI/3DScene.cpp +++ b/src/slic3r/GUI/3DScene.cpp @@ -524,7 +524,7 @@ bool GLVolume::is_sinking() const if (is_modifier) return false; const BoundingBoxf3& box = transformed_convex_hull_bounding_box(); - return box.min(2) < 0.0 && box.max(2) >= 0.0; + return box.min(2) < -EPSILON && box.max(2) >= -EPSILON; } bool GLVolume::is_below_printbed() const diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 59a4a62a4..1513c5a39 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3610,18 +3610,30 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type) if (!snapshot_type.empty()) wxGetApp().plater()->take_snapshot(_(snapshot_type)); +#if ENABLE_ALLOW_NEGATIVE_Z + // stores current min_z of instances + std::map, double> min_zs; + if (!snapshot_type.empty()) { + for (int i = 0; i < static_cast(m_model->objects.size()); ++i) { + const ModelObject* obj = m_model->objects[i]; + for (int j = 0; j < static_cast(obj->instances.size()); ++j) { + min_zs[{ i, j }] = obj->instance_bounding_box(j).min(2); + } + } + } +#endif // ENABLE_ALLOW_NEGATIVE_Z + std::set> done; // keeps track of modified instances Selection::EMode selection_mode = m_selection.get_mode(); - for (const GLVolume* v : m_volumes.volumes) - { + for (const GLVolume* v : m_volumes.volumes) { int object_idx = v->object_idx(); if (object_idx == 1000) { // the wipe tower Vec3d offset = v->get_volume_offset(); post_event(Vec3dEvent(EVT_GLCANVAS_WIPETOWER_ROTATED, Vec3d(offset(0), offset(1), v->get_volume_rotation()(2)))); } - if ((object_idx < 0) || ((int)m_model->objects.size() <= object_idx)) + if (object_idx < 0 || (int)m_model->objects.size() <= object_idx) continue; int instance_idx = v->instance_idx(); @@ -3631,15 +3643,12 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type) // Rotate instances/volumes. ModelObject* model_object = m_model->objects[object_idx]; - if (model_object != nullptr) - { - if (selection_mode == Selection::Instance) - { + if (model_object != nullptr) { + if (selection_mode == Selection::Instance) { model_object->instances[instance_idx]->set_rotation(v->get_instance_rotation()); model_object->instances[instance_idx]->set_offset(v->get_instance_offset()); } - else if (selection_mode == Selection::Volume) - { + else if (selection_mode == Selection::Volume) { model_object->volumes[volume_idx]->set_rotation(v->get_volume_rotation()); model_object->volumes[volume_idx]->set_offset(v->get_volume_offset()); } @@ -3648,12 +3657,18 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type) } // Fixes sinking/flying instances - for (const std::pair& i : done) - { + for (const std::pair& i : done) { ModelObject* m = m_model->objects[i.first]; - Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second)); - m_selection.translate(i.first, i.second, shift); - m->translate_instance(i.second, shift); +#if ENABLE_ALLOW_NEGATIVE_Z + // leave sinking instances as sinking + if (min_zs.empty() || min_zs.find({i.first, i.second})->second >= 0.0) { +#endif // ENABLE_ALLOW_NEGATIVE_Z + Vec3d shift(0.0, 0.0, -m->get_instance_min_z(i.second)); + m_selection.translate(i.first, i.second, shift); + m->translate_instance(i.second, shift); +#if ENABLE_ALLOW_NEGATIVE_Z + } +#endif // ENABLE_ALLOW_NEGATIVE_Z } if (!done.empty())