mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-04 23:10:44 +08:00
wipe towers volumes
This commit is contained in:
parent
fae06e0773
commit
5b59785456
@ -2,6 +2,7 @@
|
||||
|
||||
#include "BuildVolume.hpp"
|
||||
#include "Model.hpp"
|
||||
#include "Print.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
@ -214,5 +215,22 @@ bool MultipleBeds::update_after_load_or_arrange(Model& model, const BuildVolume&
|
||||
|
||||
|
||||
|
||||
void MultipleBeds::ensure_wipe_towers_on_beds(Model& model, const std::vector<std::unique_ptr<Print>>& prints)
|
||||
{
|
||||
for (size_t bed_idx = 0; bed_idx < get_number_of_beds(); ++bed_idx) {
|
||||
ModelWipeTower& mwt = model.get_wipe_tower_vector()[bed_idx];
|
||||
double depth = prints[bed_idx]->wipe_tower_data().depth;
|
||||
double width = prints[bed_idx]->wipe_tower_data().width;
|
||||
double brim = prints[bed_idx]->wipe_tower_data().brim_width;
|
||||
|
||||
Polygon plg(Points{Point::new_scale(-brim,-brim), Point::new_scale(brim+width, -brim), Point::new_scale(brim+width, brim+depth), Point::new_scale(-brim, brim+depth)});
|
||||
plg.rotate(Geometry::deg2rad(mwt.rotation));
|
||||
plg.translate(scaled(mwt.position));
|
||||
if (std::all_of(plg.points.begin(), plg.points.end(), [this](const Point& pt) { return !m_build_volume_bb.contains(unscale(pt)); }))
|
||||
mwt.position = 2*brim*Vec2d(1.,1.);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@ namespace Slic3r {
|
||||
class Model;
|
||||
class BuildVolume;
|
||||
class PrintBase;
|
||||
class Print;
|
||||
|
||||
extern bool s_reload_preview_after_switching_beds;
|
||||
extern bool s_beds_just_switched;
|
||||
@ -48,6 +49,7 @@ public:
|
||||
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) { m_build_volume_bb = build_volume_bb; m_build_volume_bb_incl_model = build_volume_bb_incl_model; }
|
||||
void ensure_wipe_towers_on_beds(Model& model, const std::vector<std::unique_ptr<Print>>& prints);
|
||||
|
||||
|
||||
|
||||
|
@ -502,11 +502,11 @@ int GLVolumeCollection::load_object_volume(
|
||||
#if SLIC3R_OPENGL_ES
|
||||
int GLVolumeCollection::load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle,
|
||||
float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh)
|
||||
float rotation_angle, bool size_unknown, float brim_width, size_t idx, TriangleMesh* out_mesh)
|
||||
#else
|
||||
int GLVolumeCollection::load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle,
|
||||
float rotation_angle, bool size_unknown, float brim_width)
|
||||
float rotation_angle, bool size_unknown, float brim_width, size_t idx)
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
{
|
||||
if (height == 0.0f)
|
||||
@ -604,9 +604,9 @@ int GLVolumeCollection::load_wipe_tower_preview(
|
||||
v.set_convex_hull(mesh.convex_hull_3d());
|
||||
v.set_volume_offset(Vec3d(pos_x, pos_y, 0.0));
|
||||
v.set_volume_rotation(Vec3d(0., 0., (M_PI / 180.) * rotation_angle));
|
||||
v.composite_id = GLVolume::CompositeID(INT_MAX, 0, 0);
|
||||
v.composite_id = GLVolume::CompositeID(INT_MAX - idx, 0, 0);
|
||||
v.geometry_id.first = 0;
|
||||
v.geometry_id.second = wipe_tower_instance_id(0).id;
|
||||
v.geometry_id.second = wipe_tower_instance_id(idx).id;
|
||||
v.is_wipe_tower = true;
|
||||
v.shader_outside_printer_detection_enabled = !size_unknown;
|
||||
return int(volumes.size() - 1);
|
||||
|
@ -426,10 +426,10 @@ public:
|
||||
|
||||
#if SLIC3R_OPENGL_ES
|
||||
int load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, size_t idx, TriangleMesh* out_mesh = nullptr);
|
||||
#else
|
||||
int load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width);
|
||||
float pos_x, float pos_y, float width, float depth, const std::vector<std::pair<float, float>>& z_and_depth_pairs, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, size_t idx);
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
|
@ -1699,7 +1699,7 @@ void GCodeViewer::load_wipetower_shell(const Print& print)
|
||||
const float brim_width = wipe_tower_data.brim_width;
|
||||
if (depth != 0.) {
|
||||
m_shells.volumes.load_wipe_tower_preview(wxGetApp().plater()->model().wipe_tower().position.x(), wxGetApp().plater()->model().wipe_tower().position.y(), config.wipe_tower_width, depth, z_and_depth_pairs,
|
||||
max_z, config.wipe_tower_cone_angle, wxGetApp().plater()->model().wipe_tower().rotation, false, brim_width);
|
||||
max_z, config.wipe_tower_cone_angle, wxGetApp().plater()->model().wipe_tower().rotation, false, brim_width, 0);
|
||||
GLVolume* volume = m_shells.volumes.volumes.back();
|
||||
volume->color.a(0.25f);
|
||||
volume->force_native_color = true;
|
||||
|
@ -2211,7 +2211,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
m_reload_delayed = !m_canvas->IsShown() && !refresh_immediately && !force_full_scene_refresh;
|
||||
|
||||
PrinterTechnology printer_technology = current_printer_technology();
|
||||
int volume_idx_wipe_tower_old = -1;
|
||||
std::map<size_t, size_t> volume_idxs_wipe_towers_old; // map from geometry_id.second to volume_id
|
||||
|
||||
// Release invalidated volumes to conserve GPU memory in case of delayed refresh (see m_reload_delayed).
|
||||
// First initialize model_volumes_new_sorted & model_instances_new_sorted.
|
||||
@ -2284,12 +2284,10 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
if (mvs == nullptr || force_full_scene_refresh) {
|
||||
// This GLVolume will be released.
|
||||
if (volume->is_wipe_tower) {
|
||||
// There is only one wipe tower.
|
||||
assert(volume_idx_wipe_tower_old == -1);
|
||||
#if SLIC3R_OPENGL_ES
|
||||
m_wipe_tower_mesh.clear();
|
||||
m_wipe_tower_meshes.clear();
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
volume_idx_wipe_tower_old = (int)volume_id;
|
||||
volume_idxs_wipe_towers_old.emplace(std::make_pair(volume->geometry_id.second, volume_id));
|
||||
}
|
||||
if (!m_reload_delayed) {
|
||||
deleted_volumes.emplace_back(volume, volume_id);
|
||||
@ -2451,38 +2449,46 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
const bool wt = dynamic_cast<const ConfigOptionBool*>(m_config->option("wipe_tower"))->value;
|
||||
const bool co = dynamic_cast<const ConfigOptionBool*>(m_config->option("complete_objects"))->value;
|
||||
|
||||
if (extruders_count > 1 && wt && !co) {
|
||||
|
||||
const float x = m_model->wipe_tower().position.x();
|
||||
const float y = m_model->wipe_tower().position.y();
|
||||
const float w = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_width"))->value;
|
||||
const float a = m_model->wipe_tower().rotation;
|
||||
const float bw = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_brim_width"))->value;
|
||||
const float ca = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_cone_angle"))->value;
|
||||
|
||||
const Print *print = m_process->fff_print();
|
||||
if (extruders_count > 1 && wt && !co) {
|
||||
|
||||
|
||||
for (size_t bed_idx = 0; bed_idx < s_multiple_beds.get_number_of_beds(); ++bed_idx) {
|
||||
const Print *print = wxGetApp().plater()->get_fff_prints()[bed_idx].get();
|
||||
|
||||
const float x = m_model->get_wipe_tower_vector()[bed_idx].position.x();
|
||||
const float y = m_model->get_wipe_tower_vector()[bed_idx].position.y();
|
||||
const float a = m_model->get_wipe_tower_vector()[bed_idx].rotation;
|
||||
const float depth = print->wipe_tower_data(extruders_count).depth;
|
||||
const std::vector<std::pair<float, float>> z_and_depth_pairs = print->wipe_tower_data(extruders_count).z_and_depth_pairs;
|
||||
const float height_real = print->wipe_tower_data(extruders_count).height; // -1.f = unknown
|
||||
const bool is_wipe_tower_step_done = print->is_step_done(psWipeTower);
|
||||
|
||||
// Height of a print (Show at least a slab).
|
||||
const double height = height_real < 0.f ? std::max(m_model->max_z(), 10.0) : height_real;
|
||||
|
||||
if (depth != 0.) {
|
||||
#if SLIC3R_OPENGL_ES
|
||||
if (bed_idx >= m_wipe_tower_meshes.size())
|
||||
m_wipe_tower_meshes.resize(bed_idx + 1);
|
||||
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
||||
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower),
|
||||
bw, &m_wipe_tower_mesh);
|
||||
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !is_wipe_tower_step_done,
|
||||
bw, bed_idx, &m_wipe_tower_meshes[bed_idx]);
|
||||
#else
|
||||
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
|
||||
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !print->is_step_done(psWipeTower),
|
||||
bw);
|
||||
x, y, w, depth, z_and_depth_pairs, (float)height, ca, a, !is_wipe_tower_step_done,
|
||||
bw, bed_idx);
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
if (volume_idx_wipe_tower_old != -1)
|
||||
map_glvolume_old_to_new[volume_idx_wipe_tower_old] = volume_idx_wipe_tower_new;
|
||||
auto it = volume_idxs_wipe_towers_old.find(m_volumes.volumes.back()->geometry_id.second);
|
||||
if (it != volume_idxs_wipe_towers_old.end())
|
||||
map_glvolume_old_to_new[it->second] = volume_idx_wipe_tower_new;
|
||||
m_volumes.volumes.back()->set_volume_offset(m_volumes.volumes.back()->get_volume_offset() + s_multiple_beds.get_bed_translation(bed_idx));
|
||||
}
|
||||
}
|
||||
s_multiple_beds.ensure_wipe_towers_on_beds(wxGetApp().plater()->model(), wxGetApp().plater()->get_fff_prints());
|
||||
}
|
||||
}
|
||||
|
||||
update_volumes_colors_by_extruder();
|
||||
@ -3983,11 +3989,13 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
bool object_moved = false;
|
||||
Vec3d wipe_tower_origin = Vec3d::Zero();
|
||||
std::vector<Vec3d> wipe_tower_origin = std::vector<Vec3d>(s_multiple_beds.get_max_beds(), Vec3d::Zero());
|
||||
|
||||
Selection::EMode selection_mode = m_selection.get_mode();
|
||||
int vol_id = -1;
|
||||
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
++vol_id;
|
||||
int object_idx = v->object_idx();
|
||||
int instance_idx = v->instance_idx();
|
||||
int volume_idx = v->volume_idx();
|
||||
@ -4012,9 +4020,15 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
model_object->invalidate_bounding_box();
|
||||
}
|
||||
}
|
||||
else if (m_selection.is_wipe_tower() && v->is_wipe_tower)
|
||||
else if (m_selection.is_wipe_tower() && v->is_wipe_tower && m_selection.contains_volume(vol_id)) {
|
||||
// Move a wipe tower proxy.
|
||||
wipe_tower_origin = v->get_volume_offset();
|
||||
for (size_t bed_idx = 0; bed_idx < s_multiple_beds.get_max_beds(); ++bed_idx) {
|
||||
if (v->geometry_id.second == wipe_tower_instance_id(bed_idx).id) {
|
||||
wipe_tower_origin[bed_idx] = v->get_volume_offset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes flying instances
|
||||
@ -4041,8 +4055,9 @@ void GLCanvas3D::do_move(const std::string& snapshot_type)
|
||||
if (object_moved)
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_INSTANCE_MOVED));
|
||||
|
||||
if (wipe_tower_origin != Vec3d::Zero()) {
|
||||
m_model->wipe_tower().position = Vec2d(wipe_tower_origin[0], wipe_tower_origin[1]);
|
||||
if (auto it = std::find_if(wipe_tower_origin.begin(), wipe_tower_origin.end(), [](const Vec3d& pos) { return pos != Vec3d::Zero(); }); it != wipe_tower_origin.end()) {
|
||||
size_t bed_idx = it - wipe_tower_origin.begin();
|
||||
m_model->get_wipe_tower_vector()[bed_idx].position = Vec2d((*it)[0] - s_multiple_beds.get_bed_translation(bed_idx).x(), (*it)[1] - s_multiple_beds.get_bed_translation(bed_idx).y());
|
||||
post_event(SimpleEvent(EVT_GLCANVAS_WIPETOWER_TOUCHED));
|
||||
}
|
||||
|
||||
@ -4082,14 +4097,23 @@ void GLCanvas3D::do_rotate(const std::string& snapshot_type)
|
||||
std::set<std::pair<int, int>> done; // keeps track of modified instances
|
||||
|
||||
Selection::EMode selection_mode = m_selection.get_mode();
|
||||
int v_id = -1;
|
||||
|
||||
for (const GLVolume* v : m_volumes.volumes) {
|
||||
++v_id;
|
||||
if (v->is_wipe_tower) {
|
||||
const Vec3d offset = v->get_volume_offset();
|
||||
if (m_selection.contains_volume(v_id)) {
|
||||
for (size_t bed_idx = 0; bed_idx < s_multiple_beds.get_max_beds(); ++bed_idx) {
|
||||
if (v->geometry_id.second == wipe_tower_instance_id(bed_idx).id) {
|
||||
const Vec3d offset = v->get_volume_offset() - s_multiple_beds.get_bed_translation(bed_idx);
|
||||
Vec3d rot_unit_x = v->get_volume_transformation().get_matrix().linear() * Vec3d::UnitX();
|
||||
double z_rot = std::atan2(rot_unit_x.y(), rot_unit_x.x());
|
||||
m_model->wipe_tower().position = Vec2d(offset.x(), offset.y());
|
||||
m_model->wipe_tower().rotation = (180. / M_PI) * z_rot;
|
||||
m_model->get_wipe_tower_vector()[bed_idx].position = Vec2d(offset.x(), offset.y());
|
||||
m_model->get_wipe_tower_vector()[bed_idx].rotation = (180. / M_PI) * z_rot;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const int object_idx = v->object_idx();
|
||||
if (object_idx < 0 || (int)m_model->objects.size() <= object_idx)
|
||||
|
@ -510,7 +510,7 @@ private:
|
||||
|
||||
GLVolumeCollection m_volumes;
|
||||
#if SLIC3R_OPENGL_ES
|
||||
TriangleMesh m_wipe_tower_mesh;
|
||||
std::vector<TriangleMesh> m_wipe_tower_meshes;
|
||||
#endif // SLIC3R_OPENGL_ES
|
||||
GCodeViewer m_gcode_viewer;
|
||||
|
||||
|
@ -528,8 +528,6 @@ struct Plater::priv
|
||||
|
||||
void on_object_select(SimpleEvent&);
|
||||
void on_right_click(RBtnEvent&);
|
||||
void on_wipetower_moved(Vec3dEvent&);
|
||||
void on_wipetower_rotated(Vec3dEvent&);
|
||||
void on_update_geometry(Vec3dsEvent<2>&);
|
||||
void on_3dcanvas_mouse_dragging_started(SimpleEvent&);
|
||||
void on_3dcanvas_mouse_dragging_finished(SimpleEvent&);
|
||||
@ -1599,7 +1597,10 @@ 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]() {q->canvas3D()->check_volumes_outside_state(); }))
|
||||
if (s_multiple_beds.update_after_load_or_arrange(model, q->build_volume(), [this]() {
|
||||
q->canvas3D()->check_volumes_outside_state();
|
||||
s_multiple_beds.ensure_wipe_towers_on_beds(model, fff_prints);
|
||||
}))
|
||||
update();
|
||||
|
||||
return obj_idxs;
|
||||
@ -3386,17 +3387,6 @@ void Plater::priv::on_right_click(RBtnEvent& evt)
|
||||
}
|
||||
}
|
||||
|
||||
void Plater::priv::on_wipetower_moved(Vec3dEvent &evt)
|
||||
{
|
||||
model.wipe_tower().position = Vec2d(evt.data[0], evt.data[1]);
|
||||
}
|
||||
|
||||
void Plater::priv::on_wipetower_rotated(Vec3dEvent& evt)
|
||||
{
|
||||
model.wipe_tower().position = Vec2d(evt.data[0], evt.data[1]);
|
||||
model.wipe_tower().rotation = Geometry::rad2deg(evt.data(2));
|
||||
}
|
||||
|
||||
void Plater::priv::on_update_geometry(Vec3dsEvent<2>&)
|
||||
{
|
||||
// TODO
|
||||
@ -6792,7 +6782,10 @@ void Plater::arrange(Worker &w, bool selected)
|
||||
concat_strings(names, "\n")));
|
||||
}
|
||||
|
||||
s_multiple_beds.update_after_load_or_arrange(model(), build_volume(), [this]() { canvas3D()->check_volumes_outside_state(); });
|
||||
s_multiple_beds.update_after_load_or_arrange(model(), build_volume(), [this]() {
|
||||
canvas3D()->check_volumes_outside_state();
|
||||
s_multiple_beds.ensure_wipe_towers_on_beds(model(), get_fff_prints());
|
||||
});
|
||||
|
||||
update(static_cast<unsigned int>(UpdateParams::FORCE_FULL_SCREEN_REFRESH));
|
||||
wxGetApp().obj_manipul()->set_dirty();
|
||||
@ -7289,6 +7282,11 @@ void Plater::bring_instance_forward()
|
||||
p->bring_instance_forward();
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<Print>>& Plater::get_fff_prints()
|
||||
{
|
||||
return p->fff_prints;
|
||||
}
|
||||
|
||||
wxMenu* Plater::object_menu() { return p->menus.object_menu(); }
|
||||
wxMenu* Plater::part_menu() { return p->menus.part_menu(); }
|
||||
wxMenu* Plater::text_part_menu() { return p->menus.text_part_menu(); }
|
||||
|
@ -100,6 +100,8 @@ public:
|
||||
Print& active_fff_print();
|
||||
SLAPrint& active_sla_print();
|
||||
|
||||
std::vector<std::unique_ptr<Print>>& get_fff_prints();
|
||||
|
||||
void new_project();
|
||||
void load_project();
|
||||
void load_project(const wxString& filename);
|
||||
|
@ -162,7 +162,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
|
||||
const std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = get_raycasters(type);
|
||||
const Vec3f camera_forward = camera.get_dir_forward().cast<float>();
|
||||
HitResult current_hit = { type };
|
||||
for (std::shared_ptr<SceneRaycasterItem> item : *raycasters) {
|
||||
for (const std::shared_ptr<SceneRaycasterItem>& item : *raycasters) {
|
||||
if (!item->is_active())
|
||||
continue;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/BuildVolume.hpp"
|
||||
#include "libslic3r/MultipleBeds.hpp"
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
@ -147,7 +148,7 @@ void Selection::add(unsigned int volume_idx, bool as_single_selection, bool chec
|
||||
return;
|
||||
|
||||
// wipe tower is already selected
|
||||
if (is_wipe_tower() && volume->is_wipe_tower)
|
||||
if (is_wipe_tower() && volume->is_wipe_tower && contains_volume(volume_idx))
|
||||
return;
|
||||
|
||||
bool keep_instance_mode = (m_mode == Instance) && !as_single_selection;
|
||||
|
Loading…
x
Reference in New Issue
Block a user