forked from 1b-agent/opencadstudio-upstream
fix(render): correct lineweight display scaling
Remove the global display boost and scale paper-space lineweights with the current sheet zoom across wire, block-wire, and hatch paths. Fixes #962
This commit is contained in:
1 parent
0f337db488
commit
edbc4d8ff8
7 files changed
+34
-24
No files matched your search
@@ -25,8 +25,9 @@ pub struct Uniforms {
|
|||||||
/// zooming inside MSPACE changes one scalar instead of re-tessellating and
|
/// zooming inside MSPACE changes one scalar instead of re-tessellating and
|
||||||
/// re-uploading every dashed wire.
|
/// re-uploading every dashed wire.
|
||||||
pub linetype_scale: f32,
|
pub linetype_scale: f32,
|
||||||
/// Pads the struct to the uniform alignment required by wgpu.
|
/// Multiplier for screen-space lineweights. Model space keeps `1.0`;
|
||||||
pub _pad: f32,
|
/// paper layouts derive it from the current paper zoom.
|
||||||
|
pub lineweight_scale: f32,
|
||||||
|
|
||||||
// ── Relative-to-eye (double-single) additions ───────────────────────────
|
// ── Relative-to-eye (double-single) additions ───────────────────────────
|
||||||
// Appended at the end so existing field offsets are unchanged; shaders that
|
// Appended at the end so existing field offsets are unchanged; shaders that
|
||||||
@@ -116,7 +117,7 @@ impl Uniforms {
|
|||||||
flat_shade: 0.0,
|
flat_shade: 0.0,
|
||||||
transparency_enable: 1.0,
|
transparency_enable: 1.0,
|
||||||
linetype_scale: 1.0,
|
linetype_scale: 1.0,
|
||||||
_pad: 0.0,
|
lineweight_scale: 1.0,
|
||||||
view_rot: camera.view_proj_rte(bounds),
|
view_rot: camera.view_proj_rte(bounds),
|
||||||
eye_high,
|
eye_high,
|
||||||
_pad_eh: 0.0,
|
_pad_eh: 0.0,
|
||||||
|
|||||||
+10
-11
@@ -23,6 +23,7 @@ use crate::scene::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const DISPLAY_STYLE_CACHE_LIMIT: usize = if cfg!(target_arch = "wasm32") { 4 } else { 24 };
|
const DISPLAY_STYLE_CACHE_LIMIT: usize = if cfg!(target_arch = "wasm32") { 4 } else { 24 };
|
||||||
|
const MM_TO_PX: f32 = 96.0 / 25.4;
|
||||||
|
|
||||||
// ── Camera hover state (shader::Program::State) ───────────────────────────
|
// ── Camera hover state (shader::Program::State) ───────────────────────────
|
||||||
|
|
||||||
@@ -2592,7 +2593,7 @@ impl Scene {
|
|||||||
wire.fill_tris_low.clear();
|
wire.fill_tris_low.clear();
|
||||||
}
|
}
|
||||||
if let Some(mm) = style.resolve_lineweight(wire.aci) {
|
if let Some(mm) = style.resolve_lineweight(wire.aci) {
|
||||||
wire.line_weight_px = (mm * (96.0 / 25.4) * 2.0).max(1.0);
|
wire.line_weight_px = (mm * MM_TO_PX).max(1.0);
|
||||||
}
|
}
|
||||||
for vertex in &mut wire.text_verts {
|
for vertex in &mut wire.text_verts {
|
||||||
self.apply_display_plot_style(&mut vertex.color, wire.aci, &style);
|
self.apply_display_plot_style(&mut vertex.color, wire.aci, &style);
|
||||||
@@ -2648,7 +2649,7 @@ impl Scene {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(mm) = style.resolve_lineweight(hatch.aci) {
|
if let Some(mm) = style.resolve_lineweight(hatch.aci) {
|
||||||
hatch.line_weight_px = (mm * (96.0 / 25.4) * 2.0).max(1.0);
|
hatch.line_weight_px = (mm * MM_TO_PX).max(1.0);
|
||||||
}
|
}
|
||||||
if let crate::scene::model::hatch_model::HatchPattern::Gradient {
|
if let crate::scene::model::hatch_model::HatchPattern::Gradient {
|
||||||
color2, ..
|
color2, ..
|
||||||
@@ -2710,7 +2711,7 @@ impl Scene {
|
|||||||
self.apply_display_plot_style(&mut color, wire.aci, &style);
|
self.apply_display_plot_style(&mut color, wire.aci, &style);
|
||||||
let line_weight_px = style
|
let line_weight_px = style
|
||||||
.resolve_lineweight(wire.aci)
|
.resolve_lineweight(wire.aci)
|
||||||
.map(|mm| (mm * (96.0 / 25.4) * 2.0).max(1.0))
|
.map(|mm| (mm * MM_TO_PX).max(1.0))
|
||||||
.unwrap_or(wire.line_weight_px);
|
.unwrap_or(wire.line_weight_px);
|
||||||
for (triangle_index, triangle) in wire.fill_tris.chunks_exact(3).enumerate() {
|
for (triangle_index, triangle) in wire.fill_tris.chunks_exact(3).enumerate() {
|
||||||
let mut boundary = Vec::with_capacity(4);
|
let mut boundary = Vec::with_capacity(4);
|
||||||
@@ -2943,15 +2944,8 @@ pub struct InheritStyle {
|
|||||||
|
|
||||||
/// Convert a concrete (already layer-resolved) lineweight to display pixels.
|
/// Convert a concrete (already layer-resolved) lineweight to display pixels.
|
||||||
pub(crate) fn lineweight_to_px(lw: &LineWeight) -> f32 {
|
pub(crate) fn lineweight_to_px(lw: &LineWeight) -> f32 {
|
||||||
const MM_TO_PX: f32 = 96.0 / 25.4;
|
|
||||||
// CAD apps display model-space lineweights larger than their true physical
|
|
||||||
// size so the gradations stay legible on screen — at true scale a 0.5 mm
|
|
||||||
// line is ~2 px and is indistinguishable from thinner weights (which all
|
|
||||||
// floor to 1 px). Apply the same legibility boost so weights are pronounced
|
|
||||||
// and tell apart, matching other DWG editors. (#147)
|
|
||||||
const LWT_DISPLAY_BOOST: f32 = 2.0;
|
|
||||||
lw.millimeters()
|
lw.millimeters()
|
||||||
.map(|mm| (mm as f32 * MM_TO_PX * LWT_DISPLAY_BOOST).max(1.0))
|
.map(|mm| (mm as f32 * MM_TO_PX).max(1.0))
|
||||||
.unwrap_or(1.0)
|
.unwrap_or(1.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3853,6 +3847,11 @@ impl Scene {
|
|||||||
full_bounds,
|
full_bounds,
|
||||||
self.document.header.lineweight_display || display_plot_lineweights,
|
self.document.header.lineweight_display || display_plot_lineweights,
|
||||||
);
|
);
|
||||||
|
if self.current_layout != "Model" {
|
||||||
|
let paper_per_pixel = 2.0 * self.camera.borrow().ortho_size() / canvas.1.max(1.0);
|
||||||
|
let paper_units_per_mm = self.paper_space_unit_factor() as f32;
|
||||||
|
uniforms.lineweight_scale = paper_units_per_mm / paper_per_pixel / MM_TO_PX;
|
||||||
|
}
|
||||||
|
|
||||||
// Model space: scale linetypes using the current annotation scale so their
|
// Model space: scale linetypes using the current annotation scale so their
|
||||||
// appearance can match a paper-space viewport at the same drawing scale.
|
// appearance can match a paper-space viewport at the same drawing scale.
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ struct Uniforms {
|
|||||||
flat_shade: f32,
|
flat_shade: f32,
|
||||||
transparency_enable: f32,
|
transparency_enable: f32,
|
||||||
linetype_scale: f32,
|
linetype_scale: f32,
|
||||||
_pad: f32,
|
lineweight_scale: f32,
|
||||||
view_rot: mat4x4<f32>,
|
view_rot: mat4x4<f32>,
|
||||||
eye_high: vec3<f32>,
|
eye_high: vec3<f32>,
|
||||||
_pad_eh: f32,
|
_pad_eh: f32,
|
||||||
@@ -67,7 +67,7 @@ fn resolve_hw(taper_ratio: f32, world_hw: f32, px_hw: f32) -> f32 {
|
|||||||
if world_hw > 0.0 {
|
if world_hw > 0.0 {
|
||||||
return max(world_hw / u.world_per_pixel, 0.5);
|
return max(world_hw / u.world_per_pixel, 0.5);
|
||||||
}
|
}
|
||||||
return select(0.5, px_hw, u.lwdisplay_enable > 0.5);
|
return select(0.5, max(px_hw * u.lineweight_scale, 0.5), u.lwdisplay_enable > 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn marker_relative(
|
fn marker_relative(
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ struct Uniforms {
|
|||||||
lwdisplay_enable: f32,
|
lwdisplay_enable: f32,
|
||||||
flat_shade: f32,
|
flat_shade: f32,
|
||||||
transparency_enable: f32,
|
transparency_enable: f32,
|
||||||
_pad: vec2<f32>,
|
_linetype_scale: f32,
|
||||||
|
lineweight_scale: f32,
|
||||||
// Relative-to-eye (double-single): see wire.wgsl.
|
// Relative-to-eye (double-single): see wire.wgsl.
|
||||||
view_rot: mat4x4<f32>,
|
view_rot: mat4x4<f32>,
|
||||||
eye_high: vec3<f32>,
|
eye_high: vec3<f32>,
|
||||||
@@ -162,7 +163,11 @@ fn check_family(
|
|||||||
-ddx_xz.x * sin_a + ddx_xz.y * cos_a,
|
-ddx_xz.x * sin_a + ddx_xz.y * cos_a,
|
||||||
-ddy_xz.x * sin_a + ddy_xz.y * cos_a,
|
-ddy_xz.x * sin_a + ddy_xz.y * cos_a,
|
||||||
)) * 0.5;
|
)) * 0.5;
|
||||||
let width_px = select(1.0, max(fam.line_width, 1.0), u.lwdisplay_enable > 0.5);
|
let width_px = select(
|
||||||
|
1.0,
|
||||||
|
max(fam.line_width * u.lineweight_scale, 1.0),
|
||||||
|
u.lwdisplay_enable > 0.5,
|
||||||
|
);
|
||||||
let half_line = half_px * width_px;
|
let half_line = half_px * width_px;
|
||||||
|
|
||||||
// World units per screen pixel on each axis — used to light exactly the
|
// World units per screen pixel on each axis — used to light exactly the
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ struct Uniforms {
|
|||||||
lwdisplay_enable: f32,
|
lwdisplay_enable: f32,
|
||||||
flat_shade: f32,
|
flat_shade: f32,
|
||||||
transparency_enable: f32,
|
transparency_enable: f32,
|
||||||
_pad: vec2<f32>,
|
_linetype_scale: f32,
|
||||||
|
lineweight_scale: f32,
|
||||||
view_rot: mat4x4<f32>,
|
view_rot: mat4x4<f32>,
|
||||||
eye_high: vec3<f32>,
|
eye_high: vec3<f32>,
|
||||||
_pad_eh: f32,
|
_pad_eh: f32,
|
||||||
@@ -146,7 +147,11 @@ fn check_family(
|
|||||||
-ddx_xz.x * sin_a + ddx_xz.y * cos_a,
|
-ddx_xz.x * sin_a + ddx_xz.y * cos_a,
|
||||||
-ddy_xz.x * sin_a + ddy_xz.y * cos_a,
|
-ddy_xz.x * sin_a + ddy_xz.y * cos_a,
|
||||||
)) * 0.5;
|
)) * 0.5;
|
||||||
let width_px = select(1.0, max(fam.line_width, 1.0), u.lwdisplay_enable > 0.5);
|
let width_px = select(
|
||||||
|
1.0,
|
||||||
|
max(fam.line_width * u.lineweight_scale, 1.0),
|
||||||
|
u.lwdisplay_enable > 0.5,
|
||||||
|
);
|
||||||
let half_line = half_px * width_px;
|
let half_line = half_px * width_px;
|
||||||
|
|
||||||
let wpx = length(vec2<f32>(ddx_xz.x, ddy_xz.x));
|
let wpx = length(vec2<f32>(ddx_xz.x, ddy_xz.x));
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ struct Uniforms {
|
|||||||
// every line opaque.
|
// every line opaque.
|
||||||
transparency_enable: f32,
|
transparency_enable: f32,
|
||||||
linetype_scale: f32,
|
linetype_scale: f32,
|
||||||
_pad: f32,
|
lineweight_scale: f32,
|
||||||
// ── Relative-to-eye (double-single) ──────────────────────────────────
|
// ── Relative-to-eye (double-single) ──────────────────────────────────
|
||||||
// view_rot is the rotation-only view-projection; vertices subtract the eye
|
// view_rot is the rotation-only view-projection; vertices subtract the eye
|
||||||
// (eye_high + eye_low, two f32 emulating f64) before transforming, so the
|
// (eye_high + eye_low, two f32 emulating f64) before transforming, so the
|
||||||
@@ -102,7 +102,7 @@ struct VertexOut {
|
|||||||
fn resolve_hw(taper: f32, world_hw: f32, px_hw: f32) -> f32 {
|
fn resolve_hw(taper: f32, world_hw: f32, px_hw: f32) -> f32 {
|
||||||
if taper > 0.0 { return max(taper / u.world_per_pixel, 0.5); }
|
if taper > 0.0 { return max(taper / u.world_per_pixel, 0.5); }
|
||||||
if world_hw > 0.0 { return max(world_hw / u.world_per_pixel, 0.5); }
|
if world_hw > 0.0 { return max(world_hw / u.world_per_pixel, 0.5); }
|
||||||
return select(0.5, px_hw, u.lwdisplay_enable > 0.5);
|
return select(0.5, max(px_hw * u.lineweight_scale, 0.5), u.lwdisplay_enable > 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn marker_relative(position_high: vec3<f32>, position_low: vec3<f32>, instance: InstanceIn) -> vec3<f32> {
|
fn marker_relative(position_high: vec3<f32>, position_low: vec3<f32>, instance: InstanceIn) -> vec3<f32> {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ struct Uniforms {
|
|||||||
flat_shade: f32,
|
flat_shade: f32,
|
||||||
transparency_enable: f32,
|
transparency_enable: f32,
|
||||||
linetype_scale: f32,
|
linetype_scale: f32,
|
||||||
_pad: f32,
|
lineweight_scale: f32,
|
||||||
view_rot: mat4x4<f32>,
|
view_rot: mat4x4<f32>,
|
||||||
eye_high: vec3<f32>,
|
eye_high: vec3<f32>,
|
||||||
_pad_eh: f32,
|
_pad_eh: f32,
|
||||||
@@ -81,7 +81,7 @@ fn resolve_hw(taper_ratio: f32, world_hw: f32, px_hw: f32) -> f32 {
|
|||||||
return max((taper_ratio * world_hw) / u.world_per_pixel, 0.5);
|
return max((taper_ratio * world_hw) / u.world_per_pixel, 0.5);
|
||||||
}
|
}
|
||||||
if world_hw > 0.0 { return max(world_hw / u.world_per_pixel, 0.5); }
|
if world_hw > 0.0 { return max(world_hw / u.world_per_pixel, 0.5); }
|
||||||
return select(0.5, px_hw, u.lwdisplay_enable > 0.5);
|
return select(0.5, max(px_hw * u.lineweight_scale, 0.5), u.lwdisplay_enable > 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn marker_relative(position_high: vec3<f32>, position_low: vec3<f32>, c: WireConst) -> vec3<f32> {
|
fn marker_relative(position_high: vec3<f32>, position_low: vec3<f32>, c: WireConst) -> vec3<f32> {
|
||||||
|
|||||||
Reference in new issue
Block a user