diff --git a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
index e9e0abe11..daaef3225 100644
--- a/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
+++ b/src/slic3r/GUI/Gizmos/GLGizmoEmboss.cpp
@@ -359,8 +359,62 @@ static ModelVolume *get_selected_volume(const Selection &selection);
/// Offset in screan coordinate
static Vec2d calc_mouse_to_center_text_offset(const Vec2d &mouse, const ModelVolume &mv);
+///
+/// Access to one selected volume
+///
+/// Containe what is selected
+/// Slected when only one volume otherwise nullptr
+static const GLVolume *get_gl_volume(const Selection &selection);
+
+///
+/// Get transformation to world
+/// - use fix after store to 3mf when exists
+///
+///
+/// To identify MovelVolume with fix transformation
+///
+static Transform3d world_matrix(const GLVolume *gl_volume, const Model *model);
+static Transform3d world_matrix(const Selection &selection);
+
} // namespace priv
+const GLVolume *priv::get_gl_volume(const Selection &selection) {
+ const auto &list = selection.get_volume_idxs();
+ if (list.size() != 1)
+ return nullptr;
+ unsigned int volume_idx = *list.begin();
+ return selection.get_volume(volume_idx);
+}
+
+Transform3d priv::world_matrix(const GLVolume *gl_volume, const Model *model)
+{
+ if (!gl_volume)
+ return Transform3d::Identity();
+ Transform3d res = gl_volume->world_matrix();
+
+ if (!model)
+ return res;
+ ModelVolume* mv = get_model_volume(gl_volume, model->objects);
+ if (!mv)
+ return res;
+
+ const std::optional &tc = mv->text_configuration;
+ if (!tc.has_value())
+ return res;
+
+ const std::optional &fix = tc->fix_3mf_tr;
+ if (!fix.has_value())
+ return res;
+
+ return res * (*fix);
+}
+
+Transform3d priv::world_matrix(const Selection &selection)
+{
+ const GLVolume *gl_volume = get_gl_volume(selection);
+ return world_matrix(gl_volume, selection.get_model());
+}
+
Vec2d priv::calc_mouse_to_center_text_offset(const Vec2d& mouse, const ModelVolume& mv) {
const Transform3d &volume_tr = mv.get_matrix();
const Camera &camera = wxGetApp().plater()->get_camera();
@@ -645,6 +699,20 @@ static void draw_mouse_offset(const std::optional &offset)
}
#endif // SHOW_OFFSET_DURING_DRAGGING
+static void draw_origin_ball(const GLCanvas3D& canvas) {
+ auto draw_list = ImGui::GetOverlayDrawList();
+ const Selection &selection = canvas.get_selection();
+ Transform3d to_world = priv::world_matrix(selection);
+ Vec3d volume_zero = to_world * Vec3d::Zero();
+
+ const Camera &camera = wxGetApp().plater()->get_camera();
+ Point screen_coor = CameraUtils::project(camera, volume_zero);
+ ImVec2 center(screen_coor.x(), screen_coor.y());
+ float radius = 10.f;
+ ImU32 color = ImGui::GetColorU32(ImGuiWrapper::COL_ORANGE_LIGHT);
+ draw_list->AddCircleFilled(center, radius, color);
+}
+
void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
{
if (!m_gui_cfg.has_value()) initialize();
@@ -660,6 +728,8 @@ void GLGizmoEmboss::on_render_input_window(float x, float y, float bottom_limit)
const ImVec2 &min_window_size = get_minimal_window_size();
ImGui::PushStyleVar(ImGuiStyleVar_WindowMinSize, min_window_size);
+ draw_origin_ball(m_parent);
+
#ifdef SHOW_FINE_POSITION
draw_fine_position(m_parent.get_selection(), m_parent.get_canvas_size(), min_window_size);
#endif // SHOW_FINE_POSITION
@@ -1149,16 +1219,26 @@ void GLGizmoEmboss::discard_and_close() {
// * Volume containing 3mf fix transformation - needs work around
}
-bool use_camera_dir(const Camera &camera, GLCanvas3D &canvas) {
+namespace priv {
+
+///
+/// Apply camera direction for emboss direction
+///
+/// Define view vector
+/// Containe Selected Model to modify
+/// True when apply change otherwise false
+static bool apply_camera_dir(const Camera &camera, GLCanvas3D &canvas);
+}
+
+bool priv::apply_camera_dir(const Camera &camera, GLCanvas3D &canvas) {
const Vec3d &cam_dir = camera.get_dir_forward();
Selection &sel = canvas.get_selection();
if (sel.is_empty()) return false;
- assert(sel.get_volume_idxs().size() == 1);
- GLVolume *vol = sel.get_volume(*sel.get_volume_idxs().begin());
-
+
// camera direction transformed into volume coordinate system
- Vec3d cam_dir_tr = vol->world_matrix().inverse().linear() * cam_dir;
+ Transform3d to_world = priv::world_matrix(sel);
+ Vec3d cam_dir_tr = to_world.inverse().linear() * cam_dir;
cam_dir_tr.normalize();
Vec3d emboss_dir(0., 0., -1.);
@@ -1166,6 +1246,9 @@ bool use_camera_dir(const Camera &camera, GLCanvas3D &canvas) {
// check wether cam_dir is already used
if (is_approx(cam_dir_tr, emboss_dir)) return false;
+ assert(sel.get_volume_idxs().size() == 1);
+ GLVolume *vol = sel.get_volume(*sel.get_volume_idxs().begin());
+
Transform3d vol_rot;
Transform3d vol_tr = vol->get_volume_transformation().get_matrix();
// check whether cam_dir is opposit to emboss dir
@@ -1298,7 +1381,7 @@ void GLGizmoEmboss::draw_window()
assert(priv::get_selected_volume(m_parent.get_selection()) == m_volume);
const Camera& cam = wxGetApp().plater()->get_camera();
bool use_surface = m_style_manager.get_style().prop.use_surface;
- if (use_camera_dir(cam, m_parent) && use_surface)
+ if (priv::apply_camera_dir(cam, m_parent) && use_surface)
process();
} else if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("%s", _u8L("Use camera direction for text orientation").c_str());
@@ -2591,12 +2674,8 @@ void GLGizmoEmboss::draw_style_edit() {
bool use_inch = wxGetApp().app_config->get("use_inches") == "1";
FontProp &font_prop = style.prop;
- const GLVolume* gl_vol = m_parent.get_selection().get_first_volume();
- Transform3d to_world = gl_vol->world_matrix();
- // Use fix of .3mf loaded tranformation when exist
- if (m_volume->text_configuration->fix_3mf_tr.has_value())
- to_world = to_world * (*m_volume->text_configuration->fix_3mf_tr);
-
+ // IMPROVE: calc scale only when neccessary not each frame
+ Transform3d to_world = priv::world_matrix(m_parent.get_selection());
Vec3d up_world = to_world.linear() * Vec3d(0., 1., 0.);
double norm_sq = up_world.squaredNorm();
std::optional height_scale;