New interpolation method (Clamped)

I think a new interpolation method would be desireable.

Looking at the default TCB method:

Here the curve goes smooth between waypoints, but have a closer look at #1 to #2 and also #6 to #7. Here the curves make a dip to get a smooth curve through #2 and #6. This makes very rubbery motion as default.

Changing all interpolation to ease in/out gives this:

The curve stays flat in between #1 and #2 and takes off nicely towards #3. Equally at end, it comes in nicely from #5 to #6 and stays flat to #7. But #3 and #4 gets screwed up by having ease in/out through them.

In this last image I’ve mixed TCB and ease interpolation to get the curve I want:

Of course this is how you can do it, individually go in and fix the interpolation to shave off the rubbery motion, but it is a lot of work when having many layers. I would prefer to have the curves basically right by default so I only have to go in and fix them where I feel they need to be different.

This new interpolation type would work as a kind of mix between TCB and ease where the curve does take into account how previous and next waypoints look like and makes a smooth curve through them all without getting extra bumps in between.

What do you think?

(As a side note, when #4 is TCB it looks like a tiny ease in/out in the curve, is this actually happening or is it a glitch in UI rendering the graph?)

Hi rylleman,
I think it is possible, at last conceptually. Other issue is to understand the current implementation and try to modify it.
I’ve been playing with the Bias value and it is perfectly possible to make what you want just modifying the Bias value from -1 to 1 for the extreme cases of the next or previous waipoints of have the same value than the waypoint in question.
Say you have three waypoints: a,b & c. Say b is the waypoint in study.
When b.value <= a.value then b.bias=1
When b.value >= c.value then b.bias=-1
When a.value < b.value < c. value then b.bias is interpolated between 1 and -1

If that is applied to all the waypoints, then a smooth curve without jumps is achieved. Please try it by yourself and validate that rule for the kind of curve you want (don’t forget that the waypoint applies to all the values of the type so if the type is a vector then if a coordinate looks fine, the other can look bad).

I will try to consider it in the future but can’t promise anything. :wink:

I’ve been investigating a bit more.
You’re right about the bias, tweaking that makes the curve behave as I would like it to.
However it would have to be curve specific. If bias is altered so X-curve is behaving alright the modified bias is also used for Y-curve which, if much different from X, would need different bias altering.

Looking through old Synfig animation projects of mine I realize I’ve had problems from TCB interpolation in all of them; characters moving rubbery like, shapes floating and growing, fades bouncing past it’s endpoint, colour changes also bouncing, etc.

I’m still convinced, perhaps even more so than before, that a new interpolation method is needed.
TCB makes it very hard to get the motion you are intending, it adds motion that you as the animator have not decided.

Bringing this issue up again. I’ve got nothing new really but have done some digging and found that many other animation software has had the same issue as well.

Here’s a note for Blender where they’ve created a new type of interpolation to solve the issue: … e-handles/

Here’s a paper from the New York Institute of Technology Computer Graphics Lab from february 1985! Describing the exact same issue…

And here’s a paper from a completely different field where they also use bezier curves, Chemical Engineering. Same issue though…

All in all, it is a well known problem.

I don’t know how to code the solution and I know we are very short of programmers so I’m not going to ask you to do it.
But I do think this is a very serious shortcoming of Synfig.

Those links are invaluable! Thanks for the researching!

Me thinking loudly:

I’ve been reading again the TCB definition [1] and [2] and how the curved is described. I’ve compared it to the general Hermite curve [3] and the Bezier curves too [4].

In Synfig there are two types of curves used: TCB for waypoints and Beziers for bezier lines (base of the regions and alike layers)
TCB was used initially to avoid the need to handle a tangent to define the shape of the curve on a certain point.

Aditionally to that, there is one reason to use that TCB splines instead of any other type. An animated parameter should have only one value for each frame and only one. If it is possible to define any kind of curve from one time position to other time position it maybe possible to have two values at the same time position which is not good.
TCB uses the surrounding points to calculate the tangents of the spline at the calculation point. Controlling the T, C and B parameters ensures that the achieved tangent doesn’t produce a multivalue curve for a certain intermediate time point.

The main problem we are suffering is that we are using a value of T, C and B equal to 0 which is not good for many of the situations. So my idea is (well it is yours in fact):

Create a new type (or modify the behavior for the new created ones) of waypoint that can be called “TCB smart”. The values of TCB are not always zero but have some predefined values depending on the relative situation of the surrounding time points and its amounts.

The problem is to define the rules to calculate the TCB values based on the surrounding points. :slight_smile:

Moreover, should the computer decide what’s the smart TCB combination by itself? Why don’t just offer to the user a subset of TCB combinations that “works fine”?

Imagine a simple animation like a ball bounce. No damping. The computer would see just a list of alternating values and wouldn’t have any reason to treat differntly the time points where the ball touch the ground than when the ball is in the higher position. (0,0) , (1,10), (2,0), (3,10), (4,0), (5,10), … Then the computer would produce similar TCB value for all the points because the relative position of the surrounding points are always the same: 10

What want the user want? NOT NEED TO CONTROL ANY TCB VALUE. Values are odd and strange. The user might want to have types of behavior:

-TCB Mountain (valley) point: Tangent on the time point must be horizontal regardless of the surrounding points.
-TCB Peak point: Tangent over the curve must be vertical regardless of the surrounding points.
-TCB Smooth landing/passing: Current behavior.

Aditionally I would leave some control for those new interpolations types offering a single value which would modify the intensity of the behavior (more or less smooth mountain, more or less quick peak, more or less smooth passing, etc.) So if the user wants a fine control can be obtained but with a easy value between 0 and 1.


[2] … els_spline

I’m trying to wrap my head around your argument here.

I’m not sure if I understand the need for valley and peak settings. Could you elaborate?

Is there really necessary to have two presets? horiontal/vertical? Wouldn’t just one suffice with the possibility to alter the tilt of this handle (intensity).

If waypoint A=B, bias =1
If waypoint C=B, bias = -1
Then have a falloff depending on how far apart the values are. (B is the point we are working with). Also distance in frames needs to be taken into consideration as the curve depends on this.

Am I missing something?

There are two issues mixed here.
One issue is the bounce effect due to the TCB behavior and other issue is to achieve other situations that aren’t matched with the TCB or the new TCB Smart interpolation method.
Let’s study this case:
time value
0f 0
6f 0
12f 10

With current TCB interpolation method there is a bounce effect (depression area) just before frame 6 wich is not what the user ususally want.
With future TCB Smart there will be a straight horizontal line between 0 and 6 frames and a smooth increase from 6 to 12.
Assuming that we don’t have now easy user control of the in/out speeds based on the TCB parameters (not intuitive) and that we don’t have interpolation handles to visually control the curve shape, I propose to have (apart of the TCB smart one) other types of interpolation that might help.

For the study case it can be a vertical tangent curve, which cannot be achieved by none of the current interpolation methods unless you tweak the TCB parameters.

In this case we can have
time value in out
0f 0 TCB TCB
12f 10 TCB TCB

I can imagine this curve like if you have a spring compressed from 0 to 6 frames and exactly at frame 6 you release it. The curve should quickly go vertically and would decrease the speed (tangent) along the time passes.

Sorry but I don’t have drawing facilities right now.

Did it help?

PS: I wrote the previous post and save it as a draft because I was messing my self when writting it. That’s the reason why I wrote “Thinking loudly”. :slight_smile: There is so many things to think and talk about this before settle conclusions.

Ok, now I think I understand what you mean.

So peak and valley are differnet interpolation types than smooth? So there basically is going to be 3 new interpolation methods?

I can’t help to think that all this is a workaround for the fact that we don’t have handles in the curves panel. (Except the behaviour of the TCBsmart interpolation which I think is needed)

Adding more interpolation methods is adding more abstraction to Synfig, it’s not immediately clear what they do and how to use them. Having handles in the curves panel would make the animation workflow more hands on. You can grab a handle and alter it, directly seeing the change, so you get the motion you want rather than adding another parameter.

This differers from the original discussion on interpolation method but it’s much related.

I agree with the previous post – to a large extent you can already make synfig (hooray!) do what you need, but it’s quite fiddly to do that.

I think that perhaps a GUI design approach may be better (and then, we could add more or
better interpolation types later if we still need them). Though I realise that GUI coding takes
a lot longer than a bit of maths…

I’ve been thinking about it a bit (based on my experience with version 62)

My ideas (just ideas!) are:

  1. yes, we need control points in the curves panel!

  2. don’t change the type of a point just because I changed its value (ie if I nudge a duck, I should change ONLY the parameter, not the interpolation mode)

  3. an easier way to select default waypoint types & their fine-control parameters: eg:
    3a) the user could set a global favourite default waypoint type (can you do this now?)
    3b) user override that the default type at any given frame (so, eg all waypoints at 3s 12f would be of type (say) constant in-out, unless I change them manually)
    3c) user can override the default for each kind of layer or parameter (so, eg, default for “amount” is constant, default for “origin” or BLine point waypoint is TCB, and user can modify it)
    3d) a selection of recent types available on the menu (and user might be allowed to name them?)
    3e) a way to apply a waypoint type to a whole lot of waypoints (I think we already need a way to select a lot of waypoints and slide them around, so this would be related to that)

  4. a smoothing operation (a bit like happens with the draw tool) – you set first, intermediate and final waypoints, then press “smooth action” and the software draws a nice spline through it?

