mesh_subdivide_catmullclark

compas.datastructures.mesh_subdivide_catmullclark(mesh, k=1, fixed=None)[source]

Subdivide a mesh using the Catmull-Clark algorithm.

Parameters
  • mesh (Mesh) – The mesh object that will be subdivided.

  • k (int, optional) – The number of levels of subdivision.

  • fixed (list[int], optional) – A list of fixed vertices.

Returns

Mesh – A new subdivided mesh.

Notes

Note that Catmull-Clark subdivision is like Quad subdivision, but with smoothing after every level of further subdivision. Smoothing is done according to the scheme prescribed by the Catmull-Clark algorithm.

References

1

Tony DeRose, Michael Kass and Tien Truong. Subdivision Surfaces in Character Animation. Pixar Animation Studios. see https://graphics.pixar.com/library/Geri/paper.pdf

Examples

>>> from compas.geometry import Box
>>> from compas.datastructures import Mesh
>>> box = Box.from_corner_corner_height([0.0, 0.0, 0.0], [1.0, 1.0, 0.0], 1.0)
>>> mesh = Mesh.from_shape(box)
>>> k = 2
>>> subd = mesh_subdivide_catmullclark(mesh, k=k)
>>> mesh is subd
False
>>> type(mesh) is type(subd)
True
>>> subd.number_of_faces() == mesh.number_of_faces() * 4 ** k
True

The algorithm supports “integer creasing” as described in Subdivision Surfaces in Character Animation 1. Creases are supported through the optional edge attribute “crease”, which can be set to an integer value that defines how sharp the crease is wrt the number of subdivision steps.

To add an infinitely sharp crease to an edge, set the “crease” attribute of the edge to a number higher than the number of subdivision steps.

>>> from compas.geometry import Box, dot_vectors
>>> from compas.datastructures import Mesh
>>> cage = Mesh.from_shape(Box.from_width_height_depth(1, 1, 1))
>>> cage.update_default_edge_attributes({'crease': 0})
>>> top = sorted(cage.faces(), key=lambda face: dot_vectors(cage.face_normal(face), [0, 0, 1]))[-1]
>>> cage.edges_attribute('crease', 5, keys=list(cage.face_halfedges(top)))
>>> subd = cage.subdivide(k=4)