From ead192b43bc594ce9c74b564a7486e753c341b5e Mon Sep 17 00:00:00 2001 From: Filip Sykala - NTB T15p Date: Mon, 20 Feb 2023 14:50:17 +0100 Subject: [PATCH] calculate angle when set volume --- src/libslic3r/Emboss.cpp | 62 ++++++++++++++++--------- src/libslic3r/Emboss.hpp | 8 ++++ src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp | 41 ++++++---------- 3 files changed, 61 insertions(+), 50 deletions(-) diff --git a/src/libslic3r/Emboss.cpp b/src/libslic3r/Emboss.cpp index 44fa402025..221bfbcb63 100644 --- a/src/libslic3r/Emboss.cpp +++ b/src/libslic3r/Emboss.cpp @@ -1544,7 +1544,7 @@ std::optional Emboss::ProjectZ::unproject(const Vec3d &p, double *depth) Vec3d Emboss::suggest_up(const Vec3d normal, double up_limit) { // Normal must be 1 - assert(is_approx(normal.norm(), 1.)); + assert(is_approx(normal.squaredNorm(), 1.)); // wanted up direction of result Vec3d wanted_up_side = @@ -1560,28 +1560,45 @@ Vec3d Emboss::suggest_up(const Vec3d normal, double up_limit) return wanted_up_dir; } +std::optional Emboss::calc_up(const Transform3d &tr, double up_limit) +{ + auto tr_linear = tr.linear(); + // z base of transformation ( tr * UnitZ ) + Vec3d normal = tr_linear.col(2); + // scaled matrix has base with different size + normal.normalize(); + Vec3d suggested = suggest_up(normal); + assert(is_approx(suggested.squaredNorm(), 1.)); + + Vec3d up = tr_linear.col(1); // tr * UnitY() + up.normalize(); + + double dot = suggested.dot(up); + if (dot >= 1. || dot <= -1.) + return {}; // zero angle + + Matrix3d m; + m.row(0) = up; + m.row(1) = suggested; + m.row(2) = normal; + double det = m.determinant(); + + return atan2(det, dot); +} + Transform3d Emboss::create_transformation_onto_surface(const Vec3d &position, const Vec3d &normal, float up_limit) { - // up and emboss direction for generated model - Vec3d text_up_dir = Vec3d::UnitY(); - Vec3d text_emboss_dir = Vec3d::UnitZ(); + // is normalized ? + assert(is_approx(normal.squaredNorm(), 1.)); - // wanted up direction of result - Vec3d wanted_up_side = Vec3d::UnitZ(); - if (std::fabs(normal.z()) > up_limit) wanted_up_side = Vec3d::UnitY(); + // up and emboss direction for generated model + Vec3d up_dir = Vec3d::UnitY(); + Vec3d emboss_dir = Vec3d::UnitZ(); // after cast from float it needs to be normalized again - assert(is_approx(normal.norm(), 1.)); - - // create perpendicular unit vector to surface triangle normal vector - // lay on surface of triangle and define up vector for text - Vec3d wanted_up_dir = normal - .cross(wanted_up_side) - .cross(normal); - // normal3d is NOT perpendicular to normal_up_dir - wanted_up_dir.normalize(); + Vec3d wanted_up_dir = suggest_up(normal, up_limit); // perpendicular to emboss vector of text and normal Vec3d axis_view; @@ -1591,25 +1608,24 @@ Transform3d Emboss::create_transformation_onto_surface(const Vec3d &position, axis_view = Vec3d::UnitY(); angle_view = M_PI; } else { - axis_view = text_emboss_dir.cross(normal); - angle_view = std::acos(text_emboss_dir.dot(normal)); // in rad + axis_view = emboss_dir.cross(normal); + angle_view = std::acos(emboss_dir.dot(normal)); // in rad axis_view.normalize(); } Eigen::AngleAxis view_rot(angle_view, axis_view); Vec3d wanterd_up_rotated = view_rot.matrix().inverse() * wanted_up_dir; wanterd_up_rotated.normalize(); - double angle_up = std::acos(text_up_dir.dot(wanterd_up_rotated)); + double angle_up = std::acos(up_dir.dot(wanterd_up_rotated)); - // text_view and text_view2 should have same direction - Vec3d text_view2 = text_up_dir.cross(wanterd_up_rotated); - Vec3d diff_view = text_emboss_dir - text_view2; + Vec3d text_view = up_dir.cross(wanterd_up_rotated); + Vec3d diff_view = emboss_dir - text_view; if (std::fabs(diff_view.x()) > 1. || std::fabs(diff_view.y()) > 1. || std::fabs(diff_view.z()) > 1.) // oposit direction angle_up *= -1.; - Eigen::AngleAxis up_rot(angle_up, text_emboss_dir); + Eigen::AngleAxis up_rot(angle_up, emboss_dir); Transform3d transform = Transform3d::Identity(); transform.translate(position); diff --git a/src/libslic3r/Emboss.hpp b/src/libslic3r/Emboss.hpp index cf15aa2cb9..82ef4d1ace 100644 --- a/src/libslic3r/Emboss.hpp +++ b/src/libslic3r/Emboss.hpp @@ -281,6 +281,14 @@ namespace Emboss /// Is compared with normal.z to suggest up direction /// Wanted up vector Vec3d suggest_up(const Vec3d normal, double up_limit = 0.9); + + /// + /// By transformation calculate angle between suggested and actual up vector + /// + /// Transformation of embossed volume in world + /// Is compared with normal.z to suggest up direction + /// Rotation of suggested up-vector[in rad] in the range [-Pi, Pi], When rotation is not zero + std::optional calc_up(const Transform3d &tr, double up_limit = 0.9); /// /// Create transformation for emboss text object to lay on surface point diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp index 7c0186e110..b03fb6cc9b 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp @@ -103,8 +103,12 @@ static const struct Limits } return false; } + } limits; +// Define where is up vector on model +constexpr double up_limit = 0.9; + static bool is_text_empty(const std::string &text){ return text.empty() || text.find_first_not_of(" \n\t\r") == std::string::npos; @@ -1239,7 +1243,8 @@ void GLGizmoEmboss::set_default_text(){ m_text = _u8L("Embossed text"); } void GLGizmoEmboss::set_volume_by_selection() { - ModelVolume *vol = priv::get_selected_volume(m_parent.get_selection()); + const Selection &selection = m_parent.get_selection(); + ModelVolume *vol = priv::get_selected_volume(selection); // is same volume selected? if (vol != nullptr && vol->id() == m_volume_id) return; @@ -1259,6 +1264,13 @@ void GLGizmoEmboss::set_volume_by_selection() // is select embossed volume? set_volume(vol); + + // Check if user changed up vector by rotation or scale out of emboss gizmo + if (m_volume != nullptr) { + Transform3d world = selection.get_first_volume()->world_matrix(); + std::optional angle = calc_up(world, priv::up_limit); + m_volume->text_configuration->style.prop.angle = angle; + } } bool GLGizmoEmboss::set_volume(ModelVolume *volume) @@ -3563,31 +3575,6 @@ void GLGizmoEmboss::draw_advanced() } else if (ImGui::IsItemHovered()) { ImGui::SetTooltip("%s", _u8L("Use camera direction for text orientation").c_str()); } - - ImGui::SameLine(); - if (ImGui::Button(_u8L("Reset Up").c_str())) { - GLVolume *gl_volume = priv::get_gl_volume(m_parent); - if (gl_volume != nullptr) { - Transform3d world = gl_volume->world_matrix(); - auto world_linear = world.linear(); - Vec3d z_world = world_linear.col(2); - z_world.normalize(); - Vec3d wanted_up = suggest_up(z_world); - - Vec3d y_world = world_linear.col(1); - auto z_rotation = Eigen::Quaternion::FromTwoVectors(y_world, wanted_up); - Transform3d world_new = z_rotation * world; - auto world_new_linear = world_new.linear(); - Transform3d volume_new = gl_volume->get_volume_transformation().get_matrix(); - Transform3d instance = gl_volume->get_instance_transformation().get_matrix(); - volume_new.linear() = instance.linear().inverse() * world_new.linear(); - gl_volume->set_volume_transformation(volume_new); - m_parent.do_move(L("Reset up vector")); - } - } else if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("%s", _u8L("Reset skew of text to be normal in world").c_str()); - } - #ifdef ALLOW_DEBUG_MODE ImGui::Text("family = %s", (font_prop.family.has_value() ? font_prop.family->c_str() : @@ -4079,7 +4066,7 @@ bool priv::start_create_volume_on_surface_job( Transform3d instance = gl_volume->get_instance_transformation().get_matrix(); // Create result volume transformation - Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal); + Transform3d surface_trmat = create_transformation_onto_surface(hit->position, hit->normal, priv::up_limit); const FontProp &font_prop = emboss_data.text_configuration.style.prop; apply_transformation(font_prop, surface_trmat); // new transformation in world coor is surface_trmat