Skip to content

v1.1.23 — Direct-mesh rendering path

Choose a tag to compare

@gsdali gsdali released this 16 Jul 08:08

Opt-in direct-mesh render path: ViewportBody.directMesh(id:positions:normals:indices:color:…) builds a body from de-interleaved position/normal arrays, uploaded as two GPU buffers (position @ buffer 0, normal @ buffer 2) instead of one interleaved stride-6 buffer.

Why

The interleaved path walks every vertex to repack position+normal before upload — an extra pass plus an extra in-memory copy. A CAD kernel's triangulation (OCCT Poly_Triangulation) already stores those arrays flat and contiguous, so that repack is pure overhead. Removing it is a load-time and peak-memory win that scales with mesh size.

It also skips NormalSmoothing, which is correct for OCCT-sourced geometry: those per-vertex normals are already analytically accurate. (Re-deriving them from face normals caused the striations fixed in v1.1.22 — this is complementary.)

Opt-in and source-compatible

Nothing changes unless you call directMesh(...). Interleaved bodies keep the existing path, including autoSmoothNormals. Both kinds coexist in one scene. New API: meshPositions, meshNormals, usesDirectMesh; init gains defaulted meshPositions:/meshNormals:.

Render-pass parity

All passes route direct bodies in both ViewportRenderer and OffscreenRenderer: shaded (opaque + transparent), shadow casting, SSAO/silhouette depth prepass, overlay layer, GPU pick.

Limitations (by design)

  • autoSmoothNormals and PN-triangle tessellation (renderingQuality = .enhanced) do not apply to direct bodies — their normals are used verbatim.
  • A direct body carries no separate B-Rep corner-vertex / per-segment edge pick indices (vertices holds the mesh vertices, for bbox / fit(to:) / CPU raycast). Face display, GPU pick, CPU raycast and edge display all work.
  • Only consumers holding flat contiguous [Float] arrays benefit. If your mesh stores [SIMD3<Float>], you would have to flatten anyway (SIMD3 is 16-byte padded) — stay on the interleaved path.

Fixed

  • SceneRaycast crash on direct-mesh bodies — the narrowphase read vertexData (empty on direct bodies) indexed by indices, trapping on any raycast against one. Now reads vertices when vertexData is empty.

Verification

170 tests (7 new differential/pipeline/raycast tests). Verified beyond the headless suite: macOS under Metal API + GPU Validation with SSAO/silhouettes/shadows/overlay/picking enabled (zero errors), and GPU pick readback confirmed on an iPhone 15 Pro. New Examples/DirectMeshVerify on-device rig.

Full changelog: docs/CHANGELOG.md · PR: #83