Author Topic: Animate module BUG: linear tween not so linear  (Read 7081 times)

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Animate module BUG: linear tween not so linear
« on: February 28, 2017, 01:33:57 PM »
There is a bug in the linear tween of the Animate module. When you run the following code you will see that it's "easing in" it's like it's speeding up for some reason. I recorded it on the 400fps camera and its clearly showing nonlinearity of that mode. the first 3 or 4 frames have very small delta.

https://youtu.be/e7b_uRQQTpU



Code: [Select]
fe.load_module( "animate" );

local rect = fe.add_image("white_square_32x1080.png")

local move_rect = {
    when = Transition.ToNewSelection, property = "x", start = 0, end = 1920 - 32, time = 75, tween = "linear"
}
local anim_rect = PropertyAnimation( rect, move_rect )
animation.add( anim_rect )

I'v spent 2 days trying to figure out why my scrolling is so jerky, I now I know...

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #1 on: February 28, 2017, 03:13:08 PM »
After further investigation I found that it's not only linear, the whole animation module timing is wrong. But' it's more apparent when using linear tween.
So, I added time logging in the animate.nut to see what is going on there

Code: [Select]
"linear": function (t, b, c, d) { ::print(t+"\n"); return c * t / d + b; }
I played the animations with the following durations:
10 frames * 16.6666ms = 166.66ms
30 frames * 16.6666ms = 500 ms
100 frames * 16.666ms = 1666ms



As you can see the "t" value is out of whack for the first 6 frames then there is a stutter at around frame 10-12
the results is not only stutter, but the animation itself takes longer than specified.

I appreciate some constructive comment regarding this, as this is a very serious flaw when you are trying so hard to make the interface smooth. Now I know why I struggled so much.

liquid8d

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 442
    • View Profile
Re: Animate module BUG: linear tween not so linear
« Reply #2 on: February 28, 2017, 03:54:10 PM »
I'll have to look a little more closely at what you are getting here... it is possibly a bug and the truth is things aren't always as exact as you would like because the animations operate on the tick and transition times, which don't always occur fast enough for a completely smooth animation, particularly on very short animations.

However, they should still be linear values. This might relate to a 'transform_translate' function which helps determine object position to help with centered rotation and scale and that may be the culprit.

Can you try animating a non x/y/width/height/scale/rotation value, and tell me if you get the same non-linear results? Something like alpha or anything else should be fine.

I'll take a further look at the current version and see why you might be getting this. FYI, I have been working on a completely revamped animate module, but it's taking longer than expected to get completed. This would hopefully be resolved in the new version.

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #3 on: February 28, 2017, 04:10:54 PM »
will do

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #4 on: February 28, 2017, 04:32:14 PM »
It's the same unfortunately even for alpha

Code: [Select]
local move_rect_a = {
    when = Transition.ToNewSelection, property = "alpha", start = 0, end = 255, time = frameTime * frames, tween = "linear"
}


Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #5 on: February 28, 2017, 04:45:21 PM »
Don't get me wrong, I would love to use your module, but I think I'll stick everything into tick callback, as it's the only way to do what I want to achieve. I come from c++ and I'm new to Squirrel, so that will be a good excercise. The conveyour module is a total crap, as it's freezing all other animations while it's running.

liquid8d

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 442
    • View Profile
Re: Animate module BUG: linear tween not so linear
« Reply #6 on: February 28, 2017, 07:40:59 PM »
OK, I need to be clear what you are graphing here... you are showing "frame number" and "time in ms". I assume frame number is each time update is called? Let's clarify that each time update is called is not a frame, per say, but one update during a 'tick' - so the graph here would only be showing that the updates are not consistent based on time, not that values are not distributed evenly. For example, the updates might look like this:

Code: [Select]
1: 10ms : 255
2: 20ms : 250
3: 30ms : 245
4: 100ms : 200
5: 110ms : 195
...

