The Blob







My December '16 gamejam submission features an amorphous blob that slinks around and devours donuts. This post explains how to create the blob's jiggling effect. In its natural state, the blob is a perfect sphere. We deform it by adding a position offset to each vertex via the world position offset material node. The material takes as input the offsets of six control nodes and then calculates the offset of every vertex by interpolating between the nodes. I settled on using six control nodes $N = \{n_x, n_y, n_z, ... \}$ located at the spherical poles, which are visualized by the green balls in the following picture.






Take a vertex $v$ on our sphere. If $v$ is exactly at the north pole, then its world offset should match that of the control node $n_z$. If instead $v$ lies somewhere between say, nodes $n_x$ and $n_z$, then its offset should be a blend between the two. Let's assume there is only one control node at the north pole, and that its node offset is the vertical $\Delta n_z = (0,0,20)$. We define its support $\sigma$ as its range of influence (measured by angle in radians).





I've found that a support somewhere around $\pi/2$ looks the best, where each node effects roughly half of the sphere. To calculate the vertex offset of $v$ we compute the angle $\theta$ (our distance metric) between the undeformed positions of $v$ and node $n_z$. We then normalize, invert, and smooth so that $\theta = 0 \mapsto 1$ and $\theta \geq \sigma \mapsto 0$. More precisely, $ \theta \mapsto \alpha = f \left( \max\{\theta, \sigma\}  / \sigma \right)$ where $f$ is some smooth function that maps $[0,1]$ onto itself and has vanishing derivatives at the endpoints. I specifically chose the cubic bezier $f(x) = 3 x \, (1-x)^2  + (1-x)^3$. You could also try something like $f(x) = (\cos(\pi x) + 1) \, / \, 2$ or the [BellCurve] material node. The result $\alpha$ is a percent or weight factor that we multiply with the node offset. That is, the vertex offset $\Delta v = \alpha \, \Delta n_z$. As a material in Unreal Engine we have:





When there is more than one node, we calculate the $\alpha$-weight for each node and either take their sum or their weighted average. Weighted averages tend to require larger supports (and they need special care if the support $\sigma < \pi/3$ lest you divide by zero). In the video at the top I use a simple sum. Notice how I computed the normals for the fresnel. We could very well find the exact normals but it's not a trivial calculation. We instead use the [DDX / DDY] nodes to get the flat normals of each mesh face. The final material with six control nodes is essentially the same but with the bottom chain copy-pasted five times.

Okay so we have the material to make a blob, but how do we make it wiggle? The short answer is springs and collision. Take the blob in my game. The deforming mesh doesn't actually interact with the game world. Instead the player controls the blob by applying forces to a smaller sphere located at the blob's core. This smaller sphere (pink) is what actually slides on the ground and collides with objects. The six smaller spheres (green) represent the blob's control nodes. These spheres are attached to the spherical poles by linear-springs and to eachother by distance-springs, all of which are weakly damped. We let the physics engine determine their offsets and we send the offsets dynamically to the deforming-material each frame.





2 comments:

  1. Hi, would you mind explaining how you created those control nodes and how you attached them to the sphere ?

    ReplyDelete
  2. Hello :D can you pliz teach?

    ReplyDelete