fix(render): close remaining OCS/WCS gaps for mirrored entities

Follow-up to the LINE/POINT WCS fix - the same bug class elsewhere:

- 2D SOLID rendered its OCS corners raw in both the wire path and the
  shared fill builder (solid_hatch_model); SHAPE placed its marker at
  the raw OCS insertion. Both now map through the arbitrary axis.
- Grips: central wrap in view/dispatch.rs shows planar entities' grips
  at their world position (OCS→WCS) and converts drags back (WCS→OCS
  via the new wcs_point_to_ocs) - per-entity grip code stays in raw
  field space, INSERT keeps handling its own OCS.
- Pulls acadrust 81ebfee: OCS-aware bounding boxes, translate,
  transform and mirror for the ten planar entity types, so MOVE /
  ROTATE / MIRROR and culling work on mirrored entities too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-07-21 17:58:09 +03:00
commit 87049967a2
6 changed files with 105 additions and 22 deletions

View file

@ -57,9 +57,16 @@ fn shape_marker(
impl TruckConvertible for Shape {
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
let ox = self.insertion_point.x;
let oy = self.insertion_point.y;
let oz = self.insertion_point.z;
// SHAPE insertion point is OCS (planar entity) — map through the
// arbitrary axis so a mirrored shape's marker lands where it renders.
let (ox, oy, oz) = crate::scene::view::transform::ocs_point_to_wcs(
(
self.insertion_point.x,
self.insertion_point.y,
self.insertion_point.z,
),
(self.normal.x, self.normal.y, self.normal.z),
);
let size = self.size.abs().max(0.5);
let snap_pt = glam::DVec3::new(ox, oy, oz);

View file

@ -17,20 +17,23 @@ use crate::scene::convert::acad_to_truck::{TruckEntity, TruckObject};
use crate::scene::model::object::{GripApply, GripDef, PropSection};
use crate::scene::model::wire_model::SnapHint;
fn v3(v: &acadrust::types::Vector3) -> [f64; 3] {
[v.x, v.y, v.z]
}
fn dvec3(v: &acadrust::types::Vector3) -> glam::DVec3 {
glam::DVec3::new(v.x, v.y, v.z)
}
impl TruckConvertible for Solid {
fn to_truck(&self, _document: &acadrust::CadDocument) -> Option<TruckEntity> {
let p0 = v3(&self.first_corner);
let p1 = v3(&self.second_corner);
let p2 = v3(&self.third_corner);
let p3 = v3(&self.fourth_corner);
// SOLID corners are OCS (planar entity) — map through the arbitrary
// axis so mirrored solids (normal 0,0,-1) land on the correct side.
let n = (self.normal.x, self.normal.y, self.normal.z);
let w = |v: &acadrust::types::Vector3| -> [f64; 3] {
let (x, y, z) = crate::scene::view::transform::ocs_point_to_wcs((v.x, v.y, v.z), n);
[x, y, z]
};
let p0 = w(&self.first_corner);
let p1 = w(&self.second_corner);
let p2 = w(&self.third_corner);
let p3 = w(&self.fourth_corner);
// DXF SOLID vertex order: 1-2-4-3 (Z-shaped), render as closed quad outline.
// AutoCAD stores corners in "Z" order: p0-p1 are top edge, p2-p3 are bottom edge,
@ -49,12 +52,12 @@ impl TruckConvertible for Solid {
p0,
];
let dv = |c: &acadrust::types::Vector3| glam::DVec3::new(c.x, c.y, c.z);
let dvp = |p: [f64; 3]| glam::DVec3::new(p[0], p[1], p[2]);
let snap = vec![
(dv(&self.first_corner), SnapHint::Node),
(dv(&self.second_corner), SnapHint::Node),
(dv(&self.third_corner), SnapHint::Node),
(dv(&self.fourth_corner), SnapHint::Node),
(dvp(p0), SnapHint::Node),
(dvp(p1), SnapHint::Node),
(dvp(p2), SnapHint::Node),
(dvp(p3), SnapHint::Node),
];
// Fill the visual quad p0→p1→p3→p2 (Z-order) as two triangles; a