feat: Solid3D wire fallback render + Ole2Frame placeholder
- When SAT tessellation yields no mesh (binary SAB or unsupported ACIS geometry), render the pre-computed edge-wire polylines stored in Solid3D / Region / Body entities as a visible line fallback. - Ole2Frame entities now render a bounding rectangle with diagonal X instead of an invisible stub — marks embedded OLE objects in the viewport. Closes ROADMAP 2.13 (partial), 3.2 (Ole2Frame). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
5cf7a19ca8
commit
28f5c84b09
1 changed files with 65 additions and 2 deletions
|
|
@ -181,8 +181,12 @@ pub fn tessellate(
|
||||||
}
|
}
|
||||||
|
|
||||||
TruckObject::Volume(_) => {
|
TruckObject::Volume(_) => {
|
||||||
// Solid3D → handled by tessellate_mesh(), not WireModel.
|
// Solid3D / Region / Body → handled by tessellate_mesh().
|
||||||
return WireModel::solid(name, vec![], color, selected);
|
// As a wire fallback, render the pre-computed edge wires
|
||||||
|
// stored in the entity when present (e.g. from SOLVIEW output
|
||||||
|
// or when the SAT kernel cannot parse the ACIS data).
|
||||||
|
let wire_pts = solid_wire_fallback(entity);
|
||||||
|
return WireModel::solid(name, wire_pts, color, selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -561,6 +565,30 @@ fn legacy_geometry(entity: &EntityType) -> Geometry {
|
||||||
}
|
}
|
||||||
(pts, vec![], vec![], vec![])
|
(pts, vec![], vec![], vec![])
|
||||||
}
|
}
|
||||||
|
EntityType::Ole2Frame(ole) => {
|
||||||
|
// OLE objects carry a bounding rectangle in model space.
|
||||||
|
// Render a simple X-through-rectangle placeholder.
|
||||||
|
let x0 = ole.upper_left_corner.x as f32;
|
||||||
|
let y0 = ole.lower_right_corner.y as f32;
|
||||||
|
let x1 = ole.lower_right_corner.x as f32;
|
||||||
|
let y1 = ole.upper_left_corner.y as f32;
|
||||||
|
let z = ole.upper_left_corner.z as f32;
|
||||||
|
if (x1 - x0).abs() < 1e-6 && (y1 - y0).abs() < 1e-6 {
|
||||||
|
// Degenerate / unknown size — show a small cross.
|
||||||
|
let s = 0.5_f32;
|
||||||
|
return (vec![[-s, 0.0, 0.0], [s, 0.0, 0.0]], vec![], vec![], vec![]);
|
||||||
|
}
|
||||||
|
let pts = vec![
|
||||||
|
// Outer rectangle
|
||||||
|
[x0, y0, z], [x1, y0, z], [x1, y0, z], [x1, y1, z],
|
||||||
|
[x1, y1, z], [x0, y1, z], [x0, y1, z], [x0, y0, z],
|
||||||
|
// Diagonal X
|
||||||
|
[x0, y0, z], [x1, y1, z],
|
||||||
|
[f32::NAN, f32::NAN, f32::NAN],
|
||||||
|
[x1, y0, z], [x0, y1, z],
|
||||||
|
];
|
||||||
|
(pts, vec![], vec![], vec![[x0, y0, z], [x1, y1, z]])
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let s = 0.5_f32;
|
let s = 0.5_f32;
|
||||||
(vec![[-s, 0.0, 0.0], [s, 0.0, 0.0]], vec![], vec![], vec![])
|
(vec![[-s, 0.0, 0.0], [s, 0.0, 0.0]], vec![], vec![], vec![])
|
||||||
|
|
@ -568,6 +596,41 @@ fn legacy_geometry(entity: &EntityType) -> Geometry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extract pre-computed edge-wire points from Solid3D / Region / Body entities.
|
||||||
|
///
|
||||||
|
/// AutoCAD stores explicit wire geometry (from SOLVIEW / 3DPLOT) alongside the
|
||||||
|
/// ACIS data. We use this as a visible fallback when the SAT tessellator
|
||||||
|
/// produces no mesh (e.g. binary SAB data or unsupported geometry).
|
||||||
|
fn solid_wire_fallback(entity: &EntityType) -> Vec<[f32; 3]> {
|
||||||
|
let wires: &[acadrust::entities::Wire] = match entity {
|
||||||
|
EntityType::Solid3D(s) => &s.wires,
|
||||||
|
EntityType::Region(r) => &r.wires,
|
||||||
|
EntityType::Body(b) => &b.wires,
|
||||||
|
_ => return vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
if wires.is_empty() {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut pts: Vec<[f32; 3]> = Vec::new();
|
||||||
|
for wire in wires {
|
||||||
|
if wire.points.len() < 2 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (i, v) in wire.points.iter().enumerate() {
|
||||||
|
if i > 0 {
|
||||||
|
// Connect segments: repeat previous point then add current so
|
||||||
|
// the wire renderer draws a continuous polyline per wire.
|
||||||
|
}
|
||||||
|
pts.push([v.x as f32, v.y as f32, v.z as f32]);
|
||||||
|
}
|
||||||
|
// NaN sentinel separates distinct wire segments.
|
||||||
|
pts.push([f32::NAN, f32::NAN, f32::NAN]);
|
||||||
|
}
|
||||||
|
pts
|
||||||
|
}
|
||||||
|
|
||||||
fn dimension_geometry(dim: &Dimension) -> Vec<[f32; 3]> {
|
fn dimension_geometry(dim: &Dimension) -> Vec<[f32; 3]> {
|
||||||
let mut points = Vec::new();
|
let mut points = Vec::new();
|
||||||
match dim {
|
match dim {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue