# Ozz-animation sample: Animation keyframe optimization

## Description

This sample removes redundant keyframes (within a tolerance) from an animation in order to optimize its memory footprint 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).

## 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 fbx2ozz tool with optimizations disabled. The raw animation 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 source raw animation median and maximum "error" generated by the optimization stage. 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:
  - tolerance: The maximum error that an optimization is allowed to generate on a whole joint hierarchy.
  - distance: The distance (from the joint) at which error is measured (if bigger that joint hierarchy). This allows to emulate effect on skinning or a long object (like a sword) attached to a joint (hand).
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:
- Optimization quality: 3 rendering mode are provided to check optimization quality:
   - "Raw animation": Renders the source raw animation. No tolerance optimization or compression is performed.
   - "Run time" (default): Result of the optimization and compression passes, using sample tolerances.
   - "Absolute error": Renders the difference between the optimized and the source animation. This is especially useful for debugging as it makes it easy to detect compression artifacts.
- Optimization quantity: Run-time animation size is displayed in the UI.

Some other parameters can be tuned from sample UI to affect animation playback.

## 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 (context 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:
   - "Raw animation": Every track of the source raw animation is traversed in order to extract each relevant keyframes. Keyframes are interpolated to match the exact 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 the closest to the input file, kind of lossless.
   - "Run time" (default): Samples optimized runtime animation as usual.
   - "Absolute error": Samples both Raw and runtime animations as described above. Resulting local transformed are subtracted in order to compute the error generated by the runtime animation compression and optimization.
5. The remaining code of the sample allocates runtime buffers and samples animation every frame. See playback sample for more details.
