OCCTSwiftViewport v1.1.23 adds an opt-in direct-mesh render path. Filing here for visibility — this repo needs no action. You pin occtDep("OCCTSwiftViewport", from: "1.0.4"), which already resolves forward; occtkit's RenderPreview goes through OCCTSwiftTools, so the benefit reaches you via Tools rather than through any change here.
What shipped
ViewportBody.directMesh(id:positions:normals:indices:color:…) builds a body from de-interleaved position/normal arrays, which the renderer uploads as two GPU buffers (position @ 0, normal @ 2) instead of one interleaved stride-6 buffer.
The interleaved path exists only because the old API demanded one packed array: it forces a full extra pass over every vertex plus a duplicate in-memory copy of the mesh, and then runs NormalSmoothing over normals that (for kernel-sourced geometry) were already analytically correct. Skipping that is a load-time and peak-memory win that scales with mesh size.
Full render-pass parity in both ViewportRenderer and OffscreenRenderer — shaded (opaque + transparent), shadows, SSAO/silhouette prepass, overlay, GPU pick — verified with differential renders, Metal API + GPU Validation, and on-device pick readback.
Do you need to do anything?
No. This is filed for visibility, not to ask for work.
- The API is additive and opt-in — new defaulted parameters and a new factory. Nothing changes unless you call
directMesh(...); interleaved bodies keep the existing path, including autoSmoothNormals. Both kinds coexist in one scene.
- It is source-compatible (PATCH bump), and your
from: pin is a SemVer range, so you will resolve to 1.1.23 on your next swift package update with nothing to change.
When you would care
Only if you build a ViewportBody from flat, contiguous [Float] position + normal arrays. Then directMesh(...) lets you hand them straight over and delete your interleave loop.
If your mesh stores [SIMD3<Float>], this buys you nothing — SIMD3 is 16-byte padded, so it cannot be reinterpreted as flat floats and you would have to copy/flatten anyway. Stay on the interleaved path.
If you load geometry through OCCTSwiftTools.CADFileLoader, the win arrives there rather than here: SecondMouseAU/OCCTSwiftTools#31 tracks adopting it (the bridge is already prototyped on spike/direct-mesh-bridge, which was blocked on this release). Once Tools lands it and cuts a release, you would pick it up with a Tools bump and an opt-in flag.
Also in 1.1.23
- Fixed: a
SceneRaycast crash — the narrowphase read vertexData (empty on direct bodies) indexed by indices, trapping on any raycast against a direct body. Only affects direct-mesh bodies, so it cannot bite you unless you adopt the path.
Caveats if you do adopt
- Normals are used verbatim —
NormalSmoothing, autoSmoothNormals and PN-triangle tessellation (renderingQuality = .enhanced) do not apply to direct bodies. If you rely on auto-smoothing to round a coarse mesh, stay interleaved.
- A direct body carries no separate B-Rep corner-vertex / per-segment edge pick indices (
vertices holds mesh vertices, for bbox / fit(to:) / CPU raycast). Face display, GPU pick, CPU raycast and edge display all work.
- After changing a viewport pin, run
swift package clean — stale .o artifacts cached against an older ViewportBody.init have produced link errors before even when the source was compatible.
Links
OCCTSwiftViewport v1.1.23 adds an opt-in direct-mesh render path. Filing here for visibility — this repo needs no action. You pin
occtDep("OCCTSwiftViewport", from: "1.0.4"), which already resolves forward;occtkit'sRenderPreviewgoes throughOCCTSwiftTools, so the benefit reaches you via Tools rather than through any change here.What shipped
ViewportBody.directMesh(id:positions:normals:indices:color:…)builds a body from de-interleaved position/normal arrays, which the renderer uploads as two GPU buffers (position @ 0, normal @ 2) instead of one interleaved stride-6 buffer.The interleaved path exists only because the old API demanded one packed array: it forces a full extra pass over every vertex plus a duplicate in-memory copy of the mesh, and then runs
NormalSmoothingover normals that (for kernel-sourced geometry) were already analytically correct. Skipping that is a load-time and peak-memory win that scales with mesh size.Full render-pass parity in both
ViewportRendererandOffscreenRenderer— shaded (opaque + transparent), shadows, SSAO/silhouette prepass, overlay, GPU pick — verified with differential renders, Metal API + GPU Validation, and on-device pick readback.Do you need to do anything?
No. This is filed for visibility, not to ask for work.
directMesh(...); interleaved bodies keep the existing path, includingautoSmoothNormals. Both kinds coexist in one scene.from:pin is a SemVer range, so you will resolve to 1.1.23 on your nextswift package updatewith nothing to change.When you would care
Only if you build a
ViewportBodyfrom flat, contiguous[Float]position + normal arrays. ThendirectMesh(...)lets you hand them straight over and delete your interleave loop.If your mesh stores
[SIMD3<Float>], this buys you nothing —SIMD3is 16-byte padded, so it cannot be reinterpreted as flat floats and you would have to copy/flatten anyway. Stay on the interleaved path.If you load geometry through
OCCTSwiftTools.CADFileLoader, the win arrives there rather than here: SecondMouseAU/OCCTSwiftTools#31 tracks adopting it (the bridge is already prototyped onspike/direct-mesh-bridge, which was blocked on this release). Once Tools lands it and cuts a release, you would pick it up with a Tools bump and an opt-in flag.Also in 1.1.23
SceneRaycastcrash — the narrowphase readvertexData(empty on direct bodies) indexed byindices, trapping on any raycast against a direct body. Only affects direct-mesh bodies, so it cannot bite you unless you adopt the path.Caveats if you do adopt
NormalSmoothing,autoSmoothNormalsand PN-triangle tessellation (renderingQuality = .enhanced) do not apply to direct bodies. If you rely on auto-smoothing to round a coarse mesh, stay interleaved.verticesholds mesh vertices, for bbox /fit(to:)/ CPU raycast). Face display, GPU pick, CPU raycast and edge display all work.swift package clean— stale.oartifacts cached against an olderViewportBody.inithave produced link errors before even when the source was compatible.Links