From aa63634d95d369b26da1eb4bbc9fcd26ae69c2b5 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Sun, 5 Jul 2026 03:26:07 +0300 Subject: [PATCH] fix(camera): orbit target in f64 to avoid extent-scale jitter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `orbit` revolved the target around the pivot as `p + (delta * (self.target - p).as_vec3()).as_dvec3()`, casting the target-to-pivot offset to f32. For a large model that offset is extent-scale (the cursor can sit far from the view centre), so the f32 cast quantized it — nudging the whole view a fraction of a unit each orbit step regardless of the drawing's origin. Do the revolve entirely in f64. Co-Authored-By: Claude Opus 4.8 --- src/scene/view/camera.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/scene/view/camera.rs b/src/scene/view/camera.rs index 9e76ea1f4..d50674911 100644 --- a/src/scene/view/camera.rs +++ b/src/scene/view/camera.rs @@ -294,9 +294,19 @@ impl Camera { // Revolve the target around the pivot by the same rotation delta so the // view orbits the chosen centre instead of the fixed file centre (#229). + // Do it in f64: casting `self.target - p` to f32 first quantizes the + // offset to the drawing's extent scale (a large model at ANY origin, not + // just UTM), so every orbit step nudged the whole view by a visible + // fraction of a unit — the "jump" when starting a rotate on big files. if let Some(p) = pivot { let delta = self.rotation * old_rot.conjugate(); - self.target = p + (delta * (self.target - p).as_vec3()).as_dvec3(); + let delta = glam::DQuat::from_xyzw( + delta.x as f64, + delta.y as f64, + delta.z as f64, + delta.w as f64, + ); + self.target = p + delta * (self.target - p); } // Sync legacy yaw/pitch for hit-test functions.