Wednesday, November 23, 2022

Properly Animated People

I've finally gotten around to implementing proper skeletal animation for the 3D models of people in 3DWorld's cities and buildings. This involved completing many different steps along the way. I'll discuss my process here. This will be a relatively short post with lots of technical details, so fee free to play the videos at the end without reading the text. I'll add links where I can to articles that explain these concepts and give more info.

First, I had to write a wrapper for importing models using Assimp because my built in loaders only support the OBJ and 3DS file formats, and these don't store animations. This includes adding support for reading embedded textures as found in the FBX file format. The basic OpenGL/Assimp tutorial was useful for this, but only explained how to import simple static model geometry. If anyone is curious, my model import code can be found here, and the model rendering side of the code can be found here.

I originally had no idea how to load and use model animations, so I found a GitHub/YouTube tutorial series and another blog post that showed how to implement the matrix transforms with GLM. This took many attempts to get right because the code from those tutorials wasn't easy to integrate into 3DWorld's existing rendering system. I also ran into issues with the coordinate system used (I use Z as up rather than Y) and bounding cubes of animated geometry. Getting these things right required quite a bit of trial-and-error, including generating text logs of coordinates and transforms that I had to manually review. I guess that's to be expected when trying to learn multiple new things at the same time.

I used 3DWorld's model viewer scene config for working with Assimp model loading and experimenting with animations. This view shows a single model with nothing else other than the sky background. It's much faster to load than the city/buildings scene. I was able to compare my results with the 3D Viewer application that comes with Windows, which supports loading/drawing embedded textures and animations. In addition, I took advantage of 3DWorld's hot reload of OpenGL shader programs while debugging to get the GPU side of this correct.

The models and animations I used for this were found on Adobe Mixamo, which is free but requires creating an account. While my code worked fine on the md5mesh model used in the tutorial, all of the Mixamo models looked very wrong when animations were enabled, with curvy legs and arms bent in the wrong direction. For example:

Is it my imagination, or is something wrong with the animations here? For some reason, this model doesn't look like the one on the website.

It turns out that the problem was due to a known bug in Assimp. This took me many hours to figure out. What's particularly annoying is that the version of Assimp I have on linux doesn't have this bug, it's only present on Windows. This is why I never came across it while working with the tutorial project on linux.

I replaced the four static models I was using for people in 3DWorld with five new animated people models. (Well, technically I was animating the original models in the vertex shader, but only their legs moved.) Here's a YouTube video showing the final results with five different models using walking animations.


That looks pretty good for regular people. But what about gameplay mode? We need to add some zombies, and I can finally get proper zombie models and animations. They definitely make building gameplay mode much more frightening!

That's all I have for today. The next step is to store/use multiple animations per model. I need at least an idle standing animation for people. They currently stop mid-walk with one leg up in the air, which doesn't look very natural. I can't revert to the non-animated version when stopped because these models all begin in a T-pose with their arms straight out to their sides.