I’ve been working to implement the desired behavior and I think I have a reasonable results for it.
It has taken me more time to find a math solution that works in all the possible cases than implement it. Finally I have one that works.
It follows these rules:

Given Pp, Pc and Pn values (p=previous, c= current, n=next)

  1. If Pc >= Pp and Pc >= Pn (mountain type on current) Pc <= Pp and Pc <= Pn (valley type on current) then the tangent is horizontal in current.
  2. If Pp < Pc < Pn or Pp > Pc > Pn (there is a uphill or a downhill at current) then the tangent at current is averaged to don’t allow any interpolated value between previous and current or between current and next to be below from the lower value of previous or next or be above from higher value of previous or next.

The icon for the new interpolation type is a orange diamond and it is called “Clamped”. It needs one icon on the Interpolation default widget but that’s not important by now.

The results is something like this:

It is granted since 0.63.03

I’ve built Linux binaries that include the explained feature as well as some bugs in other areas.
You can download them here:

32 bits tarball
64 bits tarball
32 bits rpm
64 bits rpm
32 bits deb
64 bits deb

It is important to me to have your feed back on this. It is possible to make little tweaks on the case 2) of the rules but the variations I’ve tested doesn’t obtain great changes and in certain limit cases it breaks the rule of not crossing the higher or lower values.


