lovr icon indicating copy to clipboard operation
lovr copied to clipboard

Animation timestamp out of place

Open piXelicidio opened this issue 1 year ago • 1 comments

Hi, great job with the engine. I'm using this model : https://sketchfab.com/3d-models/clown-fish-low-poly-animated-af7ba2aa41d2413098a59b21cfda79c2 It has 5 animations and tried with this code from the docs: game.model:animate(5, lovr.timer.getTime(), 1) The model starts static then after about 8 seconds start to show the animation. Similar thing happens with any animation other than 1. The workaround is to know in advance from an external tool where each animation start and ends. Then passing the time only in the kown range, whish I hope this is not intended by design.

GetAnimationDuration also reports incorrect values. What I guess that should be expected is that if I want to play animation number 3 that has a duration of 1.5 seconds, then I can pass any value as time parameter to animate function and the animation will loop from 0 to 1.5 seconds.

Or please let me know how is the correct way to use the animate function. Thanks.

Regards. Denys

piXelicidio avatar Aug 03 '22 22:08 piXelicidio

The :animate function is designed to allow any timestamp; it will wrap around based on the animation's duration.

The animation's duration is currently computed as the timestamp of the final keyframe.

Currently if the timestamp passed to :animate is less than the timestamp of the first keyframe, the pose of the first keyframe will be used. This means that if the first keyframe starts at e.g. 8 seconds, the initial pose will be held for 8 seconds. I think this is reasonable / by design, but it's totally open for debate if it doesn't match conventional expectations.

Do your animations start with nonzero-timestamped keyframes like this?

Thanks for the issue.

bjornbytes avatar Aug 03 '22 22:08 bjornbytes

I understand what you have explained and that's exactly what is happening. Still I found confusing to use and in some cases will bring issues. As the current design if I have a "walk" animation that start at 2:00 secs. and ends at 4:00secs:

  • getAnimationDuration will return: 4.0
  • I should call: model:animate("walk", t) where t goes from 2.0 to 4.0, to play correclty the full animation.

The issues:

  • I expect getAnimationDuration to return 2.0, because that's the actual duration of the walk animation. Currently this tell us where it ends but we don't know where it start.
  • I expect the time parameter in animate going from 0.0 to 2.0. This way we don't have to know where it starts, and each animation is independent of each other. If the artist change the duration or remove any animation when the asset is updated all the code is broken for playing the animations after the modified one.
  • Again all this assume you have to know the time where the animation starts, which would be hard to find in many cases if you are not the author of the assets, and even being it.

piXelicidio avatar Aug 07 '22 14:08 piXelicidio

The glTF spec says this:

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. 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.

The beta version has a way to get the animation keyframes, which may help with offsetting timestamps using the "start time". I get that it's annoying to do that adjustment, but I'd like LÖVR to remain consistent with the glTF spec for this.

bjornbytes avatar Aug 07 '22 16:08 bjornbytes