Vertex Mapped Bodies
or Lazy Man’s Soft Body Physics
Following the organic approach I’m taking with Mushroom 11’s creature and world design, I’ve been trying to come up with a simple solution for introducing organic, soft bodies, into the game.
Following a previous article about UV Mapped Vertices, which allowed a lightweight, random sway motion for multi-vertex sprites, I wanted to explore additional facets of organic sprite motion, but this time while enabling physical interaction with the world.
Any attempt to emulate soft bodies by manipulating Unity’s internal mesh colliders proved to be too heavy to run on low end devices (and most mid-range devices). Built-In Cloth is an interesting concept and could be tricked into displaying sprites, but it specializes on different facets of mesh interactivity and lacks features that are relevant to soft body sprites.
So, I wanted to create an animated creature that wobbles and shakes, but also contours and reacts to the physical environment. I also didn’t want to make a new type of physics-aware mesh, or a huge keyframe animation sprite system that displays different animations on different triggers.
What I wanted is to take a single sprite and morph it appropriately on cue. But more importantly, I wanted the cues to come from the existing physics system and so avoid creating a whole new soft body dynamics, which maps physics vertices to mesh vertices, like those fancy GPU-run examples we’ve all seen. I wanted to keep this light, short and low-end-device friendly.
I went with a simple idea: map each of the vertices in a sprite to the position of a reference object. In order for this to look truly organic, I created multi-vertex sprites with more than the standard 4 vertices. I can decide the number of horizontal and vertical quads as a compromise between performance and smoothness. In this implementation I can even remove unused quads to save on vertices, poly count and overdraw.
Now, I want to create the actual physics representation of the body. In this case it is made of 3 rigid spheres, suspended with spring joints to a main rigidbody. Those spheres would jiggle around and move with (and be moved by) the Jello as physics takes over. These 3 spheres are now my reference points. Additionally, the main rigidbody is used as reference point. All reference points are marked as red spheres, and the collider spheres are marked in green in the image below.
The new vertex mapping system, just before physics kicks in and all forces take over, maps each vertex’s relation to all reference points. Relation in this case, is the transformation matrix between each vertex and ref point, or simply the offset (X, Y and angles) between the two. Each vertex takes into account ALL reference points, but weighs them according to distance (or rather, distance exponent).
On runtime, all that’s left is to remap each vertex according to the above precalculated offset formulas, and repeat this operation in every frame. This is not as heavy as it sounds, especially with a decent number of vertices and reference points. Results:
Since this worked well for springy creatures, I’ve started using it frequently on many other dynamic substances and elements, such as ropes, tentacles and even for simplified fluid dynamics, like so:
The above mechanism was mostly implemented on 2D but it is readily available for 3D with no code change. Using a few reference points on a 3D model would create a very cheap real-time soft body physics simulation. Hopefully I’ll get to that soon!
Math and stuff:
The general simple formula for vertex p (Vp) position is:
Where n is the number of reference points, Ri is reference point i in local object’s space, and Oi,p represents the original offset from Ri to Vp, and all weights add up to 1.
Also note about the chosen addition (+) operation: ideally matrix multiplication, which takes rotation into account, is in order. Multiplication would allow the vertex to be ‘twisted’ with the reference objects, whereas addition yields a simple morph. Multiplication is much heavier and in most cases has no visual effect, and in some cases it has negative effects. In my implementation I allow either, but hardly use multiplication.
Feel free to ask anything or post suggestions!