forked from 1b-agent/opencadstudio-upstream
Feat: implement WCS↔UCS coordinate transform pipeline
- Add `active_ucs: Option<Ucs>` per-tab state to DocumentTab - Add `ucs_to_wcs`, `wcs_to_ucs`, `ucs_z_axis`, `ucs_rotated_z` helpers - Add `Camera::pick_on_plane` for ray–plane intersection against any plane - Mouse picks project onto the active UCS XY plane instead of world XY - Typed coordinates are converted from UCS space to WCS before dispatch - UCS command now really activates/deactivates a UCS: - `UCS W` resets to WCS (clears active_ucs) - `UCS <name>` activates a named UCS - `UCS SAVE <name>` saves the current active UCS - `UCS ORIGIN x,y,z` shifts origin (in current UCS space) - `UCS X/Y/Z <angle>` rotates the UCS around its own axes Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
98578cc5c0
commit
20629d587a
5 files changed
+272
-26
No files matched your search
@@ -101,6 +101,47 @@ impl Camera {
|
||||
OPENGL_TO_WGPU * proj * view
|
||||
}
|
||||
|
||||
/// 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.
|
||||
pub fn pick_on_plane(
|
||||
&self,
|
||||
screen: Point,
|
||||
bounds: Rectangle,
|
||||
plane_normal: Vec3,
|
||||
plane_point: Vec3,
|
||||
) -> Vec3 {
|
||||
let ndc_x = (screen.x / bounds.width) * 2.0 - 1.0;
|
||||
let ndc_y = 1.0 - (screen.y / bounds.height) * 2.0;
|
||||
let inv = self.view_proj(bounds).inverse();
|
||||
|
||||
let (ray_origin, ray_dir) = match self.projection {
|
||||
Projection::Perspective => {
|
||||
let near_pt = inv.project_point3(Vec3::new(ndc_x, ndc_y, 0.0));
|
||||
let far_pt = inv.project_point3(Vec3::new(ndc_x, ndc_y, 1.0));
|
||||
let dir = (far_pt - near_pt).normalize();
|
||||
(near_pt, dir)
|
||||
}
|
||||
Projection::Orthographic => {
|
||||
let origin = inv.project_point3(Vec3::new(ndc_x, ndc_y, 0.0));
|
||||
let forward = (self.target - self.eye()).normalize();
|
||||
(origin, forward)
|
||||
}
|
||||
};
|
||||
|
||||
let denom = ray_dir.dot(plane_normal);
|
||||
if denom.abs() < 1e-6 {
|
||||
return plane_point;
|
||||
}
|
||||
let t = (plane_point - ray_origin).dot(plane_normal) / denom;
|
||||
if t < 0.0 {
|
||||
return plane_point;
|
||||
}
|
||||
ray_origin + ray_dir * t
|
||||
}
|
||||
|
||||
pub fn pick_on_target_plane(&self, screen: Point, bounds: Rectangle) -> Vec3 {
|
||||
let ndc_x = (screen.x / bounds.width) * 2.0 - 1.0;
|
||||
let ndc_y = 1.0 - (screen.y / bounds.height) * 2.0;
|
||||
|
||||
Reference in new issue
Block a user