FIX:add "absolute rotation" in rotate gizmo

jira: STUDIO-8726
Change-Id: I23deb4ab11cf24ca4f0f0c5a35a74268c34f60f6
(cherry picked from commit d26b8f9fcadf8f7709a302991e43be711560e84e)
This commit is contained in:
zhou.xu 2024-11-25 19:22:47 +08:00 committed by Lane.Wei
parent 0e84f6acc7
commit 496d69f9d1
5 changed files with 148 additions and 21 deletions

View File

@ -447,6 +447,16 @@ const Vec3d &Transformation::get_rotation() const
return m_temp_rotation;
}
const Vec3d &Transformation::get_rotation_by_quaternion() const
{
Matrix3d rotation_matrix = m_matrix.matrix().block(0, 0, 3, 3);
Eigen::Quaterniond quaternion(rotation_matrix);
quaternion.normalize();
m_temp_rotation = quaternion.matrix().eulerAngles(2, 1, 0);
std::swap(m_temp_rotation(0), m_temp_rotation(2));
return m_temp_rotation;
}
Transform3d Transformation::get_rotation_matrix() const { return extract_rotation_matrix(m_matrix); }
void Transformation::set_rotation(const Vec3d &rotation)

View File

@ -395,6 +395,7 @@ public:
void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; }
const Vec3d &get_rotation() const;
const Vec3d &get_rotation_by_quaternion() const;
double get_rotation(Axis axis) const { return get_rotation()[axis]; }
Transform3d get_rotation_matrix() const;

View File

