guillaumeblanc / ozz-animation

Open source c++ skeletal animation library and toolset
http://guillaumeblanc.github.io/ozz-animation/
Other
2.46k stars 302 forks source link

Question about keyframe compression #133

Closed StoneWolf closed 3 years ago

StoneWolf commented 3 years ago

Is it possible to customize keyframe compression? I'm mostly interested by translations, which seem to be using half-precision floats when compressed. If I'm not mistaken, this would produce jittery animations when uncompressed translations base values are, for example, 1000.0 and change by orders of magnitude less, for example 0.001.

This is especially visible (given that my ozz-animation implementation is correct) in this scene: https://github.com/KhronosGroup/glTF-Sample-Models/tree/master/2.0/VC

Most of the animated objects appear jittery, especially the helicopter.

I understand that this might not be a "normal" use case and that I might be better off not using ozz-animation for non-skeletal animations like in this scene.

guillaumeblanc commented 3 years ago

Hi,

I think you're right, halfs are most probably the reason for the jittering. It's definitely not a use case I was expecting, as usually model space transformation would remain closer to 0, but the model be moved to a distant world space position with a fixed (precise) matrix multiplication.

Anyway, that means halfs (alone) are not the correct representation. Storing an offset value (to be subtracted to the value before half compression, and added back afterward), would allow to bing halfs back to a meaningful domain. A better way is to get rid of halfs and quantize values with an offset and a scale. I'd like to go this way in the future.

Translations format is unfortunately not customizable in ozz. You need to change the storage, and the compression / decompression functions.

Hope it helps, Guillaume

Side note, I'd really like to see what you're doing with that scene, and know how you're importing the mesh.

StoneWolf commented 3 years ago

Thank you for your answer.

I'm not doing anything special with that scene, it just happens to be the first "complex" animated glTF scene I tried to load on my engine, to see if my ozz-animation implementation was done properly or not (spoiler: it was not). After fixing quite a few bugs on my end, only this "jittery meshes" issue remained, and after digging for a few hours I figured it was most likely due to the half floats.

I'm currently making a game engine and, later on, a game using that engine. As I'm still in the early stages of engine development, I can't know yet if I will encounter other animated models that will have this issue or not. My plan for the moment is to use ozz-animation for both skinned and non-skinned meshes.

I'll try your multithreaded sample to see what the performance impact of switching to regular floats instead of halfs would be. If it's only a few percent of difference, I'll probably just switch to floats and call it a day.

As for your side note, I'm importing meshes with cgltf, including their animations at runtime (I modified gltf2ozz, which used tinygltf, to use cgltf as well as I didn't want to have two different gltf libraries). I figured importing animations with gltf2ozz was a matter of milliseconds per model, so I'm just importing the animations whenever I load a model into my editor.

guillaumeblanc commented 3 years ago

Hi,

Ideally you should be able to use ozz in both cases (skinned and non-skinned).

As a workaround if your code path is already different, you could use animation tracks which are decimated but not compressed.

I don't expect any big impact on performance for using floats for translations. It will impact memory a bit (translations only), hence cache, but will also remove a decompression stage.

Regards, Guillaume

StoneWolf commented 3 years ago

After disabling compression for translations, the animations now display correctly. Thanks for the advice.