diff --git a/src/scene/convert/tessellate.rs b/src/scene/convert/tessellate.rs index a75dcbc04..df488c8e5 100644 --- a/src/scene/convert/tessellate.rs +++ b/src/scene/convert/tessellate.rs @@ -2658,12 +2658,19 @@ fn append_custom_arrow_leaf( true, ); for wire in wires { - append_custom_wire_points( - &wire.points, - &wire.points_low, - codec::types::Vector3::ZERO, - lines, - ); + // A wide polyline's width rides on the wire as a GPU band; an arrow + // keeps only geometry, so turn the band into fill or it draws hairline. + // (#1130) + if wire.world_width > 0.0 || wire.taper_widths.iter().any(|width| *width > 0.0) { + append_custom_band(&wire, fill); + } else { + append_custom_wire_points( + &wire.points, + &wire.points_low, + codec::types::Vector3::ZERO, + lines, + ); + } append_custom_fill_points( &wire.fill_tris, &wire.fill_tris_low, @@ -2760,6 +2767,42 @@ fn append_custom_hatch_geometry( ); } +/// Triangles covering a wide polyline's band, one quad per segment. +// ponytail: no join wedges at corners; add miters if a thick arrow shows notches. +fn append_custom_band(wire: &WireModel, fill: &mut Vec<[f32; 3]>) { + let at = |index: usize| { + let point = wire.points[index]; + let low = wire.points_low.get(index).copied().unwrap_or([0.0; 3]); + (!point[0].is_nan()).then(|| { + [ + point[0] as f64 + low[0] as f64, + point[1] as f64 + low[1] as f64, + point[2] as f64 + low[2] as f64, + ] + }) + }; + let half = |index: usize| { + wire.taper_widths.get(index).copied().unwrap_or(wire.world_width).max(0.0) as f64 * 0.5 + }; + for index in 0..wire.points.len().saturating_sub(1) { + let (Some(a), Some(b)) = (at(index), at(index + 1)) else { + continue; + }; + let (dx, dy) = (b[0] - a[0], b[1] - a[1]); + let length = dx.hypot(dy); + if length <= 0.0 { + continue; + } + let (nx, ny) = (-dy / length, dx / length); + let (ha, hb) = (half(index), half(index + 1)); + let corner = |p: [f64; 3], h: f64, side: f64| { + [(p[0] + nx * h * side) as f32, (p[1] + ny * h * side) as f32, p[2] as f32] + }; + let quad = [corner(a, ha, 1.0), corner(a, ha, -1.0), corner(b, hb, -1.0), corner(b, hb, 1.0)]; + fill.extend([quad[0], quad[1], quad[2], quad[0], quad[2], quad[3]]); + } +} + fn append_custom_wire_points( points: &[[f32; 3]], points_low: &[[f32; 3]],