Twitchy animations

  • Pete

    Pete - 2016-04-08


    This is something that has been bothering me for a very longs time and now I ran into it in a different context.

    The AoI animations where the camera is moving on a smoothed (approximated) track are twitchy. At about every half a second there is a small jump in the movement and depending on how the camera is positioned at any time the jump may appear larger or smaller, but it is still always there. Especially visible this phenomenon is in the first seconds of this pendulum animation.

    However it seems that we are not alone with the problem. If you have a look the animations of Spiral One (links just below the portfolio puzzle) you'll find the exact same thing happening there. I don't know, what software they are using, but I came to think, that there must be the same or at least very similar algorithm moving the camera.

    Just a few weeks ago I was looking a the code. I found that the smoothing is done by the TimeCourse and it just splits the track into smaller and smaller pieces until it is "smooth enough" ... So the problem probably can not be the smoothing itself. There must be somethig else that brings that -- rather disturbing -- twitchiness into the movement.

    Does anyone have an idea where it comes from or how it could be fixed?

  • Luke S

    Luke S - 2016-04-09

    Thanks for bringing this back up, Pete. Seems like this has been happening for quite some time.

    I'm currently running a render on 3.0.2 with the example file you posted for the pendulums a couple of years ago, just to make sure that I can duplicate.

    I've looked at the examples for Spiral One, and though I do see the twitches, I think they are different from the ones in AOI. Can't quite put my finger on why.

    The next step would be to set up a second camera, and some sort of marker object that follows the path and rotation of the camera that is in your renders. I'd like to see if there is anything visible in the track that is being followed, or if we must look elsewhere.

  • Pete

    Pete - 2016-04-09

    Seems like this has been happening for quite some time.

    Always. Looking back at any AoI animation it's always there when you know what to look for.

    some sort of marker object that follows the path and rotation of the camera that is in your renders

    On possibility might be to write a script, that creates a new track and makes there a keyframe at every frame. Even so that the framerate would be higher like 60 or 100 fps. Then you probably could see it in the graphs. Somehow I have never gotten to do that myself :(


    I'm currently running a render on 3.0.2 with the example file

    Hope you noticed that it begins at -12 sec.

    Last edit: Pete 2016-04-09
  • Pete

    Pete - 2016-04-09

    So I wrote a script that keyframes the time from -12.0 to 0.0 at 120 fps.


    • The jump on a position track has an element in all directions, not just x,y or z.
    • The time between the twitches is not contanstant. During that time it changes from ~0.7 sec to < 0.2 sec.
    • When the movement of the camera changes from acceleration to deceleration the direction of the jump changes.
    • When the camera is moving at steady speed the jump seems to be disappearing.
    • At 120 fps it also becomes obvious, that the duration of the jump is always 1/30 seconds.
    • EDIT: I checked the Rotation tracks too. No jumps discovered there, but the smoothing could do a couple more iterations.

    At that sequece of time the original keyframing is also getting more dense towards the end. That could explain the reducing time between the jumps. And the changing direction of the jump then ... Could it be that there is an indexing error somewhere, that the smoothing is occasionally looking at a wrong keyframe or a wrong moment in time? This theory could be supported by the thing, that sometimes, when you make changes several keyframes in the future, something changes at present.

    Last edit: Pete 2016-04-09
  • Luke S

    Luke S - 2016-04-09

    Cool. That worked out a lot better than my idea would have. Interesting about the length of the offset--- no idea why that is. I'm going to have to play with your script, see if I can compare the location of the offsets to the original keyframes.

    In looking at this issue, I have to say that I love the scene overall. The lighting, etc. came together well, and the pendulums are absolutely mesmerizing.

    As bizare as it may seem, I really think that we do have some sort of bug in how position tracks are smoothed. Now just need to track it down.

  • Luke S

    Luke S - 2016-04-10

    Hmmm.... Something definitely going on here. I pulled up the original track to see what differences, if any, there were.

    In the attachment, the lines are the (rough-subdivided) graph of the original track, while the keyframe points are all from the fully subdivided version. (What actually plays)

    The rough curve is actually a set of line segments. The center of each segment is tangential to the smooth curve. As you approach the end of the segment, it of course gets farther away from the ideal curve.

    For some reason, some of the subdivided keyframes are placed on the segments for the rough lines, rather than on the curve. They seem to be balanced around the inflection point where the line segments meet. When the Camera is not changing direction, the line segments are parallel to the smoothed curve over their entire length, and therefore the displacement, if present, is a displacement of '0.0'

    I concur that the displacement is, as far as has been measured, 1/30 second in duration. When viewing a 120 frames/second track, four keyframes are displaced. When viewing a 90 frames/sec, only three frames are displaced.

  • Pete

    Pete - 2016-04-10

    EDIT over EDIT over EDIT... :D

    I thought I found something, but it seems I did not...

    File: src/artofillusion/animation/
    Method: evaluate starting at line 372
    Line 432: if (delta < 1.0/30.0 || !subdivideAdaptively)

    Removing the 'delta < ...' causes an infinity loop and anyway the timecourse should be subdivided minSubdivisions times before applying that if-condition...

    Somehow it seems that the issue is related to that, but I don't know how. For a moment I thought I had a fix, but it did not work. -- What helps is to fix the minSubdivisions to something ridiculously high like 12. EDIT: So that'd be that many local subdivisions.

    Last edit: Pete 2016-04-11
  • Pete

    Pete - 2016-04-11

    I think I understand what is happening. I hope I can explain this in a somewhat understandable manner.

    PositionTrack.apply() is calling Timecourse.evaluate().

    Timecourse.subdivideAdaptively is by default set true. --> The amount of subdivisions can change.

    The settings are, that at first interpolating tracks get subdivided once and approximating tracks 3 times and then evaluate checks if the given time is within 1/30 seconds from the timepoint to the left side of it. If it is, then it calculates the output values with linear interpolation between the two keyframes on both sides of the given time.

    The next frame will of course be farther that 1/30 sec away from the keyframe that was produced by the three first subdivisions, so the track gets subdivided at least two more times and the next frame is then calculated based on a much smoother curve than the previous one.

    And so on. Basically the farher away the time gets from the keyframes of the first subdivisions, the smoother the curve gets.

    The error in thinking there is to compare the time to one keyframe. Instead, what should be checked is the distance (in time) between the keyframes on both sides of the time. When the two keyframes, that are obtained by subdivisions, are less than 1/30 sec apart from each other, that should trigger the calculation of the returned value. Not the given time being close to one keyframe.

    On top of that, I think it would not hurt to require a bit higher accuracy too like 1/60 or 1/FrameRate/2.

    Last edit: Pete 2016-04-11
  • Pete

    Pete - 2016-04-11

    After some testing, here is the Timecourse file with corrections. The changes are on lines 29, 423, 437, 438 and 442. It may seem a bit excessive to require 9+ subdivision for approximating tracks, but actually this does not slow the rendering down at all. Just the opposite: Starting with a lower amount of subdivisions leads to checking the accuracy more often and that slows it down.

    I'm not sure if I understand why the minimum amount of subdivisions has originally been lower for interpolating that than approximating, but I chose to go with a similar approach. Though it'd probably work just as nicely with the minSubdivisions set to 9 at all times.

    Last edit: Pete 2016-04-11
  • Peter Eastman

    Peter Eastman - 2016-04-12

    Fantastic work! I'll test out your changes and then get them commited.


  • Luke S

    Luke S - 2016-04-12

    Quick check with the Study Track script seems that this stops the jumps, at least. Running a test render now, just to be sure. (Plus, I want to see that video running smoothly!)

    I remember thinking something felt odd about checking the 1/30 second, but had not graphed it out yet. (I'm a visual person. Don't do well reading lists of numbers.)

  • Pete

    Pete - 2016-04-12

    (I'm a visual person. Don't do well reading lists of numbers.)

    Likewise. It was your twitchPoint pictue that gave the the crucial hint... And then it took a few days. :)

  • Pete

    Pete - 2016-04-12

    One more thing:

    With the discontinuous mode there have always been a couple of issues, I did not quite understand:

    • The keyframes on a discontinuous track never took effect at the frame they were on but instead on the next one. Though the graphs show, that the effect should happen immediately.
    • The last keyframe never had any effect at all.
    • This could be worked around by moving each keyfrme a bit earlier (like 0.001 sec).

    The reason was on the line 387 (in this attachment). I changed a '>' into a '>=' and that took care of both of the issues above. This of course changes the behaviour of files that already exist a tiny bit, but I think this makes the behaviour more logical (= to what you'd naturally expect and to match, what the graphs show) -- and who is rendering old files anyway? ;)

    The line numbers I mentioned earlier changed a bit as I removed some 'experimental' lines, that I had only commented out the last time. They are marked with comments though.

    Last edit: Pete 2016-04-12
  • Peter Eastman

    Peter Eastman - 2016-04-14

    I commited your latest version. Thanks!


  • Pete

    Pete - 2016-04-15

    I commited your latest version. Thanks!

    Thank you!

    Fantastic work!

    I guess, I usually accept compliments silently, but thank you. :)

    To anyone who wishes to have the fix available right away, here's an ArtOfillusion.jar with those changes. I hope it's compatible with the rest. It was compiled with a relatively new Java. (Cant remember which and I'm not at that machine right now.)

    Enjoy :)


Log in to post a comment.

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:

No, thanks