wip(viewport): render UTM viewport content; _f64 cleanup; paper hit-test

Checkpoint on the way to unified in-viewport editing.

- Drop the _f64 transition suffixes: pick_on_plane / pick_on_target_plane /
  paper_to_model are single f64 functions (wrappers removed).
- Paper-space hit-test/snap projects viewport content with points_low, and
  projects its aabb / key_vertices / snap_pts into paper coords so click
  picking and snap candidates land on the visible sheet geometry.
- camera_for_viewport + paper_to_model + EnterViewport agree on an absolute
  drawing-centre view (normalize_active_viewport_view) so UTM viewports
  render instead of aiming at the origin.
- model_to_paper inverse; dynamic-input anchors map model→paper before the
  paper camera projects them, so the guide no longer tessellates a 512 MB
  buffer (clicking the first in-viewport LINE point) — crash fixed.

Known-incomplete (next: unify on the model-space path via one coordinate
adapter): in-viewport snaps stale after pan/zoom (paper_projected_cache not
keyed on the viewport view), grips don't show, command preview misplaced.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-24 14:53:38 +03:00
commit 4aa8e6681f
3 changed files with 209 additions and 89 deletions

View file

@ -232,28 +232,10 @@ impl Camera {
/// Project a screen point onto an arbitrary world-space plane.
///
/// The plane is defined by `plane_normal` (unit vector) and a `plane_point`
/// that lies on it. Returns the intersection of the view ray with the plane;
/// falls back to `plane_point` when the ray is nearly parallel to the plane.
/// that lies on it. Returns the ray–plane intersection (falling back to
/// `plane_point` when nearly parallel), eye-relative in f64 so the cursor
/// stays precise at UTM-scale coordinates.
pub fn pick_on_plane(
&self,
screen: Point,
bounds: Rectangle,
plane_normal: Vec3,
plane_point: Vec3,
) -> Vec3 {
// Delegate to the eye-relative f64 unproject so the cursor stays
// precise at UTM-scale coordinates (the old full view_proj.inverse()
// cancelled catastrophically in f32).
self.unproject_on_plane_f64(screen, bounds, plane_normal, plane_point.as_dvec3())
.as_vec3()
}
pub fn pick_on_target_plane(&self, screen: Point, bounds: Rectangle) -> Vec3 {
self.pick_on_target_plane_f64(screen, bounds).as_vec3()
}
/// f64 variant of [`pick_on_plane`] — keeps the cursor precise at UTM-scale.
pub fn pick_on_plane_f64(
&self,
screen: Point,
bounds: Rectangle,
@ -263,8 +245,8 @@ impl Camera {
self.unproject_on_plane_f64(screen, bounds, plane_normal, plane_point)
}
/// f64 variant of [`pick_on_target_plane`].
pub fn pick_on_target_plane_f64(&self, screen: Point, bounds: Rectangle) -> glam::DVec3 {
/// Project a screen point onto the plane through the orbit target.
pub fn pick_on_target_plane(&self, screen: Point, bounds: Rectangle) -> glam::DVec3 {
let forward = (self.target.as_vec3() - self.eye()).normalize_or(Vec3::NEG_Z);
self.unproject_on_plane_f64(screen, bounds, forward, self.target)
}