Skip to content

Mesh Implementations Data Structures

Lukas Kalbertodt edited this page Jan 3, 2019 · 10 revisions

There are many different ways to implement/store a mesh. These different implementations have different characteristics in terms of:

  • What neighborhood information can I obtain in constant time
  • Memory usage
  • Speed/cache friendliness
  • What elements (face, edge, vertex) are "explicitly" stored = can be referred to

A table showing all this data can be found here. The different data structures will be briefly explained here.

Comparison

Name Mem Poly Explicit Edge Multi-blade Vertex
Shared Vertex 7 -
Linked Face 13
Directed Edge 13
Half Edge 21/27
Winged Edge 27 ?

Each Data Structure in Detail

Weak data structures

I call these weak because they have a very limited feature set and are only useful in very special and rare situations. Furthermore, there are more capable data structures that do not really have any disadvantages compared to the weak ones.

However, I might want to consider still providing these to do some stuff. For example, shape creation functions can certainly create instances of these two types.

FaceList/Vertex Soup

Vec<{
   vertices: [VertexProp; 3],
}>

Just stores a list of faces, where each face just stores the properties of all its vertices. This DS has no adjacency information at all. Bad, because properties are duplicated and vertices are stored implicitly. This is sometimes used to render stuff, but it's usually better to use an index buffer instead to avoid duplicating data.

So this might be worth as some serialization/storage format, but not something to perform operations on. (Note: this is exactly the format STL files are stored in.)

Vertex-Vertex

Vec<{
    prop: VertexProp, 
    neighbors: Vec<VertexHandle>,
}>

A list of vertices is stored, where each vertex stores it's properties and its neighbors. Bad, because it contains lists and faces are stored implicitly.

Real data structures

Shared-Vertex Mesh

vertices: Vec<()>,
faces: Vec<{
    vertices: [VertexHandle; 3],
}>

Probably the most commonly used data structure in general. Graphic APIs like OpenGL are usually fed with data like this (a vertex- and an index-buffer).

Memory

  • Vertex: 1
  • Face: 3
  • Edge: 0

Total per vertex: 1 + 2·3 + 3·0 = 7

Linked Face Mesh

vertices: Vec<{
    one_face: Option<FaceHandle>,
>,
faces: Vec<{
    vertices: [{
        handle: VertexHandle,
        next_face: FaceHandle,
    }; 3],
}>

Memory

  • Vertex: 1
  • Face: 3 · 2 = 6
  • Edge: 0

Total per vertex: 1 + 2·6 + 3·0 = 13

Directed-Edge Mesh

Memory

  • Vertex: 1
  • Face: 0
  • Edge: 2 · 2 = 4

Total per vertex: 1 + 2·0 + 3·4 = 13

Edge data structures

Half Edge Mesh

vertices: Vec<{
    half_edge: Option<HeHandle>,
>,
faces: Vec<{
    half_edge: HeHandle,
}>,
half_edges: Vec<{
    next: HeHandle,
    twin: HeHandle, // stored implicitly
    prev: HeHandle, // optional
    vertex: VertexHandle,
    face: FaceHandle,
}>

Memory

  • Vertex: 1
  • Face: 1
  • Edge: 2 · 3 = 6 (or 8 with prev)

Total per vertex: 1 + 2·1 + 3·6 = 21 (or 27 with prev)

Winged-Edge Mesh

Memory

  • Vertex: 1
  • Face: 1
  • Edge: 8

Total per vertex: 1 + 2·1 + 3·8 = 27

Quad-Edge Mesh

TODO


Links