Getting Started with Expressions (Part 2/3)

August 22, 2017 Technology, Tips 0 Comments

Hello everyone,

We are back with more tips about getting started with expressions. In the second part of our mini-series we take a look at some more complex expressions to create circles. In the third, and last lesson you will learn how to create spirals.

Circles

If you look back at your school time you might remember the definition of sine and cosine functions. Both functions have been explained with the help of a so-called unit circle – this is simply a circle with a radius of 1 and its midpoint at <0,0>.

This definition opens an interesting possibility, because it can be used to draw a circular motion with just two simple expressions. Add a null object and open its “Node” panel to have access to the position values. There, enter:

Position.X =sin(t)
Position.Z =cos(t)

Please bear in mind that all examples are based on RealFlow’s YXZ setup. If your 3D software uses Z as the height axis you just have to replace Z through Y. For a Z-based setup the expressions are:

Position.X =sin(t)
Position.Y =cos(t)

These two basic expressions create a horizontal circular motion around the viewport’s origin with a radius of 1.0 m. That’s nice, but not very spectacular since there are no parameters to control things like radius, number of revolutions, or position in space. But we’ll change that, so let’s take a look at the radius first.

Radius

To get a better view of the expressions’ curves and formulas we switch to RealFlow’s “Curve Editor”: right-click on the null’s “Position” parameter and choose “Edit curves…”

In order to control a circles size we only have to multiply the two terms with the radius:

Position.X radius*sin(t)
Position.Z radius*cos(t)

With radius = 3.0, for example, the total diameter d (d = 2 * radius) of the circle is 6.0 m, with 2.25, d = 4.5 m, and so on. And if you choose different values for radius you are also able to create oval motion paths.

Number of Revolutions

In the first part of this introduction to expressions we showed you how to create oscillations, e.g. for pouring effects. The number of oscillations can be controlled by multiplying time with a factor: frequency. If we consider the number of revolutions as an oscillation we know immediately what to do:

radius*sin(t*frequency)
radius*cos(t*frequency)

Higher frequency values create more revolutions. Anyway, there is one big problem: currently we don’t know the number of revolutions within a certain frame range. What do we have to do if want exactly 3 revolutions within, let’s say 4 seconds or 150 frames?

Controlling the Number of Revolutions

We have to manipulate frequency in a way that it will match the desired number of revolutions. Expressions are always one-liners and there is no possibility of adding multiple lines of code like in Python scripts. So we have to put everything into a single, more or less complex, formula.

This circumstance makes complex expressions sometimes difficult to read and understand. It is therefore a good idea to split the expression into smaller chunks during the preparation process. A short documentation will also help to understand things even after several months. RealFlow’s “Notes” field in the “Node” panel is a huge help, because here you can save your explanations together with the scene/expression.

Calculating a Factor

Before we proceed it is necessary to switch the “Curve Editor‘s” horizontal unit from frames to seconds with the Alt + T shortcut. If you want to switch to frames again later use Alt + F.

When we take a look at our sine expression we can see that it intersects the zero line at certain times – and these times are 0 s, 3.14 s, and 6.28 s. An even closer look reveals that these values are multiples of pi (π) – pi is roughly 3.14.

A different view of a sine curve shows the relation between pi and degrees:

This means that our null object finishes a full revolution of 360° after 6.28 seconds (2*pi) and with this relation we are able to control the number of revolutions. All we need is to find an appropriate factor. Let’s say we want five full revolutions in 8 seconds. Here, the question is how long does a single revolution take:

8 s / 5 revolutions = 1.6 s per revolution

In a common notation, based on frames and fps rate, the formula is:

time per revolution = (number of frames / frames per second) / number of revolutions

We also know that a full revolution takes 2*pi seconds, and therefore we can write:

frequency = 2*pi / time per revolutions

In our example with a FPS rate of 25 frames per second, the frequency is approximately

frequency = 2*pi / 1.6 s = 3.925

An Intermediate Result

It’s time to assemble the expressions from our calculations. Fortunately, things like pi and FPS rate are part of RealFlow’s expression system and the only values we have to add manually are: radius (3.0), frame range (200), and number of revolutions (5.0).

Position.X 3.0*sin(t*(2*pi/((200/fps)/5.0)))
Position.Z 3.0*cos(t*(2*pi/((200/fps)/5.0)))

With these values full revolutions will be completed after 40, 80, 120, 160, and 200 frames – assuming a rate of 25 fps.

Position Independency

We have made some good progress so far, but still everything’s just moving around the viewport’s origin. In order to make the expression work at any position we’ll be using a comfortable function inside RealFlow’s expression system:

  • Create another null object and rename it to “Helper” – this null indicates the new midpoint of the circular motion.
  • Move the “Helper” node to an arbitrary position.

Then, go back to the “Curve Editor” and open the first expression for the X coordinate.:

  • Enter “+” after the expression.
  • Click on “Insert” and go to D vars > helper > position > x
  • Do the same for the Z (Y) coordinate and choose “z” (“y”) – RealFlow will complete the expression:
Position.X 3.0*sin(t*(2*pi/((200/fps)/5.0)))+helper.position.x
Position.Z 3.0*cos(t*(2*pi/((200/fps)/5.0)))+helper.position.z

The final sine and cosine curves with helper positions different from <0,0>.

What we have now is a self-updating, semi-procedural expression and every time you move the “Helper” node, the original null will be moved to its new position automatically. If you want to consider the height axis as well just add a new expression to Y (Z):

helper.position.y (helper.position.z)

Fields Of Application

Circular motions are needed for many purposes and expressions are an easy way to describe them. You don’t have to create keys or import animated objects from ABC or SD files, and transfer the animation to other objects. If your 3D program supports expressions, you can use the formulas from this tutorial there as well.

Maybe the most important application is the creation of a circular camera path. If you apply the expressions to a camera, and let it point in direction of an object (or a null like the “Helper”), you will be able to perform perfect camera motions. Then everything can be rendered inside RealFlow or written out as a preview. It is also possible to drive emitters with these expressions to pile up sand or shape viscous liquids. 

A very nice effect can be achieved when you animate the “Helper” null, because the camera (or any other object) will follow the helper while it describes circles, as shown in the granular simulation below. There, the camera describes two revolutions in 150 frames:

Let the revolution begin!