Tech ENABLE_WORLD_COORDINATE_SCALE_REVISITED - Alternate implementation of manipulating scale for instances and volumes using gizmo scale and sidebar object manipulator fields - 1st installment

Fixed conflicts during rebase with master
This commit is contained in:
enricoturri1966 2022-02-18 08:57:26 +01:00
parent 558bccec48
commit 622796e9e3
9 changed files with 199 additions and 15 deletions

View file

@ -1412,9 +1412,11 @@ void ModelObject::bake_xy_rotation_into_meshes(size_t instance_idx)
assert(instance_idx < this->instances.size());
const Geometry::Transformation reference_trafo = this->instances[instance_idx]->get_transformation();
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (Geometry::is_rotation_ninety_degrees(reference_trafo.get_rotation()))
// nothing to do, scaling in the world coordinate space is possible in the representation of Geometry::Transformation.
return;
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
bool left_handed = reference_trafo.is_left_handed();
bool has_mirrorring = ! reference_trafo.get_mirror().isApprox(Vec3d(1., 1., 1.));

View file

@ -77,6 +77,8 @@
#define ENABLE_COORDINATE_DEPENDENT_SELECTION_BOX (1 && ENABLE_WORLD_COORDINATE)
// Enable showing the axes of the current reference system when sidebar hints are active
#define ENABLE_WORLD_COORDINATE_SHOW_AXES (1 && ENABLE_WORLD_COORDINATE)
// Enable alternate implementation of manipulating scale for instances and volumes
#define ENABLE_WORLD_COORDINATE_SCALE_REVISITED (1 && ENABLE_WORLD_COORDINATE)
// Enable modified camera control using mouse
#define ENABLE_NEW_CAMERA_MOVEMENTS (1 && ENABLE_2_5_0_ALPHA1)
// Enable modified rectangle selection

View file

