Do not account for bed model for spacing calculation

This commit is contained in:
Lukas Matena 2024-11-13 15:18:42 +01:00
parent 45eda1a00f
commit 311434382d
5 changed files with 59 additions and 39 deletions

View File

@ -96,14 +96,20 @@ Vec3d MultipleBeds::get_bed_translation(int id) const
return Vec3d::Zero();
int x = 0;
int y = 0;
if (m_layout_linear)
if (m_legacy_layout)
x = id;
else {
BedsGrid::GridCoords coords{BedsGrid::index2grid_coords(id)};
x = coords.x();
y = coords.y();
}
return Vec3d(x * m_build_volume_bb_incl_model.size().x() * (1. + bed_gap_x), y * m_build_volume_bb_incl_model.size().y() * (1. + bed_gap_y), 0.);
// As for the m_legacy_layout switch, see comments at definition of bed_gap_relative.
Vec2d gap = bed_gap();
double gap_x = (m_legacy_layout ? m_build_volume_bb.size().x() * (2./10.) : gap.x());
return Vec3d(x * (m_build_volume_bb.size().x() + gap_x),
y * (m_build_volume_bb.size().y() + gap.y()), // When using legacy layout, y is zero anyway.
0.);
}
void MultipleBeds::clear_inst_map()
@ -207,13 +213,12 @@ void MultipleBeds::update_shown_beds(Model& model, const BuildVolume& build_volu
set_active_bed(m_number_of_beds != original_number_of_beds ? 0 : stash_active);
}
// Beware! This function is also needed for proper update of bed when normal grid project is loaded!
bool MultipleBeds::update_after_load_or_arrange(Model& model, const BuildVolume& build_volume, std::function<void()> update_fn)
bool MultipleBeds::rearrange_after_load(Model& model, const BuildVolume& build_volume, std::function<void()> update_fn)
{
int original_number_of_beds = m_number_of_beds;
int stash_active = get_active_bed();
Slic3r::ScopeGuard guard([&]() {
m_layout_linear = false;
m_legacy_layout = false;
m_number_of_beds = get_max_beds();
model.update_print_volume_state(build_volume);
int max_bed = 0;
@ -226,8 +231,7 @@ bool MultipleBeds::update_after_load_or_arrange(Model& model, const BuildVolume&
update_fn();
});
m_layout_linear = true;
std::swap(m_build_volume_bb, m_build_volume_bb_incl_model);
m_legacy_layout = true;
int abs_max = get_max_beds();
while (true) {
// This is to ensure that even objects on linear bed with higher than
@ -242,10 +246,11 @@ bool MultipleBeds::update_after_load_or_arrange(Model& model, const BuildVolume&
abs_max += get_max_beds();
}
m_number_of_beds = 1;
std::swap(m_build_volume_bb, m_build_volume_bb_incl_model);
m_legacy_layout = false;
int max_bed = 0;
// Check that no instances are out of any bed.
std::map<ObjectID, std::pair<ModelInstance*, int>> id_to_ptr_and_bed;
for (ModelObject* mo : model.objects) {
for (ModelInstance* mi : mo->instances) {
@ -267,27 +272,34 @@ bool MultipleBeds::update_after_load_or_arrange(Model& model, const BuildVolume&
return false;
// All instances are on some bed, at least two are used.
// Move everything as if its bed was in the first position.
for (auto& [oid, mi_and_bed] : id_to_ptr_and_bed) {
auto& [mi, bed_idx] = mi_and_bed;
std::swap(m_build_volume_bb, m_build_volume_bb_incl_model);
m_legacy_layout = true;
mi->set_offset(mi->get_offset() - get_bed_translation(bed_idx));
std::swap(m_build_volume_bb, m_build_volume_bb_incl_model);
}
m_layout_linear = false;
for (auto& [oid, mi_and_bed] : id_to_ptr_and_bed) {
auto& [mi, bed_idx] = mi_and_bed;
m_legacy_layout = false;
mi->set_offset(mi->get_offset() + get_bed_translation(bed_idx));
}
return true;
}
Vec2d MultipleBeds::bed_gap() const
{
// This is the only function that defines how far apart should the beds be. Used in scene and arrange.
// Note that the spacing is momentarily switched to legacy value of 2/10 when a project is loaded.
// Slicers before 2.9.0 used this value for arrange, and there are existing projects with objects spaced that way (controlled by the m_legacy_layout flag).
// TOUCHING THIS WILL BREAK LOADING OF EXISTING PROJECTS !!!
double gap = std::min(100., m_build_volume_bb.size().norm() * (3./10.));
return Vec2d::Ones() * gap;
}
Vec2crd MultipleBeds::get_bed_gap() const {
const Vec2d size_with_gap{
m_build_volume_bb_incl_model.size().cwiseProduct(
Vec2d::Ones() + Vec2d{bed_gap_x, bed_gap_y})};
return scaled(Vec2d{(size_with_gap - m_build_volume_bb.size()) / 2.0});
return scaled(Vec2d{bed_gap() / 2.0});
};
void MultipleBeds::ensure_wipe_towers_on_beds(Model& model, const std::vector<std::unique_ptr<Print>>& prints)

View File

@ -53,15 +53,15 @@ public:
int get_last_hovered_bed() const { return m_last_hovered_bed; }
void update_shown_beds(Model& model, const BuildVolume& build_volume);
bool update_after_load_or_arrange(Model& model, const BuildVolume& build_volume, std::function<void()> update_fn);
bool rearrange_after_load(Model& model, const BuildVolume& build_volume, std::function<void()> update_fn);
void set_loading_project_flag(bool project) { m_loading_project = project; }
bool get_loading_project_flag() const { return m_loading_project; }
void update_build_volume(const BoundingBoxf& build_volume_bb, const BoundingBoxf& build_volume_bb_incl_model) {
void update_build_volume(const BoundingBoxf& build_volume_bb) {
m_build_volume_bb = build_volume_bb;
m_build_volume_bb_incl_model = build_volume_bb_incl_model;
}
Vec2crd get_bed_gap() const;
Vec2d bed_gap() const;
Vec2crd get_bed_gap() const;
void ensure_wipe_towers_on_beds(Model& model, const std::vector<std::unique_ptr<Print>>& prints);
private:
@ -75,17 +75,9 @@ private:
std::map<PrintBase*, size_t> m_printbase_to_texture;
int m_last_hovered_bed = -1;
BoundingBoxf m_build_volume_bb;
BoundingBoxf m_build_volume_bb_incl_model;
bool m_layout_linear = false;
bool m_legacy_layout = false;
bool m_loading_project = false;
// The x value is bed gap as multiples of the actual printable area bounding box,
// so it can be matched to how the old slicer arranged things (in SceneBuilder.cpp).
// The y value is a multiple of the larger of printable area BB and bed model BB -
// this is to make sure that the bed models do not overlap.
const double bed_gap_x = 2./10;
const double bed_gap_y = 2./10;
};
extern MultipleBeds s_multiple_beds;

View File

@ -102,9 +102,18 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
init_internal_model_from_file();
init_triangles();
BoundingBoxf bb = m_build_volume.bounding_volume2d();
bb.max = Vec2d(bb.max.x() + std::max(0., m_model.model.get_bounding_box().size().x() - bb.size().x()), bb.max.y() + std::max(0., m_model.model.get_bounding_box().size().y() - bb.size().y()));
s_multiple_beds.update_build_volume(m_build_volume.bounding_volume2d(), bb);
s_multiple_beds.update_build_volume(m_build_volume.bounding_volume2d());
m_models_overlap = false;
if (! m_model_filename.empty()) {
// Calculate bb of the bed model and figure out if the models would overlap when rendered next to each other.
const BoundingBoxf3& mdl_bb3 = m_model.model.get_bounding_box();
const BoundingBoxf model_bb(Vec2d(mdl_bb3.min.x(), mdl_bb3.min.y()), Vec2d(mdl_bb3.max.x(), mdl_bb3.max.y()));
BoundingBoxf bed_bb = m_build_volume.bounding_volume2d();
bed_bb.translate(-m_model_offset.x(), -m_model_offset.y());
Vec2d gap = unscale(s_multiple_beds.get_bed_gap());
m_models_overlap = (model_bb.size().x() - bed_bb.size().x() > 2 * gap.x() || model_bb.size().y() - bed_bb.size().y() > 2 * gap.y());
}
// Set the origin and size for rendering the coordinate system axes.
m_axes.set_origin({ 0.0, 0.0, static_cast<double>(GROUND_Z) });
@ -345,6 +354,11 @@ void Bed3D::render_axes()
void Bed3D::render_system(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_texture, bool is_active)
{
if (m_models_overlap && s_multiple_beds.get_number_of_beds() + int(s_multiple_beds.should_show_next_bed()) > 1) {
render_default(bottom, false, show_texture, view_matrix, projection_matrix);
return;
}
if (!bottom)
render_model(view_matrix, projection_matrix);
@ -507,7 +521,8 @@ void Bed3D::render_model(const Transform3d& view_matrix, const Transform3d& proj
void Bed3D::render_custom(GLCanvas3D& canvas, const Transform3d& view_matrix, const Transform3d& projection_matrix, bool bottom, bool show_texture, bool picking, bool is_active)
{
if (m_texture_filename.empty() && m_model_filename.empty()) {
if ((m_texture_filename.empty() && m_model_filename.empty())
|| (m_models_overlap && s_multiple_beds.get_number_of_beds() + int(s_multiple_beds.should_show_next_bed()) > 1)) {
render_default(bottom, picking, show_texture, view_matrix, projection_matrix);
return;
}

View File

@ -37,6 +37,7 @@ private:
Type m_type{ Type::Custom };
std::string m_texture_filename;
std::string m_model_filename;
bool m_models_overlap;
// Print volume bounding box exteded with axes and model.
BoundingBoxf3 m_extended_bounding_box;
// Print bed polygon

View File

@ -1600,7 +1600,7 @@ std::vector<size_t> Plater::priv::load_files(const std::vector<fs::path>& input_
GLGizmoSimplify::add_simplify_suggestion_notification(
obj_idxs, model.objects, *notification_manager);
if (s_multiple_beds.update_after_load_or_arrange(model, q->build_volume(), [this]() {
if (s_multiple_beds.rearrange_after_load(model, q->build_volume(), [this]() {
q->canvas3D()->check_volumes_outside_state();
s_multiple_beds.ensure_wipe_towers_on_beds(model, fff_prints);
}))
@ -4207,11 +4207,11 @@ void Plater::load_project(const wxString& filename)
// Take the Undo / Redo snapshot.
Plater::TakeSnapshot snapshot(this, _L("Load Project") + ": " + wxString::FromUTF8(into_path(filename).stem().string().c_str()), UndoRedo::SnapshotType::ProjectSeparator);
p->reset();
s_multiple_beds.set_loading_project_flag(true);
ScopeGuard guard([](){ s_multiple_beds.set_loading_project_flag(false);});
p->reset();
if (! load_files({ into_path(filename) }).empty()) {
// At least one file was loaded.
p->set_project_filename(filename);