v0.55.1 — Per-triangle highlight overlay (closes #25)
Closes #25. Per-sub-shape highlight overlay — replaces the v0.1 OCCTSwiftAIS cheap-route pattern with a renderer-side per-triangle style buffer + dedicated render pass.
What's new
// Empty (default) — no behavioural change.
var body = ViewportBody.box(id: "part")
// Highlight specific triangles by writing per-triangle styles.
body.triangleStyles = (0..<body.indices.count / 3).map { idx in
isFaceTriangle(idx, faceID: selectedFace)
? TriangleStyle(color: SIMD4<Float>(0.1, 0.5, 1.0, 0.5))
: .none
}TriangleStyle is a single SIMD4<Float> color (16 bytes per triangle). Zero-alpha entries skip the highlight pass.
Why this beats the v0.1 cheap route
- No silhouette flicker. Identical geometry depth-tests cleanly with
.lessEqualinstead of needing the bbox-diagonal nudge along normals. - No vertex-data churn. Selection / hover state changes flip per-triangle alpha; no overlay body to spawn or kill on every selection change.
- No body-count blow-up. Style buffer scales with triangle count, not with selection count.
- Hover + multi-select for free. Per-triangle style means hover at low alpha and primary selection at higher alpha can coexist on the same body without spawning N overlay bodies.
Renderer changes
- New
triangle_highlightMTL pipeline +highlight_vertex/highlight_fragmentMSL shaders. - Per-body
triangleStyleBuffer: MTLBuffer?cached alongside the existing vertex / index / edge buffers; built only whentriangleStylesis populated, nil otherwise. - New render pass inserted between the shaded pass and the selection-outline pass.
- New
highlightDepthState(.lessEqual+ depth-write disabled) so identical-position highlights win the depth tie without disturbing depth state for subsequent passes. - Fragment shader indexes the style buffer by
[[primitive_id]]; discards triangles with alpha == 0.
Tests
4 new tests in TriangleStyleTests:
TriangleStyle.noneis transparent- Default-constructed
TriangleStyleequals.none ViewportBodydefaulttriangleStylesis emptyViewportBodyround-trips a non-empty styles array
All 50 viewport tests pass.
Driver
OCCTSwiftAIS v0.6+ will adopt this and drop its makeFaceOverlay(...) cheap-route helper. Body-level selection still routes through viewport.selectedBodyIDs (already works).
Pin
.package(url: "https://github.com/gsdali/OCCTSwiftViewport.git", from: "0.55.1"),Pure additive: existing call sites keep working with triangleStyles defaulting to [].