-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Labels
area:compressionCompression/decompressionCompression/decompressionarea:writingFile/format writing/exportFile/format writing/exportcrate:ltk_animAnimation & skeleton crateAnimation & skeleton crateenhancementNew feature or requestNew feature or requestformat:anmAnimation formatAnimation formatneeds-researchRequires reverse engineering/researchRequires reverse engineering/researchpriority:lowLow priorityLow priority
Description
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
ErrorMetricvalues 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/JumpFrameU32lookup 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
- Implement curve fitting algorithm for keyframe reduction
- Implement frame ordering by "time needed"
- Implement jump cache generation
- Implement
Compressed::to_writer - Add
CompressedBuilderAPI - Add tests with roundtrip verification
- Document the compression pipeline
References
Reactions are currently unavailable
Metadata
Metadata
Labels
area:compressionCompression/decompressionCompression/decompressionarea:writingFile/format writing/exportFile/format writing/exportcrate:ltk_animAnimation & skeleton crateAnimation & skeleton crateenhancementNew feature or requestNew feature or requestformat:anmAnimation formatAnimation formatneeds-researchRequires reverse engineering/researchRequires reverse engineering/researchpriority:lowLow priorityLow priority
Type
Projects
Status
Todo