How to handle skipped animation frames (skeletal animation)

Started by
4 comments, last by Gl2eenDl2agon 8 years, 6 months ago

I made my own model importer and animation code.

It works really well actually which is unusual for my first attempt at something.

However, I encountered one problem: what do I do when the animation plays faster than the framerate of the renderer?

In examples I've found they just kind of skip over those keyframes... basically the keyframe displayed is always an interop between the closest frame before the current time and the frame right after.

This leads to some weird looking playback as this tends to end up landing on the "weaker" parts of the animation and skips over the "largest" frames (the ones that move the mesh the most) when playback happens at a faster rate.

I did try to handle the problem though. What I did was instead of a simple interop, I iterate through all of the keyframes from last frame until the current time and find the keyframe that has the largest movements and use that one. It seems to make the animations look better as the joints/bones do get moved to the extremes of the animation instead of just undulating through all of the "halfway" points.

What do you think? How do you hadle this? What about when the animation is being played at like 10x speed?

Advertisement

If you have a lag of FPS you enter the problem you said, this is why the method of always interpolate with the last previous keyframe is not always safe.

You have to find the two keyframes using your current time and interpolate with those, it's the safe way.

If you have a lag of FPS you enter the problem you said, this is why the method of always interpolate with the last previous keyframe is not always safe.

You have to find the two keyframes using your current time and interpolate with those, it's the safe way.

...but if the model has a ton of keyframes the closest two keyframes are most likely going to be nearly identical and the keyframe that displays the most movement could have been skipped over.

Lets say for example you are playing a jumping animation. There are 10 frames. Frame #5 is the highest frame.

But because of a render-framerate to animation-framerate mismatch you only playback frames 1.25, 3, 8.5, and 10. To the end user it will appear that the model only moved like 2 inches off the ground and not the entire 12 inches that it should have moved in frame 5.

This is why I decided to go with the other approach. In that example, When I land on frame 8.5 after doing the "current time - start time" to frame time conversion I then see that I skipped everything after last frame (3) so I iterate through them all and find that frame 5 moved the most so I display frame 5 and not frame 8 iterop 9.

Because of the lagging render framerate the user doesn't notice that frame 5 is out of step and it doesn't look jerky. Whether the animation is played back at 0.5x speed or 10x speed the model still jumps 12 inches.

You store the delta in each keyframe ? Or maybe you are speaking about Root Motion ?

If you have a jump animation, interpolate from each keyframe play correctly the animation.

Maybe I didn't understand correctly the problem.

The typical approach is to just sample the animation at the time position to which it has advanced to, according to the time step between previous frame and current. If this leads to skipped keyframes, then so be it. Your idea to preserve the "dominant" movement of an animation even in low FPS conditions is noble, but I don't know any engines that actually go to such trouble. At low FPS the gameplay feel will be poor anyway, so usually the engineering effort goes to ensuring that the FPS preferably never goes unplayably low.

Of course, if you know that you will never render faster than e.g. 30 FPS, it will be a waste of memory to store animations with higher keyframe frequency than that, in which case you could just re-export the animations with a suitable frequency.

You store the delta in each keyframe ? Or maybe you are speaking about Root Motion ?

If you have a jump animation, interpolate from each keyframe play correctly the animation.

Maybe I didn't understand correctly the problem.

The files I import from typically store the keyframes inside of the joints where not every joint is present in every keyframe and its assumed you interop for the missing keyframes (each keyframe stores absolute translation and rotation and not deltas).

I convert that into my format that requires that every keyframe has every joint that moves (missing joints are assumed to be at original position) to make it easier to copy and paste frames or to play in reverse.

Anyways, as long as the rendering framerate is less than the animation framerate everything works normally. If you turn up the speed on the animation, then things start to look bad as keyframes are skipped over when using the traditional interop between frame before current time and frame after (or use the frame that is equal to current time). This is because there are alot of intermediate keyframes that were created by the artist and the keyframe that stores the largest motion that most accuratly represents the essence of that animation tends to be skipped over.

The typical approach is to just sample the animation at the time position to which it has advanced to, according to the time step between previous frame and current. If this leads to skipped keyframes, then so be it. Your idea to preserve the "dominant" movement of an animation even in low FPS conditions is noble, but I don't know any engines that actually go to such trouble. At low FPS the gameplay feel will be poor anyway, so usually the engineering effort goes to ensuring that the FPS preferably never goes unplayably low.

Of course, if you know that you will never render faster than e.g. 30 FPS, it will be a waste of memory to store animations with higher keyframe frequency than that, in which case you could just re-export the animations with a suitable frequency.

True, but if you need to playback the animation at increased speed then just increasing the rendering framerate won't be viable. (like adjusting the speed of the running animation to reflect a run speed increase spell etc)

There may also be times when the model is far away from the camera and I want to turn down the refresh rate for animations on those model instances (basically skipping frames) without the animations looking too bad.

Your idea to preserve the "dominant" movement of an animation even in low FPS conditions is noble, but I don't know any engines that actually go to such trouble.

Apparently mine does tongue.png I just though it might work and tried it. So far it looks OK. Its mostly for when I turn up the animation playback speed and not for low FPS, but it also works in those situations.


Of course, if you know that you will never render faster than e.g. 30 FPS, it will be a waste of memory to store animations with higher keyframe frequency than that, in which case you could just re-export the animations with a suitable frequency.

I mostly buy 3D assets since I'm not much of an artist myself. The 3DRT dragon had an insane amount of keyframes (like 70MB of them) so I modified my importer to use a process similar to what I'm doing above to "condense" keyframes to like only 30fps. That particular model would sometimes crash blender when I imported the Ms3d variant.

This topic is closed to new replies.

Advertisement