Prototype of scale to fit print volume command
This commit is contained in:
parent
f70cc70626
commit
844e99f84e
@ -12,7 +12,7 @@
|
|||||||
// Renders a small sphere in the center of the bounding box of the current selection when no gizmo is active
|
// Renders a small sphere in the center of the bounding box of the current selection when no gizmo is active
|
||||||
#define ENABLE_RENDER_SELECTION_CENTER 0
|
#define ENABLE_RENDER_SELECTION_CENTER 0
|
||||||
// Shows an imgui dialog with render related data
|
// Shows an imgui dialog with render related data
|
||||||
#define ENABLE_RENDER_STATISTICS 1
|
#define ENABLE_RENDER_STATISTICS 0
|
||||||
|
|
||||||
|
|
||||||
//====================
|
//====================
|
||||||
@ -47,7 +47,9 @@
|
|||||||
|
|
||||||
|
|
||||||
// Enable saving textures on GPU in compressed format
|
// Enable saving textures on GPU in compressed format
|
||||||
#define ENABLE_COMPRESSED_TEXTURES 1
|
#define ENABLE_COMPRESSED_TEXTURES 0
|
||||||
|
|
||||||
|
// Enable scale object to fit print volume
|
||||||
|
#define ENABLE_SCALE_TO_FIT_PRINT_VOLUME 1
|
||||||
|
|
||||||
#endif // _technologies_h_
|
#endif // _technologies_h_
|
||||||
|
@ -847,6 +847,19 @@ bool GLGizmosManager::on_char(wxKeyEvent& evt, GLCanvas3D& canvas)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
case 'F':
|
||||||
|
case 'f':
|
||||||
|
{
|
||||||
|
if (m_current == Scale)
|
||||||
|
{
|
||||||
|
wxGetApp().plater()->scale_selection_to_fit_print_volume();
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1286,6 +1286,9 @@ struct Plater::priv
|
|||||||
void sla_optimize_rotation();
|
void sla_optimize_rotation();
|
||||||
void split_object();
|
void split_object();
|
||||||
void split_volume();
|
void split_volume();
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void scale_selection_to_fit_print_volume();
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
bool background_processing_enabled() const { return this->get_config("background_processing") == "1"; }
|
bool background_processing_enabled() const { return this->get_config("background_processing") == "1"; }
|
||||||
void update_print_volume_state();
|
void update_print_volume_state();
|
||||||
void schedule_background_process();
|
void schedule_background_process();
|
||||||
@ -2346,6 +2349,13 @@ void Plater::priv::split_volume()
|
|||||||
wxGetApp().obj_list()->split();
|
wxGetApp().obj_list()->split();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void Plater::priv::scale_selection_to_fit_print_volume()
|
||||||
|
{
|
||||||
|
this->view3D->get_canvas3d()->get_selection().scale_to_fit_print_volume(*config);
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
|
||||||
void Plater::priv::schedule_background_process()
|
void Plater::priv::schedule_background_process()
|
||||||
{
|
{
|
||||||
delayed_error_message.clear();
|
delayed_error_message.clear();
|
||||||
@ -3008,6 +3018,11 @@ bool Plater::priv::init_common_menu(wxMenu* menu, const bool is_part/* = false*/
|
|||||||
|
|
||||||
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
|
sidebar->obj_list()->append_menu_item_fix_through_netfabb(menu);
|
||||||
|
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
append_menu_item(menu, wxID_ANY, _(L("Scale to print volume")), _(L("Scale the selected object to fit the print volume")),
|
||||||
|
[this](wxCommandEvent&) { scale_selection_to_fit_print_volume(); }, "", menu);
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
|
||||||
wxMenu* mirror_menu = new wxMenu();
|
wxMenu* mirror_menu = new wxMenu();
|
||||||
if (mirror_menu == nullptr)
|
if (mirror_menu == nullptr)
|
||||||
return false;
|
return false;
|
||||||
@ -3447,6 +3462,13 @@ bool Plater::is_selection_empty() const
|
|||||||
return p->get_selection().is_empty() || p->get_selection().is_wipe_tower();
|
return p->get_selection().is_empty() || p->get_selection().is_wipe_tower();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void Plater::scale_selection_to_fit_print_volume()
|
||||||
|
{
|
||||||
|
p->scale_selection_to_fit_print_volume();
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
|
||||||
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
|
void Plater::cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper, bool keep_lower, bool rotate_lower)
|
||||||
{
|
{
|
||||||
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
|
wxCHECK_RET(obj_idx < p->model.objects.size(), "obj_idx out of bounds");
|
||||||
|
@ -162,6 +162,9 @@ public:
|
|||||||
void decrease_instances(size_t num = 1);
|
void decrease_instances(size_t num = 1);
|
||||||
void set_number_of_copies(/*size_t num*/);
|
void set_number_of_copies(/*size_t num*/);
|
||||||
bool is_selection_empty() const;
|
bool is_selection_empty() const;
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void scale_selection_to_fit_print_volume();
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
|
||||||
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
void cut(size_t obj_idx, size_t instance_idx, coordf_t z, bool keep_upper = true, bool keep_lower = true, bool rotate_lower = false);
|
||||||
|
|
||||||
|
@ -662,14 +662,34 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
|
|||||||
{
|
{
|
||||||
GLVolume &volume = *(*m_volumes)[i];
|
GLVolume &volume = *(*m_volumes)[i];
|
||||||
if (is_single_full_instance()) {
|
if (is_single_full_instance()) {
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
if (transformation_type.relative())
|
||||||
|
{
|
||||||
|
Transform3d m = Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), scale);
|
||||||
|
Eigen::Matrix<double, 3, 3, Eigen::DontAlign> new_matrix = (m * m_cache.volumes_data[i].get_instance_scale_matrix()).matrix().block(0, 0, 3, 3);
|
||||||
|
// extracts scaling factors from the composed transformation
|
||||||
|
Vec3d new_scale(new_matrix.col(0).norm(), new_matrix.col(1).norm(), new_matrix.col(2).norm());
|
||||||
|
if (transformation_type.joint())
|
||||||
|
volume.set_instance_offset(m_cache.dragging_center + m * (m_cache.volumes_data[i].get_instance_position() - m_cache.dragging_center));
|
||||||
|
|
||||||
|
volume.set_instance_scaling_factor(new_scale);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#else
|
||||||
assert(transformation_type.absolute());
|
assert(transformation_type.absolute());
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
|
if (transformation_type.world() && (std::abs(scale.x() - scale.y()) > EPSILON || std::abs(scale.x() - scale.z()) > EPSILON)) {
|
||||||
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
|
// Non-uniform scaling. Transform the scaling factors into the local coordinate system.
|
||||||
// This is only possible, if the instance rotation is mulitples of ninety degrees.
|
// This is only possible, if the instance rotation is mulitples of ninety degrees.
|
||||||
assert(Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation()));
|
assert(Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation()));
|
||||||
volume.set_instance_scaling_factor((volume.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
|
volume.set_instance_scaling_factor((volume.get_instance_transformation().get_matrix(true, false, true, true).matrix().block<3, 3>(0, 0).transpose() * scale).cwiseAbs());
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
volume.set_instance_scaling_factor(scale);
|
volume.set_instance_scaling_factor(scale);
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
}
|
}
|
||||||
else if (is_single_volume() || is_single_modifier())
|
else if (is_single_volume() || is_single_modifier())
|
||||||
volume.set_volume_scaling_factor(scale);
|
volume.set_volume_scaling_factor(scale);
|
||||||
@ -713,6 +733,51 @@ void Selection::scale(const Vec3d& scale, TransformationType transformation_type
|
|||||||
this->set_bounding_boxes_dirty();
|
this->set_bounding_boxes_dirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void Selection::scale_to_fit_print_volume(const DynamicPrintConfig& config)
|
||||||
|
{
|
||||||
|
if (is_empty() || (m_mode == Volume))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// adds 1/100th of a mm on all sides to avoid false out of print volume detections due to floating-point roundings
|
||||||
|
Vec3d box_size = get_bounding_box().size() + 0.01 * Vec3d::Ones();
|
||||||
|
|
||||||
|
const ConfigOptionPoints* opt = dynamic_cast<const ConfigOptionPoints*>(config.option("bed_shape"));
|
||||||
|
if (opt != nullptr)
|
||||||
|
{
|
||||||
|
BoundingBox bed_box_2D = get_extents(Polygon::new_scale(opt->values));
|
||||||
|
BoundingBoxf3 print_volume(Vec3d(unscale<double>(bed_box_2D.min(0)), unscale<double>(bed_box_2D.min(1)), 0.0), Vec3d(unscale<double>(bed_box_2D.max(0)), unscale<double>(bed_box_2D.max(1)), config.opt_float("max_print_height")));
|
||||||
|
Vec3d print_volume_size = print_volume.size();
|
||||||
|
double sx = (box_size(0) != 0.0) ? print_volume_size(0) / box_size(0) : 0.0;
|
||||||
|
double sy = (box_size(1) != 0.0) ? print_volume_size(1) / box_size(1) : 0.0;
|
||||||
|
double sz = (box_size(2) != 0.0) ? print_volume_size(2) / box_size(2) : 0.0;
|
||||||
|
if ((sx != 0.0) && (sy != 0.0) && (sz != 0.0))
|
||||||
|
{
|
||||||
|
double s = std::min(sx, std::min(sy, sz));
|
||||||
|
if (s != 1.0)
|
||||||
|
{
|
||||||
|
TransformationType type;
|
||||||
|
type.set_world();
|
||||||
|
type.set_relative();
|
||||||
|
type.set_joint();
|
||||||
|
|
||||||
|
// apply scale
|
||||||
|
start_dragging();
|
||||||
|
scale(s * Vec3d::Ones(), type);
|
||||||
|
wxGetApp().plater()->canvas3D()->do_scale();
|
||||||
|
|
||||||
|
// center selection on print bed
|
||||||
|
start_dragging();
|
||||||
|
translate(print_volume.center() - get_bounding_box().center());
|
||||||
|
wxGetApp().plater()->canvas3D()->do_move();
|
||||||
|
|
||||||
|
wxGetApp().obj_manipul()->set_dirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
|
||||||
void Selection::mirror(Axis axis)
|
void Selection::mirror(Axis axis)
|
||||||
{
|
{
|
||||||
if (!m_valid)
|
if (!m_valid)
|
||||||
|
@ -287,6 +287,9 @@ public:
|
|||||||
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
void rotate(const Vec3d& rotation, TransformationType transformation_type);
|
||||||
void flattening_rotate(const Vec3d& normal);
|
void flattening_rotate(const Vec3d& normal);
|
||||||
void scale(const Vec3d& scale, TransformationType transformation_type);
|
void scale(const Vec3d& scale, TransformationType transformation_type);
|
||||||
|
#if ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
|
void scale_to_fit_print_volume(const DynamicPrintConfig& config);
|
||||||
|
#endif // ENABLE_SCALE_TO_FIT_PRINT_VOLUME
|
||||||
void mirror(Axis axis);
|
void mirror(Axis axis);
|
||||||
|
|
||||||
void translate(unsigned int object_idx, const Vec3d& displacement);
|
void translate(unsigned int object_idx, const Vec3d& displacement);
|
||||||
|
Loading…
Reference in New Issue
Block a user