Lecture_009_Meshes_and_Manifolds

Regular grid image:

Manifold: there exists a linear transform on the surface of geometry such that the geometry can be smooth.

Manifold polygon mesh has fans, but not fins. Every edge is contained in only two polygons (no "fins"). The polygons containing each vertex make a single "fan".

Boundary: every boundary forms a loop.

Datastructure

Basic Datastructure

Usual Datastructure:

Well, in theoretical computer science, one should not allow random memory access be in constant time. This is because speed of light is bounded, you can't access memory that is very faraway from the signal in constant time.

Graphics Datastructure

Polygon Soup (Cloud)

Polygon Soup: a list of triangles

Adjacency List

Adjacency List: split shape and connectivity.

# cube.obj
#

g cube

v  0.0  0.0  0.0
v  0.0  0.0  1.0
v  0.0  1.0  0.0
v  0.0  1.0  1.0
v  1.0  0.0  0.0
v  1.0  0.0  1.0
v  1.0  1.0  0.0
v  1.0  1.0  1.0

vn  0.0  0.0  1.0
vn  0.0  0.0 -1.0
vn  0.0  1.0  0.0
vn  0.0 -1.0  0.0
vn  1.0  0.0  0.0
vn -1.0  0.0  0.0

f  1//2  7//2  5//2
f  1//2  3//2  7//2
f  1//6  4//6  3//6
f  1//6  2//6  4//6
f  3//3  8//3  7//3
f  3//3  4//3  8//3
f  5//5  7//5  8//5
f  5//5  8//5  6//5
f  1//4  5//4  6//4
f  1//4  6//4  2//4
f  2//1  6//1  8//1
f  2//1  8//1  4//1

In above:

Note that there are many representation of f faces in .obj file:

Incidence Matrix

Incidence Matrix

Incidence Matrix

Incidence Matrix:

Sparse Matrix Datastructure

Sparse Matrix Datastructure

Halfedge Data Structure

Face Normal vs. Vertex Normal: https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/shading-normals

Face Normal vs. Vertex Normal: https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-shading/shading-normals

struct Halfedge {
  Halfedge*  twin;
  Halfedge* next;
  Vertex* vertex; // by convention, vertex it come from
  Edge* edge;
  Face* face;

  Vec2 corner_uv; // uv coordinate for this corner of the face
  Vec3 corner_normal; // shading normal for this corner of the face
  // Vertex normal provides information whether we need a hard or smooth edge
  // Sometimes triangles mesh are not directly converted from a smooth surface,
  // and vertex normals have to be computed on the fly.
  // There are different techniques for computing vertex normals
}
struct Edge {
  Halfedge* halfedge;

  bool sharp; // should this edge be considered sharp when computing shading normals?
}
struct Face {
  Halfedge* halfedge;

  bool boundary; // is this a boundary loop? (boundary used to traverse mesh efficiently)
}
struct Vertex {
  Halfedge* halfedge

  Vec3 position; // location of the vertex
  struct Bone_Weight {
    uint32_t bone;
    float weight;
  };
  std::vector< Bone_Weight > bone_weights; // how much this vertex follows each bone's transform (used for skinned meshes)
}

One can use minimal half-edge-like datastructure to do the job quickly cpp std::unordered_map<std::pair<Index, Index>, HalfedgeRef> halfedges; The above data structure represent a unordered map of half-edge. The std::pair<Index, Index> is the indice for vertex from and vertex to. It maps to a HalfedgeRef that is the address of the next half edge. When you want to walk back or find its twin, just look up the std::unordered_map.

Another trick is to store twin halfedges as even and odd indices instead of pointers.

Besides, we also define 2D mesh to have boundary for easy navigation. (in green shaded region as shown in images below)

If you want to visit all vertices of a face

Halfedge* h = f->halfedge;
do {
  h = h->next;
}
while (h != h->halfedge);

If you want to visit all neighbors of a vertex

Halfedge* h = v->halfedge;
do {
  h = h->twin->next;
}
while (h != v->halfedge);

The datastructure only make sense if mesh is manifold: - there is only one twin for any halfedge - twin->twin == this - twin != this - there is only one next halfedge - next == something - this == someone's next

Manifold Connectivity but not Manifold Geometry

Manifold Connectivity but not Manifold Geometry

Well, actually the connectivity should be manifold, but adjusting vertex position can generates non-manifold-looking geometry. The below image is still a valid geometry.

We assume connectivity cannot wrap

We assume connectivity cannot wrap

3 basic operations: Edge Flip, Edge Split, Edge Collapse

3 basic operations: Edge Flip, Edge Split, Edge Collapse

We can have multiple different representation of the same geometry because the pointers are different. It is non-trivial to have a one-to-one map between representation and geometry. One would build a total order of halfedge to correctly assign halfedge to faces, edges, and vertex.

Completeness: we should prove Edge Flip, Edge Split, Edge Collapse can achieve all operations

Other Similar Datastructure: https://geometry-central.net/

Other Similar Datastructure: https://geometry-central.net/

With some thought, one can design halfedge type data structure with coherent data storage and support for non-manifold connectivity.

Adjacency List Incidence Matrices Halfedge
O(1) neighborhood No Yes Yes
Add/Remove Mesh No No Yes
Non-manifold Yes Yes No

Mesh Validity

A Halfedge_Mesh structure is a sea of pointers. It is surprisingly easy to tangle these pointers into a mess that fails to represent a manifold mesh (or, really, a consistent mesh at all). In order to provide guidance on what constitutes a reasonable setting for a mesh, we define a valid mesh as one for which the following properties hold:

  1. The mesh is self-contained. All pointers are to elements in the vertices, edges, faces, or halfedges lists.
  2. Edges correspond to twinned halfedges. That is, for every edge e, e->halfedge(->twin)^n is a cycle of exactly two halfedges, and these are exactly the halfedges with h->edge equal to e.
  3. Faces correspond to cycles of halfedges. That is, for every face f, f->halfedge(->next)^n is a cycle of at least three halfedges, and these are exactly the halfedges with h->face equal to f.
  4. Vertices correspond to stars of halfedges. That is, for every vertex v, v->halfedge(->twin->next)^n is a cycle of at least two halfedges, and these are exactly the halfedges with h->vertex equal to v.
  5. Vertices are not orphaned, nor is the surface adjacent to them hourglass-shaped. That is, vertices are adjacent to at least one non-boundary face and at most one boundary face.
  6. Edges not orphaned. That is, edges are adjacent to at least one non-boundary face.
  7. Faces are simple. That is, faces touch each vertex and edge at most once.

Subdivision Modeling

Many More Operations

Many More Operations

In subdivision modling, artists work on course geometry and preview the subdivided version. There are two reasons why we don't want to work on high resolution models:

Table of Content