static ModuleAPI* ModuleAPIFactory::registerModule(std::string instancename=std::string(""))
This method will register a new module and return the appropriate module API implementation. The module gets the name composed of the concatenation of:
Most of the time the instancename parameter can be omitted, and the module gets the name returned by FLOWVR_MODNAME.
int ModuleAPI::init(std::vector<Port*>& ports)
This method initializes the module and its ports. This method must be called once before entering the loop. The list of ports used by the module can not be modified after this call. No other method of the module API should be called before calling init.
We present in this section the Parallel Interface provided by FlowVR. This interface stores information on the running mode of the process: sequential or parallel mode. The process can also retrieve its rank and the number of processes involved. We first present how to initialize the Parallel Interface (a mandatory task) before detailing the functionnality it offers. Notice that the Parallel Interface is global to a process and does not depend on a ModuleAPI.
See the fluid parallel metamodule programmed with MPI (share/flowvr/examples/fluid/modules/src/flowvr-main.cpp) thtat uses the Parallel Interface.
The Parallel Interface is automatically included with the standard FlowVR module compilation options (pkg-config module: flowvr-mod or flowvr-base).
Several methods can be used to initialize the Parallel Interface.
void Parallel::init()
This method detects the presence of the environment variables FLOWVR_RANK and FLOWVR_NBPROC. If both are present, it activates the parallel mode, the rank and the number of processes being set with those values. Otherwise it activates the sequential mode (rank is then and the number of processes is ). Note that if the parallel interface was already initialized, this method does nothing.
Notice that this is the responsability of the programmer to set and forward these environment variables when writing the corresponding <run> tag of the metamodule .desc file.
void Parallel::init(bool parallelMode)
This method is similar to the previous one, except that it manually forces the parallel mode. If parallelMode is false, the sequential mode is forced. Otherwise the parallel mode is set. If FLOWVR_RANK and FLOWVR_NBPROC are set, those values are used otherwised rank is set to and the number of processes to .
The fluid uses this function to force the sequential mode if the USE_MPI variable is not defined (share/flowvr/examples/fluid/modules/src/flowvr-main.cpp).
void Parallel::init(int rank, int nbProc)
This method sets the parallel mode with the rank and the number of processes given. This is particularly useful when the process is launched with a parallel launcher such as MPI.
The fluid uses this function to initialize the rank and number of processes running with the values returned by the MPI_Comm_size and MPI_comm_rank functions (share/flowvr/examples/fluid/modules/src/flowvr-main.cpp).
bool Parallel::isInitialized()
Test if the Parallel Interface is initialized.
bool Parallel::isParallel()
Returns true if the process is in parallel mode.
bool Parallel::getRank()
Returns the rank of the process. This value is guaranteed to be in sequential mode.
bool Parallel::getNbProc()
Returns the number of processes. This value is guaranteed to be in sequential mode.
bool Parallel::close()
Closes the Parallel Interface (the Parallel Interface is let uninitialized).
As already presented, the initModule() function uses the Parallel Interface to automatically add the rank of the process in the module's name if the process is in parallel mode. If the Parallel Interface has not been initialized, this method calls the automatic initialization of the Parallel Interface.
Initializing the Parallel Interface forcing the sequential mode prevents intiModule() to automatically adds the rank in the module's name.
A very frequent task performed by FlowVR programs and modules is to search for a file given a set of directory locations. The class FilePath implements this functionnality. A path is considered as a string composed of directory locations separated by ':' (as for the standard environment variable $PATH). Files are searched as the concatenation of the filename given and one of the directory location of the path. This class can be used in two different ways.
To compile a module using the FilePath class, you should use pkg-config with module flowvr-utils.
bool FilePath::findFileIn(std::string& filename, const std::string& path);
This static function looks for file filename in the path given by the parameter path. If the file is found with one of the directory location, the function returns true and sets filename to the correct path for the file (mainly the concatenation of this directory and the file name). Otherwise it returns false.
This function simply tests the concatenation of each directory location (in the order of the path) and the filename. It does not test in the current directory and does not take a special care for files starting by '/', './' or '../'
To handle those cases correctly, we need to first build an object FilePath with the different paths to search before searching for the file.
FilePath::FilePath(const char *envVar = "FLOWVR_DATA_PATH");
This function builds a FilePath object by loading its path from an environment variable envVar. If no parameter is passed the variable FLOWVR_DATA_PATH is then used. For not loading the path from an environment variable, one must set envVar to NULL.
void FilePath::addPath(const std::string& path);
Adds a path for the search.
bool FilePath::findFile(std::string& filename);
File filename is searched as follows:
For file name starting with '/', './' or '../' only the first step is applied. The results of the search is identical to the basic file search method.
Another common problem in Virtual Reality problems concerns standard mathematical operations on vectors or matrices.
The FlowVR Template Library provides some generic representation for frequently used objects: vectors, matrices, quaternions. FTL definitions lie in the ftl namespace. To compile modules using the FTL, you should use pkg-config with module flowvr-ftl.
#include <ftl/vec.h>
The class Vec<N, Type> represents fixed-size vectors of N elements of type Type. Elements are stored in a compact contiguous manner: a FTL vector can thus be casted from a standard C array. Standard mathematic operations are available directly by redifinition of the corresponding operators.
Different predefined vector types are available as aliases: VecNT where N is 2, 3 or 4 and T is b (unsigned char), i (int), f (float), d(double).
For more information on this class, refer to the file flowvr-ftl/include/ftl/vec.h.
#include <ftl/mat.h>
The class Mat<L, C, Type> represents fixed-size matrices with L lines and C columns, each element being of type Type. Elements are stored in a single buffer in line order. Standard mathematic operations are available through redefined operators.
For more information on this class, refer to the file flowvr-ftl/include/ftl/mat.h.
#include <ftl/quat.h>
The class Quat represents a quaternion. It can be constructed from different rotation representation and can be converted to and from rotation matrices.
For more information on this class, refer to the file flowvr-ftl/include/ftl/quat.h.
#include <ftl/cmdline.h>
To ease the parsing of command line options (a very frequent task for modules), FlowVR proposes an easy command line parsing API.
Declaring an option simply consists in creating a variable of type:
The option's short name (a letter) indicates which short command ('-' followed by this letter) triggers the option. The option can also be triggered with a long command ('-' followed by the long name) if a non NULL long name is given. The description corresponds to the help given by the help option ('-h', '-help').
Parsing the command line first requires the creation of an object of type CmdLine. The description then given corresponds to the usage line given by the help option. Parsing the option is then done by calling the fonction parse.
Testing if an option is present is simply done by testing if its count attribute is non nul. An option is automatically casted into its value (a boolean for a flag).
#include <ftl/chunks.h>
Chunks are a way to structure data in messages. Data is encapsulated in a specific chunk and appended in a chunk list that after it is send as one standard message. It eases packing and unpacking data in messages.
A chunk is based on the chunk structure. Each different kind of chunk extends this structure with the necessary extra information. The base chunk structure defines the data size and the type. These data are used to extract the chunk at reception. The size and type are usually filled automatically.
The chunks must be added in a chunkwriter object, using a simple addChunk templated function, for instance to add an keyboard button event, the user must use the following function:
ChunkEventWriter *keysMsgs = new ftl::ChunkEventWriter(); keysMsgs->addEventButton((unsigned char)i,true);
In this example this function receives the key pressed and a boolean specifying if the key is pressed or not.
After adding all the chunks, it is just necessary to send the chunk list, i.e the message, to a normal FlowVR output port.
flowvr::OutputPort* pPortOut = new flowvr::OutputPort("out");
keysMsgs->put(pPortOut);
As you can notice, their is no need to make explicit memory allocation. The chunk system takes directly care of these details.
At reception, the procedure is quite similar to message reading. The only difference is that after getting the message it is necessary to use an iterator to extract each chunk from the message. It is also necessary to check what kind of chunk we are receiving to properly read it before to actually read the data itself:
flowvr::InputPort* pPortIn = new flowvr::InputPort("in");
.....
flowvr::Message msgRead;
.....
pFlowVRModule->get(pPortIn, msgRead);
for (ftl::ChunkIterator it = ftl::chunkBegin(msgRead); it != ftl::chunkEnd(msgRead) ; it++ )
const ftl::Chunk* c = (const ftl::Chunk*) it;
switch (c->type & 0x0F)
case ftl::ChunkEvent::BUTTON:
key = ((ftl::ChunkEventButton *)c)->key;
break;
For more information on these classes, refer to these files flowvr-ftl/include/ftl/chunk.h, flowvr-ftl/include/ftl/chunkwriter.h, flowvr-ftl/include/ftl/chunkreader.h.
#include <ftl/chunkevents.h>
Chunk evants are used to deal with input devices. It enables the user to get the input events pack into chunks. The defined types of chunk events are:
It is possible to create an ID for each message source to identify which device is being used. It is quite important when we have two or more devices. Also there is a list of standard special keys that is based on GLUT and that can be used to map the keys in a FlowVR application.
For more information on this class, refer to the file flowvr-ftl/include/ftl/chunkevents.h.
The chunk support for rendering is implemented in FlowVR-Render, and uses the chunk events from the ftl library.
2009-04-06