Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modern Mixer-based Animation System #6934

Merged
merged 161 commits into from
Sep 21, 2015
Merged

Conversation

bhouston
Copy link
Contributor

@bhouston bhouston commented Aug 1, 2015

This PR is an implementation of the idea outlined here: #6881

There are five new classes in the /src/animation directory:

  • AnimationAction.js
  • AnimationClip.js
  • AnimationMixer.js
  • AnimationUtils.js
  • KeyframeTrack.js
  • PropertyBinding.js

I have also modified these classes to work with the new system:

  • MorphAnimMesh
  • BlendCharacter
  • UCSCharacter
  • MD2Character

I've updated the animation examples to work with the new system -- these are the most interesting:

https://exocortex.github.io/three.js/examples/#webgl_animation_skinning_morph
https://exocortex.github.io/three.js/examples/#webgl_animation_skinning_blending
https://exocortex.github.io/three.js/examples/#webgl_morphtargets_horse
https://exocortex.github.io/three.js/examples/#webgl_morphtargets_md2

The main benefits of this design are tremendous:

  • Compatible with the existing JSONLoader format.
  • Anything can be animated: bones, material properties (colors, opacity, booleans), visibility, transforms, morphs. This is done via the use of track names that can be resolved to anything in a scene sub-hierarchy via the PropertyBinding.
  • The mixer can do fadeIn, fadeOut, crossfade, and warping of any animatable properties.
  • AnimationClips are ways to package together hetereogeneous animations together -- a clip can even contain animations on different nodes within a sub-hierarchy.

Cool things:

  • Clips can animate anything in a sub-hierarchy of an object. This can be powerful as it can drive the animations of a number of related nodes.
  • Supports interpolation of Vector2, Vector3, Vector4, Color, Quaternion (any class with .clone and .lerp/.slerp works), as well as Boolean, Number, and String.
  • PropertyBinding is fairly fast because it uses memorization in a bunch of places.
  • Includes a lossless keyframe optimizer (lossy would be the next step) that removes unnecessary keyframes and uses precaluation to speed accessing keyframes.
  • Memory optimized to avoid allocations at runtime without sacrificing speed or flexibility.
  • It would be straightforward to add new track types.
  • You can animate the weight and timescales of clips. I use this in the "webgl_animation_skinning_blending" to simplify crossfades.
  • Clips can be used on multiple characters at the same time.
  • KeyframeTracks uses a local search strategy for the current key which is generally very fast given the access patterns. Right now it caches the local search index in the keyframe track, but eventually that should be moved into the Action for further speed improvements.

This was developed with significant input from @dsarno and @amirebrahimi.

@bhouston
Copy link
Contributor Author

@mrdoob Congratulations on the last official ThreeJS release -- the refactor is amazing.

I hope it is nearly possible to merge this PR now. :) :) :)

Myself and my colleague @jackcaron have updated this PR based on your last recommendations. We have made "animations" as a top level part of the *.json format exported from Blender. Example:

http://exocortex.github.io/three.js/examples/models/json/scene-animation.json

I have also renamed *.clips on objects and geometries to be *.animations per your recommendation. We have updated the code and examples as necessary. I have also created a THREE.AnimationLoader class.

I've tested all of these examples:

http://exocortex.github.io/three.js/examples/webgl_animation_scene.html
http://exocortex.github.io/three.js/examples/webgl_animation_skinning_morph.html
http://exocortex.github.io/three.js/examples/webgl_animation_skinning_blending.html
http://exocortex.github.io/three.js/examples/webgl_lights_hemisphere.html
http://exocortex.github.io/three.js/examples/webgl_loader_json_blender.html
http://exocortex.github.io/three.js/examples/webgl_loader_scene.html
http://exocortex.github.io/three.js/examples/webgl_morphnormals.html
http://exocortex.github.io/three.js/examples/webgl_morphtargets_horse.html
http://exocortex.github.io/three.js/examples/webgl_morphtargets_human.html
http://exocortex.github.io/three.js/examples/webgl_shading_physical.html
http://exocortex.github.io/three.js/examples/webgl_shadowmap.html
http://exocortex.github.io/three.js/examples/webgl_shadowmap_performance.html
http://exocortex.github.io/three.js/examples/webgl_skinning_simple.html
http://exocortex.github.io/three.js/examples/webgl_terrain_dynamic.html
http://exocortex.github.io/three.js/examples/canvas_morphtargets_horse.html
http://exocortex.github.io/three.js/examples/webgl_loader_md2.html

I hope this is sufficient for this monster PR. We can hopefully continue to build upon this system but as separate smaller PRs. :)

@bhouston
Copy link
Contributor Author

Just noticed via @WestLangley that there is a build/three.js in there. I'll have to remove it. Give me a bit.

@bhouston
Copy link
Contributor Author

Okay, I have removed the build/three.js that @WestLangley noticed. :) This PR is ready again to review.

@mrdoob
Copy link
Owner

mrdoob commented Sep 19, 2015

Looking really good!

Seems like http://exocortex.github.io/three.js/examples/webgl_animation_scene.html is now 90degree rotated? Is it intentional?

@bhouston
Copy link
Contributor Author

@mrdoob wrote:

Seems like http://exocortex.github.io/three.js/examples/webgl_animation_scene.html is now 90degree rotated? Is it intentional?

Good attention to detail. Yes the change is intensional. It was actually wrong before -- here is the scene it was exported from: https://clara.io/view/96106133-2e99-40cf-8abd-64defd153e61

@mrdoob
Copy link
Owner

mrdoob commented Sep 19, 2015

Ok, now that the animations are defined at the top level, how about something like this?

{
    "metadata": {},
    "animations": [{
        "uuid": "AF2ADB07-FBC5-4BAE-AD60-123456789ABC",
        "type": "vector3",
        "fps": 29,
        "tracks": [{
            "keys": [{
                "value": [1.22253,1.22253,1.22253],
                "time": 5
            },{
                "value": [1.22253,1.22253,1.22253],
                "time": 6
            }]
        }]
    }, ... ],
    "geometries": [],
    "object": {
        "name": "cylinder001",
        "uuid": "7935BB30-4CBC-3BEE-A497-8994876785B6",
        "matrix": [1.22253,-0,-0,0,-0,-0,-1.22253,0,0,1.22253,-0,0,0,38.7012,-1.71412,1],
        "visible": true,
        "type": "Mesh",
        "material": "541CFE3C-B1BD-37FD-8A82-3870870BB8A8",
        "castShadow": true,
        "receiveShadow": true,
        "geometry": "CAEC0410-6CA0-3646-AF22-DE6D5D34C387",
        "animations": {
            "position": "AF2ADB07-FBC5-4BAE-AD60-123456789ABC",
            "scale": "AF2ADB07-FBC5-4BAE-AD60-123456789ABC"
        }
    }
}

This will allow us to reuse animations with different properties and different objects. This way will also follow the format design.

Thanks so much for your patience guys! We're almost there!

@bhouston
Copy link
Contributor Author

@mrdoob wrote:

This will allow us to reuse animations with different properties and different objects. This way will also follow the format design.

Hmm... I am not sure I understand. Is the idea to save space? Or to allow an animation to be reused on multiple nodes?

One of the issues of having references from the "objects" hierarchy into the "animations" set is that usually the animations are potentially conflicting -- such as you can have walk, run, jump, which all can be applied to the same object. Thus referencing a specific animation from an object sort of conflicts with that idea of choosing different animations to apply to a object.

The other issue is that reuse is already support in the "animations" via the use of relative track names. While each track name requires a property name to be specified, e.g. "position", "scale.x", "visibility", etc., you do not have to mention a node name or UUID, you can leave it name blank. If you leave it blank the node to which the animation is applied is determined by the node you reference when creating the AnimationAction(). This means that the AnimationClip is shared between all actions, even if they are hundreds of different nodes. :) If you use a node name, and you have multiple node with that name in the scene, AnimationAction will only bind to the first node it finds as a child of the node you specify as the bind point. Thus if you have different "Gun" nodes you can reuse the Gun animations just by specifying the base character node and it will apply to the the "Gun" node under those characters, not all Guns.

The idea of relative tracks is "inspired" by what Softimage, Maya do with relative tracks. It is the same concept and it is crazy powerful.

@mrdoob
Copy link
Owner

mrdoob commented Sep 21, 2015

Hmm... I am not sure I understand. Is the idea to save space? Or to allow an animation to be reused on multiple nodes?

Both.

One of the issues of having references from the "objects" hierarchy into the "animations" set is that usually the animations are potentially conflicting -- such as you can have walk, run, jump, which all can be applied to the same object.

Ah, I see... Yeah, my suggestion collides with this... I guess experience with all this will show us the correct design. By now, lets go with your design! 😊

f you leave it blank the node to which the animation is applied is determined by the node you reference when creating the AnimationAction()

Actually, I think this is the behaviour I was suggesting.

mrdoob added a commit that referenced this pull request Sep 21, 2015
Modern Mixer-based Animation System
@mrdoob mrdoob merged commit c07a5b8 into mrdoob:dev Sep 21, 2015
@mrdoob
Copy link
Owner

mrdoob commented Sep 21, 2015

Yay! Thanks guys!

@bhouston
Copy link
Contributor Author

Wohoo! Thanks @mrdoob for putting up with me and this huge PR.

@dsarno
Copy link

dsarno commented Sep 21, 2015

Fantastic work @bhouston and those that vetted the PR. This is very exciting. Thanks @mrdoob!

@michaelybecker
Copy link
Contributor

Just chiming in to say I'm currently dealing with a big project, involving dozens of animations on the same JSON object, and this refactor was a godsend. A HUGE thank you to everyone involved!

@majimboo
Copy link

majimboo commented Nov 23, 2016

How would you use multiple animation mixers on multiple skinnedmeshes?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.