I’ve been playing around with “metaballs” today. Metaballs are a type of isosurface that can be thought of as an equipotential surface created by a set of point charges. Another way to think of them is as contour maps of mountains surrounded by water. Mathematically it’s a graph of a scalar potential function taken below (or above) some cutoff. e.g. the scalar potential from E&M:
Φ(r)= k e ∑ i=1 n q i | r− r i |When animated (ie. the mountains can move their heights add together) the effect is reminiscent of a lava lamp or an oil slick in water. Typically the way metaballs are rendered is by dividing the region of interest into small elements (typically the size of a pixel or voxel) and running a test on each element to determine if the region intersects with the equipotential surface. For example:
for x = 0 to screen_width
{
for y = 0 to screen_height
{
potential = 0
for i = 0 to num_balls
{
x2 = (meta_ball[i].x - x)^2
y2 = (meta_ball[i].y - y)^2
potential += meta_ball[i].charge / sqrt(x2 + y2)
}
if (potential < max_potential and potential > min_potential)
DrawPixel(x,y,color)
}
}
This code leaves lots of room for optimization. For example, we can eliminate points (x,y) that are too far from any charge to be be part of the equipotential surface. If all of the balls are centered on the same point in space then the distance of the equipotential surface is
r≤ 1 Φ ∑ i=1 n q iThus we only need to check points that are less than r away from the center of any metaball. We can also elminate the square root by redefining the scalar potential such that Φ is proportional to 1/r^2. The marching cubes algorithm projects a ray from the center of each metaball until it encounters an isosurface. It then traces isosurface an evaluates the smallest number of elements possible.
One can also create some nifty effects by allowing the “charge” of the metaballs to run negative as shown to the left. Here a negative charge is creating a hole in the large cluster of metaballs.
I’ll put the code in the junk folder eventually.
I really need to work on commenting my code. I’ve been trying to parallelize a Fortran program that I wrote more than three years ago as an undergraduate. It’s slow going. I’ve managed to get the thing to compile with OpenMP but the only results as of yet are NaN.