You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Downstream consumers do not use HalfEdgeMesh as their primary mesh type.
They keep their own mesh (the "raw" / pre-HEM mesh — their own vertex array and
face list) and wrap it in a HalfEdgeMesh only to flatten: build the HEM with insert_vertices/insert_faces, tear it (split_path), extract components,
parameterize, and pack/merge. They then build a per-wedge UV map from the
packed result and expect to apply it back onto their pre-HEM mesh, keyed by
their own (face, corner) identities.
Summary
The round-trip is atlas corner → (F2 maps) → torn-HEM corner → pre-HEM mesh.
Three of the four hops already round-trip cleanly:
Face index.insert_faces inserts faces in order
(HalfEdgeMesh.hpp:1040-1049) and split_path only tears edges (never
re-inserts faces), so pre-HEM face i == HEM face i, carried back by F2's face_map/face_source.
Corner order.insert_face may auto-reverse a mis-wound face to stay
manifold (HalfEdgeMesh.hpp:1706-1748), permuting a face's stored corner
order. This is not a blocker: the documented per-wedge recipe resolves
corners by vertex identity against the consumer's own face, never by raw
traversal index (ChartPacking.hpp:108-123), so the reversal is absorbed,
not inverted.
Non-seam vertices.insert_vertices preserves order and tearing only appends vertices, so a non-duplicated HEM vertex keeps its pre-HEM index;
carried back by F2's vertex_map/vertex_source.
The one hop that breaks is seam-vertex identity. Tearing duplicates seam
vertices via insert_vertex(oldStart->pos) (HalfEdgeMesh.hpp:1445,1465),
appending a new index whose only link to its origin is a copied position. split_path/split_edge return void and record no duplicate → original
map. So a torn-HEM corner that lands on a seam duplicate cannot be expressed
in the consumer's pre-HEM vertex namespace — and identity-based corner
resolution (the very mechanism that absorbs the winding reversal) fails for
exactly those corners.
Why this matters
The per-wedge UV recipe in MultiChartFlatten.cpp is self-consistent within
the torn HEM's own namespace, but the consumer's goal is to land UVs on their pre-HEM mesh. Non-seam corners already work; a seam corner silently cannot,
because the duplicate has no recoverable pre-HEM vertex identity. The same gap
blocks scattering per-vertex attributes captured on the pre-HEM mesh and
emitting output indexed by the consumer's original vertices. Surfaced during
PR #99 (multi-chart packing).
Goal
Make every torn/extracted vertex — original or seam duplicate — name its pre-HEM (input) vertex, so the documented identity-keyed per-wedge recipe
resolves corners against the consumer's own faces for all corners, seams
included. Composed with F2's vertex_map/face_map and vertex_source/face_source, a consumer can take any packed/merged atlas
corner and name the pre-HEM face, corner, and vertex it came from.
Out of scope
Removing auto-rewinding or seam duplication (both intentional).
Recording the insert_face corner-order permutation / a reversed flag.
Identity-keyed corner resolution (ChartPacking.hpp:108-123) absorbs the
reversal, so it does not need to be inverted for this use case — the
corner order is recovered implicitly once seam-duplicate vertices carry their
pre-HEM identity, by locating each vertex within the consumer's own face.
Candidate approaches (to decide in the track)
Vertex origin tracking (primary) — store an origin (pre-HEM vertex
index) set on construction and copied to duplicates by split_edge, so every
vertex names its pre-HEM vertex. Survives extraction via the clone_face_
vertex copy path. With this, corners are located by identity in the
consumer's own face and the winding reversal needs no separate record.
Returned remaps — split_edge/split_path return/accumulate duplicate → original pairs; lighter-weight but does not survive extraction
without the caller threading it through, and gives no uniform "every vertex
names its input vertex" accessor.
References
include/OpenABF/HalfEdgeMesh.hpp:1445,1465 (seam-vertex duplication — the gap)
include/OpenABF/HalfEdgeMesh.hpp:1706-1748 (winding reversal — absorbed, not a blocker)
Use case
Downstream consumers do not use
HalfEdgeMeshas their primary mesh type.They keep their own mesh (the "raw" / pre-HEM mesh — their own vertex array and
face list) and wrap it in a
HalfEdgeMeshonly to flatten: build the HEM withinsert_vertices/insert_faces, tear it (split_path), extract components,parameterize, and pack/merge. They then build a per-wedge UV map from the
packed result and expect to apply it back onto their pre-HEM mesh, keyed by
their own
(face, corner)identities.Summary
The round-trip is
atlas corner → (F2 maps) → torn-HEM corner → pre-HEM mesh.Three of the four hops already round-trip cleanly:
insert_facesinserts faces in order(
HalfEdgeMesh.hpp:1040-1049) andsplit_pathonly tears edges (neverre-inserts faces), so pre-HEM face
i== HEM facei, carried back by F2'sface_map/face_source.insert_facemay auto-reverse a mis-wound face to staymanifold (
HalfEdgeMesh.hpp:1706-1748), permuting a face's stored cornerorder. This is not a blocker: the documented per-wedge recipe resolves
corners by vertex identity against the consumer's own face, never by raw
traversal index (
ChartPacking.hpp:108-123), so the reversal is absorbed,not inverted.
insert_verticespreserves order and tearing onlyappends vertices, so a non-duplicated HEM vertex keeps its pre-HEM index;
carried back by F2's
vertex_map/vertex_source.The one hop that breaks is seam-vertex identity. Tearing duplicates seam
vertices via
insert_vertex(oldStart->pos)(HalfEdgeMesh.hpp:1445,1465),appending a new index whose only link to its origin is a copied position.
split_path/split_edgereturnvoidand record noduplicate → originalmap. So a torn-HEM corner that lands on a seam duplicate cannot be expressed
in the consumer's pre-HEM vertex namespace — and identity-based corner
resolution (the very mechanism that absorbs the winding reversal) fails for
exactly those corners.
Why this matters
The per-wedge UV recipe in
MultiChartFlatten.cppis self-consistent withinthe torn HEM's own namespace, but the consumer's goal is to land UVs on their
pre-HEM mesh. Non-seam corners already work; a seam corner silently cannot,
because the duplicate has no recoverable pre-HEM vertex identity. The same gap
blocks scattering per-vertex attributes captured on the pre-HEM mesh and
emitting output indexed by the consumer's original vertices. Surfaced during
PR #99 (multi-chart packing).
Goal
Make every torn/extracted vertex — original or seam duplicate — name its
pre-HEM (input) vertex, so the documented identity-keyed per-wedge recipe
resolves corners against the consumer's own faces for all corners, seams
included. Composed with F2's
vertex_map/face_mapandvertex_source/face_source, a consumer can take any packed/merged atlascorner and name the pre-HEM face, corner, and vertex it came from.
Out of scope
insert_facecorner-order permutation / a reversed flag.Identity-keyed corner resolution (
ChartPacking.hpp:108-123) absorbs thereversal, so it does not need to be inverted for this use case — the
corner order is recovered implicitly once seam-duplicate vertices carry their
pre-HEM identity, by locating each vertex within the consumer's own face.
Candidate approaches (to decide in the track)
origin(pre-HEM vertexindex) set on construction and copied to duplicates by
split_edge, so everyvertex names its pre-HEM vertex. Survives extraction via the
clone_face_vertex copy path. With this, corners are located by identity in the
consumer's own face and the winding reversal needs no separate record.
split_edge/split_pathreturn/accumulateduplicate → originalpairs; lighter-weight but does not survive extractionwithout the caller threading it through, and gives no uniform "every vertex
names its input vertex" accessor.
References
include/OpenABF/HalfEdgeMesh.hpp:1445,1465(seam-vertex duplication — the gap)include/OpenABF/HalfEdgeMesh.hpp:1706-1748(winding reversal — absorbed, not a blocker)include/OpenABF/ChartPacking.hpp:108-123(identity-keyed per-wedge recipe)MultiChartFlatten.cppreference comment +PackCharts/MergeMeshesprovenance maps (the downstream half of the chain).