@ -627,10 +627,17 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
if (m_world_coordinates) {
#endif // ENABLE_WORLD_COORDINATE
m_new_rotate_label_string = L("Rotate");
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale_label_string = L("Scale");
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_rotation = Vec3d::Zero();
m_new_size = selection.get_scaled_instance_bounding_box().size();
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.0;
}
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale = Vec3d(100.0, 100.0, 100.0);
#else
m_new_scale = m_new_size.cwiseProduct(selection.get_unscaled_instance_bounding_box().size().cwiseInverse()) * 100.0;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
else {
#if ENABLE_WORLD_COORDINATE
m_new_move_label_string = L("Translate");
@ -672,9 +679,16 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
m_new_position = offset;
m_new_rotate_label_string = L("Rotate");
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale_label_string = L("Scale");
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_rotation = Vec3d::Zero();
m_new_size = volume->transformed_convex_hull_bounding_box(trafo.get_matrix()).size();
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale = Vec3d(100.0, 100.0, 100.0);
#else
m_new_scale = m_new_size.cwiseProduct(volume->transformed_convex_hull_bounding_box(volume->get_instance_transformation().get_matrix() * volume->get_volume_transformation().get_matrix(false, false, true, false)).size().cwiseInverse()) * 100.0;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
else if (is_local_coordinates()) {
m_new_move_label_string = L("Translate");
@ -687,10 +701,17 @@ void ObjectManipulation::update_settings_value(const Selection& selection)
#endif // ENABLE_WORLD_COORDINATE
m_new_position = volume->get_volume_offset();
m_new_rotate_label_string = L("Rotate");
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale_label_string = L("Scale");
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_rotation = Vec3d::Zero();
#if ENABLE_WORLD_COORDINATE
m_new_size = volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix()).size();
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_new_scale = Vec3d(100.0, 100.0, 100.0);
#else
m_new_scale = m_new_size.cwiseProduct(volume->transformed_convex_hull_bounding_box(volume->get_volume_transformation().get_matrix(false, false, true, false)).size().cwiseInverse()) * 100.0;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
#else
m_new_scale = volume->get_volume_scaling_factor() * 100.0;
@ -767,20 +788,26 @@ void ObjectManipulation::update_if_dirty()
#else
if (selection.requires_uniform_scale()) {
#endif // ENABLE_WORLD_COORDINATE
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_lock_bnt->SetLock(true);
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#if ENABLE_WORLD_COORDINATE
wxString tooltip;
if (selection.is_single_volume_or_modifier()) {
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (reason == Selection::EUniformScaleRequiredReason::VolumeNotAxisAligned_Instance)
tooltip = _L("You cannot use non-uniform scaling mode for parts non aligned with the instance local axes");
else if (reason == Selection::EUniformScaleRequiredReason::VolumeNotAxisAligned_World)
tooltip = _L("You cannot use non-uniform scaling mode for parts non aligned with the printer axes");
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
else if (selection.is_single_full_instance()) {
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (reason == Selection::EUniformScaleRequiredReason::InstanceNotAxisAligned_World)
tooltip = _L("You cannot use non-uniform scaling mode for instances non aligned with the printer axes");
else if (reason == Selection::EUniformScaleRequiredReason::VolumeNotAxisAligned_Instance)
tooltip = _L("You cannot use non-uniform scaling mode for instances containing non locally axis-aligned parts");
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
else
tooltip = _L("You cannot use non-uniform scaling mode for multiple objects/parts selection");
@ -789,7 +816,9 @@ void ObjectManipulation::update_if_dirty()
#else
m_lock_bnt->SetToolTip(_L("You cannot use non-uniform scaling mode for multiple objects/parts selection"));
#endif // ENABLE_WORLD_COORDINATE
#if !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_lock_bnt->disable();
#endif // !ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
else {
m_lock_bnt->SetLock(m_uniform_scale);
@ -1108,7 +1137,11 @@ void ObjectManipulation::change_size_value(int axis, double value)
selection.get_unscaled_instance_bounding_box().size() :
wxGetApp().model().objects[selection.get_volume(*selection.get_volume_idxs().begin())->object_idx()]->raw_mesh_bounding_box().size();
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
this->do_size(axis, size.cwiseQuotient(ref_size));
#else
this->do_scale(axis, size.cwiseQuotient(ref_size));
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
m_cache.size = size;
m_cache.size_rounded(axis) = DBL_MAX;
@ -1124,8 +1157,18 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
#if ENABLE_WORLD_COORDINATE
TransformationType transformation_type;
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (is_local_coordinates())
transformation_type.set_local();
else if (is_instance_coordinates())
transformation_type.set_instance();
if (!is_local_coordinates())
transformation_type.set_relative();
#else
if (!is_world_coordinates())
transformation_type.set_local();
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale();
Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
@ -1156,6 +1199,36 @@ void ObjectManipulation::do_scale(int axis, const Vec3d &scale) const
wxGetApp().plater()->canvas3D()->do_scale(L("Set Scale"));
}
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void ObjectManipulation::do_size(int axis, const Vec3d& scale) const
{
Selection& selection = wxGetApp().plater()->canvas3D()->get_selection();
TransformationType transformation_type;
if (is_local_coordinates())
transformation_type.set_local();
else if (is_instance_coordinates())
transformation_type.set_instance();
bool uniform_scale = m_uniform_scale || selection.requires_uniform_scale();
Vec3d scaling_factor = uniform_scale ? scale(axis) * Vec3d::Ones() : scale;
if (!uniform_scale && is_world_coordinates()) {
if (selection.is_single_full_instance())
scaling_factor = (Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse() * scaling_factor).cwiseAbs();
else if (selection.is_single_volume_or_modifier()) {
const Transform3d mi = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_rotation()).inverse();
const Transform3d mv = Geometry::assemble_transform(Vec3d::Zero(), selection.get_volume(*selection.get_volume_idxs().begin())->get_volume_rotation()).inverse();
scaling_factor = (mv * mi * scaling_factor).cwiseAbs();
}
}
selection.setup_cache();
selection.scale(scaling_factor, transformation_type);
wxGetApp().plater()->canvas3D()->do_scale(L("Set Size"));
}
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void ObjectManipulation::on_change(const std::string& opt_key, int axis, double new_value)
{
if (!m_cache.is_valid())
@ -1190,21 +1263,37 @@ void ObjectManipulation::on_change(const std::string& opt_key, int axis, double
}
}
void ObjectManipulation::set_uniform_scaling(const bool new_value)
void ObjectManipulation::set_uniform_scaling(const bool use_uniform_scale)
{
const Selection &selection = wxGetApp().plater()->canvas3D()->get_selection();
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance() && is_world_coordinates() && !new_value) {
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
if (!use_uniform_scale) {
int res = selection.bake_transform_if_needed(false);
if (res == -1) {
// Enforce uniform scaling.
m_lock_bnt->SetLock(true);
return;
}
else if (res == 0) {
// Recalculate cached values at this panel, refresh the screen.
this->UpdateAndShow(true);
}
}
m_uniform_scale = use_uniform_scale;
#else
if (selection.is_single_full_instance() && m_world_coordinates && !new_value) {
#if ENABLE_WORLD_COORDINATE
if (selection.is_single_full_instance() && is_world_coordinates() && !use_uniform_scale) {
#else
if (selection.is_single_full_instance() && m_world_coordinates && !use_uniform_scale) {
#endif // ENABLE_WORLD_COORDINATE
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
// Is the angle close to a multiple of 90 degrees?
if (! Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
if (!Geometry::is_rotation_ninety_degrees(volume->get_instance_rotation())) {
// Cannot apply scaling in the world coordinate system.
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
//wxMessageDialog dlg(GUI::wxGetApp().mainframe,
MessageDialog dlg(GUI::wxGetApp().mainframe,
_L("The currently manipulated object is tilted (rotation angles are not multiples of 90°).\n"
"Non-uniform scaling of tilted objects is only possible in the World coordinate system,\n"
@ -1212,7 +1301,7 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
_L("This operation is irreversible.\n"
"Do you want to proceed?"),
SLIC3R_APP_NAME,
wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION);
wxYES_NO | wxCANCEL | wxCANCEL_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES) {
// Enforce uniform scaling.
m_lock_bnt->SetLock(true);
@ -1226,7 +1315,9 @@ void ObjectManipulation::set_uniform_scaling(const bool new_value)
this->UpdateAndShow(true);
}
}
m_uniform_scale = new_value;
m_uniform_scale = use_uniform_scale;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
}
#if ENABLE_WORLD_COORDINATE

View file

@ -196,7 +196,7 @@ public:
// Called from the App to update the UI if dirty.
void update_if_dirty();
void set_uniform_scaling(const bool uniform_scale);
void set_uniform_scaling(const bool use_uniform_scale);
bool get_uniform_scaling() const { return m_uniform_scale; }
#if ENABLE_WORLD_COORDINATE
void set_coordinates_type(ECoordinatesType type);
@ -256,6 +256,9 @@ private:
void change_scale_value(int axis, double value);
void change_size_value(int axis, double value);
void do_scale(int axis, const Vec3d &scale) const;
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void do_size(int axis, const Vec3d& scale) const;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#if ENABLE_WORLD_COORDINATE
void set_coordinates_type(const wxString& type_string);

View file

@ -69,6 +69,12 @@ public:
const Vec3d& get_scale() const { return m_scale; }
void set_scale(const Vec3d& scale) { m_starting.scale = scale; m_scale = scale; }
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
const Vec3d& get_starting_scale() const { return m_starting.scale; }
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
const Vec3d& get_offset() const { return m_offset; }
std::string get_tooltip() const override;
/// <summary>

View file

@ -205,7 +205,7 @@ public:
bool handle_shortcut(int key);
bool is_dragging() const;
ClippingPlane get_clipping_plane() const;
bool wants_reslice_supports_on_undo() const;

View file

@ -7,9 +7,15 @@
#include "GUI.hpp"
#include "GUI_ObjectManipulation.hpp"
#include "GUI_ObjectList.hpp"
#include "Gizmos/GLGizmoBase.hpp"
#include "Camera.hpp"
#include "Plater.hpp"
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#include "MsgDialog.hpp"
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
#include "Gizmos/GLGizmoBase.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/LocalesUtils.hpp"
@ -604,6 +610,9 @@ bool Selection::requires_uniform_scale() const
#endif // ENABLE_WORLD_COORDINATE
{
#if ENABLE_WORLD_COORDINATE
if (is_empty())
return false;
ECoordinatesType coord_type = wxGetApp().obj_manipul()->get_coordinates_type();
if (is_single_volume_or_modifier()) {
if (coord_type == ECoordinatesType::World) {
@ -638,7 +647,6 @@ bool Selection::requires_uniform_scale() const
}
}
}
return false;
}
else {
for (unsigned int i : m_list) {
@ -648,8 +656,8 @@ bool Selection::requires_uniform_scale() const
return true;
}
}
return false;
}
return false;
}
if (reason != nullptr)
@ -1302,6 +1310,65 @@ void Selection::translate(unsigned int object_idx, unsigned int instance_idx, co
this->set_bounding_boxes_dirty();
}
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
int Selection::bake_transform_if_needed(bool apply_scale) const
{
if ((is_single_full_instance() && wxGetApp().obj_manipul()->is_world_coordinates()) ||
(is_single_volume_or_modifier() && !wxGetApp().obj_manipul()->is_local_coordinates())) {
// Verify whether the instance rotation is multiples of 90 degrees, so that the scaling in world coordinates is possible.
// all volumes in the selection belongs to the same instance, any of them contains the needed instance data, so we take the first one
const GLVolume& volume = *get_volume(*get_volume_idxs().begin());
bool needs_baking = false;
if (is_single_full_instance()) {
// Is the instance angle close to a multiple of 90 degrees?
needs_baking |= !Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation());
// Are all volumes angles close to a multiple of 90 degrees?
for (unsigned int id : get_volume_idxs()) {
if (needs_baking)
break;
needs_baking |= !Geometry::is_rotation_ninety_degrees(get_volume(id)->get_volume_rotation());
}
}
else if (is_single_volume_or_modifier()) {
// is the volume angle close to a multiple of 90 degrees?
needs_baking |= !Geometry::is_rotation_ninety_degrees(volume.get_volume_rotation());
if (wxGetApp().obj_manipul()->is_world_coordinates())
// Is the instance angle close to a multiple of 90 degrees?
needs_baking |= !Geometry::is_rotation_ninety_degrees(volume.get_instance_rotation());
}
if (needs_baking) {
MessageDialog dlg((wxWindow*)wxGetApp().mainframe,
_L("The currently manipulated object is tilted or contains tilted parts (rotation angles are not multiples of 90°). "
"Non-uniform scaling of tilted objects is only possible in non-local coordinate systems, "
"once the rotation is embedded into the object coordinates.") + "\n" +
_L("This operation is irreversible.") + "\n" +
_L("Do you want to proceed?"),
SLIC3R_APP_NAME,
wxYES_NO | wxNO_DEFAULT | wxICON_QUESTION);
if (dlg.ShowModal() != wxID_YES)
return -1;
if (apply_scale) {
wxGetApp().plater()->get_current_canvas3D()->do_scale(L("Scale + Bake transform"));
Plater::SuppressSnapshots suppress(wxGetApp().plater());
wxGetApp().plater()->take_snapshot(_("Bake transform"));
}
else
wxGetApp().plater()->take_snapshot(_("Bake transform"));
// Bake the rotation into the meshes of the object.
wxGetApp().model().objects[volume.composite_id.object_id]->bake_xy_rotation_into_meshes(volume.composite_id.instance_id);
// Update the 3D scene, selections etc.
wxGetApp().plater()->update();
return 0;
}
}
return 1;
}
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void Selection::erase()
{
if (!m_valid)

View file

@ -366,6 +366,15 @@ public:
void translate(unsigned int object_idx, const Vec3d& displacement);
void translate(unsigned int object_idx, unsigned int instance_idx, const Vec3d& displacement);
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
// returns:
// -1 if the user refused to proceed with baking when asked
// 0 if the baking was performed
// 1 if no baking was needed
// if apply_scale == true the scaling of the current selection is applied
int bake_transform_if_needed(bool apply_scale) const;
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
void erase();
void render(float scale_factor = 1.0);

View file

@ -581,8 +581,12 @@ void LockButton::OnButton(wxCommandEvent& event)
if (m_disabled)
return;
#if ENABLE_WORLD_COORDINATE_SCALE_REVISITED
SetLock(!m_is_pushed);
#else
m_is_pushed = !m_is_pushed;
update_button_bitmaps();
#endif // ENABLE_WORLD_COORDINATE_SCALE_REVISITED
event.Skip();
}