Animations

Play the animations of a glTF model in a dashboard: by themselves, on a trigger from your application, at a linked speed, or at a linked position.

Motions you animated in Blender, such as a running conveyor belt, an opening gripper or a turning fan, are saved in the .glb file as animation clips. The 3D widget can play them, driven by time or by your application’s parameters. A clip plays only when the JSON file asks for it: without that, the model shows its rest pose, as before.

There are two ways to play clips:

  • animate on a model file plays all clips of that model from loading on. One key, nothing else to set.
  • An entry in animations chooses the clips and how they play: when they start, how they repeat, at which speed, or at which position.

Play all clips of a model

Add animate to the model’s entry in files:

"files": [
  { "file": "fan.glb", "name": "Fan", "animate": "repeat" }
]
animate Result
"repeat" or true Each clip repeats on its own length. A 1 s fan and a 4 s door: the fan turns all the time, the door cycles every 4 s
"once" All clips play once, together, and hold their end pose
"pingpong" All clips play forward and back, together
"off" or false Nothing plays, as without animate

animate applies to every copy of the model, including its instances. An entry in animations for one copy replaces it for that copy.

Animation entries

Each entry in animations plays clips of one model copy:

"animations": [
  {
    "object": "Gripper",
    "clip": "Open",
    "loop": "pingpong",
    "play": "onTrigger",
    "trigger": { "link": "root/UserParameters/IO/gripperOpen" }
  }
]
Field What it does Default
object The model copy, by the name of its files entry or of one of its instances. Required
clip The clip to play, by name, or a list of clip names All clips
loop once, repeat or pingpong, see Loop modes once
play When it plays: auto, onTrigger or whileHigh, see Start and stop auto
trigger The link that starts, stops or resets the animation
playCount Plays per trigger, with onTrigger and repeat or pingpong. 0 plays until reset 1
speed Playback speed: a number or a link, see Speed 1
position A link that sets the position in the clip instead of time, see Follow a position
count, start Numbered entries, see Many copies

trigger, speed and position are links, as in objects: link, channel, gain, offset, value and magnitude work the same way. See Links.

Find the clip names

Open the browser console (F12) on the dashboard and type grid3d.animations(). It lists every model copy that has clips, each clip with its name, its length in seconds, how many parts it moves, and which entry plays it now. Use the names in object and clip.

Loop modes

loop decides what happens at the end of a clip:

loop: once end start time → plays to the end and holds it loop: repeat end start time → starts again at the end loop: pingpong end start time → plays forward and back

With repeat and no clip, or a list of clips, each clip repeats on its own length. With once, pingpong and position, the clips play together as one animation, as long as the longest clip.

Start and stop

play decides when a clip runs. A trigger value is high when it is 0.5 or more, and low below 0.5.

play once repeat pingpong
auto Plays once after loading and holds the end pose Repeats from loading on Plays forward and back from loading on
onTrigger A rising edge plays it once; it holds the end pose A rising edge plays it playCount times; it holds the end pose A rising edge plays it playCount times forward and back; it ends at the start pose
whileHigh Plays to the end while high and holds it; low returns to the start Plays while high, pauses where it is when low Plays while high, pauses where it is when low
  • A negative trigger value resets the animation to its start and holds it there, in every mode, also during a playback. When the value is 0 or more again, the mode continues from the start: auto starts again, onTrigger waits for the next rising edge.
  • Rising edges during a playback are ignored with onTrigger. The next edge after the playback starts a new one.
  • With onTrigger, a trigger that is already high when the dashboard loads is not a rising edge. The animation waits for the trigger to go low and high again. whileHigh plays right away.
  • A trigger is read once per frame. A pulse shorter than a frame can be missed, so let the application hold the trigger high until the animation has started.

Speed

speed multiplies the playback rate. It can be a fixed number or a link, and a linked speed is applied all the time, also during a playback.