awesome feature and I like the icon too :slight_smile:

I’m really excited to test this out. I’ll try to make some time this weekend.


I’ve been doing some tests and this is particularly useful for gradients.
The attached file has a animated gradient.
At frame 0 to 48 the gradient has two waypoints with the same value. Later it has a waypoint with a different value.

The TCB gradient has a noticeable unwanted transition between 0 and 48 frame. The Clamped gradient doesn’t.
Since the gradients doesn’t have curve representation (yet) it is not easy to preview unwanted transitions before render the animation.
With the Clamped interpolation the transition is more “predictable”.
gradient_transition.sifz (746 Bytes)

Great Genete! You are very much the best!

I did a quick test and found some peculiar behaviour, here’s a few screenshots:

  1. TCB. overshoots y at fr.14 & 32. x is fairly even.

  2. Clamped. y is still overshooting at fr.14 but much better at fr.32. x however is quite lumpy at fr. 32 & 45.

with 64 bits tarball, I get bellow error

Unable to load "/home/jcome/Downloads/gradient_transition.sifz":

  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:28: error: "clamped" not a valid value for attribute "before" in <waypoint>
  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:28: error: "clamped" not a valid value for attribute "before" in <waypoint>
  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:50: error: "clamped" not a valid value for attribute "before" in <waypoint>
  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:50: error: "clamped" not a valid value for attribute "before" in <waypoint>
  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:72: error: "clamped" not a valid value for attribute "before" in <waypoint>
  * /home/jcome/Downloads/gradient_transition.sifz:<waypoint>:72: error: "clamped" not a valid value for attribute "before" in <waypoint>

Can you attach the sample file? Thanks!

I’m using the uploaded binary and I don’t have problems to open the file. Which binary are you using? Did you build by your own?

The one from

OS: Fedora16 x86_64

Ok, there are several issues:

  1. There were errors in the translations of the formulas to the code.
  2. The code can work only with the magnitude of the value (remember that the value can be real, time, angle, vector, color and gradient) The adjustment of the waypoint for a non real type (vector, color, gradient) maybe is not ideal for all the coordinates.
  3. The math formulation for real values consider the “greater than” operator. There is not such operator for the values because for example, for vectors the “greater than” operator is only valid for vector modulus. But when using real values the modulus fails for negative values: i.e. |2| < |4| is true as 2 < 4 is true too, but |-2| < |-4| is true but -2<-4 is false.

Please let me explain it a bit more to let you understand and maybe I can find a better way to perform the desired behavior.

The ValueNode_Animated class has three inherited classes: AnimBool, Constant and Hermite. AnimBool is for boolean value types and Constant are for strings and canvases. Hermite is used for the rest of types: Time, Real, Integer, Angle, Vector, Color and Gradient.
Those inherited classes are templates, this means that the code is exactly the same for all the supported types and should use common functions (subtraction, magnitude, etc.). At he moment the only common functions available are subtraction, multiply by scalar and magnitude. Although real values have more functions (“grater than” for example), others doesn’t have it (for example, vector). The magnitude of the value is the only one that can be compared.

When the code handles the curve it calculates a bezier between the two adjacent waypoints. I can control how to calculate the tangents of the bezier but to take the decision of the value for the tangent I need to know if the value in study is in a up hill, down hill, a valley or a mountain. That’s why I need to compare two values and then calculate the tangent accordingly.

The implementation I’ve made is all done inside the Hermite class so the value types must provide the functions to “compare” values and then calculate the tangent.

I think that the previous approaching is not good because, although the calculations are made all in the same portion of code (Hermite class), it is using a limited set of available common functions for each value type. I think that each value type should define a function that would return the correct tangent. That can be done internally on each type using its own resources, that maybe aren’t the same for all the value types.

So, said that I have to apologize for that wrong approaching, and even that bad implementation of it. I’m sorry for make you loose the time.
Please be patience meanwhile I look for a satisfactory solution.