September 14 2017 | 05:20 PM
How Skeletal Animation Actually Works
In this post I'm going to try to explain properly how Skeletal Animation works, mostly in the context of Unity, although I'm going to present the general algorithms that lets you implement it in any engine.
A simple way to Animate
Let's assume that you already know the basics about a 3d Model in the context of a game engine.
A model has some vertices, which when connected we get triangles describing the surface of the model.
Besides a position in 3d space, vertices can have any info you need, from color to texture coordinates, normals and other stuff.
First, let's think first about 2d games. In those you have sprites, and animation is done by having multiple frames, in which characters appear in different poses.
Now if we extend this concept to 3D, we can too have "frames", instead of being separate pictures made of pixels, it would be different versions of the same mesh, each with different positions for each vertices.
We could even also have different colors per frame, or even different texture coordinates.
Also if we make sure that each frame has exactly the same number of vertices, we can mathematically blend each frame, to get smoother animation (eg: using Unity Mathf.Lerp function).
A hierarchy of Bones
Now, now, the method we described before is nice, but it requires tons of memory, also it does not allow us to create new animation in real time (eg: physics-based animation).
The alternative (and the way most game engines do animation) is called Skeletal animation. This requires some extra stuff, besides the vertices and triangles now we need bones (also called joints in some engines).
The idea behind the bones is that we just describe animation in terms of bone movement, and then using some nice code we deform the vertices so that their position somehow follows the bones. Of course, this means that each vertex now also needs to store which bone influence it.
Another nice thing about bones is that they can be defined as an hierarchy (similar to the scene hierarchy in an Unity project), meaning bones have a parent / child relationship with other bones, making their positions dependant of their parents. This is what allows you to rotate a character shoulder and the elbow and hand moves accordingly.
Now, enough with theory and let's talk about pratice. First, let's assume that the bones and weights are done by artists in Maya / Blender / etc, and are properly loaded into the engine.
By now you should have the following ready:
- Vertices including a reference to the bone that influences them
- Triangles (of course, duh!)
- Bones (just a position, plus a reference to their parent, or NULL if root bone)
With those things, we can already animate stuff. One thing that is not explained in many tutorials is what exactly is done, so I'm going to actually explain it instead of just saying "multiply bone matrices lol!".
The animation algoritm is done with the following steps:
- All vertices positions are stored in world-space (this just means, their default positions)
- Every vertex position must be transformed into bone-space (this means transforming their coordinates so that the origin (0,0, 0) is now where their bone position is).
- An animation transform is applied, which brings the bone again to world-space.
All those transforms are done with matrix multiplication, and while this sounds complicated, what actually is happening is:
- For example, when you rotate a character finger, the finger will rotate around an origin, however this is not the point (0,0,0) but instead the finger bone position. If you remember your matrix math, any rotation is done around a pivot point, and if you want to rotate around anything other than (0,0, 0) you first must apply a transform that moves the origin around, then apply the rotation. This is kinda what we do when transforming vertices positions to bone-space,, now instead of having (0,0,0) being the origin and a vector pointing up being (0, 1, 0), the origin is the bone position and the vector pointing up/right/front depends on the bone orientation. A space transform means changing both the origin point and the up/right/front directions!
- To animate with bones we also use frames, but an animation frame in this case is just a list of new bone positions.
Typically those would be a list of bone references plus a blending weight for each bone (a number between 0 and 1). The sums of the weights should be exactly 1.
Follow me on Twitter for more cool stuff!