So, this means that you would see 3 updates within 30ms, but not see the next one until 100ms - but the value might still be where it should be at 100ms into the animation to be a linear interpolation - it's just that it is time based, not frame based. Im not saying there isn't a bug, but what you are showing me here in the graphs doesn't seem to show that the values aren't at the proper locations at the proper time. An issue with using ticks for animation is that ticks are guaranteed, like frames - but done 'as much as possible' based on performance of the machine.

That said, your animation in the video does seem awfully jumpy - is the only thing you are running that specific animation shown in this thread? Have you tried this on more than one machine?

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #7 on: February 28, 2017, 07:50:56 PM »
My machine is fine, i ve got 2 pcs and 3 gpus, same on all of them.  The graph is showing correct data, it corelates with the high speed recording. Tick is called in the beginning of each frame and once per 2 frames when you do not update any objects in it. I can animate smoothly a lot of objects from the tick callback and all of them are buttery smooth, no frame drops or speed inconsistencies.

liquid8d

  • Global Moderator
  • Sr. Member
  • *****
  • Posts: 442
    • View Profile
Re: Animate module BUG: linear tween not so linear
« Reply #8 on: February 28, 2017, 08:15:43 PM »
I'm not saying your machine is bad or that there isn't a bug - but your graph doesn't show that a linear tween doesn't have correct linear values based on time.. it only shows that update calls are not linear throughout the time of the animation. You have frequent updates early (6 in <10ms), but only 11 updates in the final 160ms. That could make it look choppy but still have correct linear values.

If your animation is specifying 75ms, perhaps that is the issue with my code with very short durations.. but if you have animation code for tick that can ensure that a graph of updates/time can be consistent, I would love to see it!

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #9 on: March 03, 2017, 07:50:18 AM »
Here is a rough example of my idea of a smooth conveyor, no fancy classes or anything. It's unoptimised as haven't implemented rawset_index_offset() yet. As you can see I'm animating surface y offset instead of tiles position.

You have to set 2 variables in attract.cfg as follows
Code: [Select]
accelerate_selection no
selection_speed_ms   51
selection_speed_ms  is 51 for 60Hz refresh rate. That is 16.6666 * 3 frames + 1 to avoid sporadical stuttering


https://s4.postimg.org/rfgzrz8m5/frame.png

Code: [Select]
local flw = fe.layout.width;
local flh = fe.layout.height;

local tilesTable = []
local tilesCount = 5
local tilesOffscreen = 3
local tilesTotal = tilesCount + tilesOffscreen * 2
local tileWidth = 300
local tilePadding = 8
local tileKeepAspect = false
local tileHeight = flh / tilesCount
local surfaceWidth = tileWidth + 4  // frame.png is 304x220
local surfaceHeight = tilesTotal * tileHeight
local surfacePosY = 0;
local surfacePosYOffset = tilesOffscreen * tileHeight
local surfacePosSmoothing = 0.9;

local surface = fe.add_surface(surfaceWidth,surfaceHeight)

local index = -floor( tilesTotal / 2 )
for( local i = 0; i < tilesTotal; i++) {
    local obj = surface.add_artwork("snap")
    obj.set_pos( 2, tileHeight * i + (tilePadding / 2), tileWidth, tileHeight - tilePadding )
    obj.preserve_aspect_ratio = tileKeepAspect
    obj.index_offset = index
    obj.video_flags = Vid.ImagesOnly;
    tilesTable.push( obj )
    index++
}
local frame = surface.add_image("frame.png", 0, tilesTotal / 2 * tileHeight - 10, 304, tileHeight + 20)

fe.add_transition_callback(this, "on_transition")

function on_transition(ttype, var, ttime) {
  if ( ttype == Transition.FromOldSelection ){
      local index = -floor( tilesTotal / 2 )
      for ( local i = 0; i < tilesTable.len(); i++ ) {
          tilesTable[i].index_offset  = index
          index++
      }
      surfacePosY -= var * tileHeight;
  }
}

fe.add_ticks_callback( "tick" )

function tick( tick_time )
{
   surfacePosY = surfacePosY * surfacePosSmoothing
   if ( surfacePosY > surfacePosYOffset) surfacePosY = surfacePosYOffset
   if ( surfacePosY < -surfacePosYOffset) surfacePosY = -surfacePosYOffset
   surface.set_pos(200, surfacePosY - surfacePosYOffset)
}

