For this post, I have been working on implementing isosurfaces as a modeling tool in Maya to create blobby things such as the one depicted in the image below.
An isosurface is a shape which is described by taking a scalar field and building a surface from all the points on the field of which value matches a given threshold level we provide. To generate a polygonal surface we can use in computer graphics, our scalar field will be given by a 3D matrix -or grid- of numbers, which we will iterate in order to fetch the points that describe our shape. Unlike the mathematical scalar field, which is defined in every point, our grid describes a discreet sampling of the field, for we only know the values of the field in the vertices of the grid cells.
To build the surface from this discretized field, we generate triangles from each one of the cells conforming the grid by using the Marching Cubes algorithm. Given a grid cell, we mark each one of the 8 vertices as above or below the threshold level we provided. From those values, the algorithm provides a set of triangles which describe the surface inside that cell (Fig 1).
This particular implementation I provide here is integrated with Maya as a Surface Plug-in. It uses Maya’s particle systems to generate the scalar field – for each particle, we define a radius that describes the sphere of influence of that particle. The influence rapidly decays to zero as soon as we move away from the particle. Next, a grid within the particle’s bounding box is created, and sampled at a frequency given by the Grid Res attribute in the shape node. The surface node can also be plugged the particle colors and interpolate them in the resulting triangles, producing nice color blends. The higher the sampling frequency, the smaller the triangles and the more detailed surface we obtain. Bear in mind however that the number of cells grows proportionally to the cube of the grid resolution, so the surface generation quickly becomes a processor-intensive task.
I started prototyping the plug-in using Maya Python, but it soon became too slow to be practical, and I had to switch to C++. While working on it, I realized that for “splashy” particle systems such as the one depicted in the picture above, applying the triangulation to the entire grid is very wasteful, as only a small portion of the total cells (around 20% in that particular example) tend to be touched by the particles and thus will actually produce triangles. Therefore I optimized the triangle generation by performing a first pass over the grid and tagging those cells that will potentially be affected by the particles, skipping all the rest. On a second pass, the marching cubes is only applied to those tagged cells (colored in white in Fig 2.). Finally, Maya seems to like copying data around when handling nodes, and the internal cell occupancy cache can generate a lot of memory fragmentation if created/deleted every frame. To avoid this, a lazy-copy wrapper around te memory chunk is provided, so that the number of memory operations is minimized.
Finally, if you would like to try it, I have posted a version of the plug-in compiled for Maya 2011 x64 here, as well as a sample scene. For the programmers among us, the source code can be found here.