← Back to team overview

kicad-developers team mailing list archive

[PATCH 2/2] Pixel perfect panning for the 3D viewer

 

Use the correct math to unproject the mouse movement from screen space
to the Z=0 plane on the camera space. This handles both perspective
and orthographic projection at any window size or zoom level.
---
 3d-viewer/3d_rendering/ctrack_ball.cpp | 22 ++++++++++++++--------
 1 file changed, 14 insertions(+), 8 deletions(-)

diff --git a/3d-viewer/3d_rendering/ctrack_ball.cpp b/3d-viewer/3d_rendering/ctrack_ball.cpp
index 95ddb71..f908c80 100644
--- a/3d-viewer/3d_rendering/ctrack_ball.cpp
+++ b/3d-viewer/3d_rendering/ctrack_ball.cpp
@@ -96,14 +96,20 @@ void CTRACK_BALL::Pan( const wxPoint &aNewMousePosition )
 {
     m_parametersChanged = true;
 
-    // Current zoom and an additional factor are taken into account
-    // for the amount of panning.
-
-    const float zoom = std::min( m_zoom, 1.0f );
-    const float panFactor = m_range_scale * zoom * (zoom * 4.0f);
-
-    m_camera_pos.x -= panFactor * ( m_lastPosition.x - aNewMousePosition.x ) / m_windowSize.x;
-    m_camera_pos.y -= panFactor * ( aNewMousePosition.y - m_lastPosition.y ) / m_windowSize.y;
+    if( m_projectionType == PROJECTION_ORTHO )
+    {
+        // With the ortographic projection, there is just a zoom factor
+        const float panFactor = m_zoom / 37.5f; // Magic number from CCAMERA::rebuildProjection
+        m_camera_pos.x -= panFactor * ( m_lastPosition.x - aNewMousePosition.x );
+        m_camera_pos.y -= panFactor * ( aNewMousePosition.y - m_lastPosition.y );
+    }
+    else // PROJECTION_PERSPECTIVE
+    {
+        // Unproject the coordinates using the precomputed frustum tangent (zoom level dependent)
+        const float panFactor = -m_camera_pos.z *  m_frustum.tang * 2;
+        m_camera_pos.x -= panFactor * m_frustum.ratio * ( m_lastPosition.x - aNewMousePosition.x ) / m_windowSize.x;
+        m_camera_pos.y -= panFactor * ( aNewMousePosition.y - m_lastPosition.y ) / m_windowSize.y;
+    }
 
     updateViewMatrix();
     updateFrustum();

Follow ups