refactor: remove dead world_offset plumbing (RTE migration is complete)
Now that geometry reaches the GPU/CPU as absolute coordinates via the double-single relative-to-eye path, world_offset is always [0,0,0]. Strip the parameter that was threaded through the whole tessellation / block- expansion / fallback / camera-decode chain and the ExpandCtx field that carried it — ~340 references across 20 files, all subtracting zero. - truck_tess: to_local / to_local_low / tessellate_* drop the offset arg; to_local is now a pure double-single split. - tessellate: offset_to_ds → points_to_ds (pure DS split); tessellate(), tessellate_entity(), fallback_geometry(), solid_wire_fallback(), entity_aabb(), expand_insert(), expand_block_meshes(), the dimension helpers (vec3_local, dimension_snap_pts, …), text_support, leader, multileader, image_model, xclip and camera_from_view all lose the param. - block_cache: ExpandCtx loses its world_offset field. - Remove the now-dead offset_snap_pts and the unused set_grid_snap. Behaviour is unchanged (the offset was zero everywhere); the compiler verifies every call site. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
02d40bd2ec
commit
56d507fd88
20 changed files with 190 additions and 343 deletions
|
|
@ -1241,7 +1241,6 @@ impl OpenCADStudio {
|
|||
let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned();
|
||||
if let Some(entity) = entity_opt {
|
||||
let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document);
|
||||
let woff = [0.0_f64; 3];
|
||||
let result = truck_entity.and_then(|te| {
|
||||
match te.object {
|
||||
TruckObject::Contour(wire) => {
|
||||
|
|
@ -1250,7 +1249,7 @@ impl OpenCADStudio {
|
|||
// tsweep(Face) → Solid
|
||||
let solid =
|
||||
builder::tsweep(&face, TruckVec3::new(0.0, 0.0, height as f64));
|
||||
match truck_tess::tessellate_solid(&solid, woff) {
|
||||
match truck_tess::tessellate_solid(&solid) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1309,7 +1308,6 @@ impl OpenCADStudio {
|
|||
let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned();
|
||||
if let Some(entity) = entity_opt {
|
||||
let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document);
|
||||
let woff = [0.0_f64; 3];
|
||||
let result = truck_entity.and_then(|te| {
|
||||
let wire: Option<truck_modeling::Wire> = match te.object {
|
||||
TruckObject::Contour(w) => Some(w),
|
||||
|
|
@ -1330,7 +1328,7 @@ impl OpenCADStudio {
|
|||
axis,
|
||||
Rad(angle_deg.to_radians() as f64),
|
||||
);
|
||||
match truck_tess::tessellate_shell(&shell, woff) {
|
||||
match truck_tess::tessellate_shell(&shell) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1389,7 +1387,6 @@ impl OpenCADStudio {
|
|||
.get_entity(profile_handle)
|
||||
.cloned();
|
||||
let path_ent = self.tabs[i].scene.document.get_entity(path_handle).cloned();
|
||||
let woff = [0.0_f64; 3];
|
||||
|
||||
let result = profile_ent.zip(path_ent).and_then(|(prof_e, path_e)| {
|
||||
let prof_truck = prof_e.to_truck_entity(&self.tabs[i].scene.document)?;
|
||||
|
|
@ -1417,7 +1414,7 @@ impl OpenCADStudio {
|
|||
// wire we get a Solid, otherwise a Shell.
|
||||
if let Ok(face) = builder::try_attach_plane(&[profile_wire.clone()]) {
|
||||
let solid = builder::tsweep(&face, dir);
|
||||
match truck_tess::tessellate_solid(&solid, woff) {
|
||||
match truck_tess::tessellate_solid(&solid) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1436,7 +1433,7 @@ impl OpenCADStudio {
|
|||
}
|
||||
} else {
|
||||
let shell = builder::tsweep(&profile_wire, dir);
|
||||
match truck_tess::tessellate_shell(&shell, woff) {
|
||||
match truck_tess::tessellate_shell(&shell) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1470,7 +1467,7 @@ impl OpenCADStudio {
|
|||
);
|
||||
if let Ok(face) = builder::try_attach_plane(&[profile_wire.clone()]) {
|
||||
let solid = builder::tsweep(&face, dir);
|
||||
match truck_tess::tessellate_solid(&solid, woff) {
|
||||
match truck_tess::tessellate_solid(&solid) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1489,7 +1486,7 @@ impl OpenCADStudio {
|
|||
}
|
||||
} else {
|
||||
let shell = builder::tsweep(&profile_wire, dir);
|
||||
match truck_tess::tessellate_shell(&shell, woff) {
|
||||
match truck_tess::tessellate_shell(&shell) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
@ -1556,7 +1553,6 @@ impl OpenCADStudio {
|
|||
}
|
||||
}
|
||||
|
||||
let woff = [0.0_f64; 3];
|
||||
let result: Option<crate::scene::model::mesh_model::MeshModel> = (|| {
|
||||
if wires.len() < 2 {
|
||||
return None;
|
||||
|
|
@ -1581,7 +1577,7 @@ impl OpenCADStudio {
|
|||
}
|
||||
|
||||
let shell = truck_modeling::Shell::from(all_faces);
|
||||
match truck_tess::tessellate_shell(&shell, woff) {
|
||||
match truck_tess::tessellate_shell(&shell) {
|
||||
truck_tess::TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
|
|||
|
|
@ -406,7 +406,6 @@ impl super::OpenCADStudio {
|
|||
0.0,
|
||||
[0.0; 8],
|
||||
1.0,
|
||||
woff,
|
||||
anno,
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -849,7 +849,6 @@ pub trait DimensionTess {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
selected_set: &rustc_hash::FxHashSet<acadrust::Handle>,
|
||||
active_viewport: Option<acadrust::Handle>,
|
||||
|
|
@ -867,7 +866,6 @@ impl DimensionTess for Dimension {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
selected_set: &rustc_hash::FxHashSet<acadrust::Handle>,
|
||||
active_viewport: Option<acadrust::Handle>,
|
||||
|
|
@ -882,7 +880,6 @@ impl DimensionTess for Dimension {
|
|||
selected,
|
||||
entity_color,
|
||||
line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
selected_set,
|
||||
active_viewport,
|
||||
|
|
@ -900,7 +897,6 @@ fn tessellate_dimension_inner(
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
// LOD hints — when present, synthesised dim text routes through the
|
||||
// top-level LOD ladder (baseline / greek / full) instead of the truck
|
||||
|
|
@ -1012,7 +1008,6 @@ fn tessellate_dimension_inner(
|
|||
let text_break = {
|
||||
let tp = vec3_local(
|
||||
dimension_text_pos_f64(dim, style, dim_txt, dim_scale),
|
||||
world_offset,
|
||||
);
|
||||
let tw = dimension_text_value(dim, style)
|
||||
.map(|t| t.chars().count() as f32 * dim_txt as f32 * 0.6)
|
||||
|
|
@ -1054,7 +1049,6 @@ fn tessellate_dimension_inner(
|
|||
dim1: dimsd1,
|
||||
dim2: dimsd2,
|
||||
},
|
||||
world_offset,
|
||||
);
|
||||
|
||||
// DIMTMOVE = 1: when the saved text_middle_point sits far from the
|
||||
|
|
@ -1062,7 +1056,7 @@ fn tessellate_dimension_inner(
|
|||
// to the dim line — no leader; =2 frees text without a leader.)
|
||||
if let Some(s) = style {
|
||||
if s.dimtmove == 1 {
|
||||
if let Some((anchor, txt)) = dimtmove_leader_endpoints(dim, world_offset) {
|
||||
if let Some((anchor, txt)) = dimtmove_leader_endpoints(dim) {
|
||||
let gap = dim_txt as f32 * 0.5;
|
||||
if (txt - anchor).length() > gap * 2.0 {
|
||||
add_segment(&mut geom.dim_lines, anchor, txt);
|
||||
|
|
@ -1120,7 +1114,7 @@ fn tessellate_dimension_inner(
|
|||
resolve_dim_color(style.map(|s| s.dimclrt).unwrap_or(0), entity_color)
|
||||
};
|
||||
|
||||
let snap_pts = dimension_snap_pts(dim, world_offset);
|
||||
let snap_pts = dimension_snap_pts(dim);
|
||||
let key_vertices: Vec<[f64; 3]> = geom
|
||||
.dim_lines
|
||||
.iter()
|
||||
|
|
@ -1244,7 +1238,7 @@ fn tessellate_dimension_inner(
|
|||
// DIMTFILL: 0=none, 1=drawing background (mask), 2=DIMTFILLCLR.
|
||||
if let Some(s) = style {
|
||||
if s.dimtfill == 1 || s.dimtfill == 2 {
|
||||
if let Some(rect) = text_fill_rect(dim, style, dim_txt, world_offset, dim_scale) {
|
||||
if let Some(rect) = text_fill_rect(dim, style, dim_txt, dim_scale) {
|
||||
let fill_color = if selected {
|
||||
WireModel::SELECTED
|
||||
} else if s.dimtfill == 1 {
|
||||
|
|
@ -1290,7 +1284,6 @@ fn tessellate_dimension_inner(
|
|||
document,
|
||||
selected_set,
|
||||
active_viewport,
|
||||
world_offset,
|
||||
bg_color,
|
||||
1.0,
|
||||
&synth_text_entity,
|
||||
|
|
@ -1308,7 +1301,6 @@ fn tessellate_dimension_inner(
|
|||
document,
|
||||
selected_set,
|
||||
active_viewport,
|
||||
world_offset,
|
||||
bg_color,
|
||||
1.0,
|
||||
&tol_entity_e,
|
||||
|
|
@ -1395,13 +1387,13 @@ fn split_ext_lines(points: &[[f32; 3]]) -> (Vec<[f32; 3]>, Vec<[f32; 3]>) {
|
|||
/// text_middle_point). Returns None when the dim has no saved text position
|
||||
/// or has no well-defined dim-line midpoint (radius/diameter handled by
|
||||
/// their own leg).
|
||||
fn dimtmove_leader_endpoints(dim: &Dimension, world_offset: [f64; 3]) -> Option<(Vec3, Vec3)> {
|
||||
fn dimtmove_leader_endpoints(dim: &Dimension) -> Option<(Vec3, Vec3)> {
|
||||
let base = dim.base();
|
||||
let txt = base.text_middle_point;
|
||||
if txt.x * txt.x + txt.y * txt.y + txt.z * txt.z <= 1e-16 {
|
||||
return None;
|
||||
}
|
||||
let lv = |v| vec3_local(v, world_offset);
|
||||
let lv = |v| vec3_local(v);
|
||||
let anchor = match dim {
|
||||
Dimension::Linear(d) => {
|
||||
let perp = Vec3::new(-(d.rotation.sin() as f32), d.rotation.cos() as f32, 0.0);
|
||||
|
|
@ -1437,7 +1429,6 @@ fn text_fill_rect(
|
|||
dim: &Dimension,
|
||||
style: Option<&DimStyle>,
|
||||
text_height: f64,
|
||||
world_offset: [f64; 3],
|
||||
dim_scale: f64,
|
||||
) -> Option<Vec<[f32; 3]>> {
|
||||
let value = dimension_text_value(dim, style)?;
|
||||
|
|
@ -1458,7 +1449,7 @@ fn text_fill_rect(
|
|||
let (sr, cr) = rot.sin_cos();
|
||||
let hx = approx_w * 0.5;
|
||||
let hy = approx_h * 0.5;
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let cx = (pos.x - ox) as f32;
|
||||
let cy = (pos.y - oy) as f32;
|
||||
let cz = (pos.z - oz) as f32;
|
||||
|
|
@ -1503,9 +1494,8 @@ fn dimension_geometry(
|
|||
arrow2: &ArrowKind,
|
||||
params: DimLineParams,
|
||||
suppress: SuppressFlags,
|
||||
world_offset: [f64; 3],
|
||||
) -> DimGeom {
|
||||
let lv = |v| vec3_local(v, world_offset);
|
||||
let lv = |v| vec3_local(v);
|
||||
let mut g = DimGeom::new();
|
||||
match dim {
|
||||
Dimension::Aligned(d) => {
|
||||
|
|
@ -1547,7 +1537,7 @@ fn dimension_geometry(
|
|||
Dimension::Radius(d) => {
|
||||
let center = lv(d.angle_vertex);
|
||||
let point = lv(d.definition_point);
|
||||
let text = dimension_text_position(dim, world_offset);
|
||||
let text = dimension_text_position(dim);
|
||||
add_segment(&mut g.dim_lines, center, point);
|
||||
// Honour leader_length: extend from the arrow tip past it
|
||||
// toward the text by that distance along (text - point).
|
||||
|
|
@ -1575,7 +1565,7 @@ fn dimension_geometry(
|
|||
append_arrow(&mut g, p2, normalized_or(p1 - p2, Vec3::X), arrow2);
|
||||
// DIMETER leader: continue past p2 toward the text.
|
||||
if d.leader_length.abs() > 1e-9 {
|
||||
let text = dimension_text_position(dim, world_offset);
|
||||
let text = dimension_text_position(dim);
|
||||
let leader_dir = normalized_or(text - p2, p2 - p1);
|
||||
add_segment(
|
||||
&mut g.dim_lines,
|
||||
|
|
@ -1839,12 +1829,12 @@ fn append_angular_dimension(
|
|||
}
|
||||
}
|
||||
|
||||
fn dimension_snap_pts(dim: &Dimension, world_offset: [f64; 3]) -> Vec<(glam::DVec3, SnapHint)> {
|
||||
fn dimension_snap_pts(dim: &Dimension) -> Vec<(glam::DVec3, SnapHint)> {
|
||||
let lv = |v: acadrust::types::Vector3| {
|
||||
glam::DVec3::new(
|
||||
v.x - world_offset[0],
|
||||
v.y - world_offset[1],
|
||||
v.z - world_offset[2],
|
||||
v.x,
|
||||
v.y,
|
||||
v.z,
|
||||
)
|
||||
};
|
||||
let node = |v: acadrust::types::Vector3| (lv(v), SnapHint::Node);
|
||||
|
|
@ -2568,8 +2558,8 @@ fn swap_decimal_sep(s: &str, dsep_code: i16) -> String {
|
|||
s.replace('.', &ch.to_string())
|
||||
}
|
||||
|
||||
fn dimension_text_position(dim: &Dimension, world_offset: [f64; 3]) -> Vec3 {
|
||||
let lv = |v| vec3_local(v, world_offset);
|
||||
fn dimension_text_position(dim: &Dimension) -> Vec3 {
|
||||
let lv = |v| vec3_local(v);
|
||||
let base = dim.base();
|
||||
let pos = lv(base.text_middle_point);
|
||||
if pos.length_squared() > 1e-8 {
|
||||
|
|
@ -2586,12 +2576,8 @@ fn dimension_text_position(dim: &Dimension, world_offset: [f64; 3]) -> Vec3 {
|
|||
}
|
||||
}
|
||||
|
||||
fn vec3_local(v: Vector3, off: [f64; 3]) -> Vec3 {
|
||||
Vec3::new(
|
||||
(v.x - off[0]) as f32,
|
||||
(v.y - off[1]) as f32,
|
||||
(v.z - off[2]) as f32,
|
||||
)
|
||||
fn vec3_local(v: Vector3) -> Vec3 {
|
||||
Vec3::new(v.x as f32, v.y as f32, v.z as f32)
|
||||
}
|
||||
|
||||
/// Style-driven text anchor on the dimension line: a point on the line through
|
||||
|
|
|
|||
|
|
@ -344,14 +344,13 @@ impl Grippable for Hatch {
|
|||
}
|
||||
|
||||
impl FallbackTess for Hatch {
|
||||
fn fallback_geometry(&self, world_offset: [f64; 3]) -> FallbackGeometry {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
fn fallback_geometry(&self) -> FallbackGeometry {
|
||||
let normal = (self.normal.x, self.normal.y, self.normal.z);
|
||||
// Convert a 2D OCS hatch boundary point to WCS, then subtract world_offset.
|
||||
// Convert a 2D OCS hatch boundary point to absolute WCS.
|
||||
let to_wcs = |x: f64, y: f64| -> [f64; 3] {
|
||||
let (wx, wy, wz) =
|
||||
crate::scene::view::transform::ocs_point_to_wcs((x, y, self.elevation), normal);
|
||||
[wx - ox, wy - oy, wz - oz]
|
||||
[wx, wy, wz]
|
||||
};
|
||||
// Snap point at a world (f64) location, cast to the f32 snap buffer.
|
||||
let snap_at = |w: [f64; 3]| Vec3::new(w[0] as f32, w[1] as f32, w[2] as f32);
|
||||
|
|
|
|||
|
|
@ -101,13 +101,11 @@ crate::impl_entity_basics!(Insert);
|
|||
impl crate::entities::traits::FallbackTess for Insert {
|
||||
fn fallback_geometry(
|
||||
&self,
|
||||
world_offset: [f64; 3],
|
||||
) -> crate::scene::convert::tess_util::FallbackGeometry {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let (ipx, ipy, ipz) = (
|
||||
self.insert_point.x - ox,
|
||||
self.insert_point.y - oy,
|
||||
self.insert_point.z - oz,
|
||||
self.insert_point.x,
|
||||
self.insert_point.y,
|
||||
self.insert_point.z,
|
||||
);
|
||||
let ip = Vec3::new(ipx as f32, ipy as f32, ipz as f32);
|
||||
let s = 0.1_f64;
|
||||
|
|
@ -139,7 +137,6 @@ pub(crate) fn append_insert_attribute_wires(
|
|||
is_xref: bool,
|
||||
pslt_factor: f32,
|
||||
anno_scale: f32,
|
||||
world_offset: [f64; 3],
|
||||
) {
|
||||
if ins.attributes.is_empty() {
|
||||
return;
|
||||
|
|
@ -172,7 +169,7 @@ pub(crate) fn append_insert_attribute_wires(
|
|||
} else {
|
||||
sub_color
|
||||
};
|
||||
let sub_aabb = crate::scene::entity_aabb(&attr_entity, world_offset);
|
||||
let sub_aabb = crate::scene::entity_aabb(&attr_entity);
|
||||
let mut attr_wires = tessellate::tessellate(
|
||||
document,
|
||||
insert_handle,
|
||||
|
|
@ -182,7 +179,6 @@ pub(crate) fn append_insert_attribute_wires(
|
|||
sub_plen * pslt_factor,
|
||||
sub_pat.map(|v| v * pslt_factor),
|
||||
sub_lw_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -567,7 +567,6 @@ pub trait LeaderTess {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
) -> crate::scene::model::wire_model::WireModel;
|
||||
}
|
||||
|
|
@ -580,7 +579,6 @@ impl LeaderTess for Leader {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
) -> crate::scene::model::wire_model::WireModel {
|
||||
use crate::scene::convert::tessellate::{append_arrow, arrow_from_block, ArrowKind, DimGeom};
|
||||
|
|
@ -591,7 +589,7 @@ impl LeaderTess for Leader {
|
|||
entity_color
|
||||
};
|
||||
let name = handle.value().to_string();
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let p3 = |v: &acadrust::types::Vector3| -> [f32; 3] {
|
||||
[(v.x - ox) as f32, (v.y - oy) as f32, (v.z - oz) as f32]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1069,7 +1069,6 @@ pub trait MultiLeaderTess {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
world_per_pixel: Option<f32>,
|
||||
) -> Vec<crate::scene::model::wire_model::WireModel>;
|
||||
|
|
@ -1083,7 +1082,6 @@ impl MultiLeaderTess for MultiLeader {
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
world_per_pixel: Option<f32>,
|
||||
) -> Vec<crate::scene::model::wire_model::WireModel> {
|
||||
|
|
@ -1129,7 +1127,7 @@ impl MultiLeaderTess for MultiLeader {
|
|||
|
||||
let name = handle.value().to_string();
|
||||
let nan = [f32::NAN; 3];
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let p3 = |v: &acadrust::types::Vector3| -> [f32; 3] {
|
||||
[(v.x - ox) as f32, (v.y - oy) as f32, (v.z - oz) as f32]
|
||||
};
|
||||
|
|
@ -1349,7 +1347,6 @@ impl MultiLeaderTess for MultiLeader {
|
|||
leader_pat_len,
|
||||
leader_pat,
|
||||
leader_lw_px,
|
||||
world_offset,
|
||||
1.0,
|
||||
None,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -182,16 +182,14 @@ crate::impl_entity_basics!(Ole2Frame);
|
|||
impl crate::entities::traits::FallbackTess for Ole2Frame {
|
||||
fn fallback_geometry(
|
||||
&self,
|
||||
world_offset: [f64; 3],
|
||||
) -> crate::scene::convert::tess_util::FallbackGeometry {
|
||||
// OLE objects carry a bounding rectangle in model space.
|
||||
// Render a simple X-through-rectangle placeholder.
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let x0 = self.upper_left_corner.x - ox;
|
||||
let y0 = self.lower_right_corner.y - oy;
|
||||
let x1 = self.lower_right_corner.x - ox;
|
||||
let y1 = self.upper_left_corner.y - oy;
|
||||
let z = self.upper_left_corner.z - oz;
|
||||
let x0 = self.upper_left_corner.x;
|
||||
let y0 = self.lower_right_corner.y;
|
||||
let x1 = self.lower_right_corner.x;
|
||||
let y1 = self.upper_left_corner.y;
|
||||
let z = self.upper_left_corner.z;
|
||||
if (x1 - x0).abs() < 1e-6 && (y1 - y0).abs() < 1e-6 {
|
||||
// Degenerate / unknown size — show a small cross.
|
||||
let s = 0.5_f64;
|
||||
|
|
|
|||
|
|
@ -344,7 +344,6 @@ pub fn tessellate_table(
|
|||
selected: bool,
|
||||
entity_color: [f32; 4],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
) -> Vec<crate::scene::model::wire_model::WireModel> {
|
||||
use crate::scene::convert::tess_util::aci_to_rgba;
|
||||
use crate::scene::model::wire_model::WireModel;
|
||||
|
|
@ -355,7 +354,7 @@ pub fn tessellate_table(
|
|||
return Vec::new();
|
||||
}
|
||||
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let rel = |p: Vec3| -> [f32; 3] {
|
||||
[
|
||||
(p.x as f64 - ox) as f32,
|
||||
|
|
|
|||
|
|
@ -1702,7 +1702,6 @@ pub(crate) fn text_obb_corners_native(
|
|||
pub(crate) fn text_baseline_points(
|
||||
e: &EntityType,
|
||||
anno_scale: f32,
|
||||
world_offset: [f64; 3],
|
||||
n_lines: usize,
|
||||
) -> Vec<[f32; 3]> {
|
||||
let Some(corners) = text_obb_corners_native(e, anno_scale, Some(n_lines)) else {
|
||||
|
|
@ -1723,7 +1722,7 @@ pub(crate) fn text_baseline_points(
|
|||
return vec![];
|
||||
}
|
||||
let n_lines = n_lines.max(1);
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let cast = |p: [f64; 3]| -> [f32; 3] {
|
||||
[(p[0] - ox) as f32, (p[1] - oy) as f32, (p[2] - oz) as f32]
|
||||
};
|
||||
|
|
@ -1763,7 +1762,6 @@ pub(crate) fn text_baseline_points(
|
|||
pub(crate) fn text_greek_obb_tris(
|
||||
e: &EntityType,
|
||||
anno_scale: f32,
|
||||
world_offset: [f64; 3],
|
||||
n_lines: usize,
|
||||
) -> Vec<[f32; 3]> {
|
||||
let Some(corners) = text_obb_corners_native(e, anno_scale, Some(n_lines)) else {
|
||||
|
|
@ -1784,7 +1782,7 @@ pub(crate) fn text_greek_obb_tris(
|
|||
return vec![];
|
||||
}
|
||||
let n_lines = n_lines.max(1);
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let cast = |p: [f64; 3]| -> [f32; 3] {
|
||||
[(p[0] - ox) as f32, (p[1] - oy) as f32, (p[2] - oz) as f32]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ pub trait TruckConvertible {
|
|||
}
|
||||
|
||||
/// Fallback geometry for entities not routed through the truck topology
|
||||
/// pipeline (Viewport, Insert, Hatch outline, Ole2Frame). Returns
|
||||
/// world-offset-relative `f32` points + snap/key vertices the
|
||||
/// dispatcher wraps into a `WireModel`.
|
||||
/// pipeline (Viewport, Insert, Hatch outline, Ole2Frame). Returns absolute
|
||||
/// WCS `f32` points + snap/key vertices the dispatcher wraps into a
|
||||
/// `WireModel`.
|
||||
pub trait FallbackTess {
|
||||
fn fallback_geometry(&self, world_offset: [f64; 3]) -> FallbackGeometry;
|
||||
fn fallback_geometry(&self) -> FallbackGeometry;
|
||||
}
|
||||
|
||||
pub trait Grippable {
|
||||
|
|
|
|||
|
|
@ -548,12 +548,10 @@ crate::impl_entity_basics!(Viewport);
|
|||
impl crate::entities::traits::FallbackTess for Viewport {
|
||||
fn fallback_geometry(
|
||||
&self,
|
||||
world_offset: [f64; 3],
|
||||
) -> crate::scene::convert::tess_util::FallbackGeometry {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let cx = self.center.x - ox;
|
||||
let cy = self.center.y - oy;
|
||||
let cz = self.center.z - oz;
|
||||
let cx = self.center.x;
|
||||
let cy = self.center.y;
|
||||
let cz = self.center.z;
|
||||
let hw = self.width / 2.0;
|
||||
let hh = self.height / 2.0;
|
||||
let pts = vec![
|
||||
|
|
|
|||
25
src/scene/cache/block_cache.rs
vendored
25
src/scene/cache/block_cache.rs
vendored
|
|
@ -423,7 +423,7 @@ fn build_nested_ref(
|
|||
// its clip when the parent block is expanded — the spatial filter object
|
||||
// isn't reachable at expand time.
|
||||
let clip_poly = crate::scene::pick::xclip::insert_spatial_filter(doc, nested_ins)
|
||||
.map(|sf| crate::scene::pick::xclip::world_clip_polygon_f64(sf, nested_ins, [0.0; 3]));
|
||||
.map(|sf| crate::scene::pick::xclip::world_clip_polygon_f64(sf, nested_ins));
|
||||
|
||||
NestedRef {
|
||||
block_name: nested_ins.block_name.clone(),
|
||||
|
|
@ -481,7 +481,7 @@ fn tessellate_sub_local(
|
|||
// top-level MTEXT outside blocks the colour split is preserved via the
|
||||
// hot path in `tessellate_entity`.
|
||||
let mut wires_out = tessellate::tessellate(
|
||||
doc, h, sub, false, sub_color, pat_len, pat, lw_px, local_offset, anno_scale, None,
|
||||
doc, h, sub, false, sub_color, pat_len, pat, lw_px, anno_scale, None,
|
||||
);
|
||||
if wires_out.is_empty() {
|
||||
return None;
|
||||
|
|
@ -654,7 +654,6 @@ pub fn expand_insert(
|
|||
ins_pat: [f32; 8],
|
||||
ins_lw_px: f32,
|
||||
selected: bool,
|
||||
world_offset: [f64; 3],
|
||||
pslt_factor: f32,
|
||||
// World-space XY view AABB (with world_offset already subtracted, so the
|
||||
// comparison is in the same f32 space as emitted wires). `None` disables
|
||||
|
|
@ -674,7 +673,7 @@ pub fn expand_insert(
|
|||
let name = ins_handle.value().to_string();
|
||||
let mut batches = Batches::default();
|
||||
let mut visited: Vec<String> = Vec::with_capacity(8);
|
||||
let [ox, oy, _] = world_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
|
||||
// `defn.aabb_local` is in the defn's offset frame — re-add
|
||||
// `defn.local_offset` (f64) before transforming so the world AABB is
|
||||
|
|
@ -717,7 +716,6 @@ pub fn expand_insert(
|
|||
ins_pat,
|
||||
ins_lw_px,
|
||||
selected,
|
||||
world_offset,
|
||||
pslt_factor,
|
||||
view_aabb,
|
||||
world_per_pixel,
|
||||
|
|
@ -744,7 +742,7 @@ fn emit_greeked_text(
|
|||
ctx: &ExpandCtx,
|
||||
out: &mut Batches,
|
||||
) {
|
||||
let [ox, oy, oz] = ctx.world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let [lo_x, lo_y, lo_z] = defn_lo;
|
||||
// Re-add the defn's `local_offset` in f64 before composing with
|
||||
// `accum_xform` so the rect corners share the batch's f32 space
|
||||
|
|
@ -879,7 +877,7 @@ fn emit_text_baseline(
|
|||
if h_local <= 0.0 {
|
||||
return;
|
||||
}
|
||||
let [ox, oy, oz] = ctx.world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let [lo_x, lo_y, lo_z] = defn_lo;
|
||||
let xf = |p: [f32; 3]| -> [f32; 3] {
|
||||
let w = accum_xform.apply(Vector3::new(
|
||||
|
|
@ -1001,7 +999,6 @@ struct ExpandCtx<'a> {
|
|||
ins_pat: [f32; 8],
|
||||
ins_lw_px: f32,
|
||||
selected: bool,
|
||||
world_offset: [f64; 3],
|
||||
pslt_factor: f32,
|
||||
// World-space XY view AABB (post world_offset). `None` = no culling.
|
||||
view_aabb: Option<[f32; 4]>,
|
||||
|
|
@ -1219,7 +1216,7 @@ fn expand_defn(
|
|||
// `defn_lo` (in f64) before composing with `accum_xform`
|
||||
// so culling uses correct world-space corners.
|
||||
let world = transform_offset_aabb_xy(lw.aabb_local, defn_lo, accum_xform);
|
||||
let [ox, oy, _] = ctx.world_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
let local = [
|
||||
world[0] - ox as f32,
|
||||
world[1] - oy as f32,
|
||||
|
|
@ -1282,7 +1279,7 @@ fn expand_defn(
|
|||
nested_defn.local_offset,
|
||||
&composed,
|
||||
);
|
||||
let [ox, oy, _] = ctx.world_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
let local = [
|
||||
world[0] - ox as f32,
|
||||
world[1] - oy as f32,
|
||||
|
|
@ -1322,7 +1319,6 @@ fn expand_defn(
|
|||
ins_pat: nested_pat,
|
||||
ins_lw_px: nested_lw_px,
|
||||
selected: ctx.selected,
|
||||
world_offset: ctx.world_offset,
|
||||
pslt_factor: ctx.pslt_factor,
|
||||
view_aabb: ctx.view_aabb,
|
||||
world_per_pixel: ctx.world_per_pixel,
|
||||
|
|
@ -1387,7 +1383,7 @@ fn emit_wire(
|
|||
if lw.points.is_empty() && lw.fill_tris.is_empty() {
|
||||
return;
|
||||
}
|
||||
let [ox, oy, oz] = ctx.world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let [lo_x, lo_y, lo_z] = defn_lo;
|
||||
|
||||
// Resolve final style for this LocalWire against the outer Insert ctx
|
||||
|
|
@ -1521,7 +1517,7 @@ fn emit_wire(
|
|||
for tg in &lw.tangent_geoms {
|
||||
entry
|
||||
.tangent_geoms
|
||||
.push(transform_tangent(tg, accum_xform, defn_lo, [ox, oy, oz]));
|
||||
.push(transform_tangent(tg, accum_xform, defn_lo));
|
||||
}
|
||||
for p in &lw.fill_tris {
|
||||
let v = accum_xform.apply(Vector3::new(
|
||||
|
|
@ -1540,9 +1536,8 @@ fn transform_tangent(
|
|||
tg: &TangentGeom,
|
||||
t: &Transform,
|
||||
defn_lo: [f64; 3],
|
||||
woff: [f64; 3],
|
||||
) -> TangentGeom {
|
||||
let [ox, oy, oz] = woff;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let [lo_x, lo_y, lo_z] = defn_lo;
|
||||
match tg {
|
||||
TangentGeom::Line { p1, p2 } => {
|
||||
|
|
|
|||
|
|
@ -43,13 +43,12 @@ fn split_ds_xyz(x: f64, y: f64, z: f64) -> ([f32; 3], [f32; 3]) {
|
|||
([xh, yh, zh], [xl, yl, zl])
|
||||
}
|
||||
|
||||
/// Subtract `world_offset` from each f64 source point and split the residual
|
||||
/// into double-single (high, low) f32 buffers in one pass.
|
||||
fn offset_to_ds(
|
||||
/// Split each absolute f64 source point into double-single (high, low) f32
|
||||
/// buffers in one pass — the relative-to-eye residual the GPU/CPU reconstruct
|
||||
/// to f64 precision at UTM-scale coordinates.
|
||||
fn points_to_ds(
|
||||
src: impl IntoIterator<Item = [f64; 3]>,
|
||||
world_offset: [f64; 3],
|
||||
) -> (Vec<[f32; 3]>, Vec<[f32; 3]>) {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let it = src.into_iter();
|
||||
let (lo, hi) = it.size_hint();
|
||||
let cap = hi.unwrap_or(lo);
|
||||
|
|
@ -62,7 +61,7 @@ fn offset_to_ds(
|
|||
low.push([0.0; 3]);
|
||||
continue;
|
||||
}
|
||||
let (h, l) = split_ds_xyz(x - ox, y - oy, z - oz);
|
||||
let (h, l) = split_ds_xyz(x, y, z);
|
||||
high.push(h);
|
||||
low.push(l);
|
||||
}
|
||||
|
|
@ -85,7 +84,6 @@ pub fn tessellate(
|
|||
pattern_length: f32,
|
||||
pattern: [f32; 8],
|
||||
line_weight_px: f32,
|
||||
world_offset: [f64; 3],
|
||||
anno_scale: f32,
|
||||
world_per_pixel: Option<f32>,
|
||||
) -> Vec<WireModel> {
|
||||
|
|
@ -127,7 +125,6 @@ pub fn tessellate(
|
|||
selected,
|
||||
entity_color,
|
||||
line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
)];
|
||||
}
|
||||
|
|
@ -148,7 +145,7 @@ pub fn tessellate(
|
|||
// single MTEXT can hand back N colour-distinct wires when the
|
||||
// value mixes inline colours.
|
||||
TruckObject::Text(stroke_groups) => {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let entity_zf = entity_z(entity) as f64;
|
||||
let elev_v = entity_zf - oz;
|
||||
|
||||
|
|
@ -212,7 +209,7 @@ pub fn tessellate(
|
|||
}
|
||||
}
|
||||
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let snap_pts = te.snap_pts;
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
|
|
@ -287,12 +284,12 @@ pub fn tessellate(
|
|||
|
||||
// ── Standard topology objects ─────────────────────────────────
|
||||
TruckObject::Point(v) => {
|
||||
let result = tessellate_vertex(&v, world_offset);
|
||||
let result = tessellate_vertex(&v);
|
||||
match result {
|
||||
TruckTessResult::Point([x, y, z], [xl, yl, zl]) => {
|
||||
let s = 0.1_f32;
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let snap_pts = te.snap_pts;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
|
|
@ -333,10 +330,10 @@ pub fn tessellate(
|
|||
|
||||
TruckObject::Curve(e) => {
|
||||
if let TruckTessResult::Lines(points, points_low) =
|
||||
tessellate_edge(&e, world_offset)
|
||||
tessellate_edge(&e)
|
||||
{
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let snap_pts = te.snap_pts;
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
|
|
@ -366,10 +363,10 @@ pub fn tessellate(
|
|||
|
||||
TruckObject::Contour(w) => {
|
||||
if let TruckTessResult::Lines(points, points_low) =
|
||||
tessellate_wire(&w, world_offset)
|
||||
tessellate_wire(&w)
|
||||
{
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let snap_pts = te.snap_pts;
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
|
|
@ -404,15 +401,15 @@ pub fn tessellate(
|
|||
// GPU shader pairs them so drawings at large UTM-style
|
||||
// coordinates keep sub-unit precision in the wire model and
|
||||
// don't jitter on camera movement.
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let (local_pts, local_pts_low) = offset_to_ds(points, world_offset);
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let (local_pts, local_pts_low) = points_to_ds(points);
|
||||
let snap_pts = te.snap_pts;
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
.map(|[x, y, z]| [x - ox, y - oy, z - oz])
|
||||
.collect();
|
||||
let (fill_tris, fill_tris_low) = offset_to_ds(te.fill_tris, world_offset);
|
||||
let (fill_tris, fill_tris_low) = points_to_ds(te.fill_tris);
|
||||
return vec![WireModel {
|
||||
name,
|
||||
points: local_pts,
|
||||
|
|
@ -435,9 +432,9 @@ pub fn tessellate(
|
|||
}
|
||||
|
||||
TruckObject::SegmentedLines(points) => {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let (local_pts, local_pts_low) = offset_to_ds(points, world_offset);
|
||||
let snap_pts = offset_snap_pts(te.snap_pts, world_offset);
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let (local_pts, local_pts_low) = points_to_ds(points);
|
||||
let snap_pts = te.snap_pts;
|
||||
let key_vertices: Vec<[f64; 3]> = te
|
||||
.key_vertices
|
||||
.into_iter()
|
||||
|
|
@ -470,10 +467,10 @@ pub fn tessellate(
|
|||
// 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, world_offset);
|
||||
let wire_pts = solid_wire_fallback(entity);
|
||||
let mut wm = WireModel::solid_f64(name, wire_pts, color, selected);
|
||||
// Add insertion snap at point_of_reference.
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
if let Some(p) = crate::entities::solid3d::point_of_reference(entity) {
|
||||
let sp = glam::DVec3::new(p.x - ox, p.y - oy, p.z - oz);
|
||||
wm.snap_pts.push((sp, SnapHint::Insertion));
|
||||
|
|
@ -485,7 +482,7 @@ pub fn tessellate(
|
|||
|
||||
// ── Fallback for Viewport / Insert / Hatch / Ole2Frame ────────────────
|
||||
let (points_f64, snap_pts, tangent_geoms, key_vertices) =
|
||||
fallback_geometry(entity, world_offset);
|
||||
fallback_geometry(entity);
|
||||
// `points_f64` are absolute world coords; split into the double-single
|
||||
// high/low pair so the outline reconstructs to f64 precision at UTM scale
|
||||
// (a NaN separator stays NaN in both buffers).
|
||||
|
|
@ -691,12 +688,12 @@ pub(crate) fn entity_z(entity: &EntityType) -> f32 {
|
|||
use crate::entities::traits::FallbackTess;
|
||||
use crate::scene::convert::tess_util::FallbackGeometry as Geometry;
|
||||
|
||||
fn fallback_geometry(entity: &EntityType, world_offset: [f64; 3]) -> Geometry {
|
||||
fn fallback_geometry(entity: &EntityType) -> Geometry {
|
||||
match entity {
|
||||
EntityType::Viewport(vp) => vp.fallback_geometry(world_offset),
|
||||
EntityType::Insert(ins) => ins.fallback_geometry(world_offset),
|
||||
EntityType::Hatch(h) => h.fallback_geometry(world_offset),
|
||||
EntityType::Ole2Frame(ole) => ole.fallback_geometry(world_offset),
|
||||
EntityType::Viewport(vp) => vp.fallback_geometry(),
|
||||
EntityType::Insert(ins) => ins.fallback_geometry(),
|
||||
EntityType::Hatch(h) => h.fallback_geometry(),
|
||||
EntityType::Ole2Frame(ole) => ole.fallback_geometry(),
|
||||
// Modeler solids render as meshes (solid3d_tess). Their wire path
|
||||
// contributes only the pre-computed edge wires (empty for binary SAB)
|
||||
// plus an insertion snap — never the placeholder segment below, which
|
||||
|
|
@ -706,10 +703,10 @@ fn fallback_geometry(entity: &EntityType, world_offset: [f64; 3]) -> Geometry {
|
|||
| EntityType::Region(_)
|
||||
| EntityType::Body(_)
|
||||
| EntityType::Surface(_) => {
|
||||
let pts = solid_wire_fallback(entity, world_offset);
|
||||
let pts = solid_wire_fallback(entity);
|
||||
let mut snap = vec![];
|
||||
if let Some(p) = crate::entities::solid3d::point_of_reference(entity) {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
snap.push((
|
||||
Vec3::new((p.x - ox) as f32, (p.y - oy) as f32, (p.z - oz) as f32),
|
||||
SnapHint::Insertion,
|
||||
|
|
@ -729,8 +726,8 @@ fn fallback_geometry(entity: &EntityType, world_offset: [f64; 3]) -> Geometry {
|
|||
/// 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, world_offset: [f64; 3]) -> Vec<[f64; 3]> {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
fn solid_wire_fallback(entity: &EntityType) -> Vec<[f64; 3]> {
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let Some(wires) = crate::entities::solid3d::fallback_wires(entity) else {
|
||||
return vec![];
|
||||
};
|
||||
|
|
@ -878,16 +875,6 @@ pub(crate) fn add_polyline(points: &mut Vec<[f32; 3]>, polyline: &[Vec3]) {
|
|||
points.extend(polyline.iter().map(|p| [p.x, p.y, p.z]));
|
||||
}
|
||||
|
||||
pub(crate) fn offset_snap_pts(
|
||||
pts: Vec<(glam::DVec3, SnapHint)>,
|
||||
off: [f64; 3],
|
||||
) -> Vec<(glam::DVec3, SnapHint)> {
|
||||
let [ox, oy, oz] = off;
|
||||
pts.into_iter()
|
||||
.map(|(p, h)| (glam::DVec3::new(p.x - ox, p.y - oy, p.z - oz), h))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Returns the text position of a dimension in DXF world-space (f64, no offset applied).
|
||||
/// Used when building a synthetic Text entity so tessellate() can apply world_offset itself.
|
||||
/// When the saved `text_middle_point` is zero (i.e. AutoCAD never wrote one),
|
||||
|
|
|
|||
|
|
@ -94,11 +94,11 @@ pub enum TruckTessResult {
|
|||
/// before truncating. This preserves sub-unit decimal precision even when the
|
||||
/// raw world coordinates are in the millions (e.g. Turkish UTM).
|
||||
#[inline]
|
||||
fn to_local(x: f64, y: f64, z: f64, off: [f64; 3]) -> [f32; 3] {
|
||||
fn to_local(x: f64, y: f64, z: f64) -> [f32; 3] {
|
||||
[
|
||||
(x - off[0]) as f32,
|
||||
(y - off[1]) as f32,
|
||||
(z - off[2]) as f32,
|
||||
x as f32,
|
||||
y as f32,
|
||||
z as f32,
|
||||
]
|
||||
}
|
||||
|
||||
|
|
@ -106,26 +106,26 @@ fn to_local(x: f64, y: f64, z: f64, off: [f64; 3]) -> [f32; 3] {
|
|||
/// with the high half so the double-single shader path reconstructs the f64
|
||||
/// source even when the high half is quantized to half a metre at UTM scale.
|
||||
#[inline]
|
||||
fn to_local_low(x: f64, y: f64, z: f64, off: [f64; 3], hi: [f32; 3]) -> [f32; 3] {
|
||||
fn to_local_low(x: f64, y: f64, z: f64, hi: [f32; 3]) -> [f32; 3] {
|
||||
[
|
||||
((x - off[0]) - hi[0] as f64) as f32,
|
||||
((y - off[1]) - hi[1] as f64) as f32,
|
||||
((z - off[2]) - hi[2] as f64) as f32,
|
||||
(x - hi[0] as f64) as f32,
|
||||
(y - hi[1] as f64) as f32,
|
||||
(z - hi[2] as f64) as f32,
|
||||
]
|
||||
}
|
||||
|
||||
// ── Vertex ────────────────────────────────────────────────────────────────
|
||||
|
||||
pub fn tessellate_vertex(v: &Vertex, offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_vertex(v: &Vertex) -> TruckTessResult {
|
||||
let p = v.point();
|
||||
let hi = to_local(p.x, p.y, p.z, offset);
|
||||
let lo = to_local_low(p.x, p.y, p.z, offset, hi);
|
||||
let hi = to_local(p.x, p.y, p.z);
|
||||
let lo = to_local_low(p.x, p.y, p.z, hi);
|
||||
TruckTessResult::Point(hi, lo)
|
||||
}
|
||||
|
||||
// ── Edge ──────────────────────────────────────────────────────────────────
|
||||
|
||||
pub fn tessellate_edge(e: &Edge, offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_edge(e: &Edge) -> TruckTessResult {
|
||||
// oriented_curve() respects the edge direction (inverts if needed).
|
||||
let curve = e.oriented_curve();
|
||||
let (t0, t1) = curve.range_tuple();
|
||||
|
|
@ -136,8 +136,8 @@ pub fn tessellate_edge(e: &Edge, offset: [f64; 3]) -> TruckTessResult {
|
|||
let mut high: Vec<[f32; 3]> = Vec::with_capacity(pts.len());
|
||||
let mut low: Vec<[f32; 3]> = Vec::with_capacity(pts.len());
|
||||
for p in &pts {
|
||||
let hi = to_local(p.x, p.y, p.z, offset);
|
||||
let lo = to_local_low(p.x, p.y, p.z, offset, hi);
|
||||
let hi = to_local(p.x, p.y, p.z);
|
||||
let lo = to_local_low(p.x, p.y, p.z, hi);
|
||||
high.push(hi);
|
||||
low.push(lo);
|
||||
}
|
||||
|
|
@ -146,11 +146,11 @@ pub fn tessellate_edge(e: &Edge, offset: [f64; 3]) -> TruckTessResult {
|
|||
|
||||
// ── Wire ──────────────────────────────────────────────────────────────────
|
||||
|
||||
pub fn tessellate_wire(w: &Wire, offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_wire(w: &Wire) -> TruckTessResult {
|
||||
let mut high: Vec<[f32; 3]> = Vec::new();
|
||||
let mut low: Vec<[f32; 3]> = Vec::new();
|
||||
for edge in w.edge_iter() {
|
||||
if let TruckTessResult::Lines(eh, el) = tessellate_edge(edge, offset) {
|
||||
if let TruckTessResult::Lines(eh, el) = tessellate_edge(edge) {
|
||||
if high.is_empty() {
|
||||
high = eh;
|
||||
low = el;
|
||||
|
|
@ -169,14 +169,14 @@ pub fn tessellate_wire(w: &Wire, offset: [f64; 3]) -> TruckTessResult {
|
|||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(feature = "solid3d")]
|
||||
pub fn tessellate_shell(s: &Shell, offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_shell(s: &Shell) -> TruckTessResult {
|
||||
let meshed = s.triangulation(MESH_TOL);
|
||||
polygon_to_result(meshed.to_polygon(), offset)
|
||||
polygon_to_result(meshed.to_polygon())
|
||||
}
|
||||
|
||||
/// Without `solid3d` (e.g. wasm) there is no mesher; a shell yields no mesh.
|
||||
#[cfg(not(feature = "solid3d"))]
|
||||
pub fn tessellate_shell(_s: &Shell, _offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_shell(_s: &Shell) -> TruckTessResult {
|
||||
TruckTessResult::Mesh {
|
||||
verts: Vec::new(),
|
||||
verts_low: Vec::new(),
|
||||
|
|
@ -189,15 +189,15 @@ pub fn tessellate_shell(_s: &Shell, _offset: [f64; 3]) -> TruckTessResult {
|
|||
|
||||
#[allow(dead_code)]
|
||||
#[cfg(feature = "solid3d")]
|
||||
pub fn tessellate_solid(s: &Solid, offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_solid(s: &Solid) -> TruckTessResult {
|
||||
let meshed = s.triangulation(MESH_TOL);
|
||||
polygon_to_result(meshed.to_polygon(), offset)
|
||||
polygon_to_result(meshed.to_polygon())
|
||||
}
|
||||
|
||||
/// Without `solid3d` (e.g. wasm) there is no mesher; a solid yields no mesh.
|
||||
#[allow(dead_code)]
|
||||
#[cfg(not(feature = "solid3d"))]
|
||||
pub fn tessellate_solid(_s: &Solid, _offset: [f64; 3]) -> TruckTessResult {
|
||||
pub fn tessellate_solid(_s: &Solid) -> TruckTessResult {
|
||||
TruckTessResult::Mesh {
|
||||
verts: Vec::new(),
|
||||
verts_low: Vec::new(),
|
||||
|
|
@ -209,13 +209,13 @@ pub fn tessellate_solid(_s: &Solid, _offset: [f64; 3]) -> TruckTessResult {
|
|||
// ── Internal ─────────────────────────────────────────────────────────────
|
||||
|
||||
#[cfg(feature = "solid3d")]
|
||||
fn polygon_to_result(mesh: PolygonMesh, offset: [f64; 3]) -> TruckTessResult {
|
||||
fn polygon_to_result(mesh: PolygonMesh) -> TruckTessResult {
|
||||
let positions = mesh.positions();
|
||||
let mut verts: Vec<[f32; 3]> = Vec::with_capacity(positions.len());
|
||||
let mut verts_low: Vec<[f32; 3]> = Vec::with_capacity(positions.len());
|
||||
for p in positions.iter() {
|
||||
let hi = to_local(p.x, p.y, p.z, offset);
|
||||
verts_low.push(to_local_low(p.x, p.y, p.z, offset, hi));
|
||||
let hi = to_local(p.x, p.y, p.z);
|
||||
verts_low.push(to_local_low(p.x, p.y, p.z, hi));
|
||||
verts.push(hi);
|
||||
}
|
||||
|
||||
|
|
|
|||
222
src/scene/mod.rs
222
src/scene/mod.rs
|
|
@ -196,17 +196,11 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
|||
.par_iter()
|
||||
.filter_map(|&handle| {
|
||||
let e = doc.get_entity(handle)?;
|
||||
let owner = e.common().owner_handle;
|
||||
let offset = if owner == model_block {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let (raw, ..) = view::render::render_style_for(doc, e);
|
||||
let color = view::render::adapt_to_bg(raw, LOAD_BG);
|
||||
let model = match e {
|
||||
EntityType::Hatch(dxf) => Scene::hatch_model_from_dxf(dxf, color, offset),
|
||||
EntityType::Solid(solid) => Some(Scene::solid_hatch_model(solid, color, offset)),
|
||||
EntityType::Hatch(dxf) => Scene::hatch_model_from_dxf(dxf, color),
|
||||
EntityType::Solid(solid) => Some(Scene::solid_hatch_model(solid, color)),
|
||||
_ => None,
|
||||
};
|
||||
model.map(|m| (handle, m))
|
||||
|
|
@ -218,7 +212,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
|||
.par_iter()
|
||||
.filter_map(|&handle| {
|
||||
if let EntityType::RasterImage(img) = doc.get_entity(handle)? {
|
||||
ImageModel::from_raster_image(img, [0.0_f64; 3]).map(|m| (handle, m))
|
||||
ImageModel::from_raster_image(img).map(|m| (handle, m))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -251,7 +245,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
|
|||
let color = view::render::adapt_to_bg(raw, LOAD_BG);
|
||||
let top_level = layout_blocks.contains(&e.common().owner_handle);
|
||||
crate::entities::solid3d::tessellate_volume(e, color, facet_res).map(|m| {
|
||||
let m = if top_level { offset_mesh_lod_set(m, [0.0_f64; 3]) } else { m };
|
||||
let m = if top_level { offset_mesh_lod_set(m) } else { m };
|
||||
(handle, m, top_level)
|
||||
})
|
||||
})
|
||||
|
|
@ -554,8 +548,8 @@ fn overlap_len(a: (f32, f32), b: (f32, f32)) -> f32 {
|
|||
/// origins would otherwise float far away from the rest of the
|
||||
/// geometry. Also recomputes `world_aabb` so per-frame LOD / cull math
|
||||
/// uses the same space.
|
||||
fn offset_mesh_lod_set(mut set: MeshLodSet, world_offset: [f64; 3]) -> MeshLodSet {
|
||||
let [ox, oy, oz] = world_offset;
|
||||
fn offset_mesh_lod_set(mut set: MeshLodSet) -> MeshLodSet {
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let mut min_x = f32::INFINITY;
|
||||
let mut min_y = f32::INFINITY;
|
||||
let mut max_x = f32::NEG_INFINITY;
|
||||
|
|
@ -596,10 +590,9 @@ fn offset_mesh_lod_set(mut set: MeshLodSet, world_offset: [f64; 3]) -> MeshLodSe
|
|||
fn transform_block_mesh_lod_set(
|
||||
set: &MeshLodSet,
|
||||
xform: &acadrust::types::Transform,
|
||||
world_offset: [f64; 3],
|
||||
) -> MeshLodSet {
|
||||
use acadrust::types::Vector3;
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let mut out = set.clone();
|
||||
let mut min_x = f32::INFINITY;
|
||||
let mut min_y = f32::INFINITY;
|
||||
|
|
@ -2318,7 +2311,6 @@ impl Scene {
|
|||
if self.block_meshes.is_empty() {
|
||||
return Vec::new();
|
||||
}
|
||||
let woff = [0.0_f64; 3];
|
||||
let mut out = Vec::new();
|
||||
for e in self.document.entities() {
|
||||
if e.common().owner_handle != layout_block {
|
||||
|
|
@ -2331,7 +2323,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
let start = out.len();
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, woff, &mut out);
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, &mut out);
|
||||
// Tag the instanced meshes with the parent INSERT handle so the
|
||||
// hover / selection highlight (keyed on the mesh name) tints the
|
||||
// block, not the inner solid's own handle which nothing selects.
|
||||
|
|
@ -2353,7 +2345,6 @@ impl Scene {
|
|||
block_name: &str,
|
||||
accum: &acadrust::types::Transform,
|
||||
depth: usize,
|
||||
woff: [f64; 3],
|
||||
out: &mut Vec<MeshLodSet>,
|
||||
) {
|
||||
if depth > 16 {
|
||||
|
|
@ -2374,9 +2365,9 @@ impl Scene {
|
|||
}
|
||||
if let EntityType::Insert(ins) = e {
|
||||
let composed = ins.get_transform().then(accum);
|
||||
self.expand_block_meshes(&ins.block_name, &composed, depth + 1, woff, out);
|
||||
self.expand_block_meshes(&ins.block_name, &composed, depth + 1, out);
|
||||
} else if let Some(set) = self.block_meshes.get(&h) {
|
||||
out.push(transform_block_mesh_lod_set(set, accum, woff));
|
||||
out.push(transform_block_mesh_lod_set(set, accum));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2425,11 +2416,6 @@ impl Scene {
|
|||
/// selectable; the click resolves to the Insert).
|
||||
pub fn insert_hatches_for_click(&self) -> Vec<(Handle, HatchModel)> {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let layer_hidden = |layer: &str| {
|
||||
self.document
|
||||
.layers
|
||||
|
|
@ -2464,7 +2450,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
let color = self.render_style(&EntityType::Hatch(dxf.clone())).0;
|
||||
if let Some(model) = Self::hatch_model_from_dxf(&dxf, color, hatch_offset) {
|
||||
if let Some(model) = Self::hatch_model_from_dxf(&dxf, color) {
|
||||
out.push((ins.common.handle, model));
|
||||
}
|
||||
}
|
||||
|
|
@ -2578,7 +2564,6 @@ impl Scene {
|
|||
let mut block_owned: Vec<(Handle, crate::scene::model::mesh_model::MeshModel)> = Vec::new();
|
||||
if !self.block_meshes.is_empty() {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let woff = [0.0_f64; 3];
|
||||
for e in self.document.entities() {
|
||||
if e.common().owner_handle != layout_block {
|
||||
continue;
|
||||
|
|
@ -2588,7 +2573,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
let mut sets = Vec::new();
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, woff, &mut sets);
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, &mut sets);
|
||||
for set in sets {
|
||||
if let Some(m) = set.lods.into_iter().next() {
|
||||
block_owned.push((ins.common.handle, m));
|
||||
|
|
@ -2621,7 +2606,6 @@ impl Scene {
|
|||
return Vec::new();
|
||||
}
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let woff = [0.0_f64; 3];
|
||||
let mut out = Vec::new();
|
||||
for e in self.document.entities() {
|
||||
if e.common().owner_handle != layout_block {
|
||||
|
|
@ -2632,7 +2616,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
let mut sets = Vec::new();
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, woff, &mut sets);
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, &mut sets);
|
||||
let hit = sets.iter().any(|set| {
|
||||
set.lods.first().map_or(false, |m| {
|
||||
!pick::hit_test::mesh_box_hit(
|
||||
|
|
@ -2667,7 +2651,6 @@ impl Scene {
|
|||
return Vec::new();
|
||||
}
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let woff = [0.0_f64; 3];
|
||||
let mut out = Vec::new();
|
||||
for e in self.document.entities() {
|
||||
if e.common().owner_handle != layout_block {
|
||||
|
|
@ -2678,7 +2661,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
let mut sets = Vec::new();
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, woff, &mut sets);
|
||||
self.expand_block_meshes(&ins.block_name, &ins.get_transform(), 0, &mut sets);
|
||||
let hit = sets.iter().any(|set| {
|
||||
set.lods.first().map_or(false, |m| {
|
||||
!pick::hit_test::mesh_poly_hit(
|
||||
|
|
@ -2860,11 +2843,6 @@ impl Scene {
|
|||
// `world_offset` subtraction even though `current_layout != "Model"`.
|
||||
// Decide based on the block being tessellated, not the layout.
|
||||
let is_model_block = block_handle == self.model_space_block_handle();
|
||||
let woff = if is_model_block {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let bg = if self.current_layout == "Model" {
|
||||
self.bg_color
|
||||
} else {
|
||||
|
|
@ -2918,9 +2896,6 @@ impl Scene {
|
|||
}
|
||||
}
|
||||
mix(anno.to_bits() as u64);
|
||||
for c in woff {
|
||||
mix(c.to_bits());
|
||||
}
|
||||
for c in bg {
|
||||
mix(c.to_bits() as u64);
|
||||
}
|
||||
|
|
@ -2952,7 +2927,7 @@ impl Scene {
|
|||
.map(|e| {
|
||||
let e: &EntityType = e;
|
||||
let w = tessellate_entity(
|
||||
doc, sel, avp, woff, bg, anno, e, Some(blk_ref), view_aabb, wpp,
|
||||
doc, sel, avp, bg, anno, e, Some(blk_ref), view_aabb, wpp,
|
||||
);
|
||||
(e.common().handle, Arc::new(w))
|
||||
})
|
||||
|
|
@ -2971,7 +2946,7 @@ impl Scene {
|
|||
.into_par_iter()
|
||||
.flat_map(|e| {
|
||||
tessellate_entity(
|
||||
doc, sel, avp, woff, bg, anno, e, Some(blk_ref), view_aabb, wpp,
|
||||
doc, sel, avp, bg, anno, e, Some(blk_ref), view_aabb, wpp,
|
||||
)
|
||||
})
|
||||
.collect()
|
||||
|
|
@ -3167,7 +3142,6 @@ impl Scene {
|
|||
&self.document,
|
||||
&self.selected,
|
||||
self.active_viewport,
|
||||
[0.0_f64; 3],
|
||||
bg,
|
||||
anno,
|
||||
e,
|
||||
|
|
@ -4150,22 +4124,17 @@ impl Scene {
|
|||
&entity,
|
||||
EntityType::Insert(_) | EntityType::Block(_) | EntityType::BlockEnd(_)
|
||||
);
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let hatch_seed = if let EntityType::Hatch(dxf) = &entity {
|
||||
let color = self.render_style(&entity).0;
|
||||
Self::hatch_model_from_dxf(dxf, color, hatch_offset)
|
||||
Self::hatch_model_from_dxf(dxf, color)
|
||||
} else if let EntityType::Solid(solid) = &entity {
|
||||
let color = self.render_style(&entity).0;
|
||||
Some(Self::solid_hatch_model(solid, color, hatch_offset))
|
||||
Some(Self::solid_hatch_model(solid, color))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let image_seed = if let EntityType::RasterImage(img) = &entity {
|
||||
ImageModel::from_raster_image(img, [0.0_f64; 3])
|
||||
ImageModel::from_raster_image(img)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -4175,9 +4144,8 @@ impl Scene {
|
|||
EntityType::Solid3D(_) | EntityType::Region(_) | EntityType::Body(_) | EntityType::Surface(_)
|
||||
) {
|
||||
let color = self.render_style(&entity).0;
|
||||
let woff = [0.0_f64; 3];
|
||||
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res)
|
||||
.map(|m| offset_mesh_lod_set(m, woff))
|
||||
.map(|m| offset_mesh_lod_set(m))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
@ -4442,11 +4410,6 @@ impl Scene {
|
|||
|
||||
fn synced_hatch_models(&self) -> Vec<HatchModel> {
|
||||
let layout_block = self.current_layout_block_handle();
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
|
||||
let layer_hidden = |layer: &str| {
|
||||
self.document
|
||||
|
|
@ -4543,7 +4506,7 @@ impl Scene {
|
|||
// XCLIP: clip this insert's exploded hatch fills to the boundary,
|
||||
// matching how the line geometry is clipped in expand_insert.
|
||||
let clip_poly = pick::xclip::insert_spatial_filter(&self.document, ins)
|
||||
.map(|sf| pick::xclip::world_clip_polygon(sf, ins, hatch_offset));
|
||||
.map(|sf| pick::xclip::world_clip_polygon(sf, ins));
|
||||
// Walk the full block tree: `explode_from_document` only descends
|
||||
// one level, so nested INSERTs are re-exploded here. Each level
|
||||
// bakes its transform into the children it returns, so nested
|
||||
|
|
@ -4571,7 +4534,7 @@ impl Scene {
|
|||
}
|
||||
let color = self.render_style(&EntityType::Hatch(dxf.clone())).0;
|
||||
if let Some(mut model) =
|
||||
Self::hatch_model_from_dxf(&dxf, color, hatch_offset)
|
||||
Self::hatch_model_from_dxf(&dxf, color)
|
||||
{
|
||||
if let Some(poly) = &clip_poly {
|
||||
let clipped = pick::xclip::clip_hatch_boundary(
|
||||
|
|
@ -4596,7 +4559,7 @@ impl Scene {
|
|||
}
|
||||
|
||||
// Wide LWPolyline and Polyline2D fills
|
||||
let [ox, oy, _] = hatch_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
let ox = ox as f32;
|
||||
let oy = oy as f32;
|
||||
for entity in self.document.entities() {
|
||||
|
|
@ -4655,7 +4618,6 @@ impl Scene {
|
|||
} else {
|
||||
self.bg_color
|
||||
};
|
||||
let model_block = self.model_space_block_handle();
|
||||
// No per-frame view-cull here: GPU wipeout buffer upload is
|
||||
// gated on geometry_epoch only (see render.rs), so any cull at
|
||||
// build time would freeze the visible subset at the geometry
|
||||
|
|
@ -4682,12 +4644,7 @@ impl Scene {
|
|||
// Per-entity world_offset selection so paper-layout content
|
||||
// viewports still see model-block wipeouts at the right local
|
||||
// coordinates (same rationale as hatches).
|
||||
let world_offset = if wo.common.owner_handle == model_block {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let boundary = Self::wipeout_boundary_2d(wo, world_offset);
|
||||
let boundary = Self::wipeout_boundary_2d(wo);
|
||||
if boundary.len() >= 3 {
|
||||
let mut fill_color = bg_color;
|
||||
if self.selected.contains(&wo.common.handle) {
|
||||
|
|
@ -4712,11 +4669,10 @@ impl Scene {
|
|||
/// Compute the 2D (XY) boundary polygon for a Wipeout entity.
|
||||
fn wipeout_boundary_2d(
|
||||
wo: &acadrust::entities::Wipeout,
|
||||
world_offset: [f64; 3],
|
||||
) -> Vec<[f32; 2]> {
|
||||
use acadrust::entities::WipeoutClipType;
|
||||
|
||||
let [wox, woy, _woz] = world_offset;
|
||||
let [wox, woy, _woz] = [0.0_f64; 3];
|
||||
let is_polygon = wo.clipping_enabled
|
||||
&& wo.clip_boundary_vertices.len() >= 3
|
||||
&& matches!(wo.clip_type, WipeoutClipType::Polygonal);
|
||||
|
|
@ -4780,9 +4736,8 @@ impl Scene {
|
|||
fn hatch_model_from_dxf(
|
||||
dxf: &DxfHatch,
|
||||
color: [f32; 4],
|
||||
world_offset: [f64; 3],
|
||||
) -> Option<HatchModel> {
|
||||
let [ox, oy, _oz] = world_offset;
|
||||
let [ox, oy, _oz] = [0.0_f64; 3];
|
||||
let normal = (dxf.normal.x, dxf.normal.y, dxf.normal.z);
|
||||
// Build the boundary in f64 first so the precision-preserving
|
||||
// origin computation below sees full WCS precision. We only cast
|
||||
|
|
@ -5126,7 +5081,7 @@ impl Scene {
|
|||
})
|
||||
.collect();
|
||||
for (handle, img) in entries {
|
||||
if let Some(model) = ImageModel::from_raster_image(&img, [0.0_f64; 3]) {
|
||||
if let Some(model) = ImageModel::from_raster_image(&img) {
|
||||
self.images.insert(handle, model);
|
||||
}
|
||||
}
|
||||
|
|
@ -5136,9 +5091,6 @@ impl Scene {
|
|||
pub fn populate_hatches_from_document(&mut self) {
|
||||
self.hatches.clear();
|
||||
|
||||
let model_block = self.model_space_block_handle();
|
||||
let world_offset = [0.0_f64; 3];
|
||||
|
||||
let entries: Vec<(Handle, EntityType)> = self
|
||||
.document
|
||||
.entities()
|
||||
|
|
@ -5154,21 +5106,14 @@ impl Scene {
|
|||
.into_par_iter()
|
||||
.filter_map(|(handle, kind)| {
|
||||
// Paper-space entities live in sheet coordinates — world_offset must not
|
||||
// be applied to them. Only model-space entities need the shift.
|
||||
let owner = kind.common().owner_handle;
|
||||
let offset = if owner == model_block {
|
||||
world_offset
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let model = match &kind {
|
||||
EntityType::Hatch(dxf) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&dxf.common.color);
|
||||
Self::hatch_model_from_dxf(dxf, color, offset)
|
||||
Self::hatch_model_from_dxf(dxf, color)
|
||||
}
|
||||
EntityType::Solid(solid) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&solid.common.color);
|
||||
Some(Self::solid_hatch_model(solid, color, offset))
|
||||
Some(Self::solid_hatch_model(solid, color))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
|
@ -5220,7 +5165,6 @@ impl Scene {
|
|||
|
||||
use crate::par::prelude::*;
|
||||
let facet_res = self.document.header.facet_resolution;
|
||||
let woff = [0.0_f64; 3];
|
||||
// Top-level solids: offset into the render frame, drawn flat.
|
||||
// Block-definition solids: keep block-local coords for per-INSERT
|
||||
// instancing (no offset applied here).
|
||||
|
|
@ -5228,7 +5172,7 @@ impl Scene {
|
|||
.into_par_iter()
|
||||
.filter_map(|(handle, entity, color, top_level)| {
|
||||
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res).map(|m| {
|
||||
let m = if top_level { offset_mesh_lod_set(m, woff) } else { m };
|
||||
let m = if top_level { offset_mesh_lod_set(m) } else { m };
|
||||
(handle, m, top_level)
|
||||
})
|
||||
})
|
||||
|
|
@ -5255,8 +5199,8 @@ impl Scene {
|
|||
/// Build a solid-fill HatchModel for a DXF Solid entity.
|
||||
/// DXF SOLID corners are in "Z-order": p0-p1 top, p2-p3 bottom.
|
||||
/// Visual quad is p0→p1→p3→p2 (closed).
|
||||
fn solid_hatch_model(solid: &DxfSolid, color: [f32; 4], world_offset: [f64; 3]) -> HatchModel {
|
||||
let [ox, oy, _oz] = world_offset;
|
||||
fn solid_hatch_model(solid: &DxfSolid, color: [f32; 4]) -> HatchModel {
|
||||
let [ox, oy, _oz] = [0.0_f64; 3];
|
||||
let boundary = vec![
|
||||
[
|
||||
(solid.first_corner.x - ox) as f32,
|
||||
|
|
@ -5298,13 +5242,8 @@ impl Scene {
|
|||
// already subtracted). The stored DXF entity must hold WCS, so add the
|
||||
// offset back — otherwise the boundary wire, re-projected through the
|
||||
// normal entity path, lands `world_offset` away from the fill.
|
||||
let off = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let wx = model.world_origin[0] + off[0];
|
||||
let wy = model.world_origin[1] + off[1];
|
||||
let wx = model.world_origin[0];
|
||||
let wy = model.world_origin[1];
|
||||
let verts: Vec<Vector2> = model
|
||||
.boundary
|
||||
.iter()
|
||||
|
|
@ -5840,11 +5779,6 @@ impl Scene {
|
|||
// ── Modify (transform / copy) ─────────────────────────────────────────
|
||||
|
||||
pub fn transform_entities(&mut self, handles: &[Handle], t: &EntityTransform) {
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
// MIRRTEXT (header.mirror_text): when false AutoCAD positions text /
|
||||
// mtext / shape by the mirror but keeps the original rotation +
|
||||
// oblique so the text stays right-reading. Capture before the
|
||||
|
|
@ -5907,12 +5841,12 @@ impl Scene {
|
|||
let existing_color = self.hatches[&h].color;
|
||||
let new_model = match self.document.get_entity(h) {
|
||||
Some(EntityType::Hatch(dxf)) => {
|
||||
Self::hatch_model_from_dxf(dxf, existing_color, hatch_offset)
|
||||
Self::hatch_model_from_dxf(dxf, existing_color)
|
||||
}
|
||||
// A DXF SOLID renders as a solid-fill hatch; rebuild it from
|
||||
// the moved corners so the fill follows the transform.
|
||||
Some(EntityType::Solid(s)) => {
|
||||
Some(Self::solid_hatch_model(s, existing_color, hatch_offset))
|
||||
Some(Self::solid_hatch_model(s, existing_color))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
|
@ -5990,11 +5924,6 @@ impl Scene {
|
|||
}
|
||||
|
||||
pub fn copy_entities(&mut self, handles: &[Handle], t: &EntityTransform) -> Vec<Handle> {
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
let clones: Vec<EntityType> = handles
|
||||
.iter()
|
||||
.filter_map(|&h| self.document.get_entity(h).cloned())
|
||||
|
|
@ -6009,11 +5938,11 @@ impl Scene {
|
|||
let new_model = match self.document.get_entity(h) {
|
||||
Some(EntityType::Hatch(dxf)) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&dxf.common.color);
|
||||
Self::hatch_model_from_dxf(dxf, color, hatch_offset)
|
||||
Self::hatch_model_from_dxf(dxf, color)
|
||||
}
|
||||
Some(EntityType::Solid(s)) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&s.common.color);
|
||||
Some(Self::solid_hatch_model(s, color, hatch_offset))
|
||||
Some(Self::solid_hatch_model(s, color))
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
|
@ -6073,15 +6002,10 @@ impl Scene {
|
|||
}
|
||||
|
||||
// Rebuild GPU hatch/solid model when a boundary vertex or corner moves.
|
||||
let hatch_offset = if self.current_layout == "Model" {
|
||||
[0.0_f64; 3]
|
||||
} else {
|
||||
[0.0; 3]
|
||||
};
|
||||
match self.document.get_entity(handle) {
|
||||
Some(EntityType::Hatch(dxf)) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&dxf.common.color);
|
||||
if let Some(model) = Self::hatch_model_from_dxf(dxf, color, hatch_offset) {
|
||||
if let Some(model) = Self::hatch_model_from_dxf(dxf, color) {
|
||||
self.hatches.insert(handle, model);
|
||||
} else {
|
||||
self.hatches.remove(&handle);
|
||||
|
|
@ -6090,7 +6014,7 @@ impl Scene {
|
|||
Some(EntityType::Solid(solid)) => {
|
||||
let color = convert::tess_util::aci_to_rgba(&solid.common.color);
|
||||
self.hatches
|
||||
.insert(handle, Self::solid_hatch_model(solid, color, hatch_offset));
|
||||
.insert(handle, Self::solid_hatch_model(solid, color));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -6204,7 +6128,7 @@ impl Scene {
|
|||
view: &acadrust::tables::View,
|
||||
model_space: bool,
|
||||
) -> bool {
|
||||
let offset = if model_space { [0.0_f64; 3] } else { [0.0; 3] };
|
||||
let _ = model_space;
|
||||
let Some(cam) = self.camera_from_view(
|
||||
view.direction,
|
||||
view.target,
|
||||
|
|
@ -6214,7 +6138,6 @@ impl Scene {
|
|||
},
|
||||
view.height,
|
||||
view.twist_angle,
|
||||
offset,
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
|
|
@ -6280,7 +6203,6 @@ impl Scene {
|
|||
// Subtracted from `view_target` to reach wire-space. Model views pass
|
||||
// `[0.0_f64; 3]`; paper-space views (whose entities carry no
|
||||
// offset) pass `[0; 3]`.
|
||||
world_offset: [f64; 3],
|
||||
) -> Option<Camera> {
|
||||
if view_height.abs() < 1e-9 {
|
||||
return None;
|
||||
|
|
@ -6317,9 +6239,9 @@ impl Scene {
|
|||
// jump on the f32 grid. The axis directions stay f32 (orientation only);
|
||||
// only the position must stay precise — matching the model camera.
|
||||
let base = glam::DVec3::new(
|
||||
view_target.x - world_offset[0],
|
||||
view_target.y - world_offset[1],
|
||||
view_target.z - world_offset[2],
|
||||
view_target.x,
|
||||
view_target.y,
|
||||
view_target.z,
|
||||
);
|
||||
let target = base
|
||||
+ view_right.as_dvec3() * view_center.x
|
||||
|
|
@ -6345,7 +6267,6 @@ impl Scene {
|
|||
vp.view_center,
|
||||
vp.view_height,
|
||||
vp.view_twist,
|
||||
[0.0_f64; 3],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -6607,7 +6528,6 @@ impl Scene {
|
|||
},
|
||||
vp.view_height,
|
||||
vp.twist_angle,
|
||||
[0.0; 3],
|
||||
) else {
|
||||
return false;
|
||||
};
|
||||
|
|
@ -7646,7 +7566,7 @@ impl Scene {
|
|||
continue;
|
||||
}
|
||||
// Paper-block wipeouts live in paper coords — no `world_offset`.
|
||||
let boundary = Self::wipeout_boundary_2d(wo, [0.0; 3]);
|
||||
let boundary = Self::wipeout_boundary_2d(wo);
|
||||
if boundary.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -7719,7 +7639,6 @@ impl Scene {
|
|||
},
|
||||
saved_h,
|
||||
vp.twist_angle,
|
||||
[0.0_f64; 3],
|
||||
) {
|
||||
let half_h = saved_h * 0.5;
|
||||
let half_w = half_h * aspect_d;
|
||||
|
|
@ -7746,7 +7665,6 @@ impl Scene {
|
|||
acadrust::types::Vector2::ZERO,
|
||||
fit_h,
|
||||
vp.twist_angle,
|
||||
[0.0_f64; 3],
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -8031,7 +7949,6 @@ pub(crate) fn tessellate_entity_dim_text(
|
|||
document: &acadrust::CadDocument,
|
||||
selected: &HashSet<Handle>,
|
||||
active_viewport: Option<Handle>,
|
||||
world_offset: [f64; 3],
|
||||
bg_color: [f32; 4],
|
||||
anno_scale: f32,
|
||||
e: &EntityType,
|
||||
|
|
@ -8040,7 +7957,7 @@ pub(crate) fn tessellate_entity_dim_text(
|
|||
text_color: [f32; 4],
|
||||
) -> Vec<WireModel> {
|
||||
let mut wires = tessellate_entity(
|
||||
document, selected, active_viewport, world_offset, bg_color,
|
||||
document, selected, active_viewport, bg_color,
|
||||
anno_scale, e, None, view_aabb, world_per_pixel,
|
||||
);
|
||||
for w in &mut wires {
|
||||
|
|
@ -8059,7 +7976,6 @@ fn tessellate_entity(
|
|||
document: &acadrust::CadDocument,
|
||||
selected: &HashSet<Handle>,
|
||||
active_viewport: Option<Handle>,
|
||||
world_offset: [f64; 3],
|
||||
bg_color: [f32; 4],
|
||||
anno_scale: f32,
|
||||
e: &EntityType,
|
||||
|
|
@ -8082,7 +7998,7 @@ fn tessellate_entity(
|
|||
match e {
|
||||
EntityType::Viewport(_) | EntityType::Insert(_) => {}
|
||||
_ => {
|
||||
let ab = entity_aabb(e, world_offset);
|
||||
let ab = entity_aabb(e);
|
||||
if ab != WireModel::UNBOUNDED_AABB {
|
||||
if let Some(view) = view_aabb {
|
||||
if cache::block_cache::aabb_disjoint_xy(ab, view) {
|
||||
|
|
@ -8129,7 +8045,7 @@ fn tessellate_entity(
|
|||
// and the geometry visibly shifts when
|
||||
// the camera crosses the LOD threshold.
|
||||
let bbox = e.as_entity().bounding_box();
|
||||
let oz = world_offset[2];
|
||||
let oz = 0.0_f64;
|
||||
let z_min = (bbox.min.z - oz) as f32;
|
||||
let z_max = (bbox.max.z - oz) as f32;
|
||||
return vec![lod_stub_wire_3d(
|
||||
|
|
@ -8189,11 +8105,10 @@ fn tessellate_entity(
|
|||
pattern_length,
|
||||
pattern,
|
||||
1.5,
|
||||
world_offset,
|
||||
1.0,
|
||||
world_per_pixel,
|
||||
);
|
||||
let ab = entity_aabb(e, world_offset);
|
||||
let ab = entity_aabb(e);
|
||||
for w in &mut wires {
|
||||
w.aabb = ab;
|
||||
}
|
||||
|
|
@ -8241,7 +8156,7 @@ fn tessellate_entity(
|
|||
let sub_color_is_byblock =
|
||||
sub.common().color == acadrust::types::Color::ByBlock;
|
||||
let sub_wires = tessellate_entity(
|
||||
document, selected, active_viewport, world_offset, bg_color,
|
||||
document, selected, active_viewport, bg_color,
|
||||
// Block contents are baked at the final WCS size —
|
||||
// don't let downstream paths re-apply anno_scale.
|
||||
1.0, sub, block_cache, view_aabb, world_per_pixel,
|
||||
|
|
@ -8260,7 +8175,7 @@ fn tessellate_entity(
|
|||
}
|
||||
}
|
||||
if !wires.is_empty() {
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
for w in &mut wires {
|
||||
w.aabb = aabb;
|
||||
}
|
||||
|
|
@ -8273,7 +8188,7 @@ fn tessellate_entity(
|
|||
}
|
||||
|
||||
if let EntityType::Dimension(dim) = e {
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
use crate::entities::dimension::DimensionTess;
|
||||
let mut wires = dim.tessellate(
|
||||
document,
|
||||
|
|
@ -8281,7 +8196,6 @@ fn tessellate_entity(
|
|||
sel,
|
||||
entity_color,
|
||||
line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
selected,
|
||||
active_viewport,
|
||||
|
|
@ -8297,7 +8211,7 @@ fn tessellate_entity(
|
|||
}
|
||||
|
||||
if let EntityType::MultiLeader(ml) = e {
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
use crate::entities::multileader::MultiLeaderTess;
|
||||
let mut wires = ml.tessellate(
|
||||
document,
|
||||
|
|
@ -8305,7 +8219,6 @@ fn tessellate_entity(
|
|||
sel,
|
||||
entity_color,
|
||||
line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
world_per_pixel,
|
||||
);
|
||||
|
|
@ -8340,7 +8253,7 @@ fn tessellate_entity(
|
|||
let sub_color_is_byblock =
|
||||
sub.common().color == acadrust::types::Color::ByBlock;
|
||||
let sub_wires = tessellate_entity(
|
||||
document, selected, active_viewport, world_offset, bg_color,
|
||||
document, selected, active_viewport, bg_color,
|
||||
anno_scale, sub, block_cache, view_aabb, world_per_pixel,
|
||||
);
|
||||
for mut w in sub_wires {
|
||||
|
|
@ -8353,7 +8266,7 @@ fn tessellate_entity(
|
|||
}
|
||||
}
|
||||
if !wires.is_empty() {
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
for w in &mut wires {
|
||||
w.aabb = aabb;
|
||||
}
|
||||
|
|
@ -8366,10 +8279,10 @@ fn tessellate_entity(
|
|||
// geometry from the rows + TableStyle so fills/colours/borders/margins
|
||||
// are honoured instead of the monochrome fallback.
|
||||
let mut wires = crate::entities::table::tessellate_table(
|
||||
tab, document, sel, entity_color, line_weight_px, world_offset,
|
||||
tab, document, sel, entity_color, line_weight_px,
|
||||
);
|
||||
if !wires.is_empty() {
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
for w in &mut wires {
|
||||
w.aci = aci;
|
||||
w.aabb = aabb;
|
||||
|
|
@ -8382,7 +8295,7 @@ fn tessellate_entity(
|
|||
// Resolve the INSERT's own style so ByBlock sub-entities can inherit it.
|
||||
let (ins_color, ins_pat_len, ins_pat, ins_lw_px, _) = view::render::render_style_for(document, e);
|
||||
let ins_color = view::render::adapt_to_bg(ins_color, bg_color);
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let [ox, oy, oz] = [0.0_f64; 3];
|
||||
let ip = glam::Vec3::new(
|
||||
(ins.insert_point.x - ox) as f32,
|
||||
(ins.insert_point.y - oy) as f32,
|
||||
|
|
@ -8425,7 +8338,6 @@ fn tessellate_entity(
|
|||
ins_pat,
|
||||
ins_lw_px,
|
||||
sel,
|
||||
world_offset,
|
||||
pslt_factor,
|
||||
view_aabb,
|
||||
world_per_pixel,
|
||||
|
|
@ -8436,7 +8348,7 @@ fn tessellate_entity(
|
|||
// clip the expanded block geometry to the boundary polygon so
|
||||
// only the portion inside the clip is drawn.
|
||||
if let Some(sf) = pick::xclip::insert_spatial_filter(document, ins) {
|
||||
let poly = pick::xclip::world_clip_polygon_f64(sf, ins, world_offset);
|
||||
let poly = pick::xclip::world_clip_polygon_f64(sf, ins);
|
||||
pick::xclip::clip_wires(&mut wires, &poly);
|
||||
}
|
||||
|
||||
|
|
@ -8459,7 +8371,6 @@ fn tessellate_entity(
|
|||
is_xref,
|
||||
pslt_factor,
|
||||
anno_scale,
|
||||
world_offset,
|
||||
);
|
||||
wires.push(marker);
|
||||
return wires;
|
||||
|
|
@ -8494,7 +8405,7 @@ fn tessellate_entity(
|
|||
} else {
|
||||
sub_color
|
||||
};
|
||||
let sub_aabb = entity_aabb(&sub, world_offset);
|
||||
let sub_aabb = entity_aabb(&sub);
|
||||
let sub_pattern_length = sub_pattern_length * pslt_factor;
|
||||
let sub_pattern = sub_pattern.map(|v| v * pslt_factor);
|
||||
let mut wires = convert::tessellate::tessellate(
|
||||
|
|
@ -8506,7 +8417,6 @@ fn tessellate_entity(
|
|||
sub_pattern_length,
|
||||
sub_pattern,
|
||||
sub_line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
world_per_pixel,
|
||||
);
|
||||
|
|
@ -8532,13 +8442,12 @@ fn tessellate_entity(
|
|||
is_xref,
|
||||
pslt_factor,
|
||||
anno_scale,
|
||||
world_offset,
|
||||
);
|
||||
wires.push(marker);
|
||||
return wires;
|
||||
}
|
||||
|
||||
let aabb = entity_aabb(e, world_offset);
|
||||
let aabb = entity_aabb(e);
|
||||
|
||||
// Text-specific LOD ladder, keyed off the entity's glyph height in
|
||||
// pixels (anno-scaled):
|
||||
|
|
@ -8575,7 +8484,7 @@ fn tessellate_entity(
|
|||
_ => 1,
|
||||
};
|
||||
if h_px < 1.0 {
|
||||
let pts = crate::entities::text_support::text_baseline_points(e, anno_scale, world_offset, n_lines);
|
||||
let pts = crate::entities::text_support::text_baseline_points(e, anno_scale, n_lines);
|
||||
if pts.len() < 2 {
|
||||
return vec![];
|
||||
}
|
||||
|
|
@ -8622,7 +8531,7 @@ fn tessellate_entity(
|
|||
}];
|
||||
}
|
||||
if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB {
|
||||
let fill_tris = crate::entities::text_support::text_greek_obb_tris(e, anno_scale, world_offset, n_lines);
|
||||
let fill_tris = crate::entities::text_support::text_greek_obb_tris(e, anno_scale, n_lines);
|
||||
if fill_tris.is_empty() {
|
||||
// Text greek fallback: also 2-D, keep stub at z=0.
|
||||
return vec![lod_stub_wire(
|
||||
|
|
@ -8672,7 +8581,6 @@ fn tessellate_entity(
|
|||
pattern_length,
|
||||
pattern,
|
||||
line_weight_px,
|
||||
world_offset,
|
||||
anno_scale,
|
||||
world_per_pixel,
|
||||
);
|
||||
|
|
@ -8836,9 +8744,9 @@ fn lod_stub_wire_3d(
|
|||
/// INSERT only stamps the geometry once, attribute text sits at the world
|
||||
/// position recorded on each ATTRIB. See #20.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn entity_aabb(e: &acadrust::EntityType, world_offset: [f64; 3]) -> [f32; 4] {
|
||||
pub(crate) fn entity_aabb(e: &acadrust::EntityType) -> [f32; 4] {
|
||||
let bbox = e.as_entity().bounding_box();
|
||||
let [ox, oy, _] = world_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
let min_x = (bbox.min.x - ox) as f32;
|
||||
let min_y = (bbox.min.y - oy) as f32;
|
||||
let max_x = (bbox.max.x - ox) as f32;
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ impl ImageModel {
|
|||
/// Returns `None` if the image file cannot be opened or decoded.
|
||||
pub fn from_raster_image(
|
||||
img: &acadrust::entities::RasterImage,
|
||||
world_offset: [f64; 3],
|
||||
) -> Option<Self> {
|
||||
let w = img.size.x;
|
||||
let h = img.size.y;
|
||||
|
|
@ -50,9 +49,9 @@ impl ImageModel {
|
|||
// Corners come from a large insertion point plus small u/v spans.
|
||||
// Split each into double-single (high, low) f32 so the GPU keeps
|
||||
// sub-unit precision at UTM scale and after a cross-drawing paste.
|
||||
let oxv = img.insertion_point.x - world_offset[0];
|
||||
let oyv = img.insertion_point.y - world_offset[1];
|
||||
let ozv = img.insertion_point.z - world_offset[2];
|
||||
let oxv = img.insertion_point.x;
|
||||
let oyv = img.insertion_point.y;
|
||||
let ozv = img.insertion_point.z;
|
||||
let ux = (img.u_vector.x * w) as f32;
|
||||
let uy = (img.u_vector.y * w) as f32;
|
||||
let uz = (img.u_vector.z * w) as f32;
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ pub fn edge_wires(solid: &Solid) -> Vec<acadrust::entities::Wire> {
|
|||
for shell in solid.boundaries() {
|
||||
for edge in shell.edge_iter() {
|
||||
if let TruckTessResult::Lines(pts, pts_low) =
|
||||
tessellate_edge(&edge, [0.0; 3])
|
||||
tessellate_edge(&edge)
|
||||
{
|
||||
if pts.len() < 2 {
|
||||
continue;
|
||||
|
|
@ -169,7 +169,7 @@ pub fn boolean(_op: Bool, _a: &Solid, _b: &Solid) -> Option<Solid> {
|
|||
/// before world_offset is applied by the caller).
|
||||
pub fn mesh_from_solid(solid: &Solid, color: [f32; 4]) -> Option<MeshLodSet> {
|
||||
use crate::scene::convert::truck_tess::{tessellate_solid, TruckTessResult};
|
||||
match tessellate_solid(solid, [0.0; 3]) {
|
||||
match tessellate_solid(solid) {
|
||||
TruckTessResult::Mesh {
|
||||
verts,
|
||||
verts_low,
|
||||
|
|
|
|||
|
|
@ -65,9 +65,8 @@ fn dict_entry(doc: &CadDocument, dict: Handle, key: &str) -> Option<Handle> {
|
|||
pub fn world_clip_polygon(
|
||||
sf: &SpatialFilter,
|
||||
ins: &Insert,
|
||||
world_offset: [f64; 3],
|
||||
) -> Vec<[f32; 2]> {
|
||||
world_clip_polygon_f64(sf, ins, world_offset)
|
||||
world_clip_polygon_f64(sf, ins)
|
||||
.into_iter()
|
||||
.map(|[x, y]| [x as f32, y as f32])
|
||||
.collect()
|
||||
|
|
@ -80,11 +79,10 @@ pub fn world_clip_polygon(
|
|||
pub fn world_clip_polygon_f64(
|
||||
sf: &SpatialFilter,
|
||||
ins: &Insert,
|
||||
world_offset: [f64; 3],
|
||||
) -> Vec<[f64; 2]> {
|
||||
let xform = ins.get_transform();
|
||||
let inv_block = &sf.inverse_block_transform;
|
||||
let [ox, oy, _] = world_offset;
|
||||
let [ox, oy, _] = [0.0_f64; 3];
|
||||
let local: Vec<[f64; 2]> = if sf.boundary_points.len() == 2 {
|
||||
let a = sf.boundary_points[0];
|
||||
let b = sf.boundary_points[1];
|
||||
|
|
|
|||
|
|
@ -162,10 +162,6 @@ impl Snapper {
|
|||
self.grid_snap_on = !self.grid_snap_on;
|
||||
}
|
||||
|
||||
pub fn set_grid_snap(&mut self, on: bool) {
|
||||
self.grid_snap_on = on;
|
||||
}
|
||||
|
||||
pub fn toggle(&mut self, t: SnapType) {
|
||||
if !self.enabled.remove(&t) {
|
||||
self.enabled.insert(t);
|
||||
|
|
|
|||
Loading…
Reference in a new issue