fix: correct MSPACE orbit and pan direction
orbit_active_viewport was writing cam.rotation*Z directly to view_direction, but yaw_pitch_to_quat(y,p)*Z has its Y component negated relative to the snap convention: (cos(p)*sin(y), -cos(p)*cos(y), sin(p)) vs (cos(p)*sin(y), +cos(p)*cos(y), sin(p)). This caused camera_for_viewport to reconstruct yaw = π - original_yaw, making every orbit appear reversed. Fix: negate Y when writing view_direction back. pan_active_viewport was using the paper-space camera to convert screen pixels to model-space delta. This gives wrong pan axes for tilted MSPACE views (e.g. front/side views where cam_up is Z, not Y). Fix: use camera_for_viewport so the pan axes match the 3-D view orientation, and update all three view_target components (X/Y/Z) for tilted views. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f176f7c80a
commit
2c5405aa49
1 changed files with 17 additions and 19 deletions
|
|
@ -897,28 +897,23 @@ impl Scene {
|
|||
Some(h) => h,
|
||||
None => return,
|
||||
};
|
||||
// Convert screen pixels → paper-space delta using the camera.
|
||||
let cam = self.camera.borrow();
|
||||
let paper_delta = cam.screen_delta_to_world(screen_dx, screen_dy, bounds);
|
||||
drop(cam);
|
||||
// Use the viewport's own camera so that the pan axes match the 3-D view
|
||||
// orientation (important for tilted/rotated MSPACE views).
|
||||
// camera_for_viewport already encodes the correct distance/scale via view_height,
|
||||
// so no additional scale division is needed.
|
||||
let vp_cam = match self.camera_for_viewport(vp_handle) {
|
||||
Some(c) => c,
|
||||
None => return,
|
||||
};
|
||||
let model_delta = vp_cam.screen_delta_to_world(screen_dx, screen_dy, bounds);
|
||||
|
||||
if let Some(acadrust::EntityType::Viewport(vp)) =
|
||||
self.document.get_entity_mut(vp_handle)
|
||||
{
|
||||
if vp.status.locked { return; }
|
||||
let scale = if vp.custom_scale.abs() > 1e-9 {
|
||||
vp.custom_scale
|
||||
} else if vp.view_height.abs() > 1e-9 {
|
||||
vp.height / vp.view_height
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
if scale.abs() < 1e-12 { return; }
|
||||
// screen_delta_to_world returns the same delta that cam.pan() ADDS to its
|
||||
// target, so we add it here too (dividing by viewport scale to convert from
|
||||
// paper-space to model-space). Using -= would invert the drag direction.
|
||||
vp.view_target.x += (paper_delta.x / scale as f32) as f64;
|
||||
vp.view_target.y += (paper_delta.y / scale as f32) as f64;
|
||||
vp.view_target.x += model_delta.x as f64;
|
||||
vp.view_target.y += model_delta.y as f64;
|
||||
vp.view_target.z += model_delta.z as f64;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -988,7 +983,10 @@ impl Scene {
|
|||
None => return,
|
||||
};
|
||||
cam.orbit(delta_x, delta_y);
|
||||
// Write the new view direction back to the viewport entity.
|
||||
// yaw_pitch_to_quat(y,p)*Z = (cos(p)*sin(y), -cos(p)*cos(y), sin(p))
|
||||
// but view_direction convention (matching snap_active_viewport_to_angles) is
|
||||
// (cos(p)*sin(y), +cos(p)*cos(y), sin(p)) ← Y has opposite sign.
|
||||
// Negate Y when writing back so camera_for_viewport round-trips correctly.
|
||||
let eye = cam.rotation * glam::Vec3::Z;
|
||||
if let Some(acadrust::EntityType::Viewport(vp)) =
|
||||
self.document.get_entity_mut(vp_handle)
|
||||
|
|
@ -997,7 +995,7 @@ impl Scene {
|
|||
return;
|
||||
}
|
||||
vp.view_direction.x = eye.x as f64;
|
||||
vp.view_direction.y = eye.y as f64;
|
||||
vp.view_direction.y = -eye.y as f64;
|
||||
vp.view_direction.z = eye.z as f64;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue