Material animations using AnimationClips

I’m trying to create an AnimationClip to change Mesh.material.map.offset values.
My goal is to obtain a material animation. What I tried so far is based on AnimationClipCreator.js:

let duration = 1000
let times = [0, duration / 2, duration],
    values = [0,0, .5,.5, 0,0]
let trackName = 'node_name.material.map.offset'

let track = new THREE.VectorKeyframeTrack(trackName, times, values)

let clip = new THREE.AnimationClip('material_animation_name', duration, [track])

let mixer = new THREE.AnimationMixer(scene)
mixer.clipAction(clip).play()

I noticed that VectorKeyframeTrack is only used for Vector3 data, such as .position or .scale values. Can it be used also for Vector2 data like Texture.offset?

I also tried setting trackName as:

let trackName = 'node_name.material.map[offset]'

but what I get in the scene graph at that location is an interpolated Scalar value instead of a Vector2 value.

The scene graph of the scene variable is:

scene: Scene {
    ...,
    children: Array(2) {
        0: Bone { uuid: "ADBCD7D7-9431-48...", name: "bone_name", type: "Bone", ... },
        1: SkinnedMesh { uuid: "56C8D82F-8E5B-47...", name: "node_name", type: "SkinnedMesh", ... }
    },
    ...
}

Thanks in advance,
Stefano

Try this approach: https://jsfiddle.net/f2Lommf5/10232/

Directly use the texture as AnimationMixer's root object. PropertyBinding is currently not able to parse track names like node_name.material.map.offset.

@Mugen87, thanks for replying so quickly.

If my model/scene has dozens of material animations, I would have to store dozens of different AnimationMixers in addition to the “skeletal animations” one.

I noticed that PropertyBinding#parseTrackName accepts UUIDs and trackNames like

"${texture.uuid}.offset"

can be used (JSFiddle).

As a temporary solution, I could add a few more lines in my parser to convert these trackNames.


I hope that PropertyBinding will eventually support more general and complex trackNames since the next step in the glTF format is to handle material animations, visibility animations and other arbitrary properties animations:

glTF Specification 2.0

Note: glTF 2.0 only supports animating node transforms and Morph Targets weights. A future version of the specification may support animating arbitrary properties, such as material colors and texture transform matrices.


Edit: in the JSFiddle, applying the AnimationMixer to the mesh breaks the search for the UUID.
The following error appears in console:

THREE.PropertyBinding: Trying to update property for track: FE961FD2-A6A8-47AF-9658-26238480BF07.offset but it wasn't found.

So looks like the only way to have a single AnimationMixer is to edit PropertyBinding.

1 Like

If you are convinced that the current animation system is too restricted, consider to open a feature request at github. That’s the best way to promote an enhancement :wink:.

There are some hacks you can use to make it the trackname system more flexible, too. The parsing is limited in the depth it can parse, e.g. object.foo.bar works but not object.foo.bar.baz I think, but try:

object.materialMapOffset = object.material.map.offset

And then object.materialMapOffset.x should work as a scalar track name. If the animation system doesn’t support vec2 types, that would probably be good to fix. The three.js animation system is pretty flexible already, there are just some things like this that could be improved. :slight_smile:


About glTF, I don’t expect the spec will allow animation of entirely arbitrary properties. But certainly more properties than the spec allows to be animated today.

3 Likes

Awesome, thanks @donmccurdy! I’ll use this hack for now (Updated JSFiddle).

Since the "material" keyword is treated as a special object name (see PropertyBinding.js#L159), then

mesh.materialMap = mesh.material.map

doesn’t work, but having

mesh.material.mapOffset = mesh.material.map.offset

does work.