Realflow C++ SDK Users Manual
Realflow C++ SDK Users Manual
0
1 introduction 8 Building your own Plugin
Introduction Pag. 3 8.01 Copying From Example Pag. 18
8.02 Change Name project & source file Pag. 19
8.03 Creating your own plugin class Pag. 19
2 Relationship with the Python SDK 8.04 Change behavior Pag. 19
Relationship with the Python SDK Pag. 4 8.05 Target Configuration Pag. 23
8.06 Compiling & Linking Pag. 23
8.07 Deploying Pag. 23
3 Limitations 8.08 Testing the Plug-in Pag. 23
Limitations Pag. 5
1 Introduction
C++ SDK is the new programming interface in RealFlow. In version 4.0. our users could
enjoy using the Python language to develop scripts to be run inside RealFlow. This new
SDK brings all the functionality of the Python interface combined with the speed of the
C++ language to deliver a powerful environment that allows the development of really
fast plug-ins. Plug-ins that would run at almost the same speed as their counterparts in
RealFlow.
The Python SDK has been improved to allow more access to the RealFlow Engine. And the
C++ counterpart has the same functionality, though much faster.
• Python uses a List object. whereas the C++ SDK uses a std::vector Object.
• Some methods in Python return a variable (that could be of several different types) -
the C++ SDK has to return a wrapper class that encapsulates the different types that
can be returned.
3 Limitations
Although you can do a lot of different tasks with the SDK, you can’t do everything and
there are limits it is worth knowing about. There are places where you can’t perform
certain operations, or where it’s unwise to do so. Although not exhaustive, the main SDK
limits are listed below:
• Within an event, realwave, daemon or fluid plug-in, you cannot create or load a new
scene, jump to other frames, or simulate individual or ranges of time substeps or
frames. These can only be done within a batch plug-in script.The reasons for this
should be obvious, since jumping to an entirely new scene in mid-simulation doesn’t
make a lot of sense and is likely to confuse both you and your workstation.
• There are a variety of parameters that you cannot set via plug-ins, such as preferences,
fps and adaptive stepping settings. Most of these are not very important to getting
results, and the ones that are related to simulations (e.g., adaptive steps) are not
accessible on purpose, to avoid confusing the solver.
• For those plug-ins that allow multithreaded execution beware that only a fraction of
the methods are thread-safe. These are marked in the documentation. The rest of the
methods may cause instability or incorrect behavior in your program.
As the SDK opens up a lot of the internals of the engine, that allows the development of
instability in the system by the added code, leading to the possibility of crashes related to
bugs in the C++ code developed by the user.
The RealFlow team has tried to prevent as many crashes as possible. We have tried hard
to catch errors produced in the plug-in code, and instead of crashing the whole application
just inform the user that an error occurred. But this is not possible in all the cases. So we
recommend that plug-in developers complete thorough testing of their plug-ins before
releasing them to the general public.
4 IntroductiontothedifferentPlug-ins
The way of enhancing RealFlow with the C++ SDK is by means of plug-ins. A plug-in can
represent different objects in RealFlow. For instance you could develop a new Daemon
plug-in to remove particles that match certain conditions, such as: velocity higher than a
certain number, pressure in certain range and so on. This new Daemon will then appears
in the menu of daemons. You just have to select it and add it to the scene. It will behave
the same way as any other Daemon. You can add any number of these new daemons to
the scene.
• Daemon plug-in
• Object plug-in
• ParticleSolver plug-in
• Wave plug-in
• Command plug-in / Event plug-in
Daemon plug-in
When you program a new daemon plug-in you must specialize a base class where you
will implement your desired behavior. With a daemon plug-in you can apply forces to
the different dynamic entities in RealFlow; you can also remove particles in the case of
particle-based fluids and even set a velocity field for a mist.
Wave plug-in
In a similar fashion to the Daemon plug-ins you can write the body of some methods
in the Wave Plug-in class. In this plug-in there is only one method, which allows you to
calculate the 3D displacement of all the points of the RealWave mesh respective of their
initial positions.
Object plug-in
You can define your own object with your own properties. For version 5 of RealFlow the
functionality of this plug-in is very limited; for instance you can’t create geometry for your
own object just set and get properties. In future versions of RealFlow the capabilities of
this plug-in will be increased.
Command plug-in
As its name states this is used to execute a general set of instructions in the same way
as as a Python script does. It has just one method (run) that will be called whenever the
command is executed.
Event plug-in
This is similar in nature to the Command Plug-in. It is intended to be added as a set of
codes to be executed at precise times in the simulation pipeline. You can add this type of
plug-in to the new Simulation Events window. This window replaces the old Events Script
window.
5 Plug-in Types
Let’s have a brief description of the methods that the developer needs to implement when
creating a new Plug-in.
// getNameId
virtual std::string getNameId() const = 0;
Name that identifies this plug-in. It is recommended to choose a name that will not likely
clash with other plug-ins. For instance you could name your own Graviton daemon like
“MyCompany_Graviton” where MyCompany stands for the name of your company.
// getClassId
virtual int getClassId() const = 0;
This is a unique worldwide ID for your plug-in. Using the tool provided with RealFlow you
will generate a unique worldwide number for your plug-in. And this method should return
that number.
This should return a line with information about the copyright holder of this plug-in. This
information will be shown in the User Plug-ins manager window.
This should return a line with a long description of what this plug-in does. Emitter::iterator iter )
{
// Get plug-in short description applyForceToEmitter( plgThis, emitter, 0, iter );
virtual std::string getShortDescription() const = 0; }
Single-Threaded version. It is called by the simulation engine when external forces should
This should return a line with a short description of what this plug-in does. This will appear be applied to the particles in the particle-based emitter. For you convenience you get an
in the User Plug-ins manager window. iterator that helps you to iterate over all the particles of the emitter.
// Is multithreading //--------------------------------------------------
virtual bool isMT( void ) const { return NL_true; }; // Function: applyForceToEmitter
// This function is called by the simulation engine
This tells the RealFlow engine that this Plug-in is multithreading. That means that RealFlow // when external forces should be applied to the
will call the right method for those methods that have a dual implementation, like single- // particles in the emitter.
threading and multi-threading. If isMT returns false then the single-thread version will be // It is only used if the plug-in is declared
called. By default all plug-ins are considered multi-threaded. // MultiThreading through
// the isMT method.
//--------------------------------------------------
virtual void applyForceToEmitter
5.02 Daemon ( Daemon* thisPlg, PB_Emitter* emitter, int nThread,
PB_Emitter::iterator iter ) =
0;
/// applyForceToEmitter:
/// This is the Multi-Threaded version of the above method. This method gets called by the
/// This function is called by the simulation engine when simulation engine when is the time to compute the external forces that this Daemon may
/// external want to apply to the particles in the given Emitter. In a similar way to the Daemon plug-in
/// forces should be applied to the the RealFlow engine creates by default a partition in n subsets of particles associated to
/// particles in the emitter. the given Emitter. N also represents the number of threads that will be used to compute
/// the forces. So this method will get called n times to produce a complete calculation. Each
/// @param [in/out] plgThis / Sdk Daemon ( Owner of this of these calls will get a number identifying which of the n threads is being used in the
/// Daemon call of the method. This is given in the nThread parameter. The method will also get the
/// Plug-in ) default partition associated to that thread as an iterator over that partition.
/// @param [in/out] emitter / Sdk Emitter which particles
/// will be //--------------------------------------------------
/// affected by external /// // Function: applyForceToBody
/// forces // This function is called by the simulation engine
/// @param [in] iter / Iterator over the Emitter´s Particles // when external forces should be applied to the body.
// //--------------------------------------------------
virtual void applyForceToEmitter virtual void applyForceToBody( Daemon* thisPlg, Object* obj
( Daemon* thisPlg, PB_Emitter* emitter, PB_
);
This is called by the simulation engine when external forces should be applied to a grid-
This is called by the simulation engine when external forces should be applied to a Body. based Fluid. It does nothing by default.
It does nothing by default.
//-------------------------------------------------- //--------------------------------------------------
// Function: applyForceToMultiBody // Function: onSimulationBegin
// This function is called by the simulation engine // This function is called by the simulation engine
// when external forces should be applied to the body. // when the simulation begins.
//-------------------------------------------------- //--------------------------------------------------
virtual void applyForceToMultiBody( virtual void onSimulationBegin( nl::rf_sdk::Daemon* plgThis
nl::rf_sdk::Daemon* plgThis, );
nl::rf_sdk::MultiBody* obj
); This is called by the simulation engine when the simulation begins. It does nothing by
This is called by the simulation engine when external forces should be applied to a default.
MultiBody. It does nothing by default.
//--------------------------------------------------
//-------------------------------------------------- // Function: onSimulationResume
// Function: applyForceToMist // This function is called by the simulation engine
// This function is called by the simulation engine // when the simulation resumes.
// when external forces should be applied to the mist. //--------------------------------------------------
//-------------------------------------------------- virtual void onSimulationResume( nl::rf_sdk::Daemon* plgThis
virtual void applyForceToMist( nl::rf_sdk::Daemon* plgThis, );
nl::rf_sdk::Mist* obj
); This is called by the simulation engine when the simulation resumes. It does nothing by
default.
This is called by the simulation engine when external forces should be applied to a Mist.
It does nothing by default. //--------------------------------------------------
// Function: onSimulationStop
//-------------------------------------------------- // This function is called by the simulation engine
// Function: applyForceToGridFluid // when the simulation stops.
// This function is called by the simulation engine //--------------------------------------------------
// when external forces should be applied to the grid fluid. virtual void onSimulationStop( nl::rf_sdk::Daemon* plgThis
//--------------------------------------------------
virtual void applyForceToGridFluid(
nl::rf_sdk::Daemon* plgThis,
nl::rf_sdk::GridDomain* obj );
);
5.04 Particle Solver
This is called by the simulation engine when the simulation stops. It does nothing by
default. // preComputeInternalForces
void preComputeInternalForces(
//-------------------------------------------------- rf_sdk::ParticleSolver* particleSolver,
// Function: onSimulationFrame rf_sdk::Emitter* emitter )
This function is called by the simulation engine
// when the simulation starts the computation of This method gets called in a single-threaded way by the simulation engine before calling the
// the next frame. multi-threaded method computeInternalForces. It simplifies the preparation calculations
//-------------------------------------------------- that may be needed to compute the internal forces - calculations that all threads need to
virtual void onSimulationFrame( nl::rf_sdk::Daemon* plgThis, have to compute the forces.
const unsigned int& frame );
// computeInternalForces
This is called by the simulation engine when the simulation of a frame starts. It does virtual void computeInternalForces(
nothing by default. rf_sdk::ParticleSolver* particleSolver,
rf_sdk::Emitter* emitter,
//-------------------------------------------------- int nThread,
// Function: removeParticles RFEmitter_It iter )
// This function is called by the simulation engine
// when it is safe to remove particles. This method gets called by the simulation engine when it is time to compute the
//-------------------------------------------------- ParticleSolver fluid internal forces. In a similar way to Daemon plug-in, the RealFlow
virtual void removeParticles(Daemon* plgThis, engine creates by default a partition in n subsets of particles associated to the given
PB_Emitter* obj ) = 0; Emitter. N also represents the number of threads that will be used to compute the internal
forces. So this method will get called n times to produce a complete calculation over all
It is called by the simulation engine when it is safe to remove particles for a particle-based the subsets of particles. Each of these calls will get the number of thread associated as
fluid. The user may leave this method blank if he has no need to delete particles. the nThread parameter. The method will also get the default partition associated to that
thread as an iterator over the partition.
// integrate
5.03 Object virtual void integrate(
rf_sdk::ParticleSolver* particleSolver,
rf_sdk::Emitter* emitter,
This Plug-in class has no methods defined at the moment. In future version of RealFlow int nThread,
we will add more functionality to this plug-in type. For the moment it just can be used to RFEmitter_It iter,
get and set properties. float dt )
This method gets called by the simulation engine when the final position of the particles
must be calculated - the integration time dt that RealFlow is using is passed to the function.
The same considerations about the way of calculation and use of partitions that have been
5.07 Events
explained in the above method can be directly applied to this calculation.
virtual void run ();
// getIntegrationTime
virtual float getIntegrationTime( The plug-ins that are used to create a command in the GUI user interface are the same
rf_sdk::ParticleSolver* particleSolver) that can be used to create Event Commands. These Event Commands are added to the
Pipeline of the engine through the Simulation Events window. Each Event Command will
The simulation engine will call this method to obtain the length of time of your integration have its method run called whenever the event holder to which it belongs is fired. Have a
step. It will use this to calculate the amount of calls it needs to do to your integration look at the Simulation Pipeline in the Appendix B for clarification.
calculations during the calculation of a frame.
5.05 Waves
virtual void updateWave(
rf_sdk::Wave* plgThis,
std::vector<Vertex>& vertices,
const std::vector<Vector>& initPosVrtxs );
This method gets called by the simulation engine when is time to update this wave. The
method gets the initial position of all the vertices of the wave mesh.
And it should return a 3D displacement of all these vertexes in the parameter vertices.
5.06 Commands
virtual void run ();
This method will get called every time the user launches the command from the GUI
interface - either by choosing it with the mouse or with the shortcut key combination.
Once you have installed RealFlow the system variable RF_XXXX_PATH must have
a value.
Something like ‘H:\Program Files\Next Limit\RealFlow’. This of course will be different in
your system, depending on where RealFlow has been installed.
Make sure that this system environment exists and that it points to your RealFlow directory.
7 Building a Plug-in
It could be a bit complex to have to set up everything that’s needed in a development
environment to build plug-ins. So to ease this task we provide examples for all possible
types of plug-in. These examples are ready to be compiled, built and deployed easily in
Windows through the Visual Studio C++ development environment. If you want to see
the details of the settings used in the environment please go to the Appendix A, where
details are given.
We will use one of the examples to show all the steps necessary to build and deploy a
plug-in. In this case the graviton example will be used.
uu Imp: You need to have the Visual Studio for C++ installed in your computer.
Go into the folder graviton_test and double-click the file ‘graviton.vcproj’. The Visual Sudio
Enviroment should open. You should see something like the window below.
7.03 Compiling & Linking
Go to the menu bar and choose ‘Build Solution’. There should be no errors and the ouput
tab should show 0 errors as shown below. The plug-in will be compiled and linked. It
generates a ‘graviton.dll’ or a ‘graviton_x64.dll’ file depending on the platform you chose
7.02 Target Configuration in the previous step.
The plug-in can be build for 4 different configurations. These result from the combination
of two possible platform targets, Win32 and X64, and two possible modes of compilation,
Release and Debug.
• The platform target: It must match the RealFlow one where you are going to
deploy the plug-in. When RealFlow is installed you can choose either to install the
Win32 or the x64 version.
• Mode Type: Generally speaking you will use the Debug mode while you are
developing your plug-in and switch to Release once you have finished developing.
Bear in mind that the Debug mode is to help the developer in finding errors but it is
not intended to be used at deployment time. Debug mode could create huge issues
with the performance of the plug-in - also it exposes information about your plug-in
that you usually would prefer not to open to everybody using it. The generated Dll can be found in the directory ‘$RF _ XXXX _PATH\sdk\examples\graviton_text\
x64\Release’ or ‘$RF _ XXXX _PATH\sdk\examples\graviton_text\Win32\Release’ if the platform
You can choose these different target configurations in the menu bar, as is shown on the is Win32.
picture. If your RealFlow version is Win32 or x64 choose Win32 or X64 from the menu bar
respectively. And choose Release mode.
7.04 Deploying
RealFlow has a directory of plug-ins called ‘$RF _ XXXX_PATH\plugins’ where there is a subdirectory
for each type of plug-in. Each one of these subdirectories will be scanned recursively and
all the plug-ins (.dll) found for the associated type will be loaded.
In this case we just need to copy the generated graviton_x64.dll or graviton.dll to the
folder ‘ $RF_ XXXX _PATH\plugins\daemons’.
The picture above shows the properties of the Graviton plug-in. Play with them to affect the
previously added cube. Remember that the cube needs to have the Dynamics properties
set to “Rigid Body” in order for the daemon to have any effect on it.
The steps that are needed to accomplish this are described in detail below.
We will show how to build your own plug-in, in this case a new Daemon plug-in. You can
apply these steps to all the other types of plug-ins in a similar fashion.
Go into the folder my_own_graviton and double-click the file ‘graviton.vcproj’. The Visual
Studio Environment should open. You should see something like the window below.
These are the minimum changes you will need to make to create your very own plug-in.
Of course this plug-in will have exactly the same functionality as the graviton one, because
we have not changed anything related to the behavior of this plug-in.
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
///////////////////////////// ///////
//
// Copyright (C) 2008 Next Limit Technologies. All rights
// reserved. class MyOwnGravitonDaemonSDK: public DaemonPlgSdk
// {
// This file is just part of the C++ SDK examples provided
// with //RealFlow(c). public:
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND,
// INCLUDING THE /// Constructor.
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A MyOwnGravitonDaemonSDK()
// PARTICULAR //PURPOSE. {
// // Gives an unique local Id
//////////////////////////////////////////////////////////// localID = MyOwnGravitonDaemonSDK::globalLocalID++;
/////////////////////////////
timesBeingCalled = 0;
#include <iostream>
#include <sstream> angleBody = 0.0f;
#include <string> angleEmitter = 0.0f;
}
#include <rf_sdk/sdk/appmanager.h>
#include <rf_sdk/sdk/scene.h> /// Destructor.
#include <rf_sdk/sdk/vector.h> virtual ~MyOwnGravitonDaemonSDK() {};
#include <rf_sdk/sdk/daemon.h>
#include <rf_sdk/sdk/pb_particle.h> /// Class id.
#include <rf_sdk/sdk/pb_emitter.h> virtual NL_INT32 getClassId() const
#include <rf_sdk/sdk/ppty.h> {
#include <rf_sdk/sdk/plgdescriptor.h> return ( id obtained in realflow );
#include <rf_sdk/daemons/daemonplgsdk.h> };
#include <rf_sdk/sdk/rfsdklibdefs.h>
#include <rf_sdk/sdk/sdkversion.h> /// Get plugin name.
virtual std::string getNameId() const
//////////////////////////////////////////////////////////// {
/////// return ( “MyOwnGraviton” );
};
using namespace std; // getCopyRight()
using namespace nextlimit::rf_sdk; virtual std::string getCopyRight() const
{ PB_Emitter::iterator
return std::string( “Copyright (C) 2008 Next Limit iter)
Technologies. All rights reserved.” ); {
} applyForceToEmitter( thisPlg, emitter, 0, iter );
}
// getCopyRight()
virtual std::string getLongDescription() const //--------------------------------------------------
{ // Function: applyForceToEmitter
return std::string( “Adds a constant force in a certain // This function is called by the simulation engine
direction.” ); // when external forces should be applied to the
} // particles in the emitter.
//--------------------------------------------------
// getCopyRight() virtual void applyForceToEmitter( Daemon* thisPlg, PB_
virtual std::string getShortDescription() const Emitter* emitter,
{ int nThread, PB_Emitter::iterator iter
return std::string( “Adds Constant Force” ); )
} {
// apply the daemon transformation to gravity direction Vector orthoGonal = Vector::cross( fDir, Vector( 0, 1, 0
vector ) ) * fPerp;
// unit direction vector
Vector forceDirWrld = thisPlg->toWorld( finalForce ); angleBody = angleBody + angleIncStep;
// assume all particles have the same mass orthoGonal.rotateAroundAxis( fDirNorm , angleBody );
Particle curpart = emitter->getFirstParticle();
float massParticle = curpart.getMass(); // Final force applied
Vector finalForce = fDir + orthoGonal;
forceDirWrld.scale( massParticle );
// apply the daemon transformation to gravity direction
while( iter.hasNext() ) vector
{ // unit direction vector
curpart = iter.next(); Vector forceDirWrld = thisPlg->toWorld( finalForce );
virtual void removeParticles(
Daemon* plgThis, PB_Emitter* obj ) 8.06 Compiling & Linking
{
} Go to the menu bar and choose ‘Build Solution’. There should be no errors and the ouput
tab should show 0 errors as shown below. The plug-in will be compiled and linked. It
int timesBeingCalled; generates a ‘my_own_graviton.dll’ or a ‘my_own_graviton _x64.dll’ file depending on the
int localID; platform you chose in the previous step.
static int globalLocalID; The generated Dll can be found in the directory ‘$RF_XXXX_PATH\sdk\examples\ my_own_
graviton\x64\Release’ or ‘$RF_XXXX_PATH\sdk\examples\ my_own_graviton\Win32\Release’ if
// Degrees the platform is Win32.
float angleBody;
float angleEmitter;
};
8.07 Deploying
int MyOwnGravitonDaemonSDK::globalLocalID = 0;
RealFlow has a directory of plug-ins called ‘$RF_XXXX_PATH\plugins’ where there is a subdirectory
//////////////////////////////////////////////////////////// for each type of plug-in. Each one of these subdirectories will be scanned recursively and
/////////////// all the plug-ins (.dll) found for the associated type will be loaded.
In our case we just need to copy the generated my_own_graviton_x64.dll or my_own_
RF_SDK_DECLARE_DAEMON_PLUGIN( MyOwnGravitonDaemonSDK ); graviton.dll to the folder ‘$RF_XXXX_PATH\plugins\daemons’
//////////////////////////////////////////////////////////// That´s all! Now you are ready to use your new plug-in. Just launch RealFlow. You
/////////////// should now see under the Daemons plugi-ns menu your graviton plug-in with the name
MyOwnGraviton.
Opening that file will launch Xcode. The version we are using to illustrate the guide is 3.1.3
on Mac OS X 10.5.8. Newer versions like the one distributed with Snow Leopard may differ
slightly. However, main views and configuration panels are almost identical.
Now, let’s check the header files are searched fo in the right place when compiling our
plug-in.
To do so, select ‘Edit Project Settings’ on the Project menu. A new window will pop up
showing the global preferences for this Xcode project.
Click on the ‘Build’ tab and make sure ‘All Configurations’ is selected in ‘Configuration:’,
Select ‘Settings Defined at This Level’ on ‘Show:’ to display only those properties that don’t
have a default value.
If you expand the three groups Source, Libs and Products will see the source code file At the very bottom there is a section with all the user-defined variables. In this case you
(graviton.cpp), RealFlow C++ SDK dynamic library (librfsdk.dylib) and the dynamic library should find one called RFSDKPATH.
created for the plug-in (graviton.dylib).
The Active Architecture value is pointless for the plug-in since RealFlow will load it on
runtime and, therefore, use the same architecture it is being run on.
Regarding target architectures, RealFlow for Mac is distributed as Intel 32/64 bit and
This variable must point to the RealFlow C++ SDK folder. In this case it is specified as a PowerPC 32 bit universal binaries. Your plug-in only needs to be compiled for the same
path relative to the project folder. Quotation is important to avoid problems with paths architecture it is going to be used on. However, in case you plan to distribute it, you should
containing whitespaces. probably compile it for as many architectures as possible.
Now just click on Build and wait until the plug-in is created. It should not take too long.
‘Header Search Paths’ and ‘Library Search Paths’ must remain as:
You might feel tempted to enable the “Recursive” checkbox and remove the second entry
of the ‘Header Search Paths’. However, leaving it this way will save some compiling time
and some potential errors due to repeated path names.
This is all you need to check to make sure RealFlow plug-ins can be compiled on your Mac
OS X machine.
9.05 Deploying
The final step to make your plugin work is to copy it into the right RealFlow plug-in folder,
just like for Windows. Right-click on ‘graviton.dylib’ and select ‘Reveal in Finder’. This will
open a Finder window with the plug-in file selected. Just drag it to the subfolder ‘plugins/
daemons’ of your RealFlow installation and open RealFlow to check if it works in the
same way as in the Windows instructions.
$(RF_INSTALL_FOLDER)/sdk/examples/cmd_show_msg_n_times
Now you should be able to launch RealFlow and use the plug-in.
$(RF_INSTALL_FOLDER)/sdk/examples/graviton
To create your own command plug-in just replace the “cmd_show_msg_n_times” string
with the name of your plug-in. If plug-in is made of several modules you might need to
make several modifications to this makefile - please refer to the makefile documentation
if you want to modify this one.
Once you have modified the makefile the procedure to compile and install is easy:
To create your own command plug-in just replace the “graviton” string with the name of
your plug-in. If your plug-in is made of several modules you might need to make several
modifications to this makefile, please refer to the makefile documentation if you want to
modify this one.
Once you have modified the makefile the procedure to compile and install is easy:
Now you should be able to launch RealFlow and use the plug-in.
$(RF_INSTALL_FOLDER)/sdk/examples/object_ppties To create your own command plug-in just replace the “object_ppties” string with the
name for your plug-in. If your plug-in is made of several modules you might need to make
The makefile in that folder looks as follows. several modifications to this makefile, please refer to the makefile documentation if you
want to modify this one.
Once you have modified the makefile the procedure to compile and install is easy:
Now you should be able to launch RealFlow and use the plug-in.
There is one example in the folder: 12. Now just copy the plugin to the appropriate folder:
$(RF_INSTALL_FOLDER)/sdk/examples/surface_tension [realflow@GRANJA3]$ make install
The makefile in that folder looks as follows:
To create your own command plug-in just replace the “surface_tension” string with the
name for your plug-in. If your plug-in is made of several modules you might need to make
several modifications to this makefile, please refer to the makefile documentation if you
want to modify this one.
Once you have modified the makefile the procedure to compile and install is easy:
11 Generalities
Once you have a scene object, you can call the methods of the scene as defined in the API.
For instance, to add a new cube object to the scene you would use:
11.02 Properties
You can add properties of different types to all the plug-ins except the Event/Command
ones.
You add these properties in the method initialize , that gets called when a plug-in is
instantiated. All the instances of a Plug-in type share the same properties. Of course, each
instance has its own values. And those values are saved with the scene.
You can get/set values of these properties the same way that you do with all the other
attributes of a RealFlow object. You can get a good feel for how you can create and use
these attributes in any of the plug-in examples provided with the RealFlow package.
Observe that some of these methods require that you provide the C++ type of the variable
that you are accessing.
12 Appendixes
• Open Visual Studio, choose to create a new project. The following window will appear.
• Press Next
F. 01 RealFlow Installation directory • Choose ‘Win32’ project type and template ‘Win32 Console Application’ as shown above.
• Choose new
• Make sure you choose the values shown on the above figure
Now you have an empty project, ready to be customized for developing plug-ins. • Press Ok
But before anything else you need to add support to compile in 64 bits. Right now it is • Press Close on the ‘Configuration Manager’ window
ready only to produce code for win32.
Done!. Now your project is ready to compile and build for 4 different configurations.
Adding x64 support
• Release for Win32
• Right-Click over your solution’s name as shown below. • Release for x64
• Debug for Win32
• Debug for x64
Do not worry too much about the debug/release options for the moment. Normally you
just want to deploy in Release mode, but if something fails then you can use the Debug
mode to trace your plug-in to find and fix bugs in your code.
Setting Compilation and Linking Options Just for convenience give each property sheet a similar name to the configuration that it
belongs to. As shown below.
Choose the ‘Property Manager’ tab. This should be just beside your ‘Solution Explorer’ tab.
If it is not visible go to the View menu and choose ‘Property Manager’ submenu. Then it
should appear. If it is floating you can embed it just beside the Solution Explorer tab for
easy access.
Expand the ‘my_own_graviton’ folder to show the above picture. Each folder represents a
possible configuration to build your plug-in. As we said before there are 4 possible ways
to build a plug-in. The combinations of the target platform( Win32 or X64) plus the mode
(Release or Debug). So you should end up with something like:
Generally speaking you should use the Debug mode while you are developing your
plug-in and switch to Release once you have finished developing. Bear in mind that the
Debug mode is to help the developer in finding errors but it is not intended to be used
at deployment time. Debug mode could create huge issues with the performance of the
plug-in - also it exposes information about your plug-in that you would usually prefer not
to open to everybody using it.
To be able to choose options for compilation you need to add what is called a property
sheet to each configuration. This is just a convenient way to group options. To do so just
right-click over each folder and choose “Add New Project Property Sheet’ as shown below.
In the next section the different settings that are needed to build plugins will be shown for
all the 4 possible configurations.
• C++ Folder
• General Tab
• Additional Include Directories = “$RF_XXXX_PATH\sdk\include”
Directory with the library headers.
• Optimization
• Optimization = Maximize Speed (/O2)
• Enable Intrinsic Functions = Yes (/Oi) Linking Settings (Release for x64)
uu These options are related to the performance of the code generated. Please refer to • Linker
the Visual Studio compiler for more information. In general you should not need to change • General Tab
them. • Output File = $(OutDir)\$(ProjectName)_x64.dll
This chooses the name of the plugin dll. You can choose whatever name you
• Preproccesor prefer - it’s good practice to identify the x64 version in a clear way. The same
• Preprocessor Definitions = NDEBUG;WIN32;_WINDOWS;_USRDLL goes for the Debug mode. You will see later on that we recommend that you
Compilation variables. These need to be defined only for the Windows version. append a D to the dll name.
In a Linux or Mac environment they should be not defined.
• Enable Incremental Linking = No (/INCREMENTAL:NO)
• Code Generation This just increases the speed of linking for projects with multiple files. In this
• Runtime Library = Multi-threaded DLL (/MD) case, because plugins tend to be small there is no need for this.
• Input
• Additional Dependencies = rfsdk_x64.lib
SDK Library used to link a plugin. If the plugin needs more external libraries
this is the place to add the library files.
• System
• System = Windows (/SUBSYSTEM:WINDOWS)
Enviroment that the plugin is compiled for.
• Optimization
• References = Eliminate Unreferenced Data (/OPT:REF)
• Enable COMDAT Folding = Remove Redundant COMDATs (/OPT:ICF)
These options are related to the performance of the code generated. Please
refer to the Visual Studio compiler for more information. In general you
should not need to change them.
• Advanced
• Target Machine = MachineX64 (/MACHINE:X64)
This is really important!. It tells the compiler to create the plugin for the x64
environment.
uu Both your RealFlow application and the plugins need to match the bits version. Either
both are Win32 or both are X64. If not the plugins loading will fail.
• Linker
• General Tab
• Output File = $(OutDir)\$(ProjectName).dll
• Enable Incremental Linking = No (/INCREMENTAL:NO)
• Additional Library Directory = $RF_XXXX_PATH\sdk\lib
• Input
• Additional Dependencies = rfsdk.lib
• System
• System = Windows (/SUBSYSTEM:WINDOWS)
• Optimization
• References = Eliminate Unreferenced Data (/OPT:REF)
• Enable COMDAT Folding = Remove Redundant COMDATs (/OPT:ICF)
• Advanced
• Target Machine = MachineX86 (/MACHINE:X86)
• C++ Folder
• General Tab
• Additional Include Directories = “$RF_XXXX_PATH\sdk\include”
The rest of the configurations share the majority of the settings. So for them we will show • Debug Information Format = Program Database (/Zi)
only the differences in configuration to the one above. • Warning Level = Level 3 (/W3) or Level 4 (/W4)
• Optimization
Compiler &Linker Settings (Release for win32) • Optimization = Disabled (/Od)
• Enable Intrinsic Functions = No
• C++ Folder • Preproccesor
• General Tab • Preprocessor Definitions = NDEBUG;WIN32;_WINDOWS;_USRDLL
• Additional Include Directories = “$RF_XXXX_PATH\sdk\include” • Code Generation
• Debug Information Format = Program Database (/Zi) • Runtime Library = Multi-threaded DLL (/MD)
• Warning Level = Level 3 (/W3) or Level 4 (/W4) • Basic Runtime Checks = Both (/RTC1, equiv. to /RTCsu)
• Optimization Helps to catch some runtime errors
• Optimization = Maximize Speed (/O2)
• Enable Intrinsic Functions = Yes (/Oi) • Linker
• Preproccesor • General Tab
• Preprocessor Definitions = NDEBUG;WIN32;_WINDOWS;_USRDLL • Output File = $(OutDir)\$(ProjectName)_DL.dll
• Code Generation • Enable Incremental Linking = No (/INCREMENTAL:NO)
• Runtime Library = Multi-threaded DLL (/MD) • Additional Library Directory = $RF_XXXX_PATH\sdk\lib
•
•
Input
Additional Dependencies = rfsdk.lib
12.02 Simulation Events Pipeline
• System
• System = Windows (/SUBSYSTEM:WINDOWS) This will be a brief introduction to the use of the new Simulation Events Pipeline. Let´s
• Optimization first have a look at the new window ‘Simulations Events’. Go to the menu ‘Menu Bar ->
• References = Default Layout-> Simulation Events’ or just press ‘Ctrl + F2’. The following screen will appear:
• Enable COMDAT Folding = Default
Because this is a Debug mode. The optimizations need to be off in order to
be able to trace the whole code
• Advanced
• Target Machine = MachineX86 (/MACHINE:X86))
Now you have a Visual Studio environment ready to start programming. For convenience
we recommend that you create a folder for your source code. Lets create one and call it
‘src’.
The easiest way to create a new plug-in is from a previously existing plug-in, using this
previous one as a template for the new one. If for instance you are going to create a new
Daemon plug-in you can use a starting point the file “graviton.cpp” from the graviton
example in the examples folder ($RF_XXXX_PATH\sdk\examples\graviton). So you will have
the next file structure in the my_own_graviton plug-in.
Now go inside the code and start changing the plug-in. See below the transformed code In the bottom half you have what is basically a copy of the old “Events Script” window,
once the original code has been stripped away and only the skeleton of a Daemon plug-in now called “Master”. It works in the same way as in RealFlow 4. You can switch it off
has been left in place. through the active option in the bottom right corner of the window.
away.
The top half of the window works in a similar fashion to the old “Events Script” window. Script from file (“Add Script From File” ), this lets you choose a Python file as the script
There you had a script window where you could define some methods that were called to be called.
at specific times in the simulation pipeline. So you had for instance a method called
“onSimulationBegin” that was called at the beginning of the simulation. We have further And the last one will be the new type based on the plug-in system.
developed further this concept into a more modular events manager. Now at the same
specific times in the simulation pipeline you can choose to run any number of scripts or Script from plugin ( “Add From Plugin” ) lets you choose a Event plug-in as the ‘script’ to
event plug-ins. be called.
To add a script, select the point at which you want it to be called and pressing the right It is that easy.
mouse button select the script type from the menu that pops up, as is shown in the
picture. These two windows define events in an independent way. You can use whichever suits
your needs, or you can use both at the same time. All the events coming from either
window will be run at their corresponding step of the simulation.
When RealFlow starts it loads all the plug-ins - so later on you will be able to choose
them from the Simulation Events screen.
Bear in mind that you can use the same Command/Event plugins loaded from the “….\
plug-ins\cmds” to create either an Event Command or a Command to be run from the GUI
interface.
If you are registered as an Apple Developer you can get access to extra updated Xcode Click on ‘New Group’ from the Project menu, and set the group name to something like
versions. ‘RFSDK Library’. Right-click on the group you just created and select ‘Add > Existing Files…’.
Creating a new project A dialog will pop up asking for the files to add. Navigate to your RealFlow installation
The first thing you have to do is open Xcode and select ‘New Project’ in the File menu. (commonly ‘/Applications/RealFlow’) and select the file named ‘librfsdk.dylib’ on ‘sdk/
Depending on your Xcode version the amount of project types may vary drastically. lib’ subfolder.
However, there is always the option of creating an Empty Project, from the ‘Other’ section.
As project name, you can use the same as in the Windows section: ‘my_own_graviton’. Right after your selection, Xcode will show another dialog asking the way the file must be
Choose any location for it. imported.
Just make sure ‘Copy items into destination group’s folder’ is not checked and close the
dialog by clicking on ‘Add’.
From all the Dynamic Library choices all you need is the cleanest one, so you can set
up your own flags and dependencies. Select the ‘Dynamic Library’ target from the ‘BSD’
section.
After typing a name for your target it will appear on the ‘Groups & Files’ section of the
project window.
Right click on it and select ‘Get Info’ to show a window with the target settings.
Activate the ‘Build’ tab and set ‘All Configurations’ as ‘Configuration:’ and ‘Settings Defined
at This Level’ on ‘Show:’. You can remove everything except the ‘Product Name’. This way
all the settings will have the default value inherited from the global settings of the project.
We will check them in the next step.
From now on, the description will continue as if you had added a ‘my_own_graviton.cpp’
file with the same content as in the Building your own Plug-in section.
You need to create a dynamic library that will represent your plug-in so, click on ‘New
target…’ from the Project menu. Tweaking project settings
This is the most important step. Click on ‘Edit Project Settings’ from the ‘Project’ menu.
On the ‘General’ tab, set ‘Base SDK for All Configurations’ to ‘Mac OS X 10.5’. RealFlow is
only compatible with Mac OS X version 10.5 or higher.
Here there is a screenshot to get a reference for all the settings from this tab:
Click on the gear button located on the bottom left corner to Add a User-Defined Setting.
Set its name to ‘RFSDKPATH’ and make it point to the ‘sdk’ folder of your RealFlow
installation. It should be something like “/Applications/RealFlow/sdk”. Double quotes
must be present to avoid problems with paths containing whitespaces.
The next step is to set the header and library search paths to point to the RealFlow C++
SDK location.
You are just a few more settings away from being able to create your plug-in.
Locate the ‘C/C++ Compiler Version’ under ‘Compiler Version’ section. This setting must
be set to ‘GCC 4.2’.
At the very top, there is an ‘Architectures’ section. ‘Architectures’ can be set at most to:
i386 x86_64 ppc.
Any other architecture will fail to compile because RealFlow C++ SDK is only compiled for
those.
Finally, under ‘GCC 4.2 – Language’ section there is an ‘Other C Flags’ setting. Set it to
‘–D_MACOSX’.
That’s all. Setting ‘Show:’ to ‘Settings Defined at This Level’ will reveal all the changes you
have made plus some differences in optimization settings between Debug and Release
configurations.
Close the dialog and go back to the main project window.
All images in this book have been reproduced with the knowledge and prior consent of the artists concerned and
no responsibility is accepted by producer, publisher, or printer for any infringement of copyright or otherwise,
arising from the contents of this publication. Every effort has been made to ensure that credits accurately
comply with information supplied.