From 38e931bc797cfb591171d259805c3e5f8c2eb824 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 17 Feb 2026 11:36:44 -0700 Subject: [PATCH] feat: Implement mouse wheel zoom to cursor position Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/Camera.cpp | 25 +++++++++++++++++++++++-- src/Camera.h | 2 +- src/ViewportWidget.cpp | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/Camera.cpp b/src/Camera.cpp index da25aff..cd733e9 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -40,11 +40,32 @@ void Camera::mouseMoveEvent(QMouseEvent* event) m_lastPos = event->pos(); } -void Camera::wheelEvent(QWheelEvent* event) +void Camera::wheelEvent(QWheelEvent* event, const QVector3D& worldPos) { QPoint numDegrees = event->angleDelta() / 8; if (!numDegrees.isNull()) { - setZoom(m_zoom + numDegrees.y() / 5.0f); + float zoomAmount = numDegrees.y() / 5.0f; + float oldZoom = m_zoom; + float newZoom = oldZoom + zoomAmount; + + QMatrix4x4 rotation; + rotation.rotate(m_xRot / 16.0f, 1, 0, 0); + rotation.rotate(m_yRot / 16.0f, 0, 1, 0); + QVector3D p_camera = rotation * worldPos; + + if (std::abs(p_camera.z() + oldZoom) < 1e-6) { + setZoom(newZoom); + return; + } + + float ratio = (p_camera.z() + newZoom) / (p_camera.z() + oldZoom); + + float newPanX = (p_camera.x() + m_panX) * ratio - p_camera.x(); + float newPanY = (p_camera.y() + m_panY) * ratio - p_camera.y(); + + setZoom(newZoom); + setPanX(newPanX); + setPanY(newPanY); } } diff --git a/src/Camera.h b/src/Camera.h index 1b35c59..baa2d34 100644 --- a/src/Camera.h +++ b/src/Camera.h @@ -21,7 +21,7 @@ public: void mousePressEvent(QMouseEvent* event); void mouseMoveEvent(QMouseEvent* event); - void wheelEvent(QWheelEvent* event); + void wheelEvent(QWheelEvent* event, const QVector3D& worldPos); QMatrix4x4 modelViewMatrix() const; diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index 7eb3f90..40d2633 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -239,7 +239,8 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event) void ViewportWidget::wheelEvent(QWheelEvent *event) { - m_camera->wheelEvent(event); + QVector3D worldPos = unproject(event->pos(), m_currentPlane); + m_camera->wheelEvent(event, worldPos); } void ViewportWidget::keyPressEvent(QKeyEvent *event)