fix(scene): greek text rect renders filled at the text's own color
Greek rects rendered through fill_tris went through the face3d 0.45
dim path; the pre-boost (color × 1/0.45) compensated only until clamp
hit at 1.0, leaving bright user colors washed out. The earlier outline
workaround dodged the dim but lost the filled box visual that AutoCAD
uses for "text lives here".
- face3d pipeline now skips the 0.45 dim when `wire.points` is
empty. PolyfaceMesh / PolygonMesh keep their dim (both points and
fill_tris populated); greek and MultiLeader background-fill emit
`points: vec![]` so they render at the literal color.
- All three greek paths (top-level, block-defn, MultiLeader) emit a
2-triangle filled rect instead of an outline / boosted fill.
- Greek rects are clamped to single-line height so 5-line MText
doesn't blow the box up to the full text-block height. MultiLeader
emits one rect per line — keeps the per-row visual hint.
- BatchEntry/StyleKey gain an `is_fill_only` discriminator so greek
batches never collide with regular wire batches; otherwise the
finalized WireModel could carry both points and fill_tris and
defeat the pipeline-side empty-points check.
Xref fade still applies to the resolved color via the existing
`fade_toward_bg` path, so xref greek stays faded as expected.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
1f1aa80f17
commit
ddd0a2de16
4 changed files with 173 additions and 107 deletions
|
|
@ -4195,22 +4195,13 @@ fn tessellate_entity(
|
|||
}
|
||||
if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB {
|
||||
let fill_tris = text_greek_obb_tris(e, anno_scale, world_offset);
|
||||
// The face3d pipeline dims fill_tris colors to 45% to fake
|
||||
// ambient occlusion on PolyfaceMesh / 3DFACE solids. Greeked
|
||||
// text doesn't want that shading — pre-boost the color so it
|
||||
// emerges close to the original text color after the dim.
|
||||
let boost = 1.0 / 0.45;
|
||||
let [r, g, b, a] = entity_color;
|
||||
let greek_color = [
|
||||
(r * boost).min(1.0),
|
||||
(g * boost).min(1.0),
|
||||
(b * boost).min(1.0),
|
||||
a,
|
||||
];
|
||||
if fill_tris.is_empty() {
|
||||
return vec![];
|
||||
}
|
||||
return vec![WireModel {
|
||||
name: h.value().to_string(),
|
||||
points: vec![],
|
||||
color: greek_color,
|
||||
color: entity_color,
|
||||
selected: sel,
|
||||
aci,
|
||||
pattern_length: 0.0,
|
||||
|
|
@ -4401,8 +4392,11 @@ fn text_baseline_points(
|
|||
vec![cast(corners[0]), cast(corners[1])]
|
||||
}
|
||||
|
||||
/// 6-vertex (2-triangle) fill for a greeked top-level Text / MText, in
|
||||
/// world-offset-subtracted f32 space.
|
||||
/// 6-vertex filled rect (2 triangles) for a greeked top-level Text / MText.
|
||||
/// Clamped to a single line's height — multi-line MText's OBB spans the
|
||||
/// whole block and using its full height would emit a misleadingly tall
|
||||
/// box. The face3d pipeline skips its 0.45 dim for wires with empty
|
||||
/// `points`, so these tris render at the literal text color.
|
||||
fn text_greek_obb_tris(
|
||||
e: &EntityType,
|
||||
anno_scale: f32,
|
||||
|
|
@ -4411,13 +4405,35 @@ fn text_greek_obb_tris(
|
|||
let Some(corners) = text_obb_corners_native(e, anno_scale) else {
|
||||
return vec![];
|
||||
};
|
||||
let line_h = match e {
|
||||
EntityType::Text(t) => (t.height * anno_scale as f64) as f32,
|
||||
EntityType::MText(m) => (m.height * anno_scale as f64) as f32,
|
||||
_ => return vec![],
|
||||
};
|
||||
if line_h <= 0.0 {
|
||||
return vec![];
|
||||
}
|
||||
let [ox, oy, oz] = world_offset;
|
||||
let cast = |p: [f64; 3]| -> [f32; 3] {
|
||||
[(p[0] - ox) as f32, (p[1] - oy) as f32, (p[2] - oz) as f32]
|
||||
};
|
||||
let [p00, p10, p11, p01] = corners;
|
||||
let (p00, p10, p11, p01) = (cast(p00), cast(p10), cast(p11), cast(p01));
|
||||
vec![p00, p10, p11, p00, p11, p01]
|
||||
let bl = cast(corners[0]);
|
||||
let br = cast(corners[1]);
|
||||
let full_tl = cast(corners[3]);
|
||||
|
||||
// Up direction = (bl → full_tl) normalized, then scale to a single
|
||||
// line. Replaces the full-block top corners so MText with N lines
|
||||
// still emits a single-line rect.
|
||||
let (ux, uy, uz) = (full_tl[0] - bl[0], full_tl[1] - bl[1], full_tl[2] - bl[2]);
|
||||
let ulen = (ux * ux + uy * uy + uz * uz).sqrt();
|
||||
if ulen < 1e-9 {
|
||||
return vec![];
|
||||
}
|
||||
let (nx, ny, nz) = (ux / ulen, uy / ulen, uz / ulen);
|
||||
let tl = [bl[0] + nx * line_h, bl[1] + ny * line_h, bl[2] + nz * line_h];
|
||||
let tr = [br[0] + nx * line_h, br[1] + ny * line_h, br[2] + nz * line_h];
|
||||
|
||||
vec![bl, br, tr, bl, tr, tl]
|
||||
}
|
||||
|
||||
fn entity_aabb(e: &acadrust::EntityType, world_offset: [f64; 3]) -> [f32; 4] {
|
||||
|
|
|
|||
Loading…
Reference in a new issue