edit1: fixed padding offset
edit2: combined both FromOldSelection if() statements
« Last Edit: March 03, 2017, 08:19:23 AM by Oomek »

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #10 on: March 03, 2017, 08:09:09 AM »
I've checked, it does work nicely with "accelerate_selection yes"

bjose2345

  • Sr. Member
  • ****
  • Posts: 107
    • View Profile
Re: Animate module BUG: linear tween not so linear
« Reply #11 on: March 03, 2017, 10:27:45 AM »
This looks great i will try it and see how is going, Thanks!!  ;D

Oomek

  • Administrator
  • Sr. Member
  • *****
  • Posts: 311
  • Radek Dutkiewicz
    • View Profile
    • github.com/oomek
Re: Animate module BUG: linear tween not so linear
« Reply #12 on: March 03, 2017, 01:27:42 PM »
Here is another version of my smooth conveyour:
- optimized for speed
- videos are now supported

Read my previous post for details

Code: [Select]
const tilesCount = 5 //keep it odd number
const tilesOffscreen = 3
const tileWidth = 300
const tilePadding = 8
const tileKeepAspect = false
const surfacePosSmoothing = 0.85
local videoFlags = Vid.ImagesOnly // Vid.NoAudio for videos



local flw = fe.layout.width;
local flh = fe.layout.height;
local tilesTable = []
local tilesTableOffset = 0
local tilesTotal = tilesCount + tilesOffscreen * 2
local tileHeight = flh / tilesCount
local surfaceWidth = tileWidth + 4  // frame.png is 304x220
local surfaceHeight = tilesTotal * tileHeight
local surfacePosY = 0
local surfacePosYOffset = tilesOffscreen * tileHeight

local surface = fe.add_surface( surfaceWidth, surfaceHeight )

local index = -floor( tilesTotal / 2 )
for( local i = 0; i < tilesTotal; i++ ) {
    local obj = surface.add_artwork( "snap" )
    obj.set_pos( 2, tileHeight * i + ( tilePadding / 2 ), tileWidth, tileHeight - tilePadding )
    obj.preserve_aspect_ratio = tileKeepAspect
    obj.index_offset = index
    obj.video_flags = videoFlags
    tilesTable.push( obj )
    index++
}

local frame = surface.add_image( "frame.png", 0, tilesTotal / 2 * tileHeight - 10, 304, tileHeight + 20 )

fe.add_transition_callback( this, "on_transition" )

function on_transition( ttype, var, ttime ) {
  if ( ttype == Transition.ToNewSelection ) {
      local index = -floor( tilesTotal / 2 )
      tilesTableOffset += var
      for ( local i = 0; i < tilesTable.len(); i++ ) {
          local indexTemp = wrap( i + tilesTableOffset, tilesTable.len() )
          tilesTable[ indexTemp ].rawset_index_offset( index );
          tilesTable[ indexTemp ].y = i * tileHeight + tilePadding / 2
          index++
      }
      surfacePosY += var * tileHeight
  }
}

fe.add_ticks_callback( "tick" )

function tick( tick_time ) {
   surfacePosY = surfacePosY * surfacePosSmoothing
   if ( surfacePosY > surfacePosYOffset) surfacePosY = surfacePosYOffset
   if ( surfacePosY < -surfacePosYOffset) surfacePosY = -surfacePosYOffset
   surface.set_pos( 200, surfacePosY - surfacePosYOffset )
}

// wrap around value witin range 0 - N
function wrap( i, N ) {
  while ( i < 0 ) { i += N }
  while ( i >= N ) { i -= N }
  return i
}

atrfate

  • Full Member
  • ***
  • Posts: 86
    • View Profile
Re: Animate module BUG: linear tween not so linear
« Reply #13 on: March 04, 2017, 08:14:58 AM »
Makes alot of since I notice when the framerate drops on my theme, the animations become sluggish