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
|
|
@ -627,11 +627,13 @@ pub fn expand_insert(
|
||||||
Some(batches.finalize(&name, selected))
|
Some(batches.finalize(&name, selected))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a greeked rectangle for a text LocalWire — same color, OBB-sized
|
/// Emit a greeked filled rect (2 triangles) for a text LocalWire. Stays in
|
||||||
/// fill (rotated to match the entity), no per-glyph stroke geometry.
|
/// the text's own color — the face3d pipeline skips its 0.45 dim for wires
|
||||||
/// Mirrors the top-level text greek in scene/mod.rs (including the 0.45
|
/// whose `points` are empty, so the rect lands at full intensity. Clamped
|
||||||
/// dim pre-boost the face3d pipeline applies to fill_tris). Falls back to
|
/// to a single line's height so multi-line MText doesn't blow the box up
|
||||||
/// the axis-aligned `local_aabb` when no OBB was precomputed.
|
/// to the full block. Mirrors `text_greek_obb_tris` in scene/mod.rs.
|
||||||
|
/// Falls back to the axis-aligned `local_aabb` when no OBB was cached;
|
||||||
|
/// xref fade still applies via the shared color resolution.
|
||||||
fn emit_greeked_text(
|
fn emit_greeked_text(
|
||||||
lw: &LocalWire,
|
lw: &LocalWire,
|
||||||
local_aabb: [f32; 4],
|
local_aabb: [f32; 4],
|
||||||
|
|
@ -642,11 +644,9 @@ fn emit_greeked_text(
|
||||||
) {
|
) {
|
||||||
let [ox, oy, oz] = ctx.world_offset;
|
let [ox, oy, oz] = ctx.world_offset;
|
||||||
let [lo_x, lo_y, lo_z] = defn_lo;
|
let [lo_x, lo_y, lo_z] = defn_lo;
|
||||||
let tris: [[f32; 3]; 6] = if let Some(obb) = lw.text_obb_local {
|
|
||||||
// Re-add the defn's `local_offset` in f64 before composing with
|
// Re-add the defn's `local_offset` in f64 before composing with
|
||||||
// `accum_xform` (the OBB corners are stored in offset frame f32 so
|
// `accum_xform` so the rect corners share the batch's f32 space
|
||||||
// they don't lose precision for distant text). Then subtract host
|
// without losing precision for distant text.
|
||||||
// `world_offset` so the fill_tris share the batch's f32 space.
|
|
||||||
let xf = |p: [f32; 3]| -> [f32; 3] {
|
let xf = |p: [f32; 3]| -> [f32; 3] {
|
||||||
let w = accum_xform.apply(Vector3::new(
|
let w = accum_xform.apply(Vector3::new(
|
||||||
p[0] as f64 + lo_x,
|
p[0] as f64 + lo_x,
|
||||||
|
|
@ -655,22 +655,46 @@ fn emit_greeked_text(
|
||||||
));
|
));
|
||||||
[(w.x - ox) as f32, (w.y - oy) as f32, (w.z - oz) as f32]
|
[(w.x - ox) as f32, (w.y - oy) as f32, (w.z - oz) as f32]
|
||||||
};
|
};
|
||||||
let p00 = xf(obb[0]);
|
|
||||||
let p10 = xf(obb[1]);
|
let corners: Option<[[f32; 3]; 4]> = if let (Some(obb), Some(h_local)) =
|
||||||
let p11 = xf(obb[2]);
|
(lw.text_obb_local, lw.text_height_local)
|
||||||
let p01 = xf(obb[3]);
|
{
|
||||||
[p00, p10, p11, p00, p11, p01]
|
if h_local <= 0.0 {
|
||||||
|
None
|
||||||
} else {
|
} else {
|
||||||
|
// OBB[3] - OBB[0] = up direction in local frame, full-block
|
||||||
|
// height for MText; normalize and rescale to a single line.
|
||||||
|
let dx = obb[3][0] - obb[0][0];
|
||||||
|
let dy = obb[3][1] - obb[0][1];
|
||||||
|
let dz = obb[3][2] - obb[0][2];
|
||||||
|
let dlen = (dx * dx + dy * dy + dz * dz).sqrt();
|
||||||
|
if dlen < 1e-9 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let nx = dx / dlen * h_local;
|
||||||
|
let ny = dy / dlen * h_local;
|
||||||
|
let nz = dz / dlen * h_local;
|
||||||
|
let bl = obb[0];
|
||||||
|
let br = obb[1];
|
||||||
|
let tl = [bl[0] + nx, bl[1] + ny, bl[2] + nz];
|
||||||
|
let tr = [br[0] + nx, br[1] + ny, br[2] + nz];
|
||||||
|
Some([xf(bl), xf(br), xf(tr), xf(tl)])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// OBB missing — fall back to the axis-aligned local AABB. Already
|
||||||
|
// a tight per-entity rect (no multi-line block to clamp).
|
||||||
let [x0, y0, x1, y1] = local_aabb;
|
let [x0, y0, x1, y1] = local_aabb;
|
||||||
let z = 0.0_f32;
|
let z = 0.0_f32;
|
||||||
[
|
Some([
|
||||||
[x0, y0, z],
|
xf([x0, y0, z]),
|
||||||
[x1, y0, z],
|
xf([x1, y0, z]),
|
||||||
[x1, y1, z],
|
xf([x1, y1, z]),
|
||||||
[x0, y0, z],
|
xf([x0, y1, z]),
|
||||||
[x1, y1, z],
|
])
|
||||||
[x0, y1, z],
|
};
|
||||||
]
|
let Some([bl, br, tr, tl]) = corners else {
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let final_color = if ctx.selected {
|
let final_color = if ctx.selected {
|
||||||
|
|
@ -680,29 +704,19 @@ fn emit_greeked_text(
|
||||||
} else {
|
} else {
|
||||||
lw.color
|
lw.color
|
||||||
};
|
};
|
||||||
// Apply the same xref fade as `emit_wire` BEFORE the face3d 0.45 boost,
|
|
||||||
// so the final on-screen color (boost × 0.45 dim) lands at the faded value.
|
|
||||||
let final_color = if ctx.is_xref && !ctx.selected {
|
let final_color = if ctx.is_xref && !ctx.selected {
|
||||||
fade_toward_bg(final_color, ctx.bg_color)
|
fade_toward_bg(final_color, ctx.bg_color)
|
||||||
} else {
|
} else {
|
||||||
final_color
|
final_color
|
||||||
};
|
};
|
||||||
let boost = 1.0 / 0.45_f32;
|
|
||||||
let [r, g, b, a] = final_color;
|
|
||||||
let greek_color = [
|
|
||||||
(r * boost).min(1.0),
|
|
||||||
(g * boost).min(1.0),
|
|
||||||
(b * boost).min(1.0),
|
|
||||||
a,
|
|
||||||
];
|
|
||||||
|
|
||||||
let key = style_key(greek_color, 0.0, [0.0; 8], 1.0, lw.aci, true);
|
let key = style_key(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true, true);
|
||||||
let entry = out
|
let entry = out
|
||||||
.by_style
|
.by_style
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| BatchEntry::new(greek_color, 0.0, [0.0; 8], 1.0, lw.aci, true));
|
.or_insert_with(|| BatchEntry::new(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true, true));
|
||||||
for p in tris {
|
|
||||||
entry.fill_tris.push(p);
|
for p in [bl, br, tr, bl, tr, tl] {
|
||||||
if p[0] < entry.min_x {
|
if p[0] < entry.min_x {
|
||||||
entry.min_x = p[0];
|
entry.min_x = p[0];
|
||||||
}
|
}
|
||||||
|
|
@ -715,6 +729,7 @@ fn emit_greeked_text(
|
||||||
if p[1] > entry.max_y {
|
if p[1] > entry.max_y {
|
||||||
entry.max_y = p[1];
|
entry.max_y = p[1];
|
||||||
}
|
}
|
||||||
|
entry.fill_tris.push(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -767,11 +782,11 @@ fn emit_text_baseline(
|
||||||
final_color
|
final_color
|
||||||
};
|
};
|
||||||
|
|
||||||
let key = style_key(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true);
|
let key = style_key(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true, false);
|
||||||
let entry = out
|
let entry = out
|
||||||
.by_style
|
.by_style
|
||||||
.entry(key)
|
.entry(key)
|
||||||
.or_insert_with(|| BatchEntry::new(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true));
|
.or_insert_with(|| BatchEntry::new(final_color, 0.0, [0.0; 8], 1.0, lw.aci, true, false));
|
||||||
|
|
||||||
let needs_sep = !entry.points.is_empty()
|
let needs_sep = !entry.points.is_empty()
|
||||||
&& !entry.points.last().map(|p| p[0].is_nan()).unwrap_or(false);
|
&& !entry.points.last().map(|p| p[0].is_nan()).unwrap_or(false);
|
||||||
|
|
@ -844,6 +859,11 @@ struct StyleKey {
|
||||||
line_weight_px: u32,
|
line_weight_px: u32,
|
||||||
aci: u8,
|
aci: u8,
|
||||||
plinegen: bool,
|
plinegen: bool,
|
||||||
|
/// Marks batches that emit only `fill_tris` with no wire `points`. The
|
||||||
|
/// face3d pipeline uses `wire.points.is_empty()` as the "skip dim"
|
||||||
|
/// discriminator, so greek fills must stay in their own batches even
|
||||||
|
/// when their color/style would otherwise collide with regular wires.
|
||||||
|
is_fill_only: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
|
|
@ -880,7 +900,20 @@ struct Batches {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BatchEntry {
|
impl BatchEntry {
|
||||||
fn new(color: [f32; 4], pat_len: f32, pat: [f32; 8], lw_px: f32, aci: u8, plinegen: bool) -> Self {
|
fn new(
|
||||||
|
color: [f32; 4],
|
||||||
|
pat_len: f32,
|
||||||
|
pat: [f32; 8],
|
||||||
|
lw_px: f32,
|
||||||
|
aci: u8,
|
||||||
|
plinegen: bool,
|
||||||
|
_is_fill_only: bool,
|
||||||
|
) -> Self {
|
||||||
|
// `is_fill_only` is part of the StyleKey hash so greek fills never
|
||||||
|
// share a batch with regular wires (otherwise the finalized
|
||||||
|
// WireModel would have both `points` and `fill_tris`, defeating
|
||||||
|
// the face3d-dim discriminator). It isn't stored on the entry
|
||||||
|
// itself — the empty `points` field is enough at finalize time.
|
||||||
Self {
|
Self {
|
||||||
color,
|
color,
|
||||||
pattern_length: pat_len,
|
pattern_length: pat_len,
|
||||||
|
|
@ -937,6 +970,7 @@ fn style_key(
|
||||||
lw_px: f32,
|
lw_px: f32,
|
||||||
aci: u8,
|
aci: u8,
|
||||||
plinegen: bool,
|
plinegen: bool,
|
||||||
|
is_fill_only: bool,
|
||||||
) -> StyleKey {
|
) -> StyleKey {
|
||||||
StyleKey {
|
StyleKey {
|
||||||
color: [
|
color: [
|
||||||
|
|
@ -959,6 +993,7 @@ fn style_key(
|
||||||
line_weight_px: lw_px.to_bits(),
|
line_weight_px: lw_px.to_bits(),
|
||||||
aci,
|
aci,
|
||||||
plinegen,
|
plinegen,
|
||||||
|
is_fill_only,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1164,6 +1199,7 @@ fn emit_wire(
|
||||||
final_lw_px,
|
final_lw_px,
|
||||||
lw.aci,
|
lw.aci,
|
||||||
lw.plinegen,
|
lw.plinegen,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
// If the open batch for this style would exceed wgpu's per-buffer limit
|
// If the open batch for this style would exceed wgpu's per-buffer limit
|
||||||
|
|
@ -1183,6 +1219,7 @@ fn emit_wire(
|
||||||
final_lw_px,
|
final_lw_px,
|
||||||
lw.aci,
|
lw.aci,
|
||||||
lw.plinegen,
|
lw.plinegen,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4195,22 +4195,13 @@ fn tessellate_entity(
|
||||||
}
|
}
|
||||||
if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB {
|
if h_px < 5.0 && aabb != WireModel::UNBOUNDED_AABB {
|
||||||
let fill_tris = text_greek_obb_tris(e, anno_scale, world_offset);
|
let fill_tris = text_greek_obb_tris(e, anno_scale, world_offset);
|
||||||
// The face3d pipeline dims fill_tris colors to 45% to fake
|
if fill_tris.is_empty() {
|
||||||
// ambient occlusion on PolyfaceMesh / 3DFACE solids. Greeked
|
return vec![];
|
||||||
// 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,
|
|
||||||
];
|
|
||||||
return vec![WireModel {
|
return vec![WireModel {
|
||||||
name: h.value().to_string(),
|
name: h.value().to_string(),
|
||||||
points: vec![],
|
points: vec![],
|
||||||
color: greek_color,
|
color: entity_color,
|
||||||
selected: sel,
|
selected: sel,
|
||||||
aci,
|
aci,
|
||||||
pattern_length: 0.0,
|
pattern_length: 0.0,
|
||||||
|
|
@ -4401,8 +4392,11 @@ fn text_baseline_points(
|
||||||
vec![cast(corners[0]), cast(corners[1])]
|
vec![cast(corners[0]), cast(corners[1])]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 6-vertex (2-triangle) fill for a greeked top-level Text / MText, in
|
/// 6-vertex filled rect (2 triangles) for a greeked top-level Text / MText.
|
||||||
/// world-offset-subtracted f32 space.
|
/// 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(
|
fn text_greek_obb_tris(
|
||||||
e: &EntityType,
|
e: &EntityType,
|
||||||
anno_scale: f32,
|
anno_scale: f32,
|
||||||
|
|
@ -4411,13 +4405,35 @@ fn text_greek_obb_tris(
|
||||||
let Some(corners) = text_obb_corners_native(e, anno_scale) else {
|
let Some(corners) = text_obb_corners_native(e, anno_scale) else {
|
||||||
return vec![];
|
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 [ox, oy, oz] = world_offset;
|
||||||
let cast = |p: [f64; 3]| -> [f32; 3] {
|
let cast = |p: [f64; 3]| -> [f32; 3] {
|
||||||
[(p[0] - ox) as f32, (p[1] - oy) as f32, (p[2] - oz) as f32]
|
[(p[0] - ox) as f32, (p[1] - oy) as f32, (p[2] - oz) as f32]
|
||||||
};
|
};
|
||||||
let [p00, p10, p11, p01] = corners;
|
let bl = cast(corners[0]);
|
||||||
let (p00, p10, p11, p01) = (cast(p00), cast(p10), cast(p11), cast(p01));
|
let br = cast(corners[1]);
|
||||||
vec![p00, p10, p11, p00, p11, p01]
|
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] {
|
fn entity_aabb(e: &acadrust::EntityType, world_offset: [f64; 3]) -> [f32; 4] {
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,22 @@ impl Face3DGpu {
|
||||||
vertices.push(v(3));
|
vertices.push(v(3));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PolyfaceMesh / PolygonMesh pre-triangulated fills.
|
// PolyfaceMesh / PolygonMesh / unlit fills (text greek, MultiLeader
|
||||||
|
// background). Wires whose `points` are empty carry pure 2-D fills
|
||||||
|
// that should render at their literal color — applying the 0.45
|
||||||
|
// AO-style dim to them would wash out user-picked colors. Wires
|
||||||
|
// with both fill_tris and points (mesh edges + faces) keep the dim
|
||||||
|
// so PolyfaceMesh / PolygonMesh still look 3-D-shaded.
|
||||||
for wire in all_wires {
|
for wire in all_wires {
|
||||||
if wire.fill_tris.is_empty() {
|
if wire.fill_tris.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let [r, g, b, a] = wire.color;
|
let [r, g, b, a] = wire.color;
|
||||||
let fill_color = [r * 0.45, g * 0.45, b * 0.45, a];
|
let fill_color = if wire.points.is_empty() {
|
||||||
|
[r, g, b, a]
|
||||||
|
} else {
|
||||||
|
[r * 0.45, g * 0.45, b * 0.45, a]
|
||||||
|
};
|
||||||
for &position in &wire.fill_tris {
|
for &position in &wire.fill_tris {
|
||||||
vertices.push(Face3DVertex {
|
vertices.push(Face3DVertex {
|
||||||
position,
|
position,
|
||||||
|
|
|
||||||
|
|
@ -909,29 +909,32 @@ pub fn tessellate_multileader(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else if lod_mode == 1 {
|
} else if lod_mode == 1 {
|
||||||
// Greeked rect — tight text bbox (no frame padding).
|
// One filled rect per line — keeps the visual "text lives here
|
||||||
let block_top = v_offset + height;
|
// per row" hint that multi-line MText carries, in the text's
|
||||||
let block_bottom = v_offset - (n_lines - 1.0) * line_h;
|
// own color. Empty `points` opts out of the face3d 0.45 dim so
|
||||||
let block_left = -max_line_w * h_anchor;
|
// the fill renders at full intensity.
|
||||||
let block_right = max_line_w * (1.0 - h_anchor);
|
let mut greek_tris: Vec<[f32; 3]> = Vec::with_capacity(lines.len() * 6);
|
||||||
let c00 = to_wcs(block_left, block_bottom);
|
for (i, _) in lines.iter().enumerate() {
|
||||||
let c10 = to_wcs(block_right, block_bottom);
|
let li = i as f32;
|
||||||
let c11 = to_wcs(block_right, block_top);
|
let line_y_bottom = -li * line_h + v_offset;
|
||||||
let c01 = to_wcs(block_left, block_top);
|
let line_y_top = line_y_bottom + height;
|
||||||
// Pre-boost the color so the face3d 0.45 fill_tris dim lands at
|
let line_w = line_widths[i];
|
||||||
// the original text color (matches scene/mod.rs greek path).
|
if line_w <= 0.0 {
|
||||||
let boost = 1.0 / 0.45_f32;
|
continue;
|
||||||
let [r, g, b, a] = text_color;
|
}
|
||||||
let greek_color = [
|
let left = -line_w * h_anchor;
|
||||||
(r * boost).min(1.0),
|
let right = line_w * (1.0 - h_anchor);
|
||||||
(g * boost).min(1.0),
|
let bl = to_wcs(left, line_y_bottom);
|
||||||
(b * boost).min(1.0),
|
let br = to_wcs(right, line_y_bottom);
|
||||||
a,
|
let tr = to_wcs(right, line_y_top);
|
||||||
];
|
let tl = to_wcs(left, line_y_top);
|
||||||
|
greek_tris.extend_from_slice(&[bl, br, tr, bl, tr, tl]);
|
||||||
|
}
|
||||||
|
if !greek_tris.is_empty() {
|
||||||
wires.push(WireModel {
|
wires.push(WireModel {
|
||||||
name: name.clone(),
|
name: name.clone(),
|
||||||
points: vec![],
|
points: vec![],
|
||||||
color: greek_color,
|
color: text_color,
|
||||||
selected,
|
selected,
|
||||||
aci: 0,
|
aci: 0,
|
||||||
pattern_length: 0.0,
|
pattern_length: 0.0,
|
||||||
|
|
@ -946,8 +949,9 @@ pub fn tessellate_multileader(
|
||||||
aabb: WireModel::UNBOUNDED_AABB,
|
aabb: WireModel::UNBOUNDED_AABB,
|
||||||
plinegen: true,
|
plinegen: true,
|
||||||
vp_scissor: None,
|
vp_scissor: None,
|
||||||
fill_tris: vec![c00, c10, c11, c00, c11, c01],
|
fill_tris: greek_tris,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Build per-line stroke points in WCS.
|
// Build per-line stroke points in WCS.
|
||||||
let mut text_points: Vec<[f32; 3]> = Vec::new();
|
let mut text_points: Vec<[f32; 3]> = Vec::new();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue