Animagica: Animation Blueprint Editor and Runtime for Three.js

Hey everyone!

I’ve been working on an animation system including a web-editor for the last 1.5 years.
It’s called Animagica and conceptually it’s similar to Unreal Engine’s Animation Blueprints, in which you create an animation graph that passes Animation Clips through several Nodes towards an Output. The indermediate nodes control animations in several ways, including things like:

  • bone masking
  • root motion control
  • blending (1D and 2D blend spaces)
  • state machine logic
  • timeline synchronization and timeline events

The system is extremely data driven, meaning in 99% of cases you will no longer do things like action.play(), action.setWeight(), action.setEffectTimeScale() yourself, instead you define a bunch of parameters at editor-time, i.e. speed, direction, isJumping etc. and feed those to your graph, which then handles everything itself. The editor allows you to export your created graphs as json files which you can then execute using the runtime in your App/Game. Under the hood the runtime binds to three’s own animation system so I’m not doing skinning or bone matrix computation myself (also means you can connect Animagica to your own low level anim system as the core has no dependency to three).

The library is still work in progress, but I’ve been posting about it regularly and since not everyone uses Twitter, I’d love to share updates in here as well :slight_smile:

Some narrated Videos (on Twitter):

  1. Intro/Core Concepts
  2. Blending
  3. Animation State Machines

Some Screenshots:




5 Likes

Also, while I haven’t finalized the api yet I thought it’d be good to give an example of how your code using it in a three project would look like. So here is some pseudo-ish code (using r3f syntax for brevity but it would work exactly the same in vanilla three):

// import some graph previously exported from the editor
import graphJSON from "./my-anim-graph.json"

// get anim clips, i.e. in React
const {animations} = useGLTF(model);

// load graph from config file and pass anim clips to it
const graph = animagica.buildGraph(graphJSON, animations);

// for each graph we pass values for the parameters that we defined in 
// the editor. I.e. if this graph controls things like walk/run anims,
// direction and jumping animations it might look like this.
useFrame(() => {
  graph.setParameter("speed", characterVelocity.length()));  
  graph.setParameter("direction", characterVelocity.normalize());
  graph.setParameter("distToGround", characterPosition.y);
  graph.setParameter("triggerJump", keyMap["jump"] || keyboard["space"]);

});

// update the global runtime (once per frame for all graph instances)
useFrame(() => {
  animagica.update(dt);
});
1 Like