Feat: Phase 3 — perspective projection and per-viewport UCS properties

- viewport_content_wires(): conditional perspective divide using
  camera_dist = view_height * lens_length / 24.0 (35mm-film equiv.);
  points behind the camera are mapped to NaN for safe clipping
- viewport.rs: expose lens_length, ucs_per_viewport, ucs_origin,
  ucs_x_axis, ucs_y_axis as editable properties; handle all new
  fields in apply_geom_prop()

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Sonnet 4.6 committed 2026-04-01 00:22:02 +03:00
1 parent 1aa44ac987
commit 5ad2f4a8cb
2 files changed
+57 -1

No files matched your search

+31
View File
@@ -168,6 +168,23 @@ fn properties(vp: &Viewport) -> PropSection {
},
edit("Target X", "vtgt_x", vp.view_target.x),
edit("Target Z", "vtgt_z", vp.view_target.z),
// Perspective lens length.
edit("Lens Length (mm)", "vp_lens", vp.lens_length),
// Per-Viewport UCS.
Property {
label: "UCS Per Viewport".into(),
field: "vp_ucs_per_vp",
value: PropValue::BoolToggle { field: "vp_ucs_per_vp", value: vp.ucs_per_viewport },
},
edit("UCS Origin X", "vp_ucs_ox", vp.ucs_origin.x),
edit("UCS Origin Y", "vp_ucs_oy", vp.ucs_origin.y),
edit("UCS Origin Z", "vp_ucs_oz", vp.ucs_origin.z),
edit("UCS X-Axis X", "vp_ucs_xx", vp.ucs_x_axis.x),
edit("UCS X-Axis Y", "vp_ucs_xy", vp.ucs_x_axis.y),
edit("UCS X-Axis Z", "vp_ucs_xz", vp.ucs_x_axis.z),
edit("UCS Y-Axis X", "vp_ucs_yx", vp.ucs_y_axis.x),
edit("UCS Y-Axis Y", "vp_ucs_yy", vp.ucs_y_axis.y),
edit("UCS Y-Axis Z", "vp_ucs_yz", vp.ucs_y_axis.z),
],
}
}
@@ -218,6 +235,10 @@ fn apply_geom_prop(vp: &mut Viewport, field: &str, value: &str) {
vp.ucs_icon_visible = if value == "toggle" { !vp.ucs_icon_visible } else { value == "true" };
return;
}
"vp_ucs_per_vp" => {
vp.ucs_per_viewport = if value == "toggle" { !vp.ucs_per_viewport } else { value == "true" };
return;
}
_ => {}
}
@@ -284,6 +305,16 @@ fn apply_geom_prop(vp: &mut Viewport, field: &str, value: &str) {
}
"vtgt_x" => vp.view_target.x = v,
"vtgt_z" => vp.view_target.z = v,
"vp_lens" if v > 0.0 => vp.lens_length = v,
"vp_ucs_ox" => vp.ucs_origin.x = v,
"vp_ucs_oy" => vp.ucs_origin.y = v,
"vp_ucs_oz" => vp.ucs_origin.z = v,
"vp_ucs_xx" => vp.ucs_x_axis.x = v,
"vp_ucs_xy" => vp.ucs_x_axis.y = v,
"vp_ucs_xz" => vp.ucs_x_axis.z = v,
"vp_ucs_yx" => vp.ucs_y_axis.x = v,
"vp_ucs_yy" => vp.ucs_y_axis.y = v,
"vp_ucs_yz" => vp.ucs_y_axis.z = v,
_ => {}
}
}