Lecture 7:
Digital Geometry
Processing
Interactive Computer Graphics
Stanford CS248, Winter 2019
A small triangle mesh
8 vertices, 12 triangles
Stanford CS248, Winter 2019
A large triangle mesh
David
Digital Michelangelo Project
28,184,526 vertices
56,230,343 triangles
Stanford CS248, Winter 2019
Even larger meshes
Google Earth
Meshes reconstructed from satellite and aerial photography
Trillions of triangles
Stanford CS248, Winter 2019
Digital geometry processing: motivations
3D Scanning
3D Printing
Stanford CS248, Winter 2019
Geometry processing pipeline
scan print
process
Stanford CS248, Winter 2019
Recall: image upsampling
Stanford CS248, Winter 2019
Recall: image upsampling
Upsampling via
bilinear interpolation
Stanford CS248, Winter 2019
Recall: image downsampling
Stanford CS248, Winter 2019
Recall: image resampling
Stanford CS248, Winter 2019
Examples of geometry processing
Stanford CS248, Winter 2019
Mesh upsampling — subdivision
Increase resolution via interpolation
Stanford CS248, Winter 2019
Mesh downsampling — simplification
Decrease resolution; try to preserve shape/appearance
Stanford CS248, Winter 2019
Mesh resampling — regularization
Modify sample distribution to improve quality
Stanford CS248, Winter 2019
More geometry processing tasks
reconstruction
filtering
remeshing
parameterization compression
shape analysis Stanford CS248, Winter 2019
Today
Study how to represent meshes (data structures)
Study how to process meshes (basic geometry processing)
- Subdivision
- Mesh simplification
- Mesh resampling
Stanford CS248, Winter 2019
Mesh representations
Stanford CS248, Winter 2019
List of triangles
Stanford CS248, Winter 2019
Lists of vertexes / indexed triangle
Stanford CS248, Winter 2019
Comparison
List of triangles
+ Simple
– Contains redundant vertex information
Vertexes + indexed triangles
+ Sharing vertices reduces memory usage
+ Ensure integrity of the mesh (moving a vertex
causes that vertex in all the polygons to move)
Stanford CS248, Winter 2019
Mesh topology vs surface geometry
Same vertex positions, different mesh topology
Same topology, different vertex positions
Stanford CS248, Winter 2019
Topological mesh information
Applications:
- Constant time access to neighbors
e.g. surface normal calculation, subdivision
- Editing the geometry
e.g. adding/removing vertices, faces, edges, etc.
Solution: topological data structures
Stanford CS248, Winter 2019
Topological validity: manifold
Recall, a 2D manifold is a surface that when cut with a small
sphere always yields a disk
Manifold Not manifold
With border With border
Stanford CS248, Winter 2019
Manifolds have useful properties
A 2D manifold is a surface that when cut with a small sphere
always yields a disk
If a mesh is manifold, we can rely on these useful properties: *
- An edge connects exactly two faces
- An edge connects exactly two vertices
- A face consists of a ring of edges and vertices
- A vertex consists of a ring of edges and faces
- Euler’s polyhedron formula holds: #f – #e + #v = 2
(for a surface topologically equivalent to a sphere)
(Check for a cube: 6 – 12 + 8 = 2)
* Some of these properties only apply to non-border mesh regions
Stanford CS248, Winter 2019
Topological validity: orientation consistency
Both facing front Inconsistent orientations
C C C C
D D D D
B A B B A A B A
OK OKbad bad
Non-orientable
(e.g., Moebius strip)
Image credit: Wikipedia
Stanford CS248, Winter 2019
Simple example: triangle-neighbor data structure
struct Tri { v[1]
Vert * v[3];
Tri * t[3]; t[2] t[1]
}
struct Vert {
v[2] v[0]
Point pt;
Tri *t; t[0]
}
Stanford CS248, Winter 2019
Triangle-neighbor – mesh traversal
Find next triangle counter-clockwise around vertex v from triangle t
v[1]
Tri* tccwvt(Vert *v, Tri *t)
{ t[2] t[1]
if (v == t->v[0])
return t[0]; t
if (v == t->v[1])
return t[1]; v[2] v[0]
if (v == t->v[2])
t[0]
return t[2];
}
Stanford CS248, Winter 2019
Half-edge data structure
struct Halfedge { Key idea: two half-edges act as “glue”
Halfedge *twin,
between mesh elements
Halfedge *next;
Vertex *vertex;
Edge *edge;
Face *face;
} next
Halfedge
edge
struct Vertex { twin
Point pt; face
Halfedge *halfedge;
}
struct Edge {
Halfedge *halfedge;
} vertex
struct Face { Each vertex, edge and face points
Halfedge *halfedge;
to one of its half edges
}
Stanford CS248, Winter 2019
Half-edge structure facilitates mesh traversal
Use twin and next pointers to move around mesh
Process vertex, edge and/or face pointers
Example 1: process all vertices of a face
Halfedge* h = f->halfedge; next
halfedge
do { Face
process(h->vertex);
next
h = h->next;
}
while( h != f->halfedge );
Stanford CS248, Winter 2019
Half-edge structure facilitates mesh traversal
Example 2: process all edges around a vertex
halfedge
twin
Halfedge* h = v->halfedge; next
do {
twin
process(h->edge);
h = h->twin->next; Vertex
next
}
while( h != v->halfedge );
Stanford CS248, Winter 2019
Local mesh operations
Stanford CS248, Winter 2019
Half-Edge – local mesh editing
Consider basic operations for linked list: insert, delete
Basic ops for half-edge mesh: flip, split, collapse edges
c flip c c split c
a d a d a d a d
m
b b b b
a a
collapse
m
c d
b b
Allocate / delete elements; reassign pointers
(Care is needed to preserve mesh manifold property)
Stanford CS248, Winter 2019
Half-edge – edge flip
Triangles (a,b,c), (b,d,c) become (a,d,c), (a,b,d):
c flip c
a d a d
b b
Long list of half-edge pointer reassignments
However, no mesh elements created/destroyed
Stanford CS248, Winter 2019
Half-edge – edge split
Insert midpoint m of edge (c,b), connect to get four triangles:
c split c
a d a m d
b b
Must add elements to mesh (new vertex, faces, edges)
Again, many half-edge pointer reassignments
Stanford CS248, Winter 2019
Half-edge – edge collapse
Replace edge (c,d) with a single vertex m:
a a
collapse
m
c d
b b
Must delete elements from the mesh
Again, many half-edge pointer reassignments
Stanford CS248, Winter 2019
Global mesh operations: geometry processing
Mesh subdivision (form of subsampling)
Mesh simplification (form of downsampling)
Mesh regularization (form of resampling)
Stanford CS248, Winter 2019
Upsampling a mesh — subdivision
Stanford CS248, Winter 2019
Upsampling via subdivision
Repeatedly split each element into smaller pieces
Replace vertex positions with weighted average of
neighbors
Main considerations:
- interpolating vs. approximating
- limit surface continuity (C1, C2, ...)
- behavior at irregular vertices
Many options:
- Quad: Catmull-Clark
- Triangle: Loop, butterfly, sqrt(3)
Stanford CS248, Winter 2019
Loop subdivision
Common subdivision rule for triangle meshes
“C2” smoothness away from irregular vertices
Approximating, not interpolating
Simon Fuhrman
Stanford CS248, Winter 2019
Loop subdivision algorithm
Split each triangle into four
Compute new vertex positions using weighted sum of prior vertex positions:
1/8 u u
3/8 3/8 u u
n: vertex degree
1 – n*u u u u: 3/16 if n=3, 3/(8n) otherwise
1/8
New vertices Old vertices
(weighted sum of vertices on
(weighted sum of
split edge, and vertices
“across from” edge) edge adjacent vertices)
Stanford CS248, Winter 2019
Loop subdivision algorithm
Example, for degree 6 vertices (“regular” vertices)
1/16 1/16
1/16 1/16
10/16
1/16 1/16
Stanford CS248, Winter 2019
Loop subdivision results
Simon Fuhrman
Stanford CS248, Winter 2019
Semi-regular meshes
Most of the mesh has vertices
with degree 6 Extraordinary vertex
But if the mesh is topologically
equivalent to a sphere, then not
all the vertices can have degree 6
Must have a few extraordinary
points (degree not equal to 6)
Stanford CS248, Winter 2019
Proof: always an extraordinary vertex
Our triangle mesh (topologically equivalent to sphere) has V vertices, E edges, and T triangles
E = 3/2 T
- There are 3 edges per triangle, and each edge is part of 2 triangles
- Therefore E = 3/2T
T = 2V – 4
- Euler Convex Polyhedron Formula: T – E + V = 2
- => V = 3/2 T – T + 2 => T = 2V – 4
If all vertices had 6 triangles, T = 2V
- There are 6 edges per vertex, and every edge connects 2 vertices
- Therefore, E = 6/2V => 3/2T = 6/2V => T = 2V
T cannot equal both 2V – 4 and 2V, a contradiction
- Therefore, the mesh cannot have 6 triangles for every vertex
Stanford CS248, Winter 2019
Loop subdivision via edge operations
First, split edges of original mesh in any order:
split
Next, flip new edges that touch a new and old vertex:
flip
(Don’t forget to update vertex positions!)
Images cribbed from Keenan Crane, cribbed from Denis Zorin Stanford CS248, Winter 2019
Continuity of loop subdivision surface
At extraordinary vertices
- Surface is at least C continuous
1
Everywhere else (“ordinary” regions)
- Surface is C 2 continuous
Stanford CS248, Winter 2019
Loop subdivision results
Stanford CS248, Winter 2019
Catmull-Clark subdivision
Stanford CS248, Winter 2019
Catmull-Clark subdivision (regular quad mesh)
Stanford CS248, Winter 2019
Catmull-Clark subdivision (regular quad mesh)
Stanford CS248, Winter 2019
Catmull-Clark subdivision (regular quad mesh)
Each subdivision step:
Add vertex in each face
Add midpoint on each edge
Connect all new vertices
Stanford CS248, Winter 2019
Catmull-Clark vertex update rules (quad mesh)
Face point v1 + v2 + v3 + v4 Edge point
f=
v1 v4 4 v1
f v1 + v2 + f1 + f2 e
e= f1 f2
4
v2 v3 v2
Vertex point
f1 m1 f
2 f1 + f2 + f3 + f4 + 2(m1 + m2 + m3 + m4) + 4p
p v=
16
m4 v m2
f3 m3 f4 m midpoint of edge, not “edge point”
p old “vertex point”
Stanford CS248, Winter 2019
Catmull-Clark subdivision (general mesh)
Non-quad face
Extraordinary
vertex
(valence != 4) Each subdivision step:
Add vertex in each face
Add midpoint on each edge
Connect all new vertices
Stanford CS248, Winter 2019
Catmull-Clark subdivision (general mesh)
How many extraordinary
vertices after first subdivision?
What are their valences?
How many non-quad faces?
Stanford CS248, Winter 2019
Catmull-Clark subdivision (general mesh)
Stanford CS248, Winter 2019
Catmull-Clark subdivision (general mesh)
Stanford CS248, Winter 2019
Catmull-Clark vertex update rules (general mesh)
f = average of surrounding vertices
f1 + f2 + v1 + v2 These rules reduce to earlier quad
e=
4 rules for ordinary vertices / faces
f¯ 2m̄ p(n 3)
v= + +
n n n
m̄ = average of adjacent midpoints
f¯ = average of adjacent face points
n = valence of vertex
p = old ”vertex” point
Stanford CS248, Winter 2019
Continuity of Catmull-Clark surface
At extraordinary points
- Surface is at least C continuous
1
Everywhere else (“ordinary” regions)
- Surface is C 2 continuous
Stanford CS248, Winter 2019
What about sharp creases?
From Pixar Short, “Geri’s Game”
Hand is modeled as a Catmull Clark surface with creases between skin and fingernail
Stanford CS248, Winter 2019
What about sharp creases?
Figure from: Hakenberg et al. Volume Enclosed by Subdivision Surfaces with Sharp Creases
Stanford CS248, Winter 2019
Creases and boundaries
Can create creases in subdivision surfaces by marking certain
edges as “sharp”. Surface boundary edges can be handled the
same way
- Use different subdivision rules for vertices along these
“sharp” edges
1 1 1 3 1
2 2 8 4 8
Insert new midpoint vertex, Update existing vertices,
weights as shown weights as shown
Stanford CS248, Winter 2019
Subdivision in action (“Geri’s Game”, Pixar)
Subdivision used for entire character:
- Hands and head
- Clothing, tie, shoes
Stanford CS248, Winter 2019
Mesh simplification — downsampling
Stanford CS248, Winter 2019
How do we resample meshes? (reminder)
Edge split is (local) upsampling:
c split c
a d a m d
b b
Edge collapse is (local) downsampling:
a a
collapse
m
c d
Edge flip is (local) resampling: b
c c
b
flip
a d a d
b b
Still need to intelligently decide which edges to modify!
Stanford CS248, Winter 2019
Mesh simplification
Goal: reduce number of mesh elements while maintaining
overall shape
30,000 triangles 3,000 300 30
Stanford CS248, Winter 2019
Estimate: error introduced by collapsing an edge?
How much geometric error is introduced by collapsing an edge?
collapse
Stanford CS248, Winter 2019
Sketch of Quadric Error
Mesh Simplification
Stanford CS248, Winter 2019
Simplification via quadric error
Iteratively collapse edges
Which edges? Assign score with quadric error metric*
- Approximate distance to surface as sum of squared
distances to planes containing nearby triangles
- Iteratively collapse edge with smallest score
- Greedy algorithm... great results!
* (Garland & Heckbert 1997)
Stanford CS248, Winter 2019
Review: point-to-plane distance
Signed distance to plane with normal N
passing through point p?
=> N • (x – p)
Stanford CS248, Winter 2019
Quadric error matrix (encodes squared distance)
- Suppose we have:
- a query point (x,y,z)
- a normal (a,b,c)
- an offset d := –(xp,yp,zp) • (a,b,c)
- Then in homogeneous coordinates, let
- u := (x,y,z,1)
- v := (a,b,c,d)
- Signed distance to plane is then
D = uvT = vuT = ax+by+cz+d
- Squared distance is D2 = (uvT)(vuT) = u (vTv) uT := uTQu
- Distance is 2nd degree (“quadric”) polynomial in x,y,z
Stanford CS248, Winter 2019
Quadric error at mesh vertex
Heuristic: error at vertex V is sum of squared distances to
triangles connected to V
Encode this as a single quadric matrix per vertex that is the sum
of quadric error matrices for all triangles
QV
Q3 Q2
Q4 Q1 N
X
Q5 QV = Qi
i=1
Stanford CS248, Winter 2019
Cost of edge collapse
How much does it cost to collapse an edge?
Idea: compute edge midpoint Vmid, measure quadric error at this point
Error at Vmid given by vmidT(Q0 + Q1)vmid
Intuition: cost is sum of squared differences to original position of
triangles now touching Vmid
collapse
V0 V1 Vmid = (V0 + V1) / 2
Better idea: choose point on edge (not necessarily the midpoint) that
minimizes quadric error
More details: Garland & Heckbert 1997
Stanford CS248, Winter 2019
Quadric error simplification: algorithm
- Compute quadric error matrix Q for each triangle’s plane
- Set Q at each vertex to sum of Q’s from neighbor triangles
- Set Q at each edge to sum of Q’s at endpoints
- Find point at each edge minimizing quadric error
- Until we reach target # of triangles:
- collapse edge (i,j) with smallest cost to get new vertex m
- add Qi and Qj to get quadric Qm at vertex m
- update cost of edges touching vertex m
Stanford CS248, Winter 2019
Quadric error mesh simplification
Garland and Heckbert ‘97
5,804 994 532 248 64
30,000 triangles 3,000 300 30
Stanford CS248, Winter 2019
Mesh Regularization
Stanford CS248, Winter 2019
What makes a “good” triangle mesh?
One rule of thumb: triangle shape
More specific condition: Delaunay “GOOD” “BAD”
- “Circumcircle interiors contain no vertices.”
Not always a good condition, but often*
- Good for simulation
- Not always best for shape approximation
*See Shewchuk, “What is a Good Linear Element”
Stanford CS248, Winter 2019
What else constitutes a good mesh?
Rule of thumb: regular vertex degree
Triangle meshes: ideal is every vertex with valence 6:
“GOOD” “OK” “BAD”
Why? Better triangle shape, important for (e.g.) subdivision:
subdivide
*See Shewchuk, “What is a Good Linear Element”
Stanford CS248, Winter 2019
Isotropic remeshing
Goal: try to make triangles uniform in shape and size
Stanford CS248, Winter 2019
How do we make a mesh “more delaunay”?
Already have a good tool: edge flips!
If α+β > π, flip it!
In practice: a simple, effective way to improve mesh quality
Stanford CS248, Winter 2019
How do we improve degree?
Edge flips!
If total deviation from degree 6 gets smaller, flip it!
flip
Iterative edge flipping acts like “discrete diffusion” of degree
No (known) guarantees; works well in practice
Stanford CS248, Winter 2019
How do we make triangles “more round”?
Delaunay doesn’t mean equilateral triangles
Can often improve shape by centering vertices:
average
[See Crane, “Digital Geometry Processing with Discrete Exterior Calculus”]
Stanford CS248, Winter 2019
Isotropic remeshing algorithm*
Repeat four steps:
- Split edges over 4/3rds mean edge length
- Collapse edges less than 4/5ths mean edge length
- Flip edges to improve vertex degree
- Center vertices tangentially
* Based on Botsch & Kobbelt, “A Remeshing Approach to Multiresolution Modeling”
Stanford CS248, Winter 2019
Things to remember
Triangle mesh representations
- Triangles vs points+triangles
- Half-edge structure for mesh traversal and editing
Geometry processing basics
- Local operations: flip, split, and collapse edges
- Upsampling by subdivision (Loop, Catmull-Clark)
- Downsampling by simplification (Quadric error)
- Regularization by isotropic remeshing
Stanford CS248, Winter 2019
Acknowledgements
Thanks to Keenan Crane, Ren Ng, Pat Hanrahan, James
O’Brien, Steve Marschner for presentation resources
Stanford CS248, Winter 2019