How to run an animation for an entity glTF model?

How can I run an animation for a gltf model that is loaded as part of an Entity? And is that possible via CZML?

I can see the CZML Model Articulations demo in Sandcastle, but articulations seem to be a different feature in gltf than animations.

Cesium.Model has activeAnimations.add() which can start an animation, however, Entity.model is Cesium.ModelGraphics and doesn’t appear to include a way to get the underlying Cesium.Model. Expose Model through the entity API · Issue #7378 · CesiumGS/cesium · GitHub being closed suggests this will not be added.

It appears possible to work around this, as suggested here: Cesium 1.6 specific documentation and examples, specifically activeAnimations and entities. - #2 by Matt_Amato by looking through all the primitives in the scene:

function getActiveAnimations(viewer, entity){
  var primitives = viewer.scene.primitives;
  var length = primitives.length;
  for(var i = 0; i < length; i++){
    var primitive = primitives.get(i);
    if(primitive.id === entity && primitive instanceof Cesium.Model){
      return primitive.activeAnimations;
    }
  }
  return undefined;
}

And then for SampleData/models/CesiumAir/Cesium_Air.glb, the propeller animation can be started with:

 getActiveAnimations(viewer, entity).add({
          name: "PropAction_Prop__2_",
      });

However, this doesn’t seem a reliable way to implement it - I would have thought there should be an API call somewhere for it. Also, it doesn’t work from CZML.

Thanks,
Jon

2 Likes

Hi @srce,

What kind of animation are you trying to run? You are correct, basic animations are possible with CZML. As the demos showcase, you can move a 3D Model to different geolocation over time using CZML. I recommend using a different data format to control more small-scale animations such as the rotor of a helicopter or the wheels of a vehicle.

-Sam

I’m referring to animations that are defined in a glTF model. For example, in Cesium_Air.glb used in various Sandcastle demos, the propellers can be rotated or stopped by running/stopping the PropAction_Prop__2_ animation, via Cesium.Model.activteAnimations.

As far as I can see, there isn’t a clean way to do this via the Entity API or CZML (other than running them continuously with Cesium.ModelGraphics.ConstructorOptions.runAnimations). I want to be able to run a specific animation when a particular event occurs. Cesium.Model supports this, but Cesium.ModelGraphics doesn’t appear to.

1 Like

Hi @srce,

I just looked through some JavaScript code that I have written in the past that adds animation to a glTF. I can send over my code for your reference.

    var apache = viewer.entities.add({
        name : 'AH64E Apache',
        position : apachePositions,
        orientation: new Cesium.VelocityOrientationProperty(apachePositions),
        model : {
            distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 400),
            uri : 'static/models/apache.glb',
            nodeTransformations : {
                'main_rotor_offset': new Cesium.NodeTransformationProperty({
                    rotation: rotorTransformation
                }),
                'tail_rotor_group': new Cesium.NodeTransformationProperty({
                    rotation: new Cesium.CallbackProperty(function(time, result) {
                        var angle = (time.secondsOfDay % (Math.PI * 2)) * 9;
                        return Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Z, angle, result);
                    }, false)
                }),
                'machinegun_trav_offset': new Cesium.NodeTransformationProperty({
                    rotation: new Cesium.CallbackProperty(function(time, result) {
                        return Cesium.Quaternion.fromAxisAngle(Cesium.Cartesian3.UNIT_Y, -sensorHeading, result);
                    }, false)
                })
            },
            scale : 1
        }
    });

It seems like NodeTransformationProperty is key here.

-Sam

2 Likes

Hi Sam. Thanks, but that’s not quite what I’m after. In your code, it looks like you are manually animating the models. i.e. your Javascript code specifies how to transform different parts of the model.

However, .gltfs can contain the details of how the animation works embedded in them - so the animations can be created in a 3D modelling tool. With Cesium.Model.activteAnimations, all you need to do is specify the name of the animation in the .gltf that you want to play. This is supported by Model, but not ModelGraphics, as far as I can see.

I see it’s actually as something still to do in the roadmap: Models Roadmap · Issue #927 · CesiumGS/cesium · GitHub

'Schedule animations via CZML, i.e., CZML for calling model.activeAnimations.add

1 Like

Hello @srce and @sam.rothstein,

I’d been following this post hoping for an update but it looks like one it’s coming any time soon in the form of a ModelGraphics.activeAnimations.

I decided to manually implement the model animations via nodeTransformations in the mean time and it seems to work well. However, if I want to update the nodeTransformations property after initialization, it doesn’t seem to work.

For example, if I wait 5 seconds after the Viewer loads and plays, and addProperty or removeProperty like this:

planeModel.nodeTransformations.addProperty('myPropertyName', myNodeTransformationProperty)

the animation does not play like it does when I add it in the original definition like so:

const model = new ModelGraphics({
      uri: './my-plane.glb',
      nodeTransformations: {
        'myPropertyName': myNodeTransformationProperty,
      }
    })

Have either of you run into this issue and have a fix?

I’ve also started doing practice on nodeTransformation, you can apply node transformation on model (not the entity) like this:

var nodeTransformations = new Cesium.PropertyBag();
nodeTransformations.addProperty('myPropertyName', myNodeTransformationProperty);
planeModel.model.nodeTransformations = nodeTransformations;

check this sandcastle.

  • Regards,