ozz-animation

Samples - Keyframe reduction

View optimize sample source code.

Description

This sample removes redundant keyframes (within a tolerance) from an animation in order to optimize its memory weight and runtime update cost. It can display optimized and non-optimized version of the animation, as well as the difference between the two (aka the error generated by the optimization).

Initializing WebGL

Concept

This sample loads a runtime skeleton and a raw animation from ozz files. The raw animation (which is usually reserved for offline purpose) was exported using ozz offline tool with optimizations disabled. The raw animtion object is converted to a run-time object using ozz::animation::offline::AnimationBuilder utility. Prior to the conversion, animation is optimized by removing redundant keyframes (within a tolerance). It uses ozz::animation::offline::AnimationOptimizer utility that takes as input a raw animation and outputs a new optimized one. The sample displays the median and maximum “error” generated by the optimization stage, compared to source raw animation. Actually it also includes the “error” generated by the quantization of the translation, rotation and scale values performed during runtime animation object creation.

Sample usage

This samples allows to tweak animation key-frame optimization stage using 2 parameters:

The sample also exposes parameters to override the tolerance for one of the joint, as supported by ozz::animation::offline::AnimationOptimizer. This is useful for example when a joint a the skeleton has a contact point which requires more precision than other part.

Optimization result can be checked within the sample:

Implementation

  1. Import the runtime skeleton and the unoptimized raw animation objects. These are imported from files as described in the how to load an object from a file section. Note that the animation is still in an offline format at this stage.
  2. Optimizes animation by removing interpolable keyframes using ozz::animation::offline::AnimationOptimizer utility. It processes the source raw animation and outputs a new one. Optimization tolerance values like translation (meter), rotation (radian) and scale (percentage) are exposed to sample UI.
  3. Convert the offline animation to the runtime format, using ozz::animation::offline::AnimationBuilder. This utility takes as input the optimized RawAnimation and outputs the runtime ozz::animation::Animation. The runtime format is the one used for sampling. In opposition with the offline one, it cannot be edited/modified. It is optimized for runtime usage in term of memory layout (cache coherence for sampling) and footprint (compression scheme).
  4. Local-space transformations (in SoA format as required by the runtime pipeline) are computed from the runtime and the source raw animations according the selected rendering mode:
    • “Non-optimized”: every track of the source raw animation is traversed in order to extract each relevant keyframes. Keyframes are interpolated to match the extact expected time. This implementation isn’t part of the API but done by the sample, as raw animations aren’t intended to be used this way in runtime. Even though it works, performance are quite low compared with sampling a runtime animation. On the other end the result is
    • “Optimized”:
    • “Difference”:
  5. The remaining code of the sample is to allocate runtime buffers and samples animation every frame. See playback sample for more details.