I noticed that on the ASSIMP forums there were many requests for an animation loader– even more specially, one that pre calculated the animation transforms. There are huge benefits to pre calculating anything, especially animation data like this. I had a test mesh with 56 bones (yeah, its alot i know, but the models animations are great) and a single texture for the entire model. So the whole model took a single draw call.
All the numbers below were taken from using NVIDIA PerfHUD, which is a great profiling tool!
To Traverse the model and recalculate the transforms each frame took about .083 ms CPU time (this is includes the total model setup time as well), GPU draw time was .083ms. You see the problem?
Afterwards, my CPU time went to .013ms, and of course my gpu time was the same. This might not seem like big savings, but if you have 20-30 animated characters on the screen the total cpu time is 25* .083 = 2.075 ms, and 25* .013 = .325ms. As you can see, this is a huge savings if I plan on having multiple animations running in the scene.
So, to use it, you must be using the ASSIMP library of course! The code also has a save to disks and load from disk that works as well. So, if you want to save the animation, use
void Save(std::ofstream& file);
void Load(std::ifstream& file);
The functions expect the file stream to be opened somewhere else in the program, then passed a reference to the stream. In this way, animations can be saved where ever you like within a custom model file, or to a separate file.
Before any Animations can be played,
void Init(const aiScene* pScene);
has to be called, which will extract the skeleton and all animations from the pScene object.
After that, to get the matrix transforms, simply call
std::vector& GetTransforms(float dt)
Now, this function will wrap your dt, so dont worry about going out of bounds. If the time is 5656565, it will wrap it correctly. So just keep a running total of the dt and pass it to the function. The return will be the array with the transforms, which you then pass to the shader.
Note: I did not comment the code completely, and there is a small reminent of my dual quaternion implementation that will work if you uncomment it and use it. You would need to check out the NVIDIA SDK10, Quaternion Skinning example for the shader code and their implementation. It is pretty straight forward. All you would need to do is change the shader. Also, I use my mat4 class, but it is complely compatible with the D3DXMATRIX class, so if you replace mat4 with D3DXMATRIX and their equivalent calls, there will be no problems. One last thing, this builds transforms for a LEFT HANDED coordinate system. ASSIMP’s matrix4x4 is a right handed matrix, which is why I do a couple of transposes in the code when converting to my mat4.
The code is free for use for anyone for any purpose.