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

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:

Frame | Value |

00 (reference frame) | 0 |

01 | 1 |

02 | 2 |

*reference frame*is 00. To make

*frame*01 the

*new*

*reference frame*, let us apply the above formula:

Frame | Value |

00 | 0 - 1 = -1 |

01 (new reference frame) | 1 - 1 = 0 |

02 | 2 - 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 :

- By the use of a second node right after the first one (a two-step process).
- 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 fram**e*: 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)*P

*oint 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:Knob | Value | Formula | Inverse Value |

Translate X | 0.5 | -1 * 0.5 | -0.5 |

However, the 'scale' knob

*default value*is 1 so it falls into the second category:Knob | Value | Formula | Inverse Value |

Scale X | 1.1 | 1 * (1/1.1) | 0.90909091 |

Conforming everything together, our final Expressions are:

*curve(new reference frame) * -1*for knobs in the first category.*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:

*curve(frame) + (curve(new reference frame) * -1)**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:

*nodename.knobname + (nodename.knobname(frame) * -1)**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.*