refactor(scene): remove the world_offset field (P7)

Delete the world_offset field from Scene and DerivedCaches and the
load-time assignment; every reader now uses a zero origin. Geometry is
absolute and the double-single relative-to-eye pipeline keeps it precise,
so the coarse origin is gone. world_offset_from_centers still derives
local_extent_max (camera/cull span) but returns no offset. The remaining
`world_offset: [f64;3]` function parameters are now always zero — dead
plumbing left for a later mechanical sweep; behaviour is unchanged.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-23 22:42:33 +03:00
commit ccc933e7b0
8 changed files with 61 additions and 68 deletions

View file

@ -610,7 +610,7 @@ impl OpenCADStudio {
// paste lands at the cursor instead of drifting by the // paste lands at the cursor instead of drifting by the
// offset gap. Zero for a same-drawing paste. (#135) // offset gap. Zero for a same-drawing paste. (#135)
let src_wo = self.clipboard_world_offset; let src_wo = self.clipboard_world_offset;
let tgt_wo = self.tabs[i].scene.world_offset; let tgt_wo = [0.0_f64; 3];
let wo_corr = glam::Vec3::new( let wo_corr = glam::Vec3::new(
(tgt_wo[0] - src_wo[0]) as f32, (tgt_wo[0] - src_wo[0]) as f32,
(tgt_wo[1] - src_wo[1]) as f32, (tgt_wo[1] - src_wo[1]) as f32,
@ -1262,7 +1262,7 @@ impl OpenCADStudio {
let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned(); let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned();
if let Some(entity) = entity_opt { if let Some(entity) = entity_opt {
let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document); let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document);
let woff = self.tabs[i].scene.world_offset; let woff = [0.0_f64; 3];
let result = truck_entity.and_then(|te| { let result = truck_entity.and_then(|te| {
match te.object { match te.object {
TruckObject::Contour(wire) => { TruckObject::Contour(wire) => {
@ -1330,7 +1330,7 @@ impl OpenCADStudio {
let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned(); let entity_opt = self.tabs[i].scene.document.get_entity(handle).cloned();
if let Some(entity) = entity_opt { if let Some(entity) = entity_opt {
let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document); let truck_entity = entity.to_truck_entity(&self.tabs[i].scene.document);
let woff = self.tabs[i].scene.world_offset; let woff = [0.0_f64; 3];
let result = truck_entity.and_then(|te| { let result = truck_entity.and_then(|te| {
let wire: Option<truck_modeling::Wire> = match te.object { let wire: Option<truck_modeling::Wire> = match te.object {
TruckObject::Contour(w) => Some(w), TruckObject::Contour(w) => Some(w),
@ -1410,7 +1410,7 @@ impl OpenCADStudio {
.get_entity(profile_handle) .get_entity(profile_handle)
.cloned(); .cloned();
let path_ent = self.tabs[i].scene.document.get_entity(path_handle).cloned(); let path_ent = self.tabs[i].scene.document.get_entity(path_handle).cloned();
let woff = self.tabs[i].scene.world_offset; let woff = [0.0_f64; 3];
let result = profile_ent.zip(path_ent).and_then(|(prof_e, path_e)| { 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)?; let prof_truck = prof_e.to_truck_entity(&self.tabs[i].scene.document)?;
@ -1577,7 +1577,7 @@ impl OpenCADStudio {
} }
} }
let woff = self.tabs[i].scene.world_offset; let woff = [0.0_f64; 3];
let result: Option<crate::scene::model::mesh_model::MeshModel> = (|| { let result: Option<crate::scene::model::mesh_model::MeshModel> = (|| {
if wires.len() < 2 { if wires.len() < 2 {
return None; return None;

View file

@ -540,7 +540,7 @@ impl OpenCADStudio {
self.clipboard_centroid = super::helpers::entities_centroid( self.clipboard_centroid = super::helpers::entities_centroid(
&self.tabs[i].scene.wire_models_for(&handles), &self.tabs[i].scene.wire_models_for(&handles),
); );
self.clipboard_world_offset = self.tabs[i].scene.world_offset; self.clipboard_world_offset = [0.0_f64; 3];
self.clipboard = entities; self.clipboard = entities;
self.clipboard_deps = super::ClipboardDeps::capture( self.clipboard_deps = super::ClipboardDeps::capture(
&self.tabs[i].scene.document, &self.tabs[i].scene.document,
@ -573,7 +573,7 @@ impl OpenCADStudio {
self.clipboard_centroid = super::helpers::entities_centroid( self.clipboard_centroid = super::helpers::entities_centroid(
&self.tabs[i].scene.wire_models_for(&handles), &self.tabs[i].scene.wire_models_for(&handles),
); );
self.clipboard_world_offset = self.tabs[i].scene.world_offset; self.clipboard_world_offset = [0.0_f64; 3];
let count = entities.len(); let count = entities.len();
self.clipboard = entities; self.clipboard = entities;
self.clipboard_deps = super::ClipboardDeps::capture( self.clipboard_deps = super::ClipboardDeps::capture(
@ -601,7 +601,7 @@ impl OpenCADStudio {
// so the ghost tracks the cursor instead of drifting by the // so the ghost tracks the cursor instead of drifting by the
// offset gap. Zero within one drawing. (#135) // offset gap. Zero within one drawing. (#135)
let src_wo = self.clipboard_world_offset; let src_wo = self.clipboard_world_offset;
let tgt_wo = self.tabs[i].scene.world_offset; let tgt_wo = [0.0_f64; 3];
let centroid = self.clipboard_centroid let centroid = self.clipboard_centroid
+ glam::Vec3::new( + glam::Vec3::new(
(src_wo[0] - tgt_wo[0]) as f32, (src_wo[0] - tgt_wo[0]) as f32,

View file

@ -203,7 +203,7 @@ impl DocumentTab {
return glam::Mat4::IDENTITY; return glam::Mat4::IDENTITY;
} }
let (o, x, y, z) = self.ucs_xform().axes(); let (o, x, y, z) = self.ucs_xform().axes();
let wo = self.scene.world_offset; let wo = [0.0_f64; 3];
let origin = glam::Vec3::new( let origin = glam::Vec3::new(
o.x - wo[0] as f32, o.x - wo[0] as f32,
o.y - wo[1] as f32, o.y - wo[1] as f32,
@ -236,7 +236,7 @@ impl DocumentTab {
} }
let xf = self.ucs_xform(); let xf = self.ucs_xform();
let (o, ..) = xf.axes(); let (o, ..) = xf.axes();
let wo = self.scene.world_offset; let wo = [0.0_f64; 3];
let origin = glam::Vec3::new( let origin = glam::Vec3::new(
o.x - wo[0] as f32, o.x - wo[0] as f32,
o.y - wo[1] as f32, o.y - wo[1] as f32,

View file

@ -395,7 +395,7 @@ impl super::OpenCADStudio {
let Some(ed) = self.mtext_editor.as_ref() else { return }; let Some(ed) = self.mtext_editor.as_ref() else { return };
let mt = ed.build_mtext(); let mt = ed.build_mtext();
let entity = EntityType::MText(mt.clone()); let entity = EntityType::MText(mt.clone());
let woff = self.tabs[i].scene.world_offset; let woff = [0.0_f64; 3];
let anno = self.tabs[i].scene.annotation_scale; let anno = self.tabs[i].scene.annotation_scale;
let wires: Vec<WireModel> = tessellate::tessellate( let wires: Vec<WireModel> = tessellate::tessellate(
&self.tabs[i].scene.document, &self.tabs[i].scene.document,

View file

@ -435,7 +435,7 @@ impl OpenCADStudio {
let wo = if is_paper { let wo = if is_paper {
[0.0f64; 3] [0.0f64; 3]
} else { } else {
self.tabs[i].scene.world_offset [0.0_f64; 3]
}; };
let (new_handle, new_grips) = { let (new_handle, new_grips) = {
let selected = self.tabs[i].scene.selected_entities(); let selected = self.tabs[i].scene.selected_entities();
@ -657,7 +657,7 @@ impl OpenCADStudio {
// DXF coordinate. Skip for paper-space entities (they use sheet mm coords). // DXF coordinate. Skip for paper-space entities (they use sheet mm coords).
let is_paper = self.tabs[i].scene.current_layout != "Model"; let is_paper = self.tabs[i].scene.current_layout != "Model";
if !is_paper { if !is_paper {
let wo = self.tabs[i].scene.world_offset; let wo = [0.0_f64; 3];
if wo[0] != 0.0 || wo[1] != 0.0 || wo[2] != 0.0 { if wo[0] != 0.0 || wo[1] != 0.0 || wo[2] != 0.0 {
let delta = acadrust::types::Vector3::new(wo[0], wo[1], wo[2]); let delta = acadrust::types::Vector3::new(wo[0], wo[1], wo[2]);
let t = acadrust::types::Transform::from_translation(delta); let t = acadrust::types::Transform::from_translation(delta);

View file

@ -633,7 +633,6 @@ impl OpenCADStudio {
)); ));
// Caches were built on the background thread inside open_path(). // Caches were built on the background thread inside open_path().
self.tabs[i].scene.world_offset = caches.world_offset;
self.tabs[i].scene.local_extent_max = caches.local_extent_max; self.tabs[i].scene.local_extent_max = caches.local_extent_max;
self.tabs[i].scene.hatches = caches.hatches; self.tabs[i].scene.hatches = caches.hatches;
self.tabs[i].scene.images = caches.images; self.tabs[i].scene.images = caches.images;
@ -2678,7 +2677,7 @@ impl OpenCADStudio {
// Paper-space entities use sheet coordinates (no world_offset). // Paper-space entities use sheet coordinates (no world_offset).
// Only add world_offset when converting local → DXF space in model space. // Only add world_offset when converting local → DXF space in model space.
let wo_vec = if self.tabs[i].scene.current_layout == "Model" { let wo_vec = if self.tabs[i].scene.current_layout == "Model" {
let wo = self.tabs[i].scene.world_offset; let wo = [0.0_f64; 3];
glam::Vec3::new(wo[0] as f32, wo[1] as f32, wo[2] as f32) glam::Vec3::new(wo[0] as f32, wo[1] as f32, wo[2] as f32)
} else { } else {
glam::Vec3::ZERO glam::Vec3::ZERO
@ -2930,7 +2929,7 @@ impl OpenCADStudio {
// offset-relative frame the renderer expects (model space // offset-relative frame the renderer expects (model space
// only; paper-space entities use sheet coordinates). // only; paper-space entities use sheet coordinates).
let wo_local = if self.tabs[i].scene.current_layout == "Model" { let wo_local = if self.tabs[i].scene.current_layout == "Model" {
self.tabs[i].scene.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -3526,7 +3525,7 @@ impl OpenCADStudio {
// TRIM/EXTEND/FILLET pick the wrong side on UTM-scale files. // TRIM/EXTEND/FILLET pick the wrong side on UTM-scale files.
let pick_wcs = { let pick_wcs = {
let wo = if self.tabs[i].scene.current_layout == "Model" { let wo = if self.tabs[i].scene.current_layout == "Model" {
self.tabs[i].scene.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };

View file

@ -144,7 +144,7 @@ impl OpenCADStudio {
(glam::Vec3::ZERO, (glam::Vec3::X, glam::Vec3::Y, glam::Vec3::Z)) (glam::Vec3::ZERO, (glam::Vec3::X, glam::Vec3::Y, glam::Vec3::Z))
} else { } else {
let (o, ux, uy, uz) = tab.ucs_xform().axes(); let (o, ux, uy, uz) = tab.ucs_xform().axes();
let wo = tab.scene.world_offset; let wo = [0.0_f64; 3];
let o_wire = glam::Vec3::new( let o_wire = glam::Vec3::new(
o.x - wo[0] as f32, o.x - wo[0] as f32,
o.y - wo[1] as f32, o.y - wo[1] as f32,
@ -901,7 +901,7 @@ impl OpenCADStudio {
let cursor_coord = { let cursor_coord = {
let lc = tab.last_cursor_world; let lc = tab.last_cursor_world;
if is_model { if is_model {
let wo = tab.scene.world_offset; let wo = [0.0_f64; 3];
let wcs = glam::Vec3::new( let wcs = glam::Vec3::new(
lc.x + wo[0] as f32, lc.x + wo[0] as f32,
lc.y + wo[1] as f32, lc.y + wo[1] as f32,

View file

@ -92,7 +92,6 @@ pub fn vp_effective_scale(custom_scale: f64, view_height: f64, vp_height: f64) -
/// Produced in the file-load background task so the UI thread only assigns. /// Produced in the file-load background task so the UI thread only assigns.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DerivedCaches { pub struct DerivedCaches {
pub world_offset: [f64; 3],
pub local_extent_max: f32, pub local_extent_max: f32,
pub hatches: HashMap<Handle, HatchModel>, pub hatches: HashMap<Handle, HatchModel>,
pub images: HashMap<Handle, ImageModel>, pub images: HashMap<Handle, ImageModel>,
@ -184,7 +183,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
centers.push(c); centers.push(c);
} }
} }
let (world_offset, local_extent_max) = world_offset_from_centers(centers, &doc.header); let (_world_offset, local_extent_max) = world_offset_from_centers(centers, &doc.header);
// Default bg adaptation target at load: the model background (paper // Default bg adaptation target at load: the model background (paper
// bg is only relevant after the user enters a paper layout, and // bg is only relevant after the user enters a paper layout, and
@ -199,7 +198,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
let e = doc.get_entity(handle)?; let e = doc.get_entity(handle)?;
let owner = e.common().owner_handle; let owner = e.common().owner_handle;
let offset = if owner == model_block { let offset = if owner == model_block {
world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -219,7 +218,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
.par_iter() .par_iter()
.filter_map(|&handle| { .filter_map(|&handle| {
if let EntityType::RasterImage(img) = doc.get_entity(handle)? { if let EntityType::RasterImage(img) = doc.get_entity(handle)? {
ImageModel::from_raster_image(img, world_offset).map(|m| (handle, m)) ImageModel::from_raster_image(img, [0.0_f64; 3]).map(|m| (handle, m))
} else { } else {
None None
} }
@ -252,7 +251,7 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
let color = view::render::adapt_to_bg(raw, LOAD_BG); let color = view::render::adapt_to_bg(raw, LOAD_BG);
let top_level = layout_blocks.contains(&e.common().owner_handle); let top_level = layout_blocks.contains(&e.common().owner_handle);
crate::entities::solid3d::tessellate_volume(e, color, facet_res).map(|m| { crate::entities::solid3d::tessellate_volume(e, color, facet_res).map(|m| {
let m = if top_level { offset_mesh_lod_set(m, world_offset) } else { m }; let m = if top_level { offset_mesh_lod_set(m, [0.0_f64; 3]) } else { m };
(handle, m, top_level) (handle, m, top_level)
}) })
}) })
@ -268,7 +267,6 @@ pub fn build_derived_caches(doc: &CadDocument) -> DerivedCaches {
} }
DerivedCaches { DerivedCaches {
world_offset,
local_extent_max, local_extent_max,
hatches, hatches,
images, images,
@ -861,9 +859,6 @@ pub struct Scene {
pub bg_color: [f32; 4], pub bg_color: [f32; 4],
/// Custom paper-space background fill color for Wipeout entities. /// Custom paper-space background fill color for Wipeout entities.
pub paper_bg_color: [f32; 4], pub paper_bg_color: [f32; 4],
/// Scene centroid subtracted from all coordinates before f32 conversion.
/// Eliminates f32 precision loss at large world coordinates (e.g. UTM 4,000,000 m).
pub world_offset: [f64; 3],
/// Largest local-space coordinate expected from real geometry, derived from /// Largest local-space coordinate expected from real geometry, derived from
/// EXTMIN/EXTMAX (10× safety margin). Used by fit_all() to ignore garbage /// EXTMIN/EXTMAX (10× safety margin). Used by fit_all() to ignore garbage
/// entity coordinates (origin-stuck entities, bad Ray/XLine direction vectors). /// entity coordinates (origin-stuck entities, bad Ray/XLine direction vectors).
@ -994,7 +989,6 @@ impl Scene {
active_viewport: None, active_viewport: None,
bg_color: [0.11, 0.11, 0.11, 1.0], bg_color: [0.11, 0.11, 0.11, 1.0],
paper_bg_color: [1.0, 1.0, 1.0, 1.0], paper_bg_color: [1.0, 1.0, 1.0, 1.0],
world_offset: [0.0; 3],
local_extent_max: 1e9, local_extent_max: 1e9,
annotation_scale: 1.0, annotation_scale: 1.0,
model_extents_cache: RefCell::new(None), model_extents_cache: RefCell::new(None),
@ -2324,7 +2318,7 @@ impl Scene {
if self.block_meshes.is_empty() { if self.block_meshes.is_empty() {
return Vec::new(); return Vec::new();
} }
let woff = self.world_offset; let woff = [0.0_f64; 3];
let mut out = Vec::new(); let mut out = Vec::new();
for e in self.document.entities() { for e in self.document.entities() {
if e.common().owner_handle != layout_block { if e.common().owner_handle != layout_block {
@ -2432,7 +2426,7 @@ impl Scene {
pub fn insert_hatches_for_click(&self) -> Vec<(Handle, HatchModel)> { pub fn insert_hatches_for_click(&self) -> Vec<(Handle, HatchModel)> {
let layout_block = self.current_layout_block_handle(); let layout_block = self.current_layout_block_handle();
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -2580,7 +2574,7 @@ impl Scene {
let mut block_owned: Vec<(Handle, crate::scene::model::mesh_model::MeshModel)> = Vec::new(); let mut block_owned: Vec<(Handle, crate::scene::model::mesh_model::MeshModel)> = Vec::new();
if !self.block_meshes.is_empty() { if !self.block_meshes.is_empty() {
let layout_block = self.current_layout_block_handle(); let layout_block = self.current_layout_block_handle();
let woff = self.world_offset; let woff = [0.0_f64; 3];
for e in self.document.entities() { for e in self.document.entities() {
if e.common().owner_handle != layout_block { if e.common().owner_handle != layout_block {
continue; continue;
@ -2622,7 +2616,7 @@ impl Scene {
return Vec::new(); return Vec::new();
} }
let layout_block = self.current_layout_block_handle(); let layout_block = self.current_layout_block_handle();
let woff = self.world_offset; let woff = [0.0_f64; 3];
let mut out = Vec::new(); let mut out = Vec::new();
for e in self.document.entities() { for e in self.document.entities() {
if e.common().owner_handle != layout_block { if e.common().owner_handle != layout_block {
@ -2666,7 +2660,7 @@ impl Scene {
return Vec::new(); return Vec::new();
} }
let layout_block = self.current_layout_block_handle(); let layout_block = self.current_layout_block_handle();
let woff = self.world_offset; let woff = [0.0_f64; 3];
let mut out = Vec::new(); let mut out = Vec::new();
for e in self.document.entities() { for e in self.document.entities() {
if e.common().owner_handle != layout_block { if e.common().owner_handle != layout_block {
@ -2797,7 +2791,7 @@ impl Scene {
// Paper space and the first-frame "settle" path fall back to the // Paper space and the first-frame "settle" path fall back to the
// full doc scan — preserving prior behaviour. // full doc scan — preserving prior behaviour.
let visible: Vec<&EntityType> = if let Some(local_view) = view_aabb { let visible: Vec<&EntityType> = if let Some(local_view) = view_aabb {
let [ox, oy, _] = self.world_offset; let [ox, oy, _] = [0.0_f64; 3];
let view_wcs: [f64; 4] = [ let view_wcs: [f64; 4] = [
local_view[0] as f64 + ox, local_view[0] as f64 + ox,
local_view[1] as f64 + oy, local_view[1] as f64 + oy,
@ -2859,7 +2853,7 @@ impl Scene {
// Decide based on the block being tessellated, not the layout. // Decide based on the block being tessellated, not the layout.
let is_model_block = block_handle == self.model_space_block_handle(); let is_model_block = block_handle == self.model_space_block_handle();
let woff = if is_model_block { let woff = if is_model_block {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -3165,7 +3159,7 @@ impl Scene {
&self.document, &self.document,
&self.selected, &self.selected,
self.active_viewport, self.active_viewport,
self.world_offset, [0.0_f64; 3],
bg, bg,
anno, anno,
e, e,
@ -3219,7 +3213,7 @@ impl Scene {
if model_block.is_null() { if model_block.is_null() {
return None; return None;
} }
let [ox, oy, _] = self.world_offset; let [ox, oy, _] = [0.0_f64; 3];
let mut min = glam::Vec3::splat(f32::INFINITY); let mut min = glam::Vec3::splat(f32::INFINITY);
let mut max = glam::Vec3::splat(f32::NEG_INFINITY); let mut max = glam::Vec3::splat(f32::NEG_INFINITY);
let mut any = false; let mut any = false;
@ -3261,7 +3255,7 @@ impl Scene {
// offset-rel coords there silently double-subtracts world_offset // offset-rel coords there silently double-subtracts world_offset
// inside `camera_for_viewport` and points the viewport at the // inside `camera_for_viewport` and points the viewport at the
// wrong location on UTM-scale drawings. // wrong location on UTM-scale drawings.
let oz = self.world_offset[2] as f32; let oz = [0.0_f64; 3][2] as f32;
for entity in self.document.entities() { for entity in self.document.entities() {
let c = entity.common(); let c = entity.common();
if c.owner_handle != model_block || c.invisible { if c.owner_handle != model_block || c.invisible {
@ -3466,9 +3460,9 @@ impl Scene {
// already folded view_center through the (twisted) view basis and // already folded view_center through the (twisted) view basis and
// applied the empty-WCS auto-fit, so taking its target keeps the CPU // applied the empty-WCS auto-fit, so taking its target keeps the CPU
// projection identical to the GPU renderer under any twist. // projection identical to the GPU renderer under any twist.
let display_center_x = cam_frame.target.x as f64 + self.world_offset[0]; let display_center_x = cam_frame.target.x as f64 + [0.0_f64; 3][0];
let display_center_y = cam_frame.target.y as f64 + self.world_offset[1]; let display_center_y = cam_frame.target.y as f64 + [0.0_f64; 3][1];
let display_center_z = cam_frame.target.z as f64 + self.world_offset[2]; let display_center_z = cam_frame.target.z as f64 + [0.0_f64; 3][2];
let view_right_d = ( let view_right_d = (
view_right.x as f64, view_right.x as f64,
view_right.y as f64, view_right.y as f64,
@ -3481,7 +3475,7 @@ impl Scene {
let scale_d = scale as f64; let scale_d = scale as f64;
let pcx_d = pcx as f64; let pcx_d = pcx as f64;
let pcy_d = pcy as f64; let pcy_d = pcy as f64;
let [wo_x, wo_y, wo_z] = self.world_offset; let [wo_x, wo_y, wo_z] = [0.0_f64; 3];
for wire in model_wires.iter() { for wire in model_wires.iter() {
let projected_pts: Vec<[f32; 3]> = wire let projected_pts: Vec<[f32; 3]> = wire
@ -4015,7 +4009,7 @@ impl Scene {
EntityType::Insert(_) | EntityType::Block(_) | EntityType::BlockEnd(_) EntityType::Insert(_) | EntityType::Block(_) | EntityType::BlockEnd(_)
); );
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -4029,7 +4023,7 @@ impl Scene {
None None
}; };
let image_seed = if let EntityType::RasterImage(img) = &entity { let image_seed = if let EntityType::RasterImage(img) = &entity {
ImageModel::from_raster_image(img, self.world_offset) ImageModel::from_raster_image(img, [0.0_f64; 3])
} else { } else {
None None
}; };
@ -4039,7 +4033,7 @@ impl Scene {
EntityType::Solid3D(_) | EntityType::Region(_) | EntityType::Body(_) | EntityType::Surface(_) EntityType::Solid3D(_) | EntityType::Region(_) | EntityType::Body(_) | EntityType::Surface(_)
) { ) {
let color = self.render_style(&entity).0; let color = self.render_style(&entity).0;
let woff = self.world_offset; let woff = [0.0_f64; 3];
crate::entities::solid3d::tessellate_volume(&entity, color, facet_res) crate::entities::solid3d::tessellate_volume(&entity, color, facet_res)
.map(|m| offset_mesh_lod_set(m, woff)) .map(|m| offset_mesh_lod_set(m, woff))
} else { } else {
@ -4307,7 +4301,7 @@ impl Scene {
fn synced_hatch_models(&self) -> Vec<HatchModel> { fn synced_hatch_models(&self) -> Vec<HatchModel> {
let layout_block = self.current_layout_block_handle(); let layout_block = self.current_layout_block_handle();
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -4547,7 +4541,7 @@ impl Scene {
// viewports still see model-block wipeouts at the right local // viewports still see model-block wipeouts at the right local
// coordinates (same rationale as hatches). // coordinates (same rationale as hatches).
let world_offset = if wo.common.owner_handle == model_block { let world_offset = if wo.common.owner_handle == model_block {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -4990,7 +4984,7 @@ impl Scene {
}) })
.collect(); .collect();
for (handle, img) in entries { for (handle, img) in entries {
if let Some(model) = ImageModel::from_raster_image(&img, self.world_offset) { if let Some(model) = ImageModel::from_raster_image(&img, [0.0_f64; 3]) {
self.images.insert(handle, model); self.images.insert(handle, model);
} }
} }
@ -5001,7 +4995,7 @@ impl Scene {
self.hatches.clear(); self.hatches.clear();
let model_block = self.model_space_block_handle(); let model_block = self.model_space_block_handle();
let world_offset = self.world_offset; let world_offset = [0.0_f64; 3];
let entries: Vec<(Handle, EntityType)> = self let entries: Vec<(Handle, EntityType)> = self
.document .document
@ -5084,7 +5078,7 @@ impl Scene {
use crate::par::prelude::*; use crate::par::prelude::*;
let facet_res = self.document.header.facet_resolution; let facet_res = self.document.header.facet_resolution;
let woff = self.world_offset; let woff = [0.0_f64; 3];
// Top-level solids: offset into the render frame, drawn flat. // Top-level solids: offset into the render frame, drawn flat.
// Block-definition solids: keep block-local coords for per-INSERT // Block-definition solids: keep block-local coords for per-INSERT
// instancing (no offset applied here). // instancing (no offset applied here).
@ -5163,7 +5157,7 @@ impl Scene {
// offset back — otherwise the boundary wire, re-projected through the // offset back — otherwise the boundary wire, re-projected through the
// normal entity path, lands `world_offset` away from the fill. // normal entity path, lands `world_offset` away from the fill.
let off = if self.current_layout == "Model" { let off = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -5705,7 +5699,7 @@ impl Scene {
pub fn transform_entities(&mut self, handles: &[Handle], t: &EntityTransform) { pub fn transform_entities(&mut self, handles: &[Handle], t: &EntityTransform) {
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -5855,7 +5849,7 @@ impl Scene {
pub fn copy_entities(&mut self, handles: &[Handle], t: &EntityTransform) -> Vec<Handle> { pub fn copy_entities(&mut self, handles: &[Handle], t: &EntityTransform) -> Vec<Handle> {
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -5938,7 +5932,7 @@ impl Scene {
// Rebuild GPU hatch/solid model when a boundary vertex or corner moves. // Rebuild GPU hatch/solid model when a boundary vertex or corner moves.
let hatch_offset = if self.current_layout == "Model" { let hatch_offset = if self.current_layout == "Model" {
self.world_offset [0.0_f64; 3]
} else { } else {
[0.0; 3] [0.0; 3]
}; };
@ -6068,7 +6062,7 @@ impl Scene {
view: &acadrust::tables::View, view: &acadrust::tables::View,
model_space: bool, model_space: bool,
) -> bool { ) -> bool {
let offset = if model_space { self.world_offset } else { [0.0; 3] }; let offset = if model_space { [0.0_f64; 3] } else { [0.0; 3] };
let Some(cam) = self.camera_from_view( let Some(cam) = self.camera_from_view(
view.direction, view.direction,
view.target, view.target,
@ -6142,7 +6136,7 @@ impl Scene {
view_height: f64, view_height: f64,
twist: f64, twist: f64,
// Subtracted from `view_target` to reach wire-space. Model views pass // Subtracted from `view_target` to reach wire-space. Model views pass
// `self.world_offset`; paper-space views (whose entities carry no // `[0.0_f64; 3]`; paper-space views (whose entities carry no
// offset) pass `[0; 3]`. // offset) pass `[0; 3]`.
world_offset: [f64; 3], world_offset: [f64; 3],
) -> Option<Camera> { ) -> Option<Camera> {
@ -6203,7 +6197,7 @@ impl Scene {
vp.view_center, vp.view_center,
vp.view_height, vp.view_height,
vp.view_twist, vp.view_twist,
self.world_offset, [0.0_f64; 3],
) )
} }
@ -6220,9 +6214,9 @@ impl Scene {
let view_dir = cam.rotation * glam::Vec3::Z; let view_dir = cam.rotation * glam::Vec3::Z;
let view_height = cam.ortho_size() * 2.0; let view_height = cam.ortho_size() * 2.0;
let target_wcs = acadrust::types::Vector3 { let target_wcs = acadrust::types::Vector3 {
x: (cam.target.x as f64) + self.world_offset[0], x: (cam.target.x as f64) + [0.0_f64; 3][0],
y: (cam.target.y as f64) + self.world_offset[1], y: (cam.target.y as f64) + [0.0_f64; 3][1],
z: (cam.target.z as f64) + self.world_offset[2], z: (cam.target.z as f64) + [0.0_f64; 3][2],
}; };
let mut entry = acadrust::tables::VPort::new(name); let mut entry = acadrust::tables::VPort::new(name);
entry.lower_left = lower_left; entry.lower_left = lower_left;
@ -6491,9 +6485,9 @@ impl Scene {
if self.current_layout == "Model" { if self.current_layout == "Model" {
let target_wcs = acadrust::types::Vector3 { let target_wcs = acadrust::types::Vector3 {
x: (cam.target.x as f64) + self.world_offset[0], x: (cam.target.x as f64) + [0.0_f64; 3][0],
y: (cam.target.y as f64) + self.world_offset[1], y: (cam.target.y as f64) + [0.0_f64; 3][1],
z: (cam.target.z as f64) + self.world_offset[2], z: (cam.target.z as f64) + [0.0_f64; 3][2],
}; };
// Write back to the *Active VPort entry (may be overridden by DWG writer). // Write back to the *Active VPort entry (may be overridden by DWG writer).
@ -7551,7 +7545,7 @@ impl Scene {
}, },
saved_h, saved_h,
vp.twist_angle, vp.twist_angle,
self.world_offset, [0.0_f64; 3],
) { ) {
let half_h = saved_h * 0.5; let half_h = saved_h * 0.5;
let half_w = half_h * aspect_d; let half_w = half_h * aspect_d;
@ -7568,8 +7562,8 @@ impl Scene {
// Auto-fit: aim at the content cluster, drop the stale view_center. // Auto-fit: aim at the content cluster, drop the stale view_center.
let fit_h = cluster_half * 2.0 * 1.05; let fit_h = cluster_half * 2.0 * 1.05;
let tgt = acadrust::types::Vector3 { let tgt = acadrust::types::Vector3 {
x: self.world_offset[0], x: [0.0_f64; 3][0],
y: self.world_offset[1], y: [0.0_f64; 3][1],
z: vp.view_target.z, z: vp.view_target.z,
}; };
self.camera_from_view( self.camera_from_view(
@ -7578,7 +7572,7 @@ impl Scene {
acadrust::types::Vector2::ZERO, acadrust::types::Vector2::ZERO,
fit_h, fit_h,
vp.twist_angle, vp.twist_angle,
self.world_offset, [0.0_f64; 3],
) )
} }