Fix LibTess tessellation NRE and post-union vertex welding#1106
Conversation
serenayl
left a comment
There was a problem hiding this comment.
@serenayl reviewed 13 files and all commit messages, and made 2 comments.
Reviewable status:complete! 1 of 1 approvals obtained (waiting on jamesbradleym).
Elements/src/Geometry/Tessellation/HyparTessCombine.cs line 24 at r1 (raw file):
/// collide with the small, sequential tags emitted by the CSG library. /// </summary> internal static class HyparTessCombine
Nit: Should this just be something like CombineCallbacks instead of sounding extra-hypar-specific?
Code quote:
HyparTessCombineElements/src/Geometry/Tessellation/HyparTessCombine.cs line 31 at r1 (raw file):
private static long _syntheticCsgTagCounter = 0x90000000L; internal static CombineCallback HyparDataCombine { get; } = Combine;
Nit: Does this maybe just want to be DataCombine? Should we name the private field it gets more consistently too, if there are two private combine fields?
Code quote:
HyparDataCombine
jamesbradleym
left a comment
There was a problem hiding this comment.
@jamesbradleym resolved 2 discussions.
Reviewable status:complete! 1 of 1 approvals obtained.
BACKGROUND:
Same MEP rendering failure as the Csg PR. Investigation surfaced two distinct Elements-side bugs in the tessellation → GLB pipeline:
LibTess NRE. When
LibTesssynthesizesnew ContourVertexs at contour T-junctions or self-intersections (e.g., for a self-intersecting polygon coming from CSG output), those vertices haveData == nullby default. The pack code (Tessellation.PackTessellationsIntoBuffers) unboxedv.Datato a 4-tuple shape without null-handling — instantNullReferenceException.Post-union vertex welding. After a CSG boolean, polygons can carry duplicate
Shared.Tagvalues across unrelated faces. The pack's vertex dedup map keyed on (tag, faceId, solidId) would weld vertices at different 3D positions into one index, producing corrupt mesh output (wrong normals, dropped triangles).Both bugs fire in the same MEP geometry path (multi-solid Union → tessellate → GLB).
DESCRIPTION:
HyparTessCombineclass providing twoCombineCallbackfactories —HyparDataCombine(4-tuple data shape for CSG/solid-face adapters) andCsgTexTagCombine((Csg.Vector2D, int)for the legacyAddToMeshpath). Each assigns unique synthetic tags viaInterlocked.Incrementfrom disjoint starting ranges.CsgPolygonTessAdapterandSolidFaceTessAdapternow passHyparDataCombineintotess.Tessellate(...), eliminating the null-Data NRE at the source.Tessellation.PackTessellationsIntoBuffershardened with:AddToMesh(the >4-vertex polygon branch) wiresCsgTexTagCombineand null-safely unboxes triangle data via a newTexTagOrDefaulthelper.CsgVertexDatastruct replaces the spread(UV, uint, uint, uint) ValueTupleacross 6+ producer/consumer sites.SkipCSGUnion = true.TESTING:
Tested with an Aliaxis workflow + function referencing local Elements:
Example workflow: workflows/edcd98fa-06bd-4a55-8e3d-f9ed103f3b1d
Example function: https://github.com/hypar-io/aliaxis/tree/main/ImportedSystemConfiguration (remember to set stream model to false when using hypar run)
FUTURE WORK:
REQUIRED:
CHANGELOG.md.COMMENTS:
BEFORE:


AFTER:


This change is