Recording Animation Keys

RealFlow is a dynamic simulation tool, which means that animations are automatically calculated based on physical properties. This process does not require any keys, but sometimes it is necessary to store the movement within an animation curve, because you want to transfer it to a different object or export the keys. Another idea is to process the keys to create more sophisticated animations with ease-in and ease-out effects. With the new functions of the "Curve Editor" you will benefit from even more advantages when dynamic animations are baked. It is now possible to combine the recorded curves with expressions, copy certain areas or selected keys, and transfer them to other curves. And you can change a key’s behaviour to “Tcb”, “Linear”, “Bezier” or “Stepped” and save everything for future use.

 

Name

KeyRecorder.rfs

Type

Simulation Events

Description

Record the individual position data for a selected node at each frame and write them to the "Curve Editor" with interpolation method "Bezier". 

 

What the script should do:

  • Initialize the needed variables before the simulation starts
  • Get time and position data for each axis, and write them to lists during simulation
  • Create and write the keys for each frame and set interpolation type to “Bezier” after stimulation

 

The workflow above indicates that three separate scripts are needed and the recorded information has to be shared between these parts. Such a process calls for global variables. Nevertheless the script’s structure should already be clear, so the main issue is to find out where the individual parts are located and how to add an key to property’s animation curve.

At the time the simulations starts there has to be a global definition of the lists for both position and time data. It is not possible to do this at another time, for example during the simulation, because in this case the contents would be overwritten with each frame and the result would be a single value.

# Simulation Pre

object = scene.getObject("Sphere01")
name   = object.getName()

scene.setGlobalVariableValue("objName", name)
scene.setGlobalVariableValue("posList", [])
scene.setGlobalVariableValue("timeList", [])

 

The next step is to read the desired data and write everything to the previously initialized lists. There some of the global variables are needed.

# FramesPost

objName     = scene.getGlobalVariableValue("objName")
posList     = scene.getGlobalVariableValue("posList")
timeList    = scene.getGlobalVariableValue("timeList")
currentTime = scene.getCurrentTime()
recObject   = scene.getObject(objName)
pos         = recObject.getParameter("Position")

posList.append(pos)
timeList.append(currentTime)

 

As you can see the current position is added to the list with each frame, as well as the current time. That is necessary because after the simulation you do not have any time information and so everything has to be stored temporarily. Time is needed to properly set a key. The rest is pretty straightforward.

 

The motion path of a sphere will be translated into animation keys.

 

All keys will be written after the simulation, because this has some advantages: imagine you have to write out the position data to a file. This could slow down RealFlow, since the script has to open the output file, write the data and close the file for every single frame! With the method outlined here, everything is written in one pass after the last simulated frame. In the last part you can find the functions for setting the keys and assigning the information from the different lists. Everything has to be done for each component of the position vectors: X, Y and Z. The code snippet here shows the process for a single axis. A counter is needed to read out the stored time information by the list’s index:

# SimulationPost   

index     = 0 
posList   = scene.getGlobalVariableValue("posList") 
timeList  = scene.getGlobalVariableValue("timeList")
objName   = scene.getGlobalVariableValue("objName")
object    = scene.getObject(objName)
curvePosX = object.getParameterCurve("Position.X") 

for posVector in posList:   
    newKeyX = Key.new() 
    simTime = timeList[index] 
    index  += 1
 
    newKeyX.time  = simTime
    newKeyX.value = posVector.getX()
    newKeyX.type  = KEY_TYPE_BEZIER
    curvePosX.addKey(newKeyX) 

 

The final statement prints a key which will be visible in the "Curve Editor". Each statement with an axis-dependent variable has to be repeated for each of the position vector’s component to record the entire movement. Instead of KEY_TYPE_BEZIER you can, of course, use other types: KEY_TYPE_TCB, KEY_TYPE_LINEAR or KEY_TYPE_STEPPED.  Another thing you should be careful with is this notation:

curvePosX = object.getParameterCurve("Position.X")

 

Please mind the dot between “Position” and “X”!

 

An enlarged section of the recorded curves shows individual keys.