Skip to content

scenix v1.4.0

Choose a tag to compare

@github-actions github-actions released this 09 Jul 07:25
· 8 commits to main since this release
8e6aab3

Scenix v1.4.0 — Animation Runtime

Scenix 1.4.0 ships a full clip-based animation runtime on top of the Animato
value engine, bringing scenix to parity with Three.js's AnimationClip /
AnimationAction / AnimationMixer model while keeping scenix's typed-ID,
deterministic, renderer-agnostic discipline.

What's new

  • Clip runtime — AnimationClip, AnimationAction, AnimationMixer with
    loop modes (Once / Repeat / PingPong), per-action time scale,
    pause/resume, named markers, crossfade, additive blending, and deterministic
    per-tick sampling.
  • Keyframe tracks — KeyframeScalar / Vec3 / Quat / Color / Bool
    with Linear, Step, and CubicSpline interpolation (quaternions use
    slerp + shortest-arc).
  • Property bindings — typed PropertyBinding targets for nodes, bones,
    materials, cameras, lights, and morph weights (no stringly paths), plus a
    stable BindingKey for accumulator lookups.
  • Events — AnimationEvent::Loop / Marker / Finished returned each
    tick for deterministic, callback-free consumption.
  • Light & morph targets — animate light color / intensity / range /
    spot-angle and morph-target weights through the mixer or the procedural
    ScenixAnimationDriver.
  • Skeletal animation — scenix-mesh SkinningData + cpu_skin CPU
    fallback, and scenix-renderer register_skin / update_bone_matrices /
    register_morph_targets / update_morph_weights GPU hooks plus the
    SKINNING_WGSL snippet.
  • Retargeting — RetargetMap copies poses between skeletons by bone name.
  • Debug helpers — AnimationPathHelper + PoseHelper line geometry.
  • Loader — animation accessor output bytes are now decoded into
    LoadedAnimationChannel::output; the facade clip_from_loaded bridges
    imported clips to the runtime.

Dependency updates

  • Animato 1.5.0 → 1.7.0 (the previous 1.6.0 release gate is
    resolved; scenix uses the stable std / tween / spring / serde
    feature set).
  • All scenix workspace crates 1.3.0 → 1.4.0.

Quick example

use scenix::{
    AnimationClip, AnimationMixer, ClipChannel, ClipTrack, KeyframeInterpolation,
    KeyframeVec3, LoopMode, NodeProperty, PropertyBinding, SceneGraph, SceneNode, Vec3,
};

let mut scene = SceneGraph::new();
let node = scene.add(SceneNode::new("mover"));

let clip = AnimationClip::empty("move").with_channel(ClipChannel {
    binding: PropertyBinding::Node { node_id: node, property: NodeProperty::Translation },
    track: ClipTrack::Vec3(KeyframeVec3::new(
        vec![0.0, 1.0],
        vec![Vec3::ZERO, Vec3::new(5.0, 0.0, 0.0)],
        KeyframeInterpolation::Linear,
    )),
});

let mut mixer = AnimationMixer::new();
let clip_index = mixer.add_clip(clip);
let action = mixer.add_action(clip_index);
mixer.action_mut(action).unwrap().set_loop_mode(LoopMode::REPEAT);
mixer.action_mut(action).unwrap().play(0.0);

// each frame:
// mixer.tick(dt, &mut scene, &mut cameras, &mut materials,
//            &mut lights, &mut skeletons, &mut morphs)

Performance

The mixer samples clips in O(channels × actions) per tick with BTreeMap-
keyed accumulators for stable blend order. A 1000-channel clip mixes in well
under a millisecond on commodity hardware (see
benches/animation_mixer_bench.rs). The CPU skinning fallback
(scenix_mesh::skin::cpu_skin) lets headless/no-GPU tests validate poses
without a wgpu device.

Migration notes

  • ScenixAnimationDriver::tick now takes lights and morphs stores in
    addition to skeletons. Pass empty stores if unused.
  • LoadedAnimationChannel gained an output: Vec<f32> field; update struct
    literals accordingly.
  • Animato 1.5.0 → 1.7.0 is a drop-in for the std / tween / spring /
    serde feature set; no scenix-side code changes required.

Known limitations

  • Cubic-spline interpolation is fully implemented for scalar tracks; vec3 /
    quat / color cubic channels fall back to linear sampling in v1.4.
  • Additive blending accumulates weighted deltas into the same normal
    accumulator for v1.4; full base-clip-relative additive is planned.
  • GPU skinning ships the registry, upload hooks, and SKINNING_WGSL snippet;
    full shader-pipeline wiring behind a SKINNING define is additive in a
    follow-up patch.

Links

What's Changed

Full Changelog: v1.3.0...v1.4.0