Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/slic3r/GUI/GLCanvas3D.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2807,6 +2807,9 @@ void GLCanvas3D::render(bool only_init)
camera.apply_projection(_max_bounding_box(true, true, true,is_volumes_limit_to_expand_plate()));
camera.update_frustum();

//BBS update gizmo camera scaling (inv_zoom + perspective depth correction)
GLGizmoBase::update_camera_scaling(camera, m_selection);

m_frame_callback_list.clear();

const std::array<int, 4>& viewport = camera.get_viewport();
Expand Down Expand Up @@ -9428,8 +9431,6 @@ void GLCanvas3D::_render_volumes_for_picking() const

void GLCanvas3D::_render_current_gizmo() const
{
//BBS update inv_zoom
GLGizmoBase::INV_ZOOM = (float)get_active_camera().get_inv_zoom();
m_gizmos.render_current_gizmo();
}

Expand Down
46 changes: 44 additions & 2 deletions src/slic3r/GUI/Gizmos/GLGizmoBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <GL/glew.h>
#include <algorithm>

#include "slic3r/GUI/Camera.hpp"
#include "slic3r/GUI/GUI_App.hpp"
#include "slic3r/GUI/GUI_Colors.hpp"
#include "slic3r/GUI/OpenGLManager.hpp"
Expand All @@ -15,6 +16,7 @@ namespace Slic3r {
namespace GUI {

float GLGizmoBase::INV_ZOOM = 1.0f;
float GLGizmoBase::DEPTH_CORRECTION = 1.0f;


const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
Expand Down Expand Up @@ -324,11 +326,51 @@ void GLGizmoBase::render_lines(const std::vector<Vec3d> &points)
wxGetApp().unbind_shader();
}

void GLGizmoBase::update_camera_scaling(const Camera& camera, const Selection& selection)
{
INV_ZOOM = (float)camera.get_inv_zoom();
DEPTH_CORRECTION = 1.0f;

if (camera.get_type() != Camera::EType::Perspective)
return;

// Left untouched on purpose: with the flag off the gizmo geometry is anchored to the object
// bounding box in world space and only the grabber cubes follow 1/zoom, so that path was never
// screen size stable to begin with. Reworking it is out of scope here.
const auto& ogl_manager = wxGetApp().get_opengl_manager();
if (!ogl_manager || !ogl_manager->is_gizmo_keep_screen_size_enabled())
return;

if (selection.is_empty())
return;

const BoundingBoxf3& box = selection.get_bounding_box();
if (!box.defined)
return;

const double near_z = camera.get_near_z();
const double gui_scale = camera.get_gui_scale(); // == near_z / orbit_distance under perspective
if (near_z <= EPSILON || gui_scale <= EPSILON)
return;

// Scaling a world space length by 1/zoom keeps it constant on screen only under an orthographic
// projection. Under perspective the projected size also scales with orbit_distance / depth, so a
// gizmo anchored away from the orbit plane grows or shrinks on its own. Cancel that term here.
const double depth = -(camera.get_view_matrix() * box.center()).z(); // eye space depth, positive in front of the camera
if (depth <= near_z) // anchor is in front of the near plane, nothing is drawn there anyway
return;

// Clamped on both ends: a large factor inflates the gizmo AABB which feeds back into
// Camera::apply_projection, a tiny one makes the grabber model matrix degenerate.
const double orbit_distance = near_z / gui_scale;
DEPTH_CORRECTION = (float)std::clamp(depth / orbit_distance, 0.1, 8.0);
}

float GLGizmoBase::get_grabber_size()
{
float grabber_size = 8.0f;
if (GLGizmoBase::INV_ZOOM > 0) {
grabber_size = GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor * GLGizmoBase::INV_ZOOM;
grabber_size = GLGizmoBase::Grabber::FixedGrabberSize * GLGizmoBase::Grabber::GrabberSizeFactor * GLGizmoBase::INV_ZOOM * GLGizmoBase::DEPTH_CORRECTION;
}
return grabber_size;
}
Expand Down Expand Up @@ -688,7 +730,7 @@ void GLGizmoBase::modify_radius(float& radius) const
uint32_t t_height = 0;
ogl_manager->get_viewport_size(t_width, t_height);
radius = 0.2f * std::min(t_width, t_height);
radius *= GLGizmoBase::INV_ZOOM;
radius *= GLGizmoBase::INV_ZOOM * GLGizmoBase::DEPTH_CORRECTION;
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions src/slic3r/GUI/Gizmos/GLGizmoBase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ namespace GUI {

class ImGuiWrapper;
class GLCanvas3D;
struct Camera;
enum class CommonGizmosDataID;
class CommonGizmosDataPool;
class Selection;
Expand All @@ -44,6 +45,16 @@ class GLGizmoBase
static const unsigned int BASE_ID = 255 * 255 * 254;

static float INV_ZOOM;
// Cancels the perspective foreshortening for screen-space-sized gizmos, stays 1.0 under an orthographic camera.
static float DEPTH_CORRECTION;

// Refreshes INV_ZOOM and DEPTH_CORRECTION for the given camera. The selection provides the anchor the
// gizmo is drawn around; DEPTH_CORRECTION falls back to 1.0 with an orthographic camera, with nothing
// selected, or when the screen size mode is off.
// Call once per frame, after Camera::apply_projection(), which is what fills in near_z and gui_scale.
// Single anchor per frame: grabbers offset from the selection center (Scale corners, the Cut plane,
// the Text/SVG cube) keep a residual error proportional to their own depth offset.
static void update_camera_scaling(const Camera& camera, const Selection& selection);

//BBS colors
static std::array<float, 4> DEFAULT_BASE_COLOR;
Expand Down
8 changes: 5 additions & 3 deletions src/slic3r/GUI/Selection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2872,9 +2872,11 @@ Transform3d get_screen_scalling_matrix()
if (p_ogl_manager) {
if (p_ogl_manager->is_gizmo_keep_screen_size_enabled()) {
const auto& t_zoom = camera.get_zoom();
screen_scalling_matrix.data()[0 * 4 + 0] = 5.0f / t_zoom;
screen_scalling_matrix.data()[1 * 4 + 1] = 5.0f / t_zoom;
screen_scalling_matrix.data()[2 * 4 + 2] = 5.0f / t_zoom;
// Same perspective correction the gizmos get, so the hints stay the same length as the gizmo arrows.
const double t_scale = 5.0 * (double)GLGizmoBase::DEPTH_CORRECTION / t_zoom;
screen_scalling_matrix.data()[0 * 4 + 0] = t_scale;
screen_scalling_matrix.data()[1 * 4 + 1] = t_scale;
screen_scalling_matrix.data()[2 * 4 + 2] = t_scale;
}
}
return screen_scalling_matrix;
Expand Down