An editable non-manifold polygon mesh data structure
28 July 2025
Tags: Geometry Data Structures
One core data structure in my 3D modeling application is a non-manifold polygon mesh data structure. This data structure is a graph of Vertices, Edges and Faces. It takes inspiration from Blender’s BMesh data structure, the Radial Edge Structure (see Nvidia SMLib - Topology documentation) and the paper Partial Entity Structure: A Compact Boundary Representation for Non-Manifold Geometric Modeling by Lee et al., but arrives at a simpler design that still has the desired feature set.
The data structure supports:
- non-manifold edges, meaning more than 2 faces can be connected to a given edge
- loose vertices (vertices with no edges connected to them)
- loose edges (edges with no faces connected to them)
The main goal of the data structure is to enable adjacency / topological queries:
- For a given vertex, which edges are connected to it?
- For a given edge, which faces are connected to it?
- For a given face, which vertices / edges make up the face?

Vertex uses #
We wish to have fast insertion and deletion of elements, and no memory fragmentation. Therefore, a naive implementation such as:
| |
would not be a good idea.
Therefore, for a given Vertex, we add a circularly linked list of VertexUses:
| |
This way, we can iterate over all Edges of a given Vertex, and not have millions of separate instances of std::vector<Edge*>.
Edge uses #
This same approach is then also used for Edges, which get an accompanying circularly linked list of EdgeUses to answer the question “for a given edge, which faces are connected to it?”:
| |
Face loop #
Then, the final task is to add the FaceLoop, which answers the question “for a given face, which vertices / edges make up the given face?”:
Note that we also store the vertex for a given FaceLoop segment, because v0 and v1 of an Edge are unordered.
| |
Merging face loop and edge uses #
Because a given EdgeUse is only attached to a single face, we can merge the FaceLoop linked list into the EdgeUse, thus reducing the need for an additional element type in the graph:
| |
This gives us the final structure:
| |
Conclusion #
This post presents a simple, performant non-manifold polygon mesh data structure, that enables topological / adjacency queries.