Hi! I am debugging some animation playback issues and I noticed something interesting about playback. Even when I export my animation from frame 1 in the DCC it starts on frame 0 in the sandbox. Is this a design decision in the sandbox UI or is there something about babylon itself that treats the first frame as zero.
As a test, I tried to export the animation from my DCC from frame 0 but was met with numerous GLTF validation issues so now I am doubly curious!
{
"code": "ACCESSOR_ANIMATION_INPUT_NEGATIVE",
"message": "Animation input accessor element at index 0 is negative: -0.03333333507180214.",
"severity": 0,
"pointer": "/animations/0/samplers/4/input"
},
{
"code": "ACCESSOR_ANIMATION_INPUT_NEGATIVE",
"message": "Animation input accessor element at index 0 is negative: -0.03333333507180214.",
"severity": 0,
"pointer": "/animations/0/samplers/6/input"
},
{
"code": "ACCESSOR_ANIMATION_INPUT_NON_INCREASING",
"message": "Animation input accessor element at index 1 is less than or equal to previous: 0 <= 0.",
"severity": 0,
"pointer": "/animations/0/samplers/1/input"
},
{
"code": "ACCESSOR_ANIMATION_INPUT_NON_INCREASING",
"message": "Animation input accessor element at index 1 is less than or equal to previous: 0 <= 0.",
"severity": 0,
"pointer": "/animations/0/samplers/2/input"
},
This is part of the glTF specification. Also, glTF stores animations using time, not frames, but it always starts at zero.
The inputs of each sampler are relative to t = 0, defined as the beginning of the parent animations entry. Before and after the provided input range, output MUST be clamped to the nearest end of the input range.
Implementation Note
For example, if the earliest sampler input for an animation is t = 10, a client implementation must begin playback of that animation channel at t = 0 with output clamped to the first available output value.
Interesting! It seems like even if GLTF talks about time in seconds the Babylon Sandbox UI (specifically the animation curve inspector) still operates on a frame paradigm (the bottom ticks represent frames not seconds). I guess there was a design decision to map second zero to frame zero instead of frame one? If so, I’ll just have to mentally do the adjustment when inspecting animations in the Babylon Sandbox.
On video editors, it starts at frame zero because when you go to the next frame (frame one) and when you click, drag and select between the frame, it will equal to one frame.
Hahaha I was worried that was the answer… in art world I have affinity with Houdini, Toon Boom and Procreate… which in full-animation shots typically starts at F1… but in hyrbird-photographic-animation typically starts at F1001… can’t say I have ever seen F0 in production but I will take your word for it!
Hilariously, in tech world I have affinity with C whose arrays start at 0 and my brain always broke a little bit using Lua whose arrays start at 1.
I guess it is just one of those cases of butter side up butter side down!
I can see how some people might want the UI to say frame 1 for the first frame, but we don’t state the number or the unit in the sandbox. It’s just a slider. If it’s code or in the asset payload (e.g. glTF), then it should definitely be zero-based or the math will be really annoying.
I mean it does state the number – thrice, it states it at the bottom of the timeline in the curve editor and in the part with all the ticks in the curve editor and in on the graph of the curve editor itself.
It’s fine, if that is the design decision but I just wanted to be clear about what I was referring to:
@ncr, this is trying to recall many years back now, but if I remember correctly, we chose 0 based timelines because when importing glTF, we get the timelines in seconds, so we don’t know what the original authored frames would be. I could start my animation in Maya on frame -10, but when we get it from the glTF file, we don’t have that association anymore. We just chose to start on 0 to be consistent with arrays in the engine.