Catmull-Clark Subdivision for Browser Sculpture
Refine a control cage through explicit face, edge, vertex, boundary, and semi-sharp rules, then export the SVG edition with its topology ledger.
Catmull-Clark subdivision can make a coarse control cage look beautifully smooth while hiding broken adjacency underneath. This tutorial implements the refinement rules in JavaScript, audits topology and boundaries at every level, and turns semi-sharp creases into a reproducible browser sculpture.
Catmull-Clark subdivision starts with topology
Catmull-Clark subdivision turns a coarse polygon cage into a smooth-looking surface, but the visible curve is downstream of bookkeeping. Before moving one point, index every face loop, undirected edge, incident face, vertex neighbor, boundary chain, and crease tag. If adjacency is wrong, later averages can remain finite while the sculpture quietly tears or folds.
The original Catmull and Clark paper defines recursive refinement for meshes of arbitrary topology. In a browser implementation I narrow that promise: finite curated cages, explicit face winding, deterministic IDs, and at most four levels. The lab approximates a limit surface through discrete refinement; it does not claim exact limit evaluation.
My control-cage ledger records V, E, F, Euler characteristic χ = V − E + F, boundary loops, nonmanifold edges, extraordinary valence, and crease sharpness. Catmull-Clark subdivision becomes visually trustworthy when those values travel with the artwork. The glowing wire cage is not decoration placed behind the result; it is the provenance of every smooth patch.
- Original vertex
- Retains neighbors, faces, boundary status, and crease incidences.
- Edge point
- Uses endpoints plus adjacent faces, or the declared boundary rule.
- Face point
- Averages the immutable source face.
- Child faces
- One quad per source face corner.
Reading rule: labels, order, values, shapes, and line styles carry the conclusion; color is supplementary.
Build reliable half-edge mesh adjacency
A full half-edge mesh is useful, but the minimum reliable representation is an oriented face loop plus a map from a canonical undirected edge key to its incidences. For each face, emit directed pairs (a,b), canonicalize the storage key as min:max, and retain the original direction. One incidence marks a boundary; two mark an interior edge; more than two fail the manifold gate.
Vertex adjacency must come from the edge map, not repeated face scans with accidental duplicates. Store incident faces, incident edges, boundary neighbors, and crease weights separately. That makes a shared edge count once even though two faces reference it. Stable IDs also make SVG projection and JSON export reproducible.
Before refinement, reject missing indices, repeated consecutive vertices, faces with fewer than three distinct vertices, non-finite coordinates, and edge incidence above two. Catmull-Clark subdivision is forgiving visually at low resolution, which is exactly why structural validation belongs before rendering. A slightly rounded cube can conceal a duplicated edge until level four explodes the face count.
The adjacency build is also the first edition checkpoint. I serialize canonical edge keys in sorted order and hash the cage before refinement. Two files that produce similar silhouettes but disagree on winding, duplicate vertices, or crease ownership are different source editions. That provenance matters in generative 3D art, where a dramatic camera angle can otherwise disguise a structural change. The cage is the artwork's source record.
Derive face, edge, and vertex points
The refinement pass creates three families. A face point F is the average of a face’s original vertices. A smooth interior edge point is the average of its two endpoints and its two adjacent face points. A smooth interior vertex of valence n moves to (F̄ + 2R̄ + (n−3)P) / n, where F̄ averages incident face points and R̄ averages incident edge midpoints.
Apply those rules from the same immutable level. Do not overwrite original vertices while later points still need them. Then rebuild each n-sided face as n quads in consistent order: updated vertex, next edge point, face point, previous edge point. The expected face count after one pass is the sum of source face degrees; this is a powerful independent check.
Catmull-Clark subdivision code often fails by swapping a face point for an edge point. The result can still look “organic,” especially under dramatic lighting. The lab therefore computes production geometry and a separate topological oracle: predicted counts, finite coordinates, valid indices, and incidence. Beauty is allowed only after the ledger reconciles.
Handle boundaries and extraordinary vertices
Boundaries need an explicit policy. For an open boundary edge, use its endpoint midpoint as the new edge point. For a boundary vertex with exactly two boundary neighbors, use the cubic B-spline rule (6P + Pprev + Pnext) / 8. Corners or ambiguous boundary fans should be pinned or rejected according to the cage contract, not pushed through the interior formula.
Extraordinary vertices are ordinary inputs with valence other than four. The general vertex rule supports them, but the local parameterization and curvature differ near the extraordinary point. Record valence so the artist knows where a star-like compression or soft dimple originates. The OpenSubdiv topology overview is useful context for separating topological refinement from later evaluation machinery.
I compare the resulting topology with marching-cubes browser sculpture: marching cubes extracts a surface from a field, while this workflow preserves and refines authored cage connectivity. Catmull-Clark subdivision is the better fit when edge flow and deliberate control points are part of the composition.
| Point | Inputs | Independent gate |
|---|---|---|
| Face | all source-face vertices | finite centroid |
| Interior edge | 2 endpoints + 2 faces | incidence = 2 |
| Vertex | faces, edge midpoints, valence | actual n retained |
| Boundary | vertex + 2 boundary neighbors | declared open chain |
Reading rule: labels, order, values, shapes, and line styles carry the conclusion; color is supplementary.
Art-direct semi-sharp creases
A uniformly smooth object often feels inflated. Semi-sharp creases let the control cage keep a ridge for several levels before relaxing into the surface. Store a nonnegative sharpness per edge. At each pass, compute both the smooth edge point and the crease midpoint, blend according to clamped sharpness, then decay sharpness by one for child crease edges.
Vertex handling needs the same policy. Two incident sharp edges use the crease vertex rule; three or more can pin a corner for that level; fractional sharpness blends smooth and sharp positions. The exact scheme must be declared because production libraries differ at corners and boundaries. The Pixar paper on Geri’s Game subdivision surfaces is the historical bridge from rules to expressive production shapes.
Catmull-Clark subdivision becomes sculptural when crease placement follows the silhouette, not when every cage edge receives the same weight. I use three families: a smooth torso, a semi-sharp shoulder that decays, and one persistent base boundary. The receipt exports the initial and remaining sharpness so the rounded result cannot erase its construction history.
Bound growth and project an SVG study
Refinement grows quickly. A quad mesh produces roughly four times as many faces per level, so the lab caps levels at four and checks a hard vertex/face budget before allocation. The level selector estimates counts first. If a cage would exceed the bound, the run stops with a readable message instead of freezing the browser.
The visual output is a deterministic axonometric SVG projection, not a WebGL renderer. Rotate each point with fixed matrices, sort faces by projected depth, and fit the resulting bounds into a known viewBox. Fill colors come from face normal and depth bands; control edges remain available as a separate overlay. This makes the edition portable, inspectable, and accessible without claiming physically based rendering.
The adjacent WebGPU minimal surfaces article explores iterative geometric fields; spherical harmonics light sculpture explores lighting as form. Here, the artistic constraint is topology-first: the same cage, crease ledger, projection, and palette must reproduce the same SVG bytes.
- Smooth edition: every edge uses the smooth rule.
- Semi-sharp edition: shoulder edges blend toward midpoints.
- Decay: child crease weights decrease once per refinement level.
- Receipt: initial and remaining sharpness are exported.
Reading rule: labels, order, values, shapes, and line styles carry the conclusion; color is supplementary.
Verify manifold and geometry invariants
After every level, recompute topology from scratch. Check that all coordinates are finite, every face index exists, no edge has incidence above two, boundary counts match the declared cage type, and the projected bounds remain finite. For closed orientable cages, Euler characteristic should remain stable under subdivision; for open cages, compare the declared boundary-loop structure as well.
The negative fixtures alter real calculation paths: swap face and edge points, omit the boundary rule, double-count a shared edge, force every vertex to valence four, stop crease decay, and bypass the crease-vertex rule. Independent checks must catch changed counts, boundary drift, geometry residual, or sharpness mismatch. A mutation is not killed merely because its name appears in a list.
Catmull-Clark subdivision does not guarantee a pleasing sculpture. The gates establish that this edition follows its declared rules. Self-intersection, material thickness, manufacturing tolerances, and exact limit-surface curvature remain outside the lab. That boundary is important: a correct topology receipt is evidence, not a certificate for every downstream use.
Export a reproducible sculpture edition
An edition should be reconstructible from more than a screenshot. Export the cage name, original vertices and faces, level, crease inputs, refinement policy version, topology at every level, projection matrix, palette, SVG hash, and final SVG. JSON preserves structure; CSV exposes level-by-level counts; SVG is the visible artifact.
For platform choice, WebGPU vs Canvas generative art offers the wider rendering trade-off. This lab intentionally stays with SVG because the bounded meshes remain small and the vector file makes paths, stacking, and metadata easy to inspect. A future interactive renderer can consume the same cage receipt without changing the subdivision truth.
Catmull-Clark subdivision is most compelling when the technical and artistic layers remain legible together. The control cage explains the smooth body; extraordinary valence explains local character; semi-sharp creases explain the silhouette; and the topology ledger explains why the exported edition can be trusted and regenerated.
Runnable local artifact — The lab performs discrete refinement that approximates a limit surface for its curated cages; it does not evaluate the exact limit, certify self-intersection freedom, or claim production rendering or fabrication readiness.
Choose an open or closed cage, a level from zero through four, and crease sharpness; derive adjacency, refine geometry, verify incidence/Euler/finite/bounds gates, kill six mutations, and export SVG/JSON/CSV.