forked from 1b-agent/opencadstudio-upstream
fix(scene): block text keeps its draw-order slot against sibling wipes
Unselected block text (the BS33-11 Mark/SectionMark labels) was erased by its own block's wipeout pass and only came back through the selection xray. Two compounding causes: - Glyph quads rendered at the bare insert level, an exact depth tie with every sibling fill, so the later wipeout pass won LessEqual. Wire batches now carry the composed child rank as depth_override (the same units the scene graph composes: depths[insert] + label * half), which the block-text upload resolves per instance. Glyph vertices stay neutral on purpose — baking the raw per-block label into them double-counts and, for a negative rank, sinks the text BELOW its own masks. - The wipeout pipeline's depth bias (-8 quanta) was larger than the whole within-block band: once child ranks compress into the insert's half-band, sibling steps are ~3 quanta and a wipeout-to-text gap is only 9-16 quanta of the 24-bit buffer. The mask only needs to break exact ties, so the bias is now WIPEOUT_DEPTH_BIAS_QUANTA = 2. block_text_draw_depth regression pins the contract: neutral vertices, override carrying the rank, and a margin over the wipe that exceeds the bias on a 600-entity scene.
This commit is contained in:
1 parent
472bb9883d
commit
454d99b1d3
3 files changed
+182
-6
No files matched your search
Vendored
+19
-5
@@ -1703,6 +1703,14 @@ impl Batches {
|
||||
);
|
||||
}
|
||||
}
|
||||
// Glyph quads stay at neutral depth on purpose: the per-wire
|
||||
// depth_override (b.local_depth) is composed with the insert's
|
||||
// scene-graph level at upload time (wire_draw_depth:
|
||||
// depths[insert] + override * half), the same place the
|
||||
// wipeout/hatch fills get theirs. Baking the raw child rank
|
||||
// into the vertices here would double-count it in per-block
|
||||
// label units — for a negative rank that sinks the text below
|
||||
// its own block's wipes instead of ahead of them.
|
||||
if !b.pattern_stations.is_empty() {
|
||||
b.pattern_stations = encode_pattern_stations(
|
||||
std::mem::take(&mut b.pattern_stations),
|
||||
@@ -2571,11 +2579,17 @@ fn emit_wire(
|
||||
.map(|marker| transformed_point_marker(marker, accum_xform));
|
||||
let point_marker = marker_transform.map(|(marker, _)| marker);
|
||||
|
||||
// Only band wires take a per-child composed depth: their solid area is
|
||||
// what covers siblings, and their width already splits them into their own
|
||||
// batches — thin wires keep the shared whole-insert depth so same-style
|
||||
// batches stay merged.
|
||||
let local_depth = (lw.world_width > 0.0)
|
||||
// Band wires take a per-child composed depth: their solid area is what
|
||||
// covers siblings, and their width already splits them into their own
|
||||
// batches. Text-bearing wires need it too — but as `depth_override`, not
|
||||
// baked into vertices: the upload resolves it against the insert's
|
||||
// scene-graph entry (depths[insert] + override * half), which is what
|
||||
// keeps text interleaved with its sibling wipeout/hatch fills. Without a
|
||||
// composed rank the text sits at the bare insert level, an exact tie with
|
||||
// every sibling fill, and the later wipeout pass erases it (unselected
|
||||
// block text vanished under its wipeout; selecting won only because the
|
||||
// xray pass ignores depth).
|
||||
let local_depth = (lw.world_width > 0.0 || !lw.text_verts.is_empty())
|
||||
.then(|| d_range.0 + lw.local_rank * d_range.1);
|
||||
let plot_visible = ctx.plot_visible
|
||||
&& lw.plot_visible
|
||||
|
||||
Reference in new issue
Block a user