With rigid body dynamics, it is often necessary to slightly change physical properties of an object. Good examples are random differences in mass or elasticity. Though the variations are sometimes very subtle it is a good idea to think about this possibility, because it adds some extra realism to a simulation. Changing the properties for a few dozens or even hundreds of nodes is not a fun job. Doing it once is already a hassle, but what if you have to present several simulations with different values? Here a script is the only solution!
Name | ChangeRBDMass.rfs |
---|---|
Type | Batch script |
Description | This program automatically activates the rigid body property for a custom selection of nodes and randomly changes the "@ mass" parameter. |
What the script should do:
- Detect the user’s selection from the Nodes window and loop through the objects
- Activate rigid body dynamics for all objects or skip this process if it is already turned on
- Access the “@ mass” parameter, read it out and create a random percentage variation
- Insert the calculated value
- Write out a message when the process is finished, together with the elapsed time
The user selection is an easy, but powerful way to limit the execution of the script to certain nodes. As shown previously, RealFlow’s Python engine can recognise an instruction to detect such a selection and store it within a list:
userSelection = scene.getSelectedNodes()
Now it is easy to loop through the individual elements of userSelection. A simple for … in loop will do the job. The process of checking whether rigid body dynamics is already activated or not should not be difficult, as it is simply an if-condition. In case an object is already an active rigid body, the script will change its mass. So the body of the script could look like this:
userSelection = scene.getSelectedNodes() for node in userSelection: rbdState = node.getParameter("Dynamics") if (rbdState != "Active rigid body"): node.setParameter("Dynamics", "Active rigid body") currentMass = node.getParameter("@ mass")
The core function of this script is to apply a certain amount of randomness. This value should be within a given range based on the original “@ mass” setting, e.g. vary the current mass within 10% of the current value. Let’s say the initial mass is 100 for each object. This means that the new mass should be somewhere between 95 and 105. The statement for this operation uses the random module and actually the code should already look familiar to you:
import random percentVariation = 10 rangeMass = (currentMass / 100) * (percentVariation / 2) randomValue = random.uniform(-range, range) newMass = currentMass + randomValue
The last action is to print out a little message together with the time the script needed for applying the new mass value. Since this little program is a batch script it is not possible to use RealFlow’s simulation time. The scene.getCurrentTime()
statements has no effect here, but fortunately Python provides a module called “time”. This module comes with Python’s standard distribution and should be installed by default. To access the specific clock()
function a new notation is required:
from time import *
Here you can see a different notation for the "import" command. If you would like to learn more about advanced techniques to load modules, we suggest that you do some research online. The clock()
function from this module simply measures and stores the current time during function call. Keeping this in mind it is easy to create a time difference:
from time import * startTime = clock() ... go through the selected nodes and calculate the new mass values here stopTime = clock() diffTime = stopTime - startTime scene.message("Elapsed time: "+str(diffTime)+" seconds")
The final message should also print out a little note that the process is finished. To make everything more appealing, a formatting operator is introduced:
scene.message("\nProcess finished...\nElapsed time: "+str(diffTime)+" seconds")
The "\n" operator introduces a new line, called “escape sequence”. As you can see it is not necessary to include any separators, because Python automatically recognizes these sequences and translates them.
So the entire script looks like this:
from time import * import random startTime = clock() percentVariation = 10 userSelection = scene.getSelectedNodes() for node in userSelection: rbdState = node.getParameter("Dynamics") if (rbdState != "Active rigid body"): node.setParameter("Dynamics", "Active rigid body") currentMass = node.getParameter("@ mass") rangeMass = (currentMass / 100) * (percentVariation / 2) randomValue = random.uniform(-rangeMass, rangeMass) newMass = currentMass + randomValue node.setParameter("@ mass", newMass) endTime = clock() diffTime = endTime - startTime scene.message("\nProcess finished...\nElapsed time: "+str(diffTime)+" seconds")
You can extend this script to perform more than one parameter change or add a nice little GUI. With ChangeRBDMass.rfs, a simulation looks much better, because the different masses cause “instabilities”, forcing the bodies to act in a different way and the result looks moch more vivid. The example below shows a fixed mass of 1,000, the second uses a “percentVariation” value of 25.