@ -91,12 +91,19 @@ void GizmoObjectManipulation::update_ui_from_settings()
update_buffered_value();
}
}
void delete_negative_sign(Vec3d& value) {
for (size_t i = 0; i < value.size(); i++) {
if (abs(value[i]) < 0.001)
value[i] = 0.f;
}
}
void GizmoObjectManipulation::update_settings_value(const Selection& selection)
void GizmoObjectManipulation::update_settings_value(const Selection &selection)
{
m_new_move_label_string = L("Position");
m_new_rotate_label_string = L("Rotate (relative)");
m_new_rotation = Vec3d::Zero();
m_new_absolute_rotation = Vec3d::Zero();
m_new_scale_label_string = L("Scale ratios");
ObjectList* obj_list = wxGetApp().obj_list();
@ -104,7 +111,9 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
// 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());
m_new_position = volume->get_instance_offset();
auto rotation = volume->get_instance_transformation().get_rotation_by_quaternion();
m_new_absolute_rotation = rotation * (180. / M_PI);
delete_negative_sign(m_new_absolute_rotation);
if (is_world_coordinates()) {//for move and rotate
m_new_size = selection.get_bounding_box_in_current_reference_system().first.size();
m_unscale_size = selection.get_unscaled_instance_bounding_box().size();
@ -132,6 +141,9 @@ void GizmoObjectManipulation::update_settings_value(const Selection& selection)
m_new_title_string = L("Object Operations");
} else if (selection.is_single_volume_or_modifier()) {
const GLVolume *volume = selection.get_first_volume();
auto rotation = volume->get_volume_transformation().get_rotation_by_quaternion();
m_new_absolute_rotation = rotation * (180. / M_PI);
delete_negative_sign(m_new_absolute_rotation);
if (is_world_coordinates()) {//for move and rotate
const Geometry::Transformation trafo(volume->world_matrix());
const Vec3d &offset = trafo.get_offset();
@ -180,7 +192,7 @@ void GizmoObjectManipulation::update_buffered_value()
m_buffered_position = this->m_new_position;
m_buffered_rotation = this->m_new_rotation;
m_buffered_absolute_rotation = this->m_new_absolute_rotation;
m_buffered_scale = this->m_new_scale;
if (this->m_imperial_units)
@ -206,6 +218,7 @@ void GizmoObjectManipulation::update_if_dirty()
};
update_label(m_cache.move_label_string, m_new_move_label_string);
update_label(m_cache.rotate_label_string, m_new_rotate_label_string);
update_label(m_cache.rotate_label_string, m_new_rotate_label_string);
update_label(m_cache.scale_label_string, m_new_scale_label_string);
enum ManipulationEditorKey
@ -234,6 +247,7 @@ void GizmoObjectManipulation::update_if_dirty()
update(m_cache.scale, m_cache.scale_rounded, m_new_scale);
update(m_cache.size, m_cache.size_rounded, m_new_size);
update(m_cache.rotation, m_cache.rotation_rounded, m_new_rotation);
update(m_cache.absolute_rotation, m_cache.absolute_rotation_rounded, m_new_absolute_rotation);
}
update_reset_buttons_visibility();
@ -274,6 +288,7 @@ void GizmoObjectManipulation::reset_settings_value()
{
m_new_position = Vec3d::Zero();
m_new_rotation = Vec3d::Zero();
m_new_absolute_rotation = Vec3d::Zero();
m_new_scale = Vec3d::Ones() * 100.;
m_new_size = Vec3d::Zero();
m_new_enabled = false;
@ -345,6 +360,34 @@ void GizmoObjectManipulation::change_rotation_value(int axis, double value)
this->UpdateAndShow(true);
}
void GizmoObjectManipulation::change_absolute_rotation_value(int axis, double value) {
if (std::abs(m_cache.absolute_rotation_rounded(axis) - value) < EPSILON)
return;
Vec3d absolute_rotation = m_cache.absolute_rotation;
absolute_rotation(axis) = value;
Selection &selection = m_glcanvas.get_selection();
TransformationType transformation_type;
transformation_type.set_relative();
if (selection.is_single_full_instance())
transformation_type.set_independent();
if (is_local_coordinates())
transformation_type.set_local();
if (is_instance_coordinates())
transformation_type.set_instance();
selection.setup_cache();
auto diff_rotation = transformation_type.absolute() ? absolute_rotation : absolute_rotation - m_cache.absolute_rotation;
selection.rotate((M_PI / 180.0) * diff_rotation, transformation_type);
wxGetApp().plater()->take_snapshot("set absolute orientation", UndoRedo::SnapshotType::GizmoAction);
m_glcanvas.do_rotate("");
m_cache.absolute_rotation = absolute_rotation;
m_cache.absolute_rotation_rounded(axis) = DBL_MAX;
this->UpdateAndShow(true);
}
void GizmoObjectManipulation::change_scale_value(int axis, double value)
{
if (value <= 0.0)
@ -441,6 +484,8 @@ void GizmoObjectManipulation::on_change(const std::string &opt_key, int axis, do
change_position_value(axis, new_value);
else if (opt_key == "rotation")
change_rotation_value(axis, new_value);
else if (opt_key == "absolute_rotation")
change_absolute_rotation_value(axis, new_value);
else if (opt_key == "scale")
change_scale_value(axis, new_value);
else if (opt_key == "size")
@ -578,9 +623,10 @@ void GizmoObjectManipulation::set_coordinates_type(ECoordinatesType type)
}
static const char* label_values[2][3] = {
static const char* label_values[3][3] = {
{ "##position_x", "##position_y", "##position_z"},
{ "##rotation_x", "##rotation_y", "##rotation_z"}
{ "##rotation_x", "##rotation_y", "##rotation_z"},
{ "##absolute_rotation_x", "##absolute_rotation_y", "##absolute_rotation_z"}
};
static const char* label_scale_values[2][3] = {
@ -800,7 +846,6 @@ void GizmoObjectManipulation::set_init_rotation(const Geometry::Transformation &
Vec3d display_position = m_buffered_position;
// Rotation
Vec3d rotation = this->m_buffered_rotation;
float unit_size = imgui_wrapper->calc_text_size(MAX_SIZE).x + space_size;
int index = 1;
int index_unit = 1;
@ -949,7 +994,7 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
Vec3d display_position = m_buffered_position;
// Rotation
Vec3d rotation = this->m_buffered_rotation;
Vec3d absolute_rotation = this->m_buffered_absolute_rotation;
float unit_size = imgui_wrapper->calc_text_size(MAX_SIZE).x + space_size;
int index = 1;
int index_unit = 1;
@ -967,33 +1012,41 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::TextAlignCenter("Z");
if (m_show_reset_0_rotation) {
ImGui::SameLine(caption_max + 3 * unit_size + 4 * space_size + end_text_size);
if (reset_zero_button(imgui_wrapper, caption_max, unit_size, space_size, end_text_size)) { reset_rotation_value(false); }
if (ImGui::IsItemHovered()) {
float tooltip_size = imgui_wrapper->calc_text_size(_L("Reset current rotation to real zeros.")).x + 3 * space_size;
imgui_wrapper->tooltip(_L("Reset current rotation to real zeros."), tooltip_size);
}
}
index = 1;
index_unit = 1;
// ImGui::PushItemWidth(unit_size * 2);
bool is_relative_input = false;
ImGui::AlignTextToFramePadding();
imgui_wrapper->text(_L("Rotate (relative)"));
ImGui::SameLine(caption_max + index * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::BBLInputDouble(label_values[1][0], &rotation[0], 0.0f, 0.0f, "%.2f");
if (ImGui::BBLInputDouble(label_values[1][0], &rotation[0], 0.0f, 0.0f, "%.2f")) {
is_relative_input = true;
}
ImGui::SameLine(caption_max + unit_size + (++index) * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::BBLInputDouble(label_values[1][1], &rotation[1], 0.0f, 0.0f, "%.2f");
if (ImGui::BBLInputDouble(label_values[1][1], &rotation[1], 0.0f, 0.0f, "%.2f")) {
is_relative_input = true;
}
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
ImGui::PushItemWidth(unit_size);
ImGui::BBLInputDouble(label_values[1][2], &rotation[2], 0.0f, 0.0f, "%.2f");
if (ImGui::BBLInputDouble(label_values[1][2], &rotation[2], 0.0f, 0.0f, "%.2f")) {
is_relative_input = true;
}
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
imgui_wrapper->text(_L("°"));
m_buffered_rotation = rotation;
update(current_active_id, "rotation", this->m_new_rotation, m_buffered_rotation);
if (is_relative_input) {
m_last_rotate_type = RotateType::Relative;
}
if (m_last_rotate_type == RotateType::Relative) {
bool is_valid = update(current_active_id, "rotation", this->m_new_rotation, m_buffered_rotation) >= 0;
if (is_valid) {
m_last_rotate_type = RotateType::None;
}
}
if (m_show_clear_rotation) {
ImGui::SameLine(caption_max + 3 * unit_size + 4 * space_size + end_text_size);
@ -1008,7 +1061,6 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
ImGui::SameLine(caption_max + 3 * unit_size + 5 * space_size + end_text_size);
ImGui::InvisibleButton("", ImVec2(ImGui::GetFontSize(), ImGui::GetFontSize()));
}
// send focus to m_glcanvas
bool focued_on_text = false;
for (int j = 0; j < 3; j++) {
@ -1019,7 +1071,61 @@ void GizmoObjectManipulation::do_render_rotate_window(ImGuiWrapper *imgui_wrappe
break;
}
}
if (!focued_on_text) m_glcanvas.handle_sidebar_focus_event("", false);
index = 1;
index_unit = 1;
ImGui::AlignTextToFramePadding();
imgui_wrapper->text(_L("Rotate (absolute)"));
ImGui::SameLine(caption_max + index * space_size);
ImGui::PushItemWidth(unit_size);
bool is_absolute_input = false;
if (ImGui::BBLInputDouble(label_values[2][0], &absolute_rotation[0], 0.0f, 0.0f, "%.2f")) {
is_absolute_input = true;
}
ImGui::SameLine(caption_max + unit_size + (++index) * space_size);
ImGui::PushItemWidth(unit_size);
if (ImGui::BBLInputDouble(label_values[2][1], &absolute_rotation[1], 0.0f, 0.0f, "%.2f")) {
is_absolute_input = true;
}
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
ImGui::PushItemWidth(unit_size);
if (ImGui::BBLInputDouble(label_values[2][2], &absolute_rotation[2], 0.0f, 0.0f, "%.2f")) {
is_absolute_input = true;
}
ImGui::SameLine(caption_max + (++index_unit) * unit_size + (++index) * space_size);
imgui_wrapper->text(_L("°"));
m_buffered_absolute_rotation = absolute_rotation;
if (is_absolute_input) {
m_last_rotate_type = RotateType::Absolute;
}
if (m_last_rotate_type == RotateType::Absolute) {
bool is_valid = update(current_active_id, "absolute_rotation", this->m_new_absolute_rotation, m_buffered_absolute_rotation) >= 0;
if (is_valid) {
m_last_rotate_type = RotateType::None;
}
}
if (m_show_reset_0_rotation) {
ImGui::SameLine(caption_max + 3 * unit_size + 4 * space_size + end_text_size);
if (reset_zero_button(imgui_wrapper, caption_max, unit_size, space_size, end_text_size)) { reset_rotation_value(false); }
if (ImGui::IsItemHovered()) {
float tooltip_size = imgui_wrapper->calc_text_size(_L("Reset current rotation to real zeros.")).x + 3 * space_size;
imgui_wrapper->tooltip(_L("Reset current rotation to real zeros."), tooltip_size);
}
}
// send focus to m_glcanvas
bool absolute_focued_on_text = false;
for (int j = 0; j < 3; j++) {
unsigned int id = ImGui::GetID(label_values[2][j]);
if (current_active_id == id) {
m_glcanvas.handle_sidebar_focus_event(label_values[2][j] + 2, true);
absolute_focued_on_text = true;
break;
}
}
if (!focued_on_text && !absolute_focued_on_text)
m_glcanvas.handle_sidebar_focus_event("", false);
float get_cur_y = ImGui::GetContentRegionMax().y + ImGui::GetFrameHeight() + y;
float tip_caption_max = 0.f;
float total_text_max = 0.f;

View File

@ -27,6 +27,8 @@ public:
Vec3d position_rounded;
Vec3d rotation;
Vec3d rotation_rounded;
Vec3d absolute_rotation;
Vec3d absolute_rotation_rounded;
Vec3d scale;
Vec3d scale_rounded;
Vec3d size;
@ -72,11 +74,13 @@ public:
std::string m_new_unit_string;
Vec3d m_new_position;
Vec3d m_new_rotation;
Vec3d m_new_absolute_rotation;
Vec3d m_new_scale;
Vec3d m_new_size;
Vec3d m_unscale_size;
Vec3d m_buffered_position;
Vec3d m_buffered_rotation;
Vec3d m_buffered_absolute_rotation;
Vec3d m_buffered_scale;
Vec3d m_buffered_size;
Vec3d cs_center;
@ -89,6 +93,9 @@ public:
bool m_show_clear_rotation { false };
bool m_show_clear_scale { false };
bool m_show_drop_to_bed { false };
enum class RotateType { None, Relative, Absolute
};
RotateType m_last_rotate_type{RotateType::None}; // 0:no input 1:relative 2:absolute
protected:
float last_move_input_window_width = 0.0f;
@ -150,6 +157,7 @@ private:
// change values
void change_position_value(int axis, double value);
void change_rotation_value(int axis, double value);
void change_absolute_rotation_value(int axis, double value);
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;

View File

@ -2048,6 +2048,8 @@ void Selection::render_sidebar_hints(const std::string& sidebar_field, bool unif
render_sidebar_position_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "rotation"))
render_sidebar_rotation_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "absolute_rotation"))
render_sidebar_rotation_hints(sidebar_field);
else if (boost::starts_with(sidebar_field, "scale") || boost::starts_with(sidebar_field, "size"))
//BBS: GUI refactor: add uniform_scale from gizmo
render_sidebar_scale_hints(sidebar_field, uniform_scale);