Summary
Implement the ability to create compressed animation assets (.anm with r3d2canm magic) from raw animation data, enabling workflows like Blender → League animation export.
Background
Currently, ltk_anim can read and evaluate compressed animations, but cannot write them. The Compressed::to_writer method is unimplemented:
pub fn to_writer<W: Write + ?Sized>(&self, _writer: &mut W) -> crate::Result<()> {
unimplemented!("TODO: animation::asset::Compressed writing");
}
Proposed Implementation
Based on Riot's animation compression article, the pipeline would involve:
1. Curve Fitting (Keyframe Reduction)
- Start with dense per-frame samples (e.g., 30/60 fps from Blender)
- Use iterative Catmull-Rom spline fitting to reduce keyframe count
- Insert keyframes at midpoints of highest-error sections until error < threshold
- Use
ErrorMetric values to control quality vs compression tradeoff
2. Quantization
- Quaternions → 48-bit format (already implemented in
quantized.rs)
- Vectors → 48-bit format with min/max bounds
- Time → 16-bit normalized to duration
3. Frame Ordering
- Order frames by "time needed" not "key time" for cache-efficient playback
- For Catmull-Rom, frame Tn+2 is ordered by Tn's time
4. Jump Cache Generation
- Pre-compute hot frames at regular intervals for random access seeking
- Build
JumpFrameU16/JumpFrameU32 lookup tables
Proposed API
pub struct CompressedBuilder {
fps: f32,
duration: f32,
joints: Vec<u32>,
error_metrics: ErrorMetrics,
}
impl CompressedBuilder {
pub fn new(fps: f32, joints: Vec<u32>) -> Self;
/// Add raw samples for a joint (one per frame)
pub fn add_joint_samples(
&mut self,
joint_hash: u32,
samples: &[(Quat, Vec3, Vec3)], // rotation, translation, scale
) -> &mut Self;
/// Set error thresholds for curve fitting
pub fn with_error_metrics(&mut self, metrics: ErrorMetrics) -> &mut Self;
/// Build the compressed animation
pub fn build(self) -> Result<Compressed, Error>;
}
Tasks
References
Summary
Implement the ability to create compressed animation assets (
.anmwithr3d2canmmagic) from raw animation data, enabling workflows like Blender → League animation export.Background
Currently,
ltk_animcan read and evaluate compressed animations, but cannot write them. TheCompressed::to_writermethod is unimplemented:Proposed Implementation
Based on Riot's animation compression article, the pipeline would involve:
1. Curve Fitting (Keyframe Reduction)
ErrorMetricvalues to control quality vs compression tradeoff2. Quantization
quantized.rs)3. Frame Ordering
4. Jump Cache Generation
JumpFrameU16/JumpFrameU32lookup tablesProposed API
Tasks
Compressed::to_writerCompressedBuilderAPIReferences