Monthly Archives: February 2015

Open source Skeletal Animation and Software Skinning

tl;dr I wrote a tiny open source skeletal animation and software skinning library for C++:

Why Skeletal Animations?

Animations can really bring life to projects, that’s why for some projects I am working on I want to have skeletal animation. Looking around on the internet I could not really find an open source solution that did what I wanted. I was looking for something really simple.


On my Google adventure I came across ozz-animation which I thought would do exactly what I was looking for. A complete package for animating skeletons and software skinning. There was a problem though. This library added tools to convert FBX files to skeletons and animations, and one tool to convert FBX files to a skinned mesh. The mesh however does not contain materials or texture coordinates or any other things you might be interested in, just vertices and normals. The source of the converters also seem really complicated so I was not sure how to add materials and texture coordinates to that. Instead I decided to roll out my own library, which may be useful to other people as well.

My own open source solution

As it turned out, it was really easy to write a library that handles skeletal animation and skinning. Following a simple tutorial that actually included skinning in vertex shaders I was able to write a library that does the skinning on the CPU.

Included in my library is also a converter that converts loaded Assimp scenes to models that can be animated, as well as (de)serialization functions to store and load these models on and from disk.

Why software skinning? Just for the sake of simplicity. I am not looking to animate models with millions of vertices, just simple models which can easily be skinned on the CPU. It is also easier to port to different platforms without worrying about shader languages.

It is really easy to load a model from Assimp:

void LoadModel()
    Assimp::Importer Importer;
    const aiScene* pScene = Importer.ReadFile("some_animated_model.fbx",
        aiProcess_LimitBoneWeights |
        aiProcess_Triangulate |
        aiProcess_JoinIdenticalVertices |

    AssimpConverter::Convert(pScene, g_AnimatedModel);

Then to make the model animate, just call the Update function:

void Update(float a_Dt) // a_Dt is the elapsed time since last frame in seconds

Rendering the model is very straightforward because you have direct access to the model’s vertices and normals. As an example here is one way how you could render the model with OpenGL.

void Render()
    for (unsigned int i = 0; i < g_AnimatedModel.GetNumMeshes(); ++i)
        const SA::sAnimatedMesh& AnimMesh = g_AnimatedModel.GetMesh(i);

        for (unsigned int i = 0; i < AnimMesh.NumIndices; ++i)
            unsigned int Index = AnimMesh.pIndices[i];
            glm::vec3 n = AnimMesh.pNormals[Index];
            glm::vec3 v = AnimMesh.pTransformedVertices[Index];

            glColor4f(n.x, n.y, n.z, 1);
            glVertex3f(v.x, v.y, v.z);

The license I decided to go with is the MIT License, so why not check it out?