This page describes the results from my implementation of the Catmull-Clark subdivision surfaces algorithm. I implemented this algorithm for Asssignment 3 in CS294-13 (Advanced Rendering).

The Catmull-Clark subdivision surfaces algorithm provides a method for recursively defining a B-Spline surface from an arbitrary mesh topology.


* Subdivide arbitrary meshes

* Interactive tagging of vertices to fix their position

* Push vertices to the limit solution

* Calculate and visualize tangents, normals, and curvature

* Optimize surface according to curvature

Basic Results

In the above set of images, I demonstrate a simple subdivision of a cube.

Tagging Vertices

The left image above demonstrates the subdivision of the same cube after two of the original vertices are tagged. The image on the right shows an icosahedron with all vertices tagged.

In the above two images, I demonstrate how my system can initially tag all of the vertices and edges for the first couple subdivision passes (left), before treating the new mesh as a regular subdivision surface control mesh and subdividing normally (right).

Arbitrary Meshes

My implementation allows the user to subdivide arbitrary meshes composed of either triangles or quads. In this set of images above, I demonstrate the subdivision of an icosahedron. After each subdivision step, I randomly perturb the vertices to create an irregularly-shaped 3D object.

The above examples illustrate subdivided surfaces of arbitrary meshes along with the control points (shown in red).

Visualizing Tangents, Normals and Curvature

In the above example, I demonstrate how my code can render a surface (left) and then calculate and visualize the tangents and normals at each vertex (right). I represent the tangents and normals by drawing a small gauge figure at each vertex and orienting it such that the disc is in the tangent plane and the central axis points in the direction of the normal vector.

In the above images, I demonstrate how the surfaces can be shaded using different parameters. The object is displayed using diffuse shading in top-left. The user can also color the surface using the surface normals (top-right). My code also calculates curvature, and the surface can be colored according to mean curvature (bottom-left) or Gaussian curvature (bottom-right). (bottom-right).

In the above example images, I've subdivided a simple ridge from a ground plane. In the top-left image, I've rendered the ridge using diffuse shading. The top-right image shows the ridge colored according to the surface normals. The bottom-left image is shaded according to the mean curvature, and the bottom-right image is shaded using Gaussian curvature.

Pushing to Limit Solution

In my implementation, the user can also push the vertices to the limit surface after an arbitrary number of subdivisions. In the above example, I start with a cube control mesh (top left), make one subdivision pass (top right), and then push the vertices to the limit surface (bottom left). The limit surface after many more subdivision passes is shown in the bottom-right image. Note how the vertices in the bottom-left image are inline with the surface in the bottom-right image.

Here is another example (above) in which an arbitrary mesh (top-left) is subdivided once (top-right) and then pushed to the limit solution (bottom-left). The image on the bottom-right shows how the smoothed surface appears after several subdivision iterations.


My code can also move selected vertices of a control mesh to optimize certain surface characteristics. I implemented this using a version of gradient descent to optimize the vertex positions.

In the above example, I demonstrate how the control mesh can be optimized to minimize the max principal curvature of the limit surface. The image on the left shows the input control mesh in red and the resulting subdivision surface (shaded object). The image on the right shows the new surface after optimizing the select vertices (left and right points) to minimize the max principal curvature of the object. The new control mesh (after optimization) is shown in red.

I recorded a screencast of the control mesh as it was being optimized. The mesh was redrawn at each step of the optimization to show how the vertices are changing. The movie can be found here: movie1.

Here is another example (above). The original control mesh contains about 100 vertices and they are positioned in an irregular pattern. In this version of my optimization, all the vertices were free to be moved. The surface without any optimization is shown on the left. The surface after minimizing the max principal curvature is shown on the right. Another movie illustrating how the code moved the vertices during optimization can be found here: movie2.