forked from 1b-agent/opencadstudio-upstream
perf(wire): move LWDISPLAY toggle from CPU rebake to wire shader uniform
LWDISPLAY (Show Lineweight) flipping the toggle no longer triggers a full retessellate. `render_style_for` always bakes the entity's resolved (layer- inherited) lineweight, and the wire shader reads `Uniforms.lwdisplay_enable` to either honour the per-vertex half_width or collapse the quad to a 1 px line. Side effect: PDF export now uses the real lineweight regardless of LWDISPLAY, matching AutoCAD's plot semantics (LWDISPLAY only affects screen render). Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
fb3dd58d09
commit
e9488f99dd
5 files changed
+38
-33
No files matched your search
+1
-1
@@ -4522,7 +4522,7 @@ impl H7CAD {
|
||||
Ok(Some(v)) => {
|
||||
self.push_undo_snapshot(i, "LWDISPLAY");
|
||||
self.tabs[i].scene.document.header.lineweight_display = v;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
// No retessellate — the wire shader honours the flag via uniforms.
|
||||
self.tabs[i].dirty = true;
|
||||
self.command_line.push_output(&format!(
|
||||
"LWDISPLAY {}",
|
||||
|
||||
+1
-1
@@ -2514,7 +2514,7 @@ impl H7CAD {
|
||||
if i < self.tabs.len() {
|
||||
let h = &mut self.tabs[i].scene.document.header;
|
||||
h.lineweight_display = !h.lineweight_display;
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
// No retessellate — the wire shader reads the flag from uniforms.
|
||||
self.tabs[i].dirty = true;
|
||||
}
|
||||
Task::none()
|
||||
|
||||
@@ -11,11 +11,13 @@ pub struct Uniforms {
|
||||
/// hatch shader to substitute solid fill when pattern line spacing
|
||||
/// falls below ~2 px (Phase 3.3 LOD).
|
||||
pub world_per_pixel: f32,
|
||||
pub _pad: f32,
|
||||
/// LWDISPLAY toggle (1.0 = show lineweights, 0.0 = force 1 px).
|
||||
/// Read by the wire shader so the toggle does not require a retessellate.
|
||||
pub lwdisplay_enable: f32,
|
||||
}
|
||||
|
||||
impl Uniforms {
|
||||
pub fn new(camera: &Camera, bounds: Rectangle) -> Self {
|
||||
pub fn new(camera: &Camera, bounds: Rectangle, lwdisplay_enable: bool) -> Self {
|
||||
let half_h = camera.ortho_size();
|
||||
let world_per_pixel = if bounds.height > 0.0 {
|
||||
(2.0 * half_h) / bounds.height
|
||||
@@ -27,7 +29,7 @@ impl Uniforms {
|
||||
camera_pos: camera.position_vec4(),
|
||||
viewport_size: [bounds.width, bounds.height],
|
||||
world_per_pixel,
|
||||
_pad: 0.0,
|
||||
lwdisplay_enable: if lwdisplay_enable { 1.0 } else { 0.0 },
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
-23
@@ -253,27 +253,24 @@ pub(super) fn render_style_for(
|
||||
let (pattern_length, pattern) = resolve_pattern(&document.line_types, lt_name, lt_scale);
|
||||
|
||||
let line_weight_px = {
|
||||
// LWDISPLAY (header.lineweight_display): when false, every entity
|
||||
// draws at the 1-pixel base width regardless of its assigned weight.
|
||||
// AutoCAD's "Show Lineweight" toggle maps onto this header var.
|
||||
if !document.header.lineweight_display {
|
||||
1.0
|
||||
} else {
|
||||
let ew = &e.common().line_weight;
|
||||
let resolved = match ew {
|
||||
LineWeight::ByLayer | LineWeight::ByBlock | LineWeight::Default => document
|
||||
.layers
|
||||
.get(layer_name)
|
||||
.map(|l| &l.line_weight)
|
||||
.unwrap_or(&LineWeight::Default),
|
||||
_ => ew,
|
||||
};
|
||||
const MM_TO_PX: f32 = 96.0 / 25.4;
|
||||
resolved
|
||||
.millimeters()
|
||||
.map(|mm| (mm as f32 * MM_TO_PX).max(1.0))
|
||||
.unwrap_or(1.0)
|
||||
}
|
||||
// LWDISPLAY is no longer evaluated here — the toggle is now applied in
|
||||
// the wire shader via `Uniforms.lwdisplay_enable`, so we always bake the
|
||||
// entity's resolved (layer-inherited) weight. Toggling lineweight
|
||||
// visibility costs only a uniform write, not a retessellate.
|
||||
let ew = &e.common().line_weight;
|
||||
let resolved = match ew {
|
||||
LineWeight::ByLayer | LineWeight::ByBlock | LineWeight::Default => document
|
||||
.layers
|
||||
.get(layer_name)
|
||||
.map(|l| &l.line_weight)
|
||||
.unwrap_or(&LineWeight::Default),
|
||||
_ => ew,
|
||||
};
|
||||
const MM_TO_PX: f32 = 96.0 / 25.4;
|
||||
resolved
|
||||
.millimeters()
|
||||
.map(|mm| (mm as f32 * MM_TO_PX).max(1.0))
|
||||
.unwrap_or(1.0)
|
||||
};
|
||||
|
||||
(entity_color, pattern_length, pattern, line_weight_px, aci)
|
||||
@@ -376,7 +373,7 @@ impl Scene {
|
||||
wipeout_hatches: self.wipeout_models_arc(),
|
||||
images: self.images_arc(),
|
||||
meshes: self.meshes_arc(),
|
||||
uniforms: Uniforms::new(&cam, bounds),
|
||||
uniforms: Uniforms::new(&cam, bounds, self.document.header.lineweight_display),
|
||||
cam_rotation: cam.view_rotation_mat(),
|
||||
hover_region,
|
||||
bg_color,
|
||||
@@ -420,7 +417,7 @@ impl Scene {
|
||||
wipeout_hatches: self.wipeout_models_arc(),
|
||||
images: self.images_arc(),
|
||||
meshes: self.meshes_arc(),
|
||||
uniforms: Uniforms::new(&cam, bounds),
|
||||
uniforms: Uniforms::new(&cam, bounds, self.document.header.lineweight_display),
|
||||
cam_rotation: cam.view_rotation_mat(),
|
||||
hover_region,
|
||||
bg_color: self.bg_color,
|
||||
|
||||
+11
-5
@@ -11,10 +11,13 @@
|
||||
// • pat0/pat1 encode up to 8 elements: positive=dash, negative=gap.
|
||||
|
||||
struct Uniforms {
|
||||
view_proj: mat4x4<f32>,
|
||||
camera_pos: vec4<f32>,
|
||||
viewport_size: vec2<f32>,
|
||||
_pad: vec2<f32>,
|
||||
view_proj: mat4x4<f32>,
|
||||
camera_pos: vec4<f32>,
|
||||
viewport_size: vec2<f32>,
|
||||
world_per_pixel: f32,
|
||||
// LWDISPLAY toggle: 0.0 = force 1 px (half_width 0.5), 1.0 = use per-vertex
|
||||
// baked half_width. Lets the LWT button switch without retessellating.
|
||||
lwdisplay_enable: f32,
|
||||
}
|
||||
@group(0) @binding(0) var<uniform> u: Uniforms;
|
||||
|
||||
@@ -70,8 +73,11 @@ struct VertexOut {
|
||||
// Select the clip-space position for this vertex's endpoint.
|
||||
let clip_pos = mix(clip_a, clip_b, in.which_end);
|
||||
|
||||
// LWDISPLAY off → collapse to a 1-pixel-wide line (half_width = 0.5).
|
||||
let hw = select(0.5, in.half_width, u.lwdisplay_enable > 0.5);
|
||||
|
||||
// Offset in clip space (multiply by w to un-apply perspective division).
|
||||
let ndc_offset = perp_ndc * in.half_width * in.side;
|
||||
let ndc_offset = perp_ndc * hw * in.side;
|
||||
let final_clip = clip_pos + vec4<f32>(ndc_offset * clip_pos.w, 0.0, 0.0);
|
||||
|
||||
var out: VertexOut;
|
||||
|
||||
Reference in new issue
Block a user