+ All Categories
Home > Documents > RF Magazine 0207

RF Magazine 0207

Date post: 04-Jun-2018
Category:
Upload: sreezb
View: 226 times
Download: 0 times
Share this document with a friend

of 67

Transcript
  • 8/13/2019 RF Magazine 0207

    1/67

    RF_magazineREALFLOW USER MAGAZINE

    FLUID DYNAMICS :: PHYSICAL SIMULATION :: SCRIPTING :: CONNECTIVITY :: REALWAVE

    ISSUE 02_2007

    RF_magazine is brought to you by Liquidlight.tv www.liquidlight.tv

    Scripting with RealFlow - Introduction

    Basics of Python Scripting with RealFlow

    Learn how to use Python inside RealFlow

    First Steps

    Accessing particles and changing parameters

    Creating GUIs

    Write out your own user interfaces

    The Foam Project

    Learn, how to create foam and spray

    and many more ...

    http://www.liquidlight.tv/http://www.liquidlight.tv/
  • 8/13/2019 RF Magazine 0207

    2/67

    RF_magazine 1

    Welcome to RF_magazine 02/2007

    This issue deals with scripting. With RF4, Next Limit

    introduced a Python interface. Remembering the first

    reactions in the old official forum, scripting wasnt verypopular at that time. But in the meantime, scripting

    became one of the most important parts of the package.

    On the other hand, many users are still afraid of using this

    mighty tool.

    When people think about scripting and programming,

    many of them still have the impression that you need a

    deep understanding of maths. This edition wants to show

    - or even proof - that you can achieve stunning effects with

    little effort. Python scripting in RealFlow is your friend, not

    an enemy, because it makes life so much easier in manyways.

    The principles are fairly the same with each script.

    RF_magazine uncovers these techniques with lots of

    examples and projects. With this issue you can discover

    the advantages and power of scripting.

    Next Limit chose Python, because its an easy to learn and

    wide spread language. In many terms, Python almost

    reads as spoken English. This feature makes Python suited

    for beginners. With growing knowledge and experience,youll get a deep insight into Python and a better under-

    standing of RealFlow. Altering parameters with a self-

    written program is completely different from changing

    values within in a Node Paramswindow.

    But theres one thing, even the best book or tutorial cant

    do for you: Reading carefully and trying to understand

    whats going on in a particular script. The basics, like Data

    Typesor simple Vector maths are very important and cant

    be left out. Programming is also learning by doing!

    So, dont hesitate and dive into scripting with RealFlow.

    After a few hours youll be able to write your own first

    script.

    Sincerely yours,Thomas

    Thomas Schlick (tsn)

    Liquidlight.tv

    Nuremberg/Germany

    www.liquidlight.tv

    This magazine has been certified by Next Limit:

    Editorial02_2007

    http://www.liquidlight.tv/http://www.nextlimit.com/http://www.liquidlight.tv/
  • 8/13/2019 RF Magazine 0207

    3/67

    RF_magazine 2

    Editorial

    Welcome to RF_magazine Page 1

    The Power of Scripting

    A First Glance Page 4

    What is Scripting Page 4

    The Advantage of Scripting Page 4

    Python and RealFlow Page 5

    Where to Start? Page 5

    The Basics of Python Scripting in RealFlow

    Variables - First Steps with Scalars Page 6

    Other Types of Variables Page 7

    Creating Lists Page 8

    Creating Dictionaries Page 8

    Appending Values Page 9

    Operators Page 9

    Data Types Page 11

    Vectors Page 13

    Calculating with Vectors Page 13

    Notation and Syntax Page 16

    Getting Started

    Setting the Preferences Page 18

    The Scripting Windows Page 19

    Scripted Objects Page 20

    Your First Steps

    Calling Emitters and Objects Page 22Accessing Particles Page 23

    Building Vectors Page 25

    If & Else Page 27

    Changing Attributes with Get & Set

    Introduction Page 29

    How to Use Get & Set Page 29

    Working with Particles Page 34

    Conclusion Page 36

    Contents02_2007

  • 8/13/2019 RF Magazine 0207

    4/67

    RF_magazine 3

    Creating Graphical User Interfaces

    Whats a Graphical User Interface Page 37

    The Structure of RealFlow GUIs Page 37

    File and Node Pickers Page 49

    The Foam Project

    Project Overview Page 41

    The Nature of Foam and Spray Page 41

    Creating Foam Page 42

    Controlling Values Through Objects Page 46

    Collision Based Foam Creation Page 47

    Optimizing the Script Page 49

    Threshold Parameters Page 50Credits Page 50

    Fun with Freeze

    Project Overview Page 52

    Freezing Time and Particles Page 52

    Circular Particle Freezing Page 53

    Relaxing Particles with Freeze Page 55

    Inverting the Effect Page 55

    Summary Page 56

    Examples and Ideas

    Overview Page 57

    Image Based Emitter Speed Page 57

    Boxed Daemons Page 58

    Exporting Position Data to AfterEffects Page 59

    Appendix

    Reserved and Forbidden Words Page 64

    Notes

    Issue 01_2008 Page 65

    Legal Notes Page 65

    Contents02_2007

  • 8/13/2019 RF Magazine 0207

    5/67

    RF_magazine 4

    Scripting with RealFlow02_2007

    A First Glance

    Since version 4, scripting is an important part of RealFlow.

    Many well known studios asked for this feature and Next

    Limit met this demand. The implementation of a scripting

    interface was one of the major leaps in the developmentof RealFlow and took almost two years.

    Unfortunately therere still many users around, who want

    to explore the power of scripting, but often dont know

    where to start. Of course, the manual is an obvious source

    for information regarding scripting. Fusion CI Studio

    co-founder Dr. Mark Stasiuk did a very good job, as he

    explains lots of fundamental questions and ideas behind

    scripting.

    Anyhow I met many people in search of a compendium ora comprehensive tutorial, covering the entire range from

    beginning to intermediate or even advanced scripting. At

    realflowforum.com I already published a series of free

    tutorials for beginners, and I had positive feedback. This

    feedback encouraged me to deal with scripting in this

    issue.

    What is Scripting?

    Scripting is the process of developing programs for customtailored applications. In our case, inside of RealFlow. For

    scripting, a programming language is needed. This

    language provides a set of statements and functions the

    programmer can use, to write his own scripts. The main

    difference between scripting and, e.g. C or Java program-

    ming is the way, the code is treated:

    Scripts are normally interpreted. You all know this from

    web browsers. JavaScript and PHP are very popular

    examples. The code (this is the sequence of statements in

    your program) is often directly visible to the user. At themoment, a visitor calls a webpage, the code is sent to the

    interpreter and directly processed.

    Unlike scripts, programs like RealFlow are compiled. This

    means, the code will be preprocessed and converted into a

    completely different format. Compiling has some great

    advantages and the most obvious are speed and visibility.

    A compiled program is much faster than an interpreted

    script, because the compiler optimizes the code for certainhardware needs. Simultaneously the program is converted

    and the content becomes invisible. This helps to protect

    your development. Today, there are already some compil-

    ers available for scripting languages.

    The Advantage of Scripting

    I was talking about the benefits of compiled programs.

    Now, youll surely ask, why does RealFlow use a scripting

    language and not C/C++ or Java? With scripting languagesyou dont have to deal with compiling. This sometimes

    can be a very heavy task to solve and you need certain

    compilers for different operating systems and hardware

    requirements.

    With the available scripting languages you dont have to

    care about all these things. You just start coding, execute

    the script and the interpreter does everything else. Many

    people also say that its easier to start with a scripting

    language, but in my personal opinion, its also a matter

    of what you want to do. Both, interpreted and compiledlanguages have clear benefits and disadvantages.

    Modern scripting languages are very powerful tools with

    hundreds of extensions and libraries, mighty built-in

    functions and sophisticated methods, like object orienta-

    tion.

    Often used scripting languages are Perl, Python, Java-

    Script, VBScript, PHP, Tcl and also AppleScript. During the

    first years of the WWW, Perl was the main language for

    online applications. After the rising of PHP and Python,Perl lost its importance, but still has a vivid and strong

    community.

    The Power of Scripting

  • 8/13/2019 RF Magazine 0207

    6/67

    RF_magazine 5

    Scripting with RealFlow02_2007

    Python and RealFlow

    Now, Python is an integral part of RealFlow, but there is

    much more: The Next Limit developers extended the

    existing Python language by hundreds of new statements

    and functions. You can now directly access almost anyobject and attribute of RealFlow via Python scripting.

    This fantastic development opens the door to an infinite

    variety of possibilities.

    RealFlow comes together with a complete version of

    Python and the user doesnt have to struggle with instal-

    lation directories and libraries. With the installation of

    RealFlow you get the complete Python package, ready to

    start.

    Some of the main advantages of Python are:

    Free license, even for commercial use

    Common and wide spread language

    Perfect for beginners

    OS independent (Unix, Linux, OS X, Windows etc.)

    Hundreds of online resources, books and forums are

    available

    Standard scripting language for many applications

    Code is platform independent and easy to exchange

    Python scripting in RealFlow lets you directly addressobject, daemon and emitter parameters and alter them.

    Where to Start?

    One of the most important questions for beginners is

    where to start. Many users are doubtful and insecure

    when they think about making their own scripts.

    One very common prejudice is that scripts always have to

    be complicated and highly sophisticated artworks.

    Just discard this attitude and think of it as a normallanguage. Not every sentence has to be a poem, mostly

    its better to speak in a clear and easy way.

    Another misunderstanding is that you have to be a maths

    genius to write good programs. Of course a basic knowl-

    edge of mathematics is useful, but not mandatory. If you

    just want to automate some processes, you wont need

    very much mathematics.

    A very good starting point for each programming novice is

    to create a simple example with a great feeling of success.

    Since RealFlow is a 3D application with a high visual

    impact, its rather easy to find those examples. No matter

    what youre doing, it will directly influence the objects on

    your screen.

    Maybe youve already started to learn a programming

    language? Then you also might have seen the famous

    Hello World program. This is always a nice start, but for

    our purposes its not suitable. Were after completely

    different things.

    Before we can kick off, its indispensable to learn the

    basics of Syntax and Notation to understand the principles

    of how Python works.

    The Power of Scripting

    Fig 1. Script affected particles of an emitter

  • 8/13/2019 RF Magazine 0207

    7/67

    RF_magazine 6

    Scripting with RealFlow02_2007

    Variables - First Steps with Scalars

    Variables are the key to everything, independent of the

    used programming language. A Variable could be consid-

    ered as a placeholder. You can fill this placeholder with any

    content you like. In programming languages,Variableshave to be declared. This means that you have to introduce

    a name for your Variable and assign a value to it.

    Imagine the following easy example. We got some infor-

    mation from a person: 25,female, Claudia. Without setting

    these information into a logical context, we cant capital-

    ise on these data. Im sure you already started bringing

    these information into an order:

    Name = "Claudia"

    Age = 25

    Gender = "female"

    Now these attributes start making sense. You assigned

    certain properties to Claudia and you already declared

    three Variables. The names of these Variables are Name,

    Ageand Gender, their properties (or values) are Claudia,

    25andfemale.

    You can also see, that its very important to choose strong

    and meaningful names for your Variables. In this case we

    declare our Variables like this:

    A = "Claudia"

    B = 25

    C = "female"

    Formally thats absolutely correct, but the information

    isnt very clear, especially when there are similar values or

    properties:

    A = "Claudia"

    B = 25

    C = "Beatrice"

    D = 56

    After a while, youd certainly have no clue what the

    Variable names are standing for. With Variables declared

    like this, its no problem:

    First_Name = "Claudia"

    Age = 25

    Second_Name = "Beatrice"

    Weight = 56

    Its very important that Variables always share the same

    name over the entire script, because Python and other

    languages are case sensitive. In a script Genderis not the

    same asgender. Variables can be declared wherever

    theyre needed, but its a good idea to find common

    places for your Variables and arrange them clearly. Never

    use special characters for Variablesnames. The range of

    allowed characters is a-z, A-Z, 0-9 and the underscore.Variables must start with a character, not with a number.

    Variables are a very flexible facility. You can change their

    values within the script and you can assign numbers,

    characters, and strings. But each of the Variables above

    can only carry one value. This type is called a Scalar.

    By defining a new value for an existing Variable, the old

    value will be substituted:

    Name = "Claudia"

    Name = "Lydia"

    If we had a script to print out the variables content, the

    result would be Lydia. Only the very last value will be used.

    An important convention is that strings and characters

    have to be written in quotation marks. With numbers this

    is not necessary. If youre writing numbers within quota-

    tion marks, theyll be treated as a string.

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    8/67

    RF_magazine 7

    Scripting with RealFlow02_2007

    Other Types of Variables

    As youve learned, a Scalar can only carry one value, but

    there also are Variables, you can fill with two or more

    values. Python programmers differentiate between two

    types: Lists and Dictionaries. A Listis something, wecertainly need very often with Python and RealFlow.

    You can consider a List as a cupboard with drawers. Each

    value has its own drawer, and theyre all arranged in a

    fixed order. The numeration of these drawers starts with 0

    (Zero). Python also starts the numeration of Lists with 0.

    Lets assume that each drawer contains coloured marbles:

    0 = red, 1 = blue, 2 = green, 3 = yellow, 4 = purple

    By opening drawer number 2, youll have access to the

    green marbles, opening number 0, will lead to red ones.

    The List provides a container with a fixed sequence.

    Whenever you want to have purple marbles, you have to

    call position number five. But wouldnt it be nice to have

    a method to arrange the marbles the way we want?The solution is called Dictionary. In a Dictionary, theres

    no sequence and all contents could be disordered.

    In difference to Lists, its not necessary to call the entries

    via a fixed index. In Dictionaries we use search keys.

    A very good example for a Dictionary is a private phone or

    address book, in which we often see pairs of values, e.g.

    a name and a phone number. These pairs are stuck

    together and we cant identify one without the other:

    Claudia : 54358

    Lydia : 43663

    Agnes : 65586

    Susan : 94343

    Imagine the phone book from your cell phone. By entering

    a name, the software prints out the according phone

    number. Thats exactly the way, a Dictionary is working.

    It doesnt matter, where the entries are located within the

    book, because theyll always be identified via a search key.

    In RealFlow Dictionaries is rarely used, but nevertheless

    there might be some cases, where you need them.

    Now you know all three types of Variables for storing

    values in Python and respectively in RealFlow: Scalar,

    List and Dictionary. For Lists and Dictionariesyou have to

    obey the same rules as for Scalars. The Variables names

    should be meaningful and special characters are forbid-

    den.

    Just one final note: a List is sometimes called anArray, and

    a Dictionary is also known as Hash or Associative Array.

    Fig 2. A List can be used to arrange values and entries

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    9/67

    RF_magazine 8

    Scripting with RealFlow02_2007

    Creating Lists

    Creating a List structure in Python is an easy task. An

    empty List is written as:

    my_list = []

    If you want to define the values directly with the creation

    of the List, the format is:

    my_list = [value1,value2,value3, ...,value n]

    For better understanding, Id like to create a List with the

    colours of our marbles from page 7:

    colours = ["red","blue","green","yellow","purple"]

    As you can see, all colour names are between quotation

    marks. You dont need these marks for numbers:

    diameter = [2.0, 2.5, 3.0, 3.5, 4.0, 4.5]

    In Python its easy to find elements, stored in a List:

    favourite_colour= "yellow"

    colours = ["red","blue","green","yellow","purple"]

    if (favorite_colourin colours):

    print "Your favourite colour is in stock."

    else:

    print "Sorry. Your favourite colour is not available."

    Result: Your favourite colour is in stock.

    In this short example, I introduced a Scalar Variable,

    named favourite_colour. The value isyellow. Now, the in

    statement goes through the List in search ofyellow.

    Ifyellowhas been found, the script writes out a success

    message. If the value of favourite_colour (e.g. brown) isnt

    part of colours, the result would be

    Sorry. Your favourite colour is not available.

    The next method uses the stored indices. Since each value

    has a fixed position within the List, its possible to address

    a colour using this index. Remember that List indices

    always start with 0.

    colours = ["red","blue","green","yellow","purple"]

    selection = colours[2]

    print selection

    Result: green

    Another very important function with Lists is to find the

    total number of elements. This is also called the Length of

    a List. You can get it with:

    colours = ["red","blue","green","yellow","purple"]

    number_of_entries = len(colours)

    print number_of_entries

    Result: 5

    Creating Dictionaries

    Youve already learned that elements in a Dictionary dont

    need a specific order to find them. A Dictionary uses

    key/value pairs to search through the content. An empty

    Dictionary can be created by typing

    my_dictionary = {}

    Of course you can directly start entering values and

    performing a query:

    phonebook = { "Claudia":54358, "Lydia":43663,

    "Agnes":65586, "Susan":94343 }

    print phonebook["Agnes"]

    Result: 65586

    Isnt that easy? You dont have to worry about indices,

    numeration or positions.

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    10/67

    RF_magazine 9

    Scripting with RealFlow02_2007

    Analogue to Lists, its also possible to get the length of a

    Dictionary. The function calls all key-value pairs and stores

    the result in a predefined Scalar:

    phonebook = { "Claudia":54358, "Lydia":43663,

    "Agnes":65586, "Susan":94343 }

    number_of_entries = len(phonebook)

    print number_of_entries

    Result: 4

    Appending Values

    Now you know how to create Lists and Dictionaries manu-

    ally and how to read out specific values. In RealFlow we

    often have to deal with thousands of particles. Collectingtheir data and writing them to a List by hand wont be a

    good solution. For this purpose, Python provides a special

    function called append.

    The append function adds values to the end of a List. This

    is important, since a List is working with index numbers.

    There are also functions to insert values at certain

    positions, but theyre rarely used with RealFlow. In most

    cases you extend a List by simply appending a new value.

    This is the syntax for Lists:

    colours = ["red","blue","green","yellow","purple"]

    new_colour = "orange"

    colours.append(new_colour)

    Adding a value to Dictionary is slightly different. We dont

    need a fixed order and therefore the position of the new

    element isnt important. An entry of a Dictionary always

    consists of two elements: The key and its value. Its very

    important to define which one will serve as a key, respec-

    tively as a value.

    phonebook = { "Claudia":54358, "Lydia":43663,

    "Agnes":65586, "Susan":94343 }

    phonebook["Helen"] = 22986

    Its also possible to use Scalars and add their values to the

    Dictionary:

    new_name = "Helen"

    new_number = 22986

    phonebook[new_name] = new_number

    For the moment this should be enough. Youll learn more

    about these data types in connection with scripts.

    Operators

    Operators are one of the most important things in Python.

    With an Operator its possible to perform basic arithmetic

    calculations and comparisons. And thats truly a bless.Without Operators, you wouldnt be able to compare

    particle velocities or positions against a Scalar and thered

    been no way to multiply or substract values. You can find

    Operators anywhere in a script and Python knows a lot of

    them. The first group contains all arithmetical Operators:

    + Addition 15 + 17 = 32

    - Substraction 64 - 30 = 34

    * Multiplication 10 * 12 = 120

    / Division 80 / 10 = 8

    ** Exponentiation 12 ** 2 = 144% Modulus 28 % 7 = 0

    + String concatenation John + Doe = JohnDoe

    * String repetition Hi * 3 = HiHiHi

    A very nice Operator is Modulus, but it needs some expla-

    nation. In general, Modulus tells you, if theres a remain-

    der after performing a calculation or not. With Modulus

    its possible to find out whether a number is even or not,

    for example. If the result is different from 0, the number is

    uneven. A result of 0indicates an even number.

    The String Operators are rarely used with RealFlow and

    more important for text processing applications.

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    11/67

    RF_magazine 10

    Scripting with RealFlow02_2007

    The next group contains Operators for comparisons:

    < Less than

    > Greater than

    = Greater than or equal== Equal

    != Not equal

    Equality is tested with ==. The single = is just used for

    assignment, e.g. in Variable names:

    Name = Claudia

    The result you get with Comparison Operatorsis true or

    false. These are the two possibilities and theres nothing

    between:

    velocity_a = 5.0

    velocity_b = 7.3

    if (velocity_a < velocity_b):

    print "This is true."

    By swapping the Variables, the result would be false. In

    RealFlow you normally wont calculate with true or false.

    Its just a means for making decisions, what should

    happen with your values or parameters. It can be consid-ered as a crossover, where you also have two or more ways

    to go. Lets say, you want to limit the velocity of a parti-

    cle:

    max_velocity = 7.5

    current_velocity = 8.2

    if (current_velocity > max_velocity):

    new_velocity = max_velocity

    else:

    new_velocity = current_velocity

    What happens here? The current velocity of a certain

    particle has been determined as 8.2. With an Operator

    were testing, if the value of the current velocity is greater

    than the maximum velocity. This value is a threshold.

    Whenever a particles velocity is greater than this limit,

    its just cut down to 7.5. If this condition is not fulfilled,

    the script calculates with the current value, stored in

    current_velocity. In this example, the condition is true,because current_velocity is actually greater than

    max_velocity.

    Another example using the equality Operator:

    max_y_position= 3.5

    current_y_position = 2.9

    if (current_y_position == max_y_position):

    attractor_force = 25

    else:

    attractor_force = 10

    At the moment, the observed particle reaches the

    max_y_position value, attractor force will be 25. Here,

    current_y_position is less than 3.5, and the condition is

    false. The assigned value for attractor_force is 10.

    A third group consists of so called Boolean Operators.

    The keywords are:

    andor

    not

    Youll mostly need these Operators when you have to

    check more than one condition.

    if (cur_vel >= threshold_1 or cur_vel

  • 8/13/2019 RF Magazine 0207

    12/67

    RF_magazine 11

    Scripting with RealFlow02_2007

    The last class Im talking about here, areAugmented

    Operators. This is a very special class and mostly used for

    abbreviations. In some cases, its necessary to write

    expressions like:

    while (particles):

    total_mass = total_mass + particle_mass

    In this example, the script loops through all particles and

    sums up their individual masses to get a total mass value.

    This calculation could also be written as:

    while (particles):

    total_mass += particle_mass

    The most common Operators are

    += -= /= *= **= %=

    There are some more Operators in Python, but theyre not

    often used with RealFlow. By knowing the discussed

    classes, you already have the tools to create your own

    conditional expressions and basic calculations.

    Data Types

    Coders have to distinguish between various Data Types.At school you probably already met most of them and

    with RealFlow you will need these types again. The most

    common format is surely the Integer type. Integers are

    wide spread and we use them in our daily life without

    thinking about them. Integers are numbers like:

    -5, 2, 100, -4335, 757, 423843, -3289988, 45, 234, -775647

    The set of Integers is infinite, it can be positive or negative

    and it doesnt contain fractures like 3.645, -1.3333or 12.7.

    Fractured elements arent members of the Integer family.Also fractures, apparently consisting of two Integers arent

    valid elements: or . Though the result of such a

    division can be an Integer!

    There are two subtypes of Integers in Python. The first one

    is called Plain Integer, or just Integer. The abbreviation of

    this type is known as int. This type is not endless and

    theres a maximum range. For the sake of calculation

    performance its necessary to differentiate, because Plain

    Integersare processed much faster. In 99% of all cases, thePlain Integertype will serve your needs. These are the

    specifications:

    int (Integer or Plain Integer)

    2,147,483,648to+2,147,483,648

    This range is also called 32-bit precision and its the

    minimum for all modern operating systems. Most operat-

    ing systems also support 64-bit precision. The valid range

    for this type is:

    9,223,372,036,854,77,.808to+9,223,372,036,854,775,808

    long (Long Integer)

    In Python this subtype has infinite precision, but the

    effective length of your number depends on the amount

    of RAM in your computer.

    The next, very important type is called Float. Youve

    already seen Floats (also called floating point numbers)on the left. They were introduced as decimal fractures

    (1.8543). The most significant attribute of Floats is the

    decimal point. Its possible to calculate with decimal

    places of different length. Of course its allowed to

    combine Integers and Floats together. Valid expressions

    would be:

    75.543 / 8.4 + 1.3 * 67.55

    5.8564 * 6 + 23.98

    Floats can also be negative or positive. The length orprecision of Floats strongly depends on your computer and

    operating system, but most likely you wont encounter

    any problems. The token in Python is simply float.

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    13/67

    RF_magazine 12

    Scripting with RealFlow02_2007

    The last Data Type, Im talking about, is called Complex. In

    RealFlow this type will be rarely used and its only men-

    tioned for completeness. Complex numbers consist of two

    parts: A real and an imaginary part. The Complex type is

    therefore always written as a pair of numbers. The real

    number is just an Integer or a Float type, while the imagi-nary part must own ajcharacter:

    (3 + 6j)

    Even if the imaginary part is Zero, you have to write this

    value in conjunction withj:

    (12 + 0j)

    With Complex numbers its possible to perform calcula-

    tions as usual:

    (2 + 4j) * (8 + 3j) or (11 + 1j) * (7 + 5j)

    In Python, this special Data Typecan be introduced with a

    complex statement.

    Now youve heard about int, long, floatand complex,

    but you surely have no idea, how to use these types. One

    main application for Data Typesare Variables, of course.

    The good thing is that you dont have to introduce each

    Variable with the appropriate index. Python automaticallyrecognizes the correct type. But there are some other

    cases, where you have to determine, which type youd like

    to use. One of these cases are GUIs - Graphical User

    Interfaces. Youll read about GUIs later, starting on

    p. 37, but Id like to introduce some basic information

    about the usage of Data Types:

    With GUIs its often allowed and wanted, to enter custom

    values for initializing a calculation. Lets assume, your goal

    is to build a tower made of cubes. Within the GUI you can

    type in values for the number of stacks, the width and theheight of a stack. This number has to be an Integer,

    because you cant build a tower with 5.278 floors. The

    width and height instead, can measure 2.5 or 7.84 units.

    The used Data Typesin this example are:

    levels = int e.g. 10

    width = float e.g. 2.5

    height = float e.g. 3.75

    Another often used exercise is the conversion of Data

    Types. Its possible to translate a Float number into an

    Integer and vice versa. You could also translate a Long type

    into a Float number. But with all these transformations,

    you have to keep in mind that youre probably losing

    precision. Converting a Float type number into an Integer

    truncates the decimal places:

    int(3.256) = 3

    int(9.999) = 9

    This conversion only takes the Integer part of the original

    number, without caring about rounding. The same can be

    observed when converting Long to Float.

    The Basics of Python Scripting in RealFlow

    Fig 3. A tower based upon integer and float values

  • 8/13/2019 RF Magazine 0207

    14/67

    RF_magazine 13

    Scripting with RealFlow02_2007

    Vectors

    Another Data Typeare Vectors. Vectors are not a built-in

    element of Python, but there are some languages,

    supporting Vectors as a Data Type. The Python extension

    of RealFlow, for example, knows Vectors and theyre fullyintegrated. Since theyre not part of Pythons standard

    installation, Id call them a Pseudo Data Typehere.

    In RealFlow, Vectors are one of the most important

    elements and this is another reason, why I chose to

    discuss them separately.

    A Vector could be considered as an arrow, pointing into a

    certain direction. To describe a Vectors direction, we need

    at least two dimensions: x and y. By drawing a Vector into

    a coordinate system, we get the main properties:Direction and Magnitude. The Direction tells you, where

    the Vector is pointing at, while the Magnitude is the length

    of the arrow.

    Vector coordinates can consist of Integers and Floats.

    The graphical illustration of a Vector might help to get

    an understanding, but its not suitable for calculations.

    Therefore we have to find a notation. Therere some

    established forms to represent a Vector, but according to

    RealFlows notation, a Vector in RF_magazine is always

    written as:

    a= (x, y) or a = (1.0, 1.0)

    In RealFlow were dealing with 3D space and the represen-

    tation of a Vector needs a third coordinate:

    a = (x, y, z) or a = (1.0, 1.0, 1.0)

    If yourre interested in real life examples or the math-ematical background, Id suggest to have a look at physics

    books or the internet, e.g. Wikipedia.

    Calculating with Vectors

    Its not possible to calculate with Vectors directly. The

    most common calculation type with Vectors isAddition.

    For performing Vector calculations, you have to use either

    the individual elements x, y, z or its Magnitude. The

    coordinates of a Vector are called Scalars. You alreadyheard about Scalars at the very beginning of this chapter.

    a = (5.0, 2.5, 4.2)

    b = (1.7, 3.9, 8.1)

    In this case were looking for c = a + b. Maybe its just

    c = (ax+ bx, ay+ by, az+ bz)

    c = (5.0 + 1.7, 2.5 + 3.9, 4.2 + 8.1)

    c = (6.7, 6.4, 12.3)

    This really is the answer, and its analogue with Vector

    Substraction c = a - b:

    c = (ax- bx, ay- by, az- bz)

    c = (5.0 - 1.7, 2.5 - 3.9, 4.2 - 8.1)

    c = (3.3, -1.4, -3.9)

    As you can see here, a Vector can also point into negative

    directions.

    The coordinates of a Vector are Scalars. For this reason itspossible to multiply the Vector components with another

    Scalar. Its likely that you will use this method very often,

    especially with forces.

    The Basics of Python Scripting in RealFlow

    Fig 4. Different vectors pointing at various directions

    y

    x

  • 8/13/2019 RF Magazine 0207

    15/67

    RF_magazine 14

    Scripting with RealFlow02_2007

    Multiplication with a Scalaris calculated this way:

    a = (4.8, 2.9, 1.4)

    s = 2.5

    b = s * ab = (s * ax, s * ay, s * az)

    b = (2.5 * 4.8, 2.5 * 2.9, 2.5 * 1.4)

    b = (12, 7.25, 3.5)

    Another very important calculation rule is the Scalar

    Product. Dont mix it up with last rule, the Multiplication

    with a Scalar. These operations are completely different!

    The result of a Scalar Productis a Scalar and it can be

    considered as the multiplication of two Vectors:

    a = (1.7, 7.3, 3.3)b = (2.4, 0.7, 5.1)

    c = a * b

    c = ax* bx+ ay* by+ az* bzc = 1.7 * 2.4 + 7.3 * 0.7 + 3.3 * 5.1

    c = 4.08 + 5.11 + 18.83

    c = 26.02

    A special form of the Scalar Productis the square of a

    Vector:

    c = a2

    c = ax2+ ay

    2+az2

    Extracting the square root from this term, yields to a

    Vectors Magnitude (often called Norm or Length).

    | c| = ax2+ ay

    2+az2

    As you can see clearly here, the result of this operation is a

    Scalar, not a Vector. The lines around cindicate that its a

    Norm. In RealFlow you wont have to worry about thisrule, because theres a built-in function for calculating the

    Scalar Product. In RealFlow its called Dot Product, repre-

    sented by an asterisk character ( *).

    The next rule, Im talking about, is named Cross Product.

    The result of a Cross Productis also a Vector. The most

    common way to calculate a Cross Productis done by

    multiplying the components of two Vectors:

    a = (2.2, 6.1, 1.0)b = (0.7, 0.4, 3.8)

    c = a x b

    cx= ay* bz- az* bycy= az* bx- ax* bzcz= ax* by- ay* bx

    cx= 6.1 * 3.8 - 1.0 * 0.4

    cy= 1.0 * 0.7 - 2.2 * 3.8

    cz= 2.2 * 0.4 - 6.1 * 0.7

    cx= 23.18 - 0.40 = 22.78

    cy= 0.70 - 8.36 = -7.66

    cz= 0.88 - 4.27 = - 3.39

    c = (cx, cy, cz)

    c = (22.78, -7.66, -3.39)

    This operation is also implemented in RealFlow by default

    and you dont have to calculate this manually. Many

    physical values can be determined with the Cross Product,e.g. the Lorentz Forceor the torisonal moment. There

    surely comes a time, when you start looking for special

    formulas to enhance your simulations. Then youll

    certainly meet theCross Productagain. Many formulas,

    dealing with the simulation of natural, turbulent phenom-

    ena use the Cross Productto mimic the desired forces.

    The last rule has already been introduced: The Norm or

    Magnitude of a Vector. The result of this operation is a

    Scalar. Youll often use Magnitudes with forces. The

    resulting Scalar can be multiplied with a Vector again (seeMultiplication with a Scalar above). The Magnitude is

    calculated using an old friend: Pythagoras theorem.

    If you cant remember it, dont worry and turn over...

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    16/67

    RF_magazine 15

    Scripting with RealFlow02_2007

    Pythagoras theorem is normally used for triangle calcula-

    tions. In Vector maths, where you also could represent a

    Vector as an arrow, its possible to extract values by

    constructing triangles from the given Vectors.

    With Pythagoras theoremyoure now able to get the

    Length, or Magnitude of a Vector:

    Pythagoras theoremfor right-angled triangles:

    a2+ b2= c2

    You can get the value forcby extracting the square root:

    c= sqrt( a2+ b2)

    This term is also valid in three dimensional coordinate

    systems and for Vectors. The Magnitude of a Vector is

    always positive, because you have to square the values.

    a = (3.2, 2.8, 1.5)

    | a| = sqr(ax2+ ay

    2+az2)

    | a] = sqr(10.24 + 7.84 + 2.25)

    | a| = 4.51

    For fluid, smoke and fire simulations, physicians intro-

    duced Vector Fields. In a Vector Field, a Vector is assigned to

    each point of the considered space. The idea is to create

    field of variable strength at different points. Very good

    examples are gravity or the magnetic field. In reality these

    depend on where you are and therefore have differentvalues.

    Creating Vector Fieldsin RealFlow with Python is not

    trivial. For this reason I dont want to dive into the depth

    of these fields.

    The maths behind Vector Fieldsis complicated and the

    main problem with RealFlow is that we need the previous

    and the current value to solve the equations. RealFlow

    doesnt provide functions to store values over time and

    substitutes the previous results.

    A big variety of very interesting Vector Fieldscan beexplored here with a Java Applet:

    http://www.falstad.com/vector3d/

    The Basics of Python Scripting in RealFlow

    Fig 5. The Magnitude of a Vector

    Fig 6. 3D representation of a Vector Field with arrows

    x

    y

    a

    b

    c

    pos

    http://www.falstad.com/vector3d/http://www.falstad.com/vector3d/
  • 8/13/2019 RF Magazine 0207

    17/67

    RF_magazine 16

    Scripting with RealFlow02_2007

    Notation and Syntax

    Now youre getting closer to scripting and the theoretical

    part lies almost behind you. In this chapter youll learn

    how to organize a RealFlow script and what you have to

    attend.

    When youre writing Python scripts for RealFlow you have

    to follow certain rules. Without obeying these rules, youll

    receive error messages and your program wont run. The

    best idea is, to avoid those errors from the very beginning.

    As Ive seen in the unofficial RealFlow forum, the most

    common error is related to shifting and spacing. Python

    recognizes clauses, conditions and syntax groups auto-

    matically. The indicators are leading tabs and blanks.

    program start:

    statement 1

    if ( condition ):

    statement 2

    else:

    statement 3

    while loop:

    statement 4

    if ( condition ):

    statement 5

    else:

    statement 6

    statement 7

    The example above is a typical structure of a Python script.

    For each new instruction set, theres got to be a new

    clause. The interpreter allows blanks as well as tabs, but

    you must never use them together. Always make a

    decision on one method for shifting. Id recommend to use

    the Tab key. With this key you dont have to worry about

    the number of blanks and this makes life much easier.

    Other scripting languages, like Perl, often use brackets toseparate statements and functions. The advantage is that

    you dont have to care about tabs, but you shouldnt

    forget to close all branches. Otherwise youll receive an

    error. This an example of a code structure in Perl:

    sub function {

    statement 1;

    if ( condition ) { statement 2 }

    else { statement 3 }

    while loop {

    statement 4

    if ( condition ) { statement 5 }

    else { statement 6 }

    statement 7

    } # end while

    } # end sub function

    Though all conditions, definitions and loops are embedded

    into branches, its still a very good idea to use tabs forbetter readability. With Python its essential and especially

    with copied and pasted scripts, you have to be extremely

    careful. Scripts from forums, discussion boards or other

    sources often dont follow these rules for leading tabs,

    and this directly leads to problems.

    Python is a very flexible programming language. It allows

    many short forms and convoluted statements. For begin-

    ners its often very hard to understand, whats going on in

    scripts, made by Python pros. To grant access to everyone,

    the scripts from this issue use a step-by-step technique.Thus many scripts may be longer than necessary, but

    beginners can follow the code, too. I leave it to you, to find

    the shortest form for a script. With growing experience

    youll surely learn how to contract statements effectively.

    Another issue is the spelling of Variables. Python and the

    RealFlow extension use certain words for introducing

    particular functions. These words cant be used for

    Variables. You can find a list of the currently reserved

    words on page 64. Another limitation with Variable names

    is the usage of the dot character. The dot character is usedas an identifier for an objects properties, like:

    emitter.getPosition()

    The Basics of Python Scripting in RealFlow

  • 8/13/2019 RF Magazine 0207

    18/67

    RF_magazine 17

    Scripting with RealFlow02_2007

    The Syntax of a script can be seen as a grammar. Violating

    the rules leads to errors. Therere many definitions and

    essays about Syntax and especially for beginners its not

    easy to understand its importance. In brief terms:

    Syntax is the logical structure of a script.

    This structure is not a fixed rule type, its flexible and

    theres always more than one way to achieve a result.

    I think this should be enough about the nature of Syntax.

    If you need further information, just have a look at the

    internet.

    One of the most common error messages youll receive in

    RealFlow is Script Syntax error at line XX. A Syntax error

    often has marginal reasons, like:

    leading spaces are wrong

    wrong order of statements

    using Variables before assigning them

    misspelling of Variable names

    unmatched brackets

    infinite loops

    using improper operators

    using reserved or forbidden words

    using the wrong Data Type

    The Basics of Python Scripting in RealFlow

    Fig 7: RealFlow error message

  • 8/13/2019 RF Magazine 0207

    19/67

    RF_magazine 18

    Scripting with RealFlow02_2007

    Setting the Preferences

    RealFlow provides a complete scripting environment, fully

    equipped with Syntax highlighting, a debugger (this is an

    error detection facility) and a set of predefined func-

    tions. To adjust this environment to your needs, Idrecommend to set the scripting preferences first:

    realflow > Preferences > Script

    After the Script tab has been selected, a new panel

    appears, showing a variety of settings:

    Adjusting the Syntax Coloris a matter of taste. You can

    choose any colour you want. With the predefined colours,

    a typical statement would look like this:

    # Get the scene emitter

    particle_source = scene.getEmitter("Circle01")

    Highlighting certain keywords of a script helps you to keep

    the code readable and its easier to differentiate the

    individual elements.

    The Tab sizedetermines, how many leading blanks are

    inserted to structure the Python code. You should always

    use tabs instead of blanks or spaces to introduce new

    instructional blocks (also see p. 16). In conjunction with

    this setting, its a good idea to use a so called monospace

    font. Glyphs from these fonts all have a the same fixed

    width, which is great for organizing a script. With mono-

    space fonts its possible to arrange Variable names likethis:

    pi = 3.14

    gravity = 9.81

    e = 2.718

    ini_vel = 12

    With fonts using variable widths, its not possible to align

    names, numbers and other characters correctly:

    pi = 3.14gravity = 9.81

    e = 2.718

    ini_vel = 12

    Very common monospace fonts are Monaco, which is used

    here for all scripting examples, and Courier. Both fonts

    should be installed on most computers by default.

    In RealFlow its possible to choose a directory for your own

    scripts. These scripts can be filed in the toolbar of RealFlow

    and you have direct access to them, just by clicking on theappropriate icon. You can either use the default path or

    define another location anywhere on your harddisc(s). The

    Scripts Organizerfile carries all information about the user

    scripts.

    The last three icons are customized and indicate some of

    my own scripts. Please note that its only possible to use

    Batch Scripts(see p. 19) with the toolbar. Many free scripts

    already come with icons, ready to use with the toolbar.After youve made the settings, just click OK to use them

    as new defaults.

    Getting Started

  • 8/13/2019 RF Magazine 0207

    20/67

    RF_magazine 19

    Scripting with RealFlow02_2007

    The Scripting Windows

    The Scripting Windowsare a true obstacle for many

    beginners, because they simply dont know which type to

    use. In RealFlow there are three basic types: Batch, Events

    and Custom. The Batch and Events Script windows can becalled via the menu bar or by pressing F10, respectively F11:

    Layout > Batch Script

    Layout > Events Script

    Batch Scripts

    Lets have a look at Batch Scriptsfirst. Whats a Batch

    script and whats it used for? In Batch Scriptsyou mostly

    define routines for repeating tasks. Good examples are:

    Creating a brick wall

    Simulating two or more scenes successively

    Changing hundreds of values simultaneously

    Creating a basic scene with default objects

    Changing states from inactive to active

    Adding constraints to multiple objects

    Have you ever built a brick wall in your 3D application? You

    have to set brick by brick, or use a copy and paste method.

    With scripting you can define rules, how many floors thewall should have and how many bricks you want to use.

    The arrangement will be done automatically while

    running the Batch Scripts. After this task has been

    completed, another Batch Scriptscould alter the mass of

    each brick to get a more random effect, while destroying

    the wall with a bullet, for example.

    Whenever you need to change properties, create lots of

    similar objects, export values or add features, a Batch

    Scriptsis the proper choice. The way of developing Batch

    Scriptsis the same as coding Events or Custom Scripts. Themain difference lies in the way, the script will be executed

    by RealFlow.

    Events Scripts

    The second type, Events Scripts is needed, whenever you

    want to influence particles or objects directly during the

    simulation process. With a Batch Scriptyou dont need to

    start a simulation, with an Events Scriptits crucial.

    RealFlow knows a couple of predefined events:

    onSimulationBegin

    onSimulationEnd onSimulationStep

    onSimulationFrame

    onChangeToFrame

    onSimulationBeginis suited for applying initial param-

    eters, You can also add some basic elements to a scene

    that will be used for simulation. After this initialization,

    the routine wont be called again. onSimulationEndworks

    analogue to onSimulationBegin. Maybe the most impor-

    tant event is onSimulationStep. Here, RealFlow applies

    calculations for each time step. With heavy maths, thismay result in long simulation times. Please also remember

    that scripts only use one processor/core of a computer.

    Fig. 8: The Batch Script window

    Getting Started

  • 8/13/2019 RF Magazine 0207

    21/67

    RF_magazine 20

    Scripting with RealFlow02_2007

    Maybe the best example for a script using an onSimula-

    tionStepevent is the well known foam script. This script

    will be discussed later as separate project, starting on

    page 41.

    With onSimulationFrameits possible to make changes oncertain frames. The actual frame serves as trigger to

    switch on or off certain properties of one or more objects.

    Also changes can be performed with each frame, e.g.

    animating an object or exporting custom bin files.

    The last type, onChangeToFrameis great for post-

    processing. With this event, scripts can be applied while

    playing back a cached scene. Its rarely used, but neverthe-

    less a powerful means for some applications.

    After opening the EventsScriptswindow, youll recognize

    that these functions are already implemented.

    Each function wears apass statement. This statement tells

    RealFlow to simply jump over this function. By removing

    pass and replacing it through your own code, RealFlow

    starts executing the script. The best thing is that youre

    not limited to just one of the given functions. You can

    initialize a scene with onSimulationBegin, activate objectswith onSimulationFrameand perform calculations using

    onSimulationStep. Thats no problem, but before youll be

    able to run a script, you have to checkActive.

    Scripted Objects

    Custom scripts are sectioned into a couple of subtypes and

    theyre surely the most powerful means to customize your

    simulations. The three types are:

    Scripted Daemon

    Scripted Emitter

    Scripted RealWave

    The Scripted Daemonis probably the most often used

    subtype. In simple terms, a Scripted Daemonapplies a

    force to an object. For this purpose, the scripting window

    provides three predefined functions:

    applyForceToEmitter( emitter ):

    applyForceToBody( body ): removeParticles( emitter ):

    Its necessary to distinguish between particles and (rigid)

    bodies. With a Scripted Daemonyou can write your own

    gravity or attractor daemons, add friction to particles or

    objects, bound forces or define falloffs. As youre dealing

    with forces, represented as Vectors, some basic knowledge

    of applied mathematics is recommended.

    On page 36 and 58 you can also find two Scripted

    Daemons, showing, how Vector forces are implemented.The only limitation is that forces from Scripted Daemons

    seem to act a little bit different from the predefined

    Daemons in RealFlow.

    Fig. 9: The Events Script window

    Getting Started

  • 8/13/2019 RF Magazine 0207

    22/67

    RF_magazine 21

    Scripting with RealFlow02_2007

    Another very powerful facility is the Scripted Emitter. With

    this type its theoretically possible to write your own fluid

    solver, but we dont want to go that far. Maybe youre

    asking, why one should use a Scripted Emitter,though

    RealFlow already makes a wide range of predefined

    emitters available?

    The answer to this question lies deep within the way,

    RealFlow solves fluid dynamic equations. Maybe youve

    already tried to animate viscosity or density of a particle

    stream over time? If so, you might have encountered some

    serious crashes. The fluid becomes instable and the

    calculation suddenly aborts. With a Scripted Emitteryou

    can avoid this behaviour and define ranges for the param-

    eters from an emitters Particles panel. This is truly a

    mighty feature! The Scripted Emitteris not an indivdual

    object you can choose from the emitter list. The ScriptedEmitter is available for each type, like Circle, Sphere, Spline

    etc. All you have to do, is changing the type from Liquid to

    Custom:

    Emitter > Node Params > Particles > Type > Custom

    After this change, a new button, named Edit appears.

    To open the related scripting window, simply hit this

    button.

    The Custom type provides just one function to calculate

    the forces:

    computeInternalForces( emitter )

    The last subtype is the Scripted RealWaveobject. Similar tothe Scripted Emitter, this object is also part of the different

    RealWavetypes. You first have to add a new RealWave

    surface and then place a new deformer viaAdd Wave.

    Heres a screenshot of how you can access this feature:

    Again, an Edit button appears, to open the scripting

    window. There, youll also find just one function to update

    the vertices of the RealWave object:

    updateWave( vertices )

    Please note, that only its only possible to alter the y

    direction of the vertices. Translations in x or z direction will

    be ignored. The best application for a Scripted RealWaveis

    to import greyscale images as displacement templates.

    This technique is described in detail in RF_magazine Issue

    01_2007 Cinema 4D Special Edition, page 40 et seqq.

    Of course its possible to develop your own formulas tocreate new, not implemented wave types.

    Fig. 10. Parameter rollout for the Custom Emitter type

    Getting Started

  • 8/13/2019 RF Magazine 0207

    23/67

    RF_magazine 22

    Scripting with RealFlow02_2007

    Calling Emitters and Objects

    Now your persistence and patience will be rewarded

    finally, because youre about to make the first steps with

    Python and RealFlow!

    Start with a Circle emitter by choosing:

    Edit > Add > Emitters > Circle

    > Square

    The Node window now shows a new object called Circle01.

    To use this emitter within a script, its necessary to

    address it and store it in a Variable. The Variable type,

    were introducing here is a Scalar:

    emitter= scene.getEmitter("Circle01")

    emitter is the name of the Variable, scene tells Python to

    look at the Nodes panel for an emitter named Circle01. The

    basic keyword in this statement is getEmitter to fetch the

    desired object.

    Now add a Torus object. To get this item, we use a very

    similar construction:

    object= scene.getObject("Torus01")

    In this case, the Scalar variable is object and with the

    getObject keyword we have access to the Torus01 item

    from your basic scene.

    Of course, sometimes its required to change an objects

    name. Lets say you want to change the name from

    Circle01 to Water. To identify the emitter again, you also

    have to alter the name in the script:

    emitter= scene.getEmitter("Water")

    The Variable name may also be subject to change. In many

    cases theres more than one emitter and you need a more

    meaningful name. As youve already learned, its always a

    good idea to use significant names. Later were developing

    a foam script. This type of script uses multiple emitters

    and we have to distinguish them by name:

    water = scene.getEmitter("Water")

    foam = scene.getEmitter("Foam")

    Please note that the names of the emitters have to be

    identical with the names used in the Nodes window and

    the names must be written between quotation marks.

    Another possibility would be to declare Variables with

    emitter names:

    water_emitter= "Water"

    foam_emitter = "Foam"

    water = scene.getEmitter(water_emitter)

    foam = scene.getEmitter(foam_emitter)

    In this case were using the Variables as a substitute for

    the real name from the Nodes window. To make Pythonunderstand that we want to use a Variable withgetEmit-

    ter( )and not a String (= sequence of characters), we dont

    write quotation marks.

    With objects and other items its the same procedure:

    collission_object = scene.getObject("Torus")

    animated_daemon = scene.getDaemon("MainAttractor")

    main_camera = scene.getCamera("Camer01")

    rope_constraint = scene.getConstraint("Rope01")

    fluid_mesh = scene.getMesh("Fluid")

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    24/67

    RF_magazine 23

    Scripting with RealFlow02_2007

    Accessing Particles

    Lets stay with emitters for a while. As you certainly know,

    RealFlow is a particle based software. Each emitter type

    spills out a number of particles, dependent on the Resolu-

    tionparameter. Through Python you have direct access oneach individual particle. But how is it possible to read out

    values, like Velocity or Position for a single particle?

    The basic idea is to gather all existent particles and loop

    through this amount. Fortunately RealFlow knows various

    methods to detect the total number of particles and

    provides direct access.

    A very common construction is to look for the first particle

    and then go through the total amount. As long as therere

    particles in the scene, the loop will be executed:

    fluid = scene.getEmitter("Circle01")

    particle = fluid.getFirstParticle()

    while (particle):

    do something here

    particle = particle.getNextParticle()

    Whats happening here? First you have to identify the

    emitter Circle01. The statement fluid.getFirstParticle( )

    means: Search for the first particle emitted from fluid,

    actually from Circle01.

    Now, the script starts looping through all existent parti-

    cles. With this method its possible to get information

    from each particle in your scene. While the loop is

    executed, youre able to perform calculations or check and

    compare values.

    To seize the next particle, the script replaces the current

    particle Variable with the ID of following particle. The

    keyword for this action is getNextParticle( ).

    In some cases its recommended to skip particles for

    speeding up a simulation or for testing purposes.

    On page 9 I was talking about the Modulus Operator %.

    This is exactly what youll need for this purpose. With this

    example Im also introducing a new principle - the if

    clause. Youll learn more about this later (see p. 27).

    The operation you have to perform is the following:

    skip = 5

    counter = 0

    fluid = scene.getEmitter("Circle01")

    particle = fluid.getFirstParticle()

    while (particle):

    counter = counter + 1

    if (counter % skip== 0):

    do something here

    particle = particle.getNextParticle()

    In this example the script counts the total number ofparticles. With each particle the counter Variable will be

    increased by 1. Theres also a short form available (please

    see page 11) :

    counter += 1

    The result is exactly the same value you can see under

    Node Params > Statistics > Emitted Particles

    The Modulus Operator%tells you, whether the operationproduces a remainder or not. Only if theres no remainder

    (in this case the result is exactly 0) the instructions below

    the ifstatement will be executed. This means that the

    script skips four particles, because with the fifth particle

    the condition is true. The higher the skip value, the more

    particles will be missed out. With a skip value of 1, the

    condition is always true and all particles will be included.

    Besides the while method, RealFlow also knows the

    for ... inand thefor ... in rangeloop. The first one is also

    often used with particles and additionally with largenumbers of objects. Amongst others,for ... inallows you to

    change object properties simultaneously.

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    25/67

    RF_magazine 24

    Scripting with RealFlow02_2007

    Thefor ... inloop is often used with a defined number of

    particles. You have to collect the wanted data first, and

    then go through them one by one. Especially when its

    necessary to gather colliding particles for foam genera-

    tion, thefor ... inmethod is applied.

    fluid = scene.getEmitter("Circle01")

    collided_particles= fluid.getParticlesColliding()

    for particle in collided_particles:

    do something here

    As you can see from the code, you have to store the

    desired particles in the Variable collided_particles.

    RealFlow identifies those particles with getParticlesCollid-

    ing. After the particles have been stored, the script can

    read out the Variable, calling each particle individually.

    With lots of particles, this method may become very RAMconsuming, because RealFlow makes a copy of the particle

    set with all its values and settings.

    This statement could also be read as: Perform a given

    calculation for each particle from the collided_particleset.

    Thefor ... inrange method works similar to thefor ... in

    loop. The main difference is that you can define a stop

    value for the loop. Lets say, you have a group of six

    spheres, but the operation should only affect the first

    three objects.

    spheres = [S0,S1,S2,S3,S4,S5]

    no_of_spheres= len(spheres)

    stop = no_of_spheres/ 2

    start = 0

    step = 1

    for object in range(start, stop, step):

    current_sphere= spheres[object]

    do something here

    Whooo! Whats going on here? Well, nothing special. I just

    used another Data Type. Do you remember Lists? If not,

    then please have a look at page 7 and 8 again. But dont

    worry, because everythings explained here, too. The first

    expression is a List, containing six entries - the spheres.

    The Variables in this List are named S0- S5. Since Lists

    always start with 0, its better to adopt your names to this

    circumstance and avoid trouble. The spheres in the Nodes

    panel must wear exactly the same name.

    You only want the first three objects to be affected, so youhave to find a stop value. To get the total number of List

    entries, its necessary to determine the length. This value

    is stored in no_of_spheres. The List carries six entries and

    we need three spheres. So the stop value is:

    6 / 2 = 3

    Of course you simply could write stop = 3, but here I

    wanted to illustrate how to deal with Lists and their

    entries. And in some cases it might be useful to get start

    or stop values directly from a List.

    To read out the current_sphere, youre using the current

    value of the loop as a reference on the List containing the

    spheres:

    current_sphere= spheres[object]

    Since were starting with start = 0, in our example wed

    get these expressions (actually we cant see this term, but

    this is the way it looks like internally):

    current_sphere= spheres[0] ( S0)

    current_sphere= spheres[1] ( S1)

    current_sphere= spheres[2] ( S2)

    After youve stored the sphere in a Variable, youll be able

    to perform calculations. With current_sphere= spheres[3],

    the loop ends. Id suggest to make a few tests with this

    method to get a better understanding.

    The step value indicates an increment. So with each

    step the loop adds 1 to the current_sphere Variable.

    The increment hasnt got to be 1 necessarily. Other Integer

    values are also allowed, but with different steps, you

    might have to change the stop value!

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    26/67

    RF_magazine 25

    Scripting with RealFlow02_2007

    The List expression shows the names of all objects. On

    page 8, I explained that names have to written between

    quotation marks. In this case, the entries of spheres serve

    as Variables, used by RealFlow to identify the objects in the

    Nodes window. In RealFlow, quotation marks with Lists are

    a rarely used.

    spheres= [S0,S1,S2,S3,S4,S5]

    This notation would cause a Syntax error:

    spheres= ["S0","S1","S2","S3","S4","S5"]

    The creation of loops is a crucial task, used with almost

    any Events or Custom Script (e.g. Daemon or RealWave).

    Even Batch Scriptsoften show loops, especially in conjunc-

    tion with Lists.

    Building Vectors

    Vectors are one of the most important Data Typeswithin

    RealFlow. Theres already been a detailed introduction on

    page 13 et. seqq. Here, youll learn how to use Vectors in a

    script and how to extract a Vectors components.

    All RealFlow calculations are done in 3D space. The posi-

    tions of a particle, emitter or object can be described with

    their x, y, and z coordinates. Starting at the origin of a

    scenes coordinate system, these three values can be

    considered as an address, where you can find the object.

    So itd be possible to draw an arrow from the origin to the

    objects position. This arrow is the graphical representa-tion of a Vector. But not only positions can be written as

    Vectors. This is also possible for forces or velocities.

    The mathematical representation of a Vector is:

    a = (x, y, z)

    In RealFlow its possible to determine Vectors simply by

    writing a series of three values to a Variable. The complete

    Python statement for initializing a new Vector is:

    my_first_vector = Vector.new(x, y, z)

    In RealFlow its often required to extract the x, y, zvalues or further calculations, sometimes you may also

    just need the y or z component of a Vector. The elements

    of a Vector are called Scalars:

    position = (1.0, 3.3, 2.7)

    Now we want to calculate new y and z positions for a

    single particle. But how could this be realised? Theres got

    to be a way to split the Vector into its elements. Indeed,

    RealFlow knows such a method:

    position_x = position.getX()

    position_y = position.getY()

    position_z = position.getZ()

    Fig. 11: Velocity vectors in RealFlow

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    27/67

    RF_magazine 26

    Scripting with RealFlow02_2007

    In most cases youll deconstruct a Vector, perform a

    calculation, and then build a new Vector using the fresh

    values. The process for performing this operation is finally

    always the same. Similar to the loop methods, you just

    have to remember a few fixed steps:

    Events Script: ParticleNewPos.rfsfluid = scene.getEmitter("Circle01")

    particle = fluid.getFirstParticle()

    while (particle):

    # 1. Get global position data in Vector format

    pos_g= particle.getPosition()

    # 2. Get components from the position Vector

    pos_x= pos_g.getX()

    pos_y = pos_g.getY()

    pos_z = pos_g.getZ()

    # 3. Calculate the new coordinates individually

    new_pos_y = pos_y + 0.01

    new_pos_z = pos_z + 0.01

    # 4. Build a new Vector

    new_pos_g= Vector.new(pos_x, new_pos_y, new_pos_z)

    # 5. Use the new Vector for position change

    particle.setPosition(new_pos_g)

    particle = particle.getNextParticle()

    This is already a complete script. To show you whats

    happening here, I want to deconstruct this little proggie.

    The first part uses a well known method to loop through

    the emitters (Circle01) particles.

    The first step is to get vectorized value, in this case the

    script reads out the global position Vector and stores it in

    the pos_g Variable.

    In a second step, the script disassembles the x, y, and z

    components from the pos_g Vector.

    The task in this program is to alter only the y and z values,

    while the x component remains untouched. The new

    position values have to be calculated individually as well,

    and theyre based upon the old pos_y and pos_z values.

    The new_pos_y, new_pos_z, and the unchanged pos_x

    values provide a basis for the new global position vector.

    The Vector.new statement puts everything together.

    Of course this Vector has to be stored again in a Variable

    (new_pos_g) for further use.

    The last steps assigns the new_pos_g Vector to the

    particles using a setPositioninstruction. Youll learn more

    about theget and set functions later. Here, just put up

    with the fact that these instructions are responsible forgetting and setting positions.

    The last line of the script simply calls the next particle.

    The representation in RealFlow isnt very spectacular, but

    the script implements most of the principles, introduced

    so far.

    Fig. 12: The result from the Events Script ParticleNewPos.rfs

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    28/67

    RF_magazine 27

    Scripting with RealFlow02_2007

    If & Else

    When youre writing a script, its often required to set

    certain conditions or alternative ways. Differentiations can

    be achieved with if and else statements. The Syntax of this

    function is rather simple and well known from your dailylife: Im sure you love new and fast computers, but money

    is always the obstacle for buying the latest killer machine.

    You have to calculate to get the maximum out of the

    available money. This example is well suited for an if-else

    construction:

    available_money= 2500

    computer_price = 3200

    if (available_money< computer_price):

    cant buy computer

    else:

    go to computer store

    In this case, the amount of available_money is less than

    computer price. The condition for this example is true, and

    youre not able to buy the new computer. But Variables

    can change over time and some new decisions can be

    made:

    available_money= 2500

    computer_price = 3200

    grannies_gift = 750

    if (available_money + grannies_gift < computer_price):

    cant buy computer

    else:

    go to computer store

    Here, Granny saved your day, because 2500 + 750 = 3250.

    As you can see, comparisons are not only limited to oneVariable, its also possible to perform calculations within

    the if clause.

    Another, equivalent notation would be:

    total_money= availabe_money + grannies_gift

    if (total_money < computer_price):

    cant buy computer

    else:

    go to computer store

    You could also reverse the comparison:

    if (total_money >= computer_price):

    go to computer store

    else

    cant buy computer

    As you can see from this example, if-elseconditions are

    mostly connected with comparisons. There are also ways

    to compare more than one value:

    ram = 200

    my_money = 250

    birthday_gift = 210

    if (my_money >= ram or birthday_gift >= ram):

    set max_particles to 50,000,000

    else:

    set_max_particles to 100,000

    Its also possible to use an and statement. This is often

    needed for setting a certain limit:

    ram= 200

    gpu = 350

    if (ram

  • 8/13/2019 RF Magazine 0207

    29/67

    RF_magazine 28

    Scripting with RealFlow02_2007

    Another effective method for multiple queries is the elif

    statement. The elif expression is an abbreviation and

    stands for else if. You can use (almost) as many elif state-

    ments as you want to:

    if mandatory onceelif optional mutliple

    else optional once

    This time you want to sell your old computer. The decision

    chain could be like this:

    offer = 475

    retail_price= 500

    min_price = 400

    if (offer >= retail_price):

    sell computer immediatly

    elif (offer >= min_price and offer < retail_price):

    contact customer for further negotation

    else:

    dont sell computer

    In this case, the customer will be contacted, because offer,

    lies between retail_price and min_price. elif statements

    mostly need a second criteria to complete a decision.Have a look at this example:

    offer = 520

    retail_price = 500

    min_price = 400

    if (offer >= retail_price):

    sell computer immediatly

    elif (offer >= min_price):

    contact customer for further negotiation

    else:

    dont sell computer

    The result from this example is ambiguous. The first

    criteria is fulfilled, since 520 is greater than 500, but the

    second condition is also true, because 520 is greater than

    400, too. To avoid such an inconsistency, you have to

    introduce a second requirement, like in the first example

    on the left.

    In Python (and all other programming languages) its

    allowed to construct convoluted if-else-conditions:

    offer = 540

    retail_price = 500

    zip = 90482

    if (offer >= retail_price):

    if (location == zip):

    shipping_cost = 10

    else:

    shipping_cost = 25

    else:

    dont sell computer

    With nested if-else constructions, its possible to assign

    case dependent values to a Variable. Having a look at the

    example above, youll recognize that the computer has

    been sold (offer is greater than retail_price). The secondclause is used to determine, whether the customer is

    located in your hometown or not. The shipping_cost value

    directly depends on the customers location.

    Your First Steps

  • 8/13/2019 RF Magazine 0207

    30/67

    RF_magazine 29

    Scripting with RealFlow02_2007

    Introduction

    You already know the basics of Python scripting in

    RealFlow. Youre able to loop through an emitters parti-

    cles, youve heard about building Vectors and else-if

    clauses. The coming chapter is about getting and settingvalues directly from RealFlow. This is the quasi-core of

    RealFlows Python extension. With theget and set state-

    ments, you have direct access to all properties of an

    emitter, object, daemon etc.

    The variety ofget and set statements seems to be endless.

    So its necessary to sort the instructions, to keep an

    overview. In this issue, were dealing with the most

    common get and set directives. RealFlow also provides

    commands for getting and setting vertices, polygon faces,

    animation keys, image pixels and more.

    Youve already met a few statements:

    getEmitter( )

    getPosition( )

    getFirstParticle( )

    getNextParticle( )

    These instructions had been used to find a scene emitter,

    to have access to individual particles or make use of a

    particles Vector position data. With differentget instruc-tions, youll receive different values and results,

    e.g. Integers, Vectors, Floats and Strings.

    The online manual shows a rather long index of different

    get and set commands. These commands are written in a

    particular format, like:

    Emitter getEmitter( string )

    Object getObject( string )

    The first word describes the allowed object type, likeemitter, object (primitive), camera, mesh and so on. The

    second part is the specificget command, available for

    many parameters and RealFlow objects. The next expres-

    sion determines the Data Typeyou have to use with this

    particular instruction. The Data Typealso specifies, how

    the argument will be treated:

    Particle getParticle( int )

    This operation can only be used with particles and the

    input value has to be an Integer. Using it with a daemon

    and a string, like Gravity01, would cause an error.

    The manual sometimes gives more hints:

    Emitter [ ] getEmitters( )

    The brackets [ ]tell you that the resulting Data Typewill be

    a List. Do you remember? With a Scalar its only possible tostore one value, while Lists can carry two or more entries.

    All descriptions of the available commands are working

    the same way, as the examples above. With a little experi-

    ence, youll be able to forecast the used object and Data

    Type, but if youre not sure, you can always refer to the

    manual:

    Help > Contents... (opens a new application) > Index

    Help > Contents... > Contents > Scripting Reference

    The second source contains a more structured compila-

    tion, sorted by object types.

    How to Use Get & Set

    The concept behind theget and set statements is simple,

    but very clever, because its directly connected to

    RealFlows user interface. The commands share exactly

    the same names you can see in the Nodes and Node

    Params windows. The main difference is the number andtype of arguments, aget or set command needs. The

    commands are not limited to loops, they can be used

    anywhere.

    Changing Attributes with Get & Set

  • 8/13/2019 RF Magazine 0207

    31/67

    RF_magazine 30

    Scripting with RealFlow02_2007

    In this example, a Cone had been added to the scene.

    The parameter rollout above contains everything you need

    to access the objects properties. The most interestingparameters are certainly located within the Node tab. Here

    you can find basic attributes, like Position, Rotation or

    Scale.

    The online help describes the correspondingget

    commands as follows:

    any getParameter( any )

    This notation tells us that we can use any object or Data

    Typewith thegetParameter command. This operation isnot limited to primitives, emitters or cameras. Also the

    arguments can be an Integer, Float, Vector etc.

    The Data Typeyou receive with thegetParameter

    command can also be read out from the Node tab. When-

    ever you see a triplet of values, the result will be a Vector:

    Position 0.0 0.0 0.0

    Rotation 0.0 0.0 0.0Scale 1.0 1.0 1.0

    Pivot 0.0 0.0 0.0

    Please note: The individual values of the Vector are Floats.

    Even Color is represented by three values for red, green

    and blue (RGB). The Data Typesfor Simulation and Dynam-

    ics are Strings. The fields can contain words or expressions:

    Simulation Active

    Dynamics No

    If WetDry Texturewas set to Yes, wed also have some

    Integer values, like

    @ resolution 256

    The values for @ filter strengthand@ ageingare Float

    types again.

    As already mentioned, its crucial to know, which Data

    Typeaget command spits out, because in the reverse

    process with setParameter, you need exactly the sameData Typeagain to alter the appropriate value. Let me

    show you an example:

    cone = scene.getObject("Cone01")

    pos_global = cone.getParameter("Position")

    The result is a Vector, consisting of three Floats. After a

    calculation has been finished, you can build a new Vector.

    This new Vector must carry three Floats (Integers are

    allowed, too) again. You cant replace the Floats with

    Strings. This would cause a Syntax error:

    pos_new = Vector.new("left", "up", "right")

    Changing Attributes with Get & Set

  • 8/13/2019 RF Magazine 0207

    32/67

    RF_magazine 31

    Scripting with RealFlow02_2007

    The next example is a complete script, ready to use within

    RealFlow. The program adds a value of 0.2 to the y position

    of a Cone with each new frame:

    Events Script: ChangeConeYPos.rfs

    def onSimulationFrame():

    cone = scene.getObject("Cone01")

    # 1. Get global position data in Vector format

    pos_g = cone.getParameter("Position")

    # 2. Get components from the position Vector

    pos_x= pos_g.getX()

    pos_y = pos_g.getY()

    pos_z = pos_g.getZ()

    # 3. Add 0.2 to the y component

    new_pos_y = pos_y + 0.2

    # 4. Build a new Vector

    new_pos_g= Vector.new(pos_x, new_pos_y, pos_z)

    # 5. Use the new Vector for position change

    cone.setParameter("Position", new_pos_g)

    This script is very similar to the Events Scripton page 26

    (ParticleNewPos.rfs). There, the script adds values to the y

    and z positions of all particles. Here, were just using a

    single object. The process of getting, splitting and assem-

    bling the Vectorsis finally the same. The main difference

    lies in the last statement:

    cone.setParameter("Position", new_pos_g)

    With the particle method, its just

    particle.setPosition(new_pos_g)

    Particles dont use the sameget and set commands as

    physical objects in RealFlow. For an emitter or a mesh, its

    possible to see values directly in the corresponding Node

    Paramswindow. Position or Velocity values arent

    displayed at all. Theyll be used internally. For faster access

    and better distinction, the particle attributes dont use theParameter keyword.

    And theres another difference: ThegetParameter

    command only takes one argument, named Position. The

    setParameter shows Position and new_pos_g. So, with

    setParameteryou have to tell RealFlow which type of

    parameter you want to change (Position, Pivot, Rough-

    ness...) and the new value using the correct Data Type.

    The changing values can be monitored in the Node Params

    window during the simulation. Just give it a try and watchthe y component of the Position value.

    Tip

    Dont copy and paste scripts to from the original source toRealFlow. Different fonts, character sets and spaces or

    blanks will cause errors almost any time. Its better to type

    scripts manually and think about whats happening.

    Fig. 13: The Cone performs a constant movement in y direction

    Changing Attributes with Get & Set

  • 8/13/2019 RF Magazine 0207

    33/67

    RF_magazine 32

    Scripting with RealFlow02_2007

    WithgetParameter and setParameteryou can have lots of

    fun, since you can alter, change or turn off and on almost

    everything. Some tasks could also be solved manually and

    with easy means, but scripting is much more accurate.

    Especially with collisions its sometimes not easy to get

    exactly the moment of the first interaction between twoobjects or particles. With a Python script, the solution is

    just a few lines of code away. This is the initial situation:

    Our goal is to deactivate the objects, after theyve hit thefloor. All items have different positions. Deactivating them

    manually could be an ungrateful job. This scene just uses

    three objects, but imagine 20, 30 or 60 items.

    According to the methods you have seen so far, we always

    called objects individually, but with more than three items,

    this could get rather annoying. To ease this task, RealFlow

    provides mighty tools for object selection. The operation,

    Im going to use here is named:

    getSelectedNodes()

    With this command, you just select the objects you want

    to be affected by the script from the Nodes window.

    RealFlow recognizes your selection and stores all items in a

    List object. So the correct expression is:

    items = scene.getSelectedNodes()

    Just for remembrance: With a selection of the threeobjects Cone, Cubeand Cylinder, the entries of items

    would be internally:

    items = [Cone,Cube,Cylinder]

    The next step is to collect all objects, colliding with the

    Floor item. RealFlow also knows a function for this

    purpose. The Data Typecreated with this command is

    again a List, because theres more than one object to

    collide with Floor:

    floor = scene.getObject("Floor")

    colliding_objects = floor.getCollidingObjects()

    Now we have to browse through the list of collided objects

    and deactivate the appropriate primitive:

    if (colliding_objects != []):

    for object in colliding_objects:

    object.setParameter("Simulation","Inactive")

    The if condition checks, whether the List colliding_objectsis empty or not. The expression

    if (colliding_objects!= []):

    means: If the List colliding_objects is not (!= ) empty, then

    do something. An empty List is written as [ ]. Another idea

    is to check the length of the List.

    If a collided object has been detected and written to

    colliding_objects, the Simulation parameter will be set to

    Inactive. In other words: As soon as an object hits the floorcompletely, itll be set to Inactive and the enclosed fluid

    can be released. On the next page youll find the listing for

    this script.

    Changing Attributes with Get & Set

  • 8/13/2019 RF Magazine 0207

    34/67

    RF_magazine 33

    Scripting with RealFlow02_2007

    Events Script: InactiveOnCollision.rfs

    def onSimulationBegin():

    items = scene.getSelectedNodes()

    for object in items:

    object.setParameter("Simulation", "Active")

    object.setParameter("Dynamics", "Rigid body")

    def onSimulationStep():

    items = scene.getSelectedNodes()

    floor = scene.getObject("Floor")

    colliding_objects = floor.getCollidingObjects()

    if ( colliding_objects != [] ):

    for object in colliding_objects:

    state = object.getParameter("Simulation")

    if (state == "Inactive"):

    pass

    else:

    object.setParameter("Simulation", "Inactive")

    object.setParameter("Dynamics", "No")

    The first function initializes the selected items and makes

    them active. This is useful in case of starting multiple

    simulation passes, because you dont have to switch back

    each time you want to simulate the scene.

    This program identifies all objects colliding with the floor

    item and writes them to a List Variable:

    colliding_objects = floor.getCollidingObjects()

    The last if clause is just a little construction for checking,whether the Simulation state has been changed. So if the

    Simulation state is already set to Inactive, then the script


Recommended