From ddf6f6fd853ba9dcb36987983de1bcac47017091 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 17 Feb 2026 11:59:24 -0700 Subject: [PATCH] feat: Implement pixel-perfect camera panning Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/Camera.cpp | 17 +++++++++++------ src/Camera.h | 2 +- src/ViewportWidget.cpp | 2 +- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/Camera.cpp b/src/Camera.cpp index 8ecc86d..bde413d 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -21,7 +21,7 @@ void Camera::mousePressEvent(QMouseEvent* event) m_lastPos = event->pos(); } -void Camera::mouseMoveEvent(QMouseEvent* event) +void Camera::mouseMoveEvent(QMouseEvent* event, int viewportHeight) { int dx = event->pos().x() - m_lastPos.x(); int dy = event->pos().y() - m_lastPos.y(); @@ -29,12 +29,17 @@ void Camera::mouseMoveEvent(QMouseEvent* event) if (event->buttons() & Qt::MiddleButton) { if (QApplication::keyboardModifiers() & Qt::ShiftModifier) { // Pan + if (viewportHeight == 0) viewportHeight = 1; + + // This logic is based on a 45-degree field of view. + float fov = 45.0f; float dist = -m_zoom; - dist = qMin(dist, 200.0f); // Cap distance to avoid crazy fast pan. - // Match old speed at default zoom, and have a minimum speed. - float panFactor = dist * 0.000495f + 0.0001f; - setPanX(m_panX + dx * panFactor); - setPanY(m_panY - dy * panFactor); + + float world_height = 2.0f * dist * tan(qDegreesToRadians(fov / 2.0f)); + float pixels_to_world = world_height / viewportHeight; + + setPanX(m_panX + dx * pixels_to_world); + setPanY(m_panY - dy * pixels_to_world); } else { // Rotate setXRotation(m_xRot + 8 * dy); diff --git a/src/Camera.h b/src/Camera.h index baa2d34..8d06e61 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -20,7 +20,7 @@ public: explicit Camera(QObject *parent = nullptr); void mousePressEvent(QMouseEvent* event); - void mouseMoveEvent(QMouseEvent* event); + void mouseMoveEvent(QMouseEvent* event, int viewportHeight); void wheelEvent(QWheelEvent* event, const QVector3D& worldPos); QMatrix4x4 modelViewMatrix() const; diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index b6d5a37..29d8f0f 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -233,7 +233,7 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event) m_activeSketchTool->mouseMoveEvent(event); } - m_camera->mouseMoveEvent(event); + m_camera->mouseMoveEvent(event, height()); update(); }