Speed Result
Left out 1: the speed the clip was made at
0 Pauses
Negative Plays backwards. once then runs from the end to the start
A link without a usable value: no data yet, not a number, or an invalid value 0: an unknown speed does not play
A fixed value that is not a number 0

The clock is the real time between frames. On a slow device the animation keeps its speed; after the browser tab was in the background, it continues at most 1 s further instead of jumping ahead.

Example: a conveyor belt at its real speed

A belt clip that repeats at the measured belt velocity makes the conveyor in the dashboard run like the real one: standing still at 0 m/s, faster at higher speeds, backwards when the velocity is negative.

"animations": [
  {
    "object": "Conveyor",
    "loop": "repeat",
    "speed": { "link": "root/Conveyor/beltVelocityActual", "gain": 2.372 }
  }
]

gain turns the velocity into a playback speed. It is 1 ÷ (the belt speed of the clip at speed 1). In this example the belt slats move at 0.4215 m/s when the clip plays at speed 1, so gain is 1 ÷ 0.4215 = 2.372 for a velocity in m/s, or 0.002372 for mm/s. Measure the belt speed of your clip in Blender: the distance a slat moves in one cycle, divided by the length of the cycle in seconds.

Follow a position

With position, a parameter sets where in the clip the model is, instead of time: a lift whose platform follows the measured lift height, or a door that follows its drive position.

"animations": [
  { "object": "Lift", "position": { "link": "root/Lift/positionFraction", "unit": "fraction" } }
]
unit The value means
fraction 0 is the start of the clip and 1 the end. The default
seconds The time in the clip

Use gain and offset to turn a measured value into a fraction: a lift that travels 0.4 m needs gain 2.5 for a height in metres. Outside the clip, loop decides: once stops at the start or end, repeat wraps around (fraction 1.3 shows 0.3), and pingpong goes back and forth (fraction 1.3 shows 0.7).

play, trigger, speed and playCount do not apply to a position, and the widget warns when they are set.

Several motions on one model

A model often has more than one clip: a machine with a door and a fan, a conveyor with a clip per belt slat.

  • Without clip, all clips play.
  • "clip": "Door" plays one clip. The others stay at their rest pose.
  • "clip": ["Door", "Hatch"] plays the listed clips. A name that is not found is reported, and the other clips still play.
  • Several entries for one model each play their own clips with their own settings, as long as they move different parts:
"animations": [
  { "object": "Machine", "clip": "Fan", "loop": "repeat", "speed": { "link": "root/Machine/fanSpeed" } },
  { "object": "Machine", "clip": "Door", "play": "whileHigh", "trigger": { "link": "root/Machine/doorOpen" } }
]

Two entries cannot move the same part: the second one is ignored, and the warning names the parts they share. Two clips that move the same part at the same time would be averaged, and the motion would look wrong. Make motions such as open and close one clip, and play it with pingpong or whileHigh, or follow a position.

An animation is applied after the object links. If a link and a clip move the same part, the clip wins, and the widget warns about it.

Many copies

count makes one entry stand for numbered entries, as for numbered objects. %d in object and in the link paths becomes the number, starting at start (default 1):

{
  "object": "Gripper_%d", "count": 6,
  "clip": "Open", "loop": "pingpong", "play": "onTrigger",
  "trigger": { "link": "root/UserParameters/IO/gripperOpen%d" }
}

Make clips that play well

  • Make a repeating clip seamless. Its first and last frame must look the same. For a belt with slats in two alternating colours, move the slats two slat spacings per cycle, so the colours line up again.
  • Start the clip at frame 0. Blender starts at frame 1, so a clip exported from frame 1 holds its first pose for one frame (1/24 s at 24 fps) at every repeat: a small hitch. Set the scene’s start frame to 0 before exporting.
  • One clip per motion, one motion per part. Clips that each move their own parts can be combined freely, see Several motions on one model.

Performance

The widget draws the scene every frame only while a time-based animation is running, at most at renderSettings.fps. A paused, finished or position-driven animation costs nothing between parameter updates. Models without an animation cost nothing.