Setting a new reference frame - Guillermo Algora

Guillermo Algora
Go to content
A look at how to set a new reference frame: the principle behind it, which is useful as it can have multiple applications, and some methods to achieve it in our scripts using nodes and/or Expressions.

Lastly, we will review the peculiarities of how to set a new reference frame for the Transform and CornerPin nodes (there is a tool -link- that I built to achieve precisely that).
 
I. A new reference frame:

Establishing a new reference frame is based on the following principle:
Keep the original information while subtracting from it the value at the new reference frame
, thus making the new reference frame become the point of non-transformation and the others offset over the whole frame range. This principle is formulated as: value at frame + inverse of value at new reference frame

To illustrate, we have the following frame/values:
FrameValue
00 (reference frame)0
011
022
At this point, our reference frame is 00. To make frame 01 the new reference frame, let us apply the above formula:
FrameValue
000 - 1 = -1
01 (new reference frame)1 - 1 = 0
022 - 1 = 1
As we can see in the results, we have changed the reference frame while preserving the motion of the animation curve intact.

This process can be applied in two ways in our scripts :
  1. By the use of a second node right after the first one (a two-step process).
  2. By the use of an Expression on the original node or by forming a new independent node (one-step processes).

In practical terms, we should do this in one step most of the time. The reason is that in a 'two-step' process any node that does not concatenate can make an irreversible modification to the input before the compensation on the second node takes effect, and therefore the effect of a new reference frame will likely fail. However, some nodes are suitable for a second step because they either concatenate (e.g. Transforms) or because they are reversible by their nature (e.g. Add).
 
1. Two-step processes (or using a second node):

While keeping the original node (hence the original information), we create a duplicate of it but only keep the inverse of the values at the new reference frame. We will stack the two: the first node (with the original information) followed by the second node (which makes the new reference frame). To create the conditions for the effect in the second node, we can do it either manually or with an Expression.

1.1 Manually (for Transform and CornerPin nodes):
By performing while at the new reference frame: knob (right-click) → no animation. And then the subtraction by activating the 'invert' knob.

1.2 With an Expression:
We could also do the above operation with an Expression. It may be necessary because not all the nodes have an invert option, and because of some of the advantages of Expressions: non destructive (keeps the original animation in the knob), allows continuous modifications, and is reversible. But on the other hand, it can make things harder to read/understand for other users.

The Expression curve retrieves the animation curve of the knob. The Expression to retrieve a value at a specific frame is curve(frame), which we will use to retrieve the value at the new reference frame.

curve(new reference frame) *Substitute 'new reference frame' with the frame number
e.g. curve(10)

The next thing to do in the process is to invert the values. When doing that manually, unlike with the 'invert' knob that handles everything internally, we must pay attention to the characteristics of the knob to do it accordingly. From this, we can mathematically differentiate two categories of knobs: those whose default value is 0 and those whose default value is any other than 0.

For the first kind, the inversion is as simple as multiplying the value by -1.
For the second kind though, the formula is: point of reference * (point of reference / new reference frame)

Point of reference refers to the value in which we consider the transformation to be non-existent. In most cases, it will be the knob's default value, but there could be other scenarios, for example, if we want to measure changes from the maximum value, then that would become our point of reference.

To illustrate the two categories, if we take a Transform node as an example, the 'translate' knob default value is 0 so it belongs to the first category:
KnobValueFormulaInverse Value
Translate X0.5-1 * 0.5-0.5
However, the 'scale' knob default value is 1 so it falls into the second category:
KnobValueFormulaInverse Value
Scale X1.11 * (1/1.1)0.90909091
Conforming everything together, our final Expressions are:
  1. curve(new reference frame) * -1 for knobs in the first category.
  2. point of reference * (point of reference / curve(new ref. frame)) for knobs in the second category.

2. One-step process:

2.1 Using an Expression on the original node:
To set a new reference frame within the original node, we will make use of the formulas we have seen already, but we will also have to keep the initial information. To do so, we will incorporate into the previous the following Expression: curve(frame), to retrieve the value at each frame from the original animation curve.

The final formulas for both categories would be:
  1. curve(frame) + (curve(new reference frame) * -1)
  2. curve(frame) * (point of reference * (point of reference / curve(new ref. frame)))

2.2 Forming an independent node:
If we don't want to not operate on the original node, we can create a new node and parent it to the original. The way we parent inside an Expression is nodename.knobname, and to retrieve the value at a frame we add (frame). e.g. Grade1.blackpoint(10)

Now, it is just a matter of substituting the information we have already seen but with the parenting in it:

  1. nodename.knobname + (nodename.knobname(frame) * -1)
  2. nodename.knobname * (point of reference * (point of reference / nodename.knobname(frame))
     e.g. Grade1.whitepoint * (1 * (1 / Grade1.whitepoint(10)))

II. A new reference frame for Transform and CornerPin nodes:

1. Transform nodes:

Unlike with other nodes, when setting a new reference frame for Transform nodes we have to take into account the center point, which for any regular match-move is static and for stabilization in motion. For a different context than the one just stated, to 'generate' the correct values will be necessary to work with matrices and vectors. It is something my tool covers (link) but is not realistic to cover in this guide.

So, if the function of the Transform node is to stabilize, no further action from us is required. However, if the function of the node is to match-move the center point at the new reference frame requires compensation by the translation values. The formula is: center point + inverse of translation at the previous reference frame

We will retrieve the values from the translate knob using the Expression:
[expression this.translate.index(frame)]  the index will be either 'x' or 'y'.
e.g. [expression this.translate.x(10)]

The last thing we need to do is invert the translate values. Since the default value of translate is 0, it belongs to the first category (as we have seen). The final formula is:
curve(new reference frame) + ([expression this.translate.index(previous ref. frame)] * -1)
e.g. curve(1) + ([expression this.translate.x(10)] * -1)

2. CornerPin nodes:

CornerPin nodes are a lot easier. The transformation is denoted by the difference between the points 'from' and 'to'. Therefore, to make a new reference frame we just need to keep the original information in 'to' while making 'from' (it is static) the same as 'to' at the new reference frame.
Back to content