forked from 1b-agent/opencadstudio-upstream
Merge pull request #1738 from gianlucafiore/fix/block-wipeout-hatch-order
This commit is contained in:
commit
5581bbeedb
4 files changed
+47
-33
No files matched your search
Vendored
+21
-3
@@ -1038,7 +1038,20 @@ pub fn expand_insert(
|
||||
scale_policy,
|
||||
);
|
||||
let name = ins_handle.value().to_string();
|
||||
let prototype_key = if !ins.is_array() && cache.prototype_blocks.contains(&ins.block_name) {
|
||||
// Mask-bearing blocks must not reuse translated GPU prototypes: ordinary
|
||||
// strokes and wipeout fills have different upload paths. Their shared
|
||||
// source_id plus per-copy translated geometry can make a moved INSERT
|
||||
// display stale wipeout geometry or disappear as the view changes.
|
||||
// Expand these from their definition until both GPU paths share a
|
||||
// verified identical instancing convention.
|
||||
let has_masks = defn.subs.iter().any(|sub| match sub {
|
||||
LocalSub::Wire(wire) => wire.canvas_color,
|
||||
LocalSub::Nested(_) => false,
|
||||
});
|
||||
let prototype_key = if !ins.is_array()
|
||||
&& !has_masks
|
||||
&& cache.prototype_blocks.contains(&ins.block_name)
|
||||
{
|
||||
Some(expansion_prototype_key(
|
||||
ins,
|
||||
&xform,
|
||||
@@ -2618,8 +2631,13 @@ fn emit_wire(
|
||||
// MTEXT background (a dimension's DIMTFILL box) left at the bare insert
|
||||
// level sat in front of its own text whenever that text's rank was
|
||||
// below zero.
|
||||
let local_depth = (lw.world_width > 0.0 || lw.is_fill_only || !lw.text_verts.is_empty())
|
||||
.then(|| d_range.0 + lw.local_rank * d_range.1);
|
||||
// Every block member must retain its block-local draw rank, including
|
||||
// ordinary thin LINE/LWPOLYLINE wires. Previously these wires had no
|
||||
// depth_override, so they were drawn at the INSERT's bare depth while
|
||||
// wipeout/hatch fills were positioned at the member rank. COPY and grip
|
||||
// moves rebuild instance batches and exposed this mismatch in model,
|
||||
// paper-space and PDF output.
|
||||
let local_depth = Some(d_range.0 + lw.local_rank * d_range.1);
|
||||
let plot_visible = ctx.plot_visible && lw.plot_visible && (!lw.plot_l0 || ctx.l0_plottable);
|
||||
|
||||
// Batched wires share one dash distance, which runs on across the NaN
|
||||
|
||||
+8
-4
@@ -7932,15 +7932,19 @@ impl Scene {
|
||||
let cache = self.wipeout_cache.borrow();
|
||||
match cache.get(&key) {
|
||||
Some((cached_epoch, arc))
|
||||
// wipeout_models scans the whole document for Wipeout
|
||||
// entities; relevance = the changed handle is a Wipeout.
|
||||
// The displayed wipeout set also contains masks
|
||||
// expanded from INSERTs. COPY and grip edits modify or
|
||||
// add INSERT handles without changing the child WIPEOUT
|
||||
// entity, so the old predicate reused stale positions
|
||||
// until REGEN. Track both categories, including
|
||||
// removed INSERTs via the recorded removal bits.
|
||||
if self.category_cache_valid(
|
||||
*cached_epoch,
|
||||
CACHE_CATEGORY_WIPEOUT,
|
||||
CACHE_CATEGORY_WIPEOUT | CACHE_CATEGORY_INSERT_HATCH,
|
||||
|h| {
|
||||
matches!(
|
||||
self.document.get_entity(h),
|
||||
Some(EntityType::Wipeout(_))
|
||||
Some(EntityType::Wipeout(_) | EntityType::Insert(_))
|
||||
)
|
||||
},
|
||||
) =>
|
||||
|
||||
@@ -172,23 +172,16 @@ impl WipeoutGpu {
|
||||
models: &[HatchModel],
|
||||
bgl1: &wgpu::BindGroupLayout,
|
||||
) -> Vec<Self> {
|
||||
let mut slots = rustc_hash::FxHashMap::default();
|
||||
let mut groups: Vec<Vec<&HatchModel>> = Vec::new();
|
||||
for (index, model) in models.iter().enumerate() {
|
||||
let key = model
|
||||
.render_instance
|
||||
.map(|instance| (true, instance.source_id))
|
||||
.unwrap_or((false, index as u64));
|
||||
let slot = *slots.entry(key).or_insert_with(|| {
|
||||
let slot = groups.len();
|
||||
groups.push(Vec::new());
|
||||
slot
|
||||
});
|
||||
groups[slot].push(model);
|
||||
}
|
||||
groups
|
||||
.into_iter()
|
||||
.map(|group| Self::new(device, queue, &group, bgl1))
|
||||
// A source_id only identifies reusable render geometry, not an
|
||||
// interchangeable hatch boundary in world space. Grouping masks by
|
||||
// source_id can incorrectly reuse the first model's boundary, origin,
|
||||
// plane and uniform for later INSERT copies. Unlike wires, a mask's
|
||||
// GPU shader clips against its own boundary, so build each mask from
|
||||
// its actual transformed model until we have a geometry-local,
|
||||
// translation-safe instancing path.
|
||||
models
|
||||
.iter()
|
||||
.map(|model| Self::new(device, queue, &[model], bgl1))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// Positive order draws in front; zero retains geometric depth. Keep the usual
|
||||
// 0.001 NDC offset away from the clipping planes, but reduce it near either
|
||||
// plane: perspective depth can be much closer to 1 than this fixed offset.
|
||||
//
|
||||
// Using order / (1 + abs(order)) for the limited region keeps ordering monotonic
|
||||
// (including the paper background's -2). Less than half the remaining depth is
|
||||
// consumed, so valid vertices stay valid. Out-of-range/behind-eye vertices get
|
||||
// no offset and remain subject to the real near/far clipping planes.
|
||||
// Positive draw order moves geometry towards the camera. In dense blocks,
|
||||
// child ranks occupy a narrow fraction of the INSERT depth band: a 0.001
|
||||
// NDC bias can quantize two overlapping lines/masks to the same depth value,
|
||||
// especially after changing view/zoom. Use a wider, yet bounded range for
|
||||
// CAD 2D draw order. Limit displacement to less than half the available
|
||||
// clip-space room, so we never push valid geometry across near/far planes.
|
||||
// This is a screen-only GPU change; PDF order uses its own stable sorting.
|
||||
fn apply_draw_order(clip: vec4<f32>, order: f32) -> vec4<f32> {
|
||||
let room = 0.5 * max(0.0, min(clip.z, clip.w - clip.z));
|
||||
let scale = min(0.001 * max(clip.w, 0.0), room / (1.0 + abs(order)));
|
||||
let scale = min(0.02 * max(clip.w, 0.0), room / (1.0 + abs(order)));
|
||||
return vec4<f32>(clip.xy, clip.z - order * scale, clip.w);
|
||||
}
|
||||
Reference in new issue
Block a user