SEARCH
TOOLBOX
LANGUAGES
CppSyntax

CppSyntax

From SOFAWiki

Jump to: navigation, search

Writing C++ scenes

For new comers, writing C++ scenes can be a difficult task; in Sofa, we made an intensive use of templates to achieve a good genericity and modularity. For the user, the side effect is a code more difficult to read, and the almost compulsory need to use typedef. To help people to write C++ scenes, we made a tool to generate typedef files. They are placed within the directory: $SOFA/modules/sofa/component/typedef.

You just need to add the header

#include <sofa/component/typedef/Sofa_typedef.h>

And then all the typedef for all the Sofa components using template will be available. For instance, to create a mechanical object, instead of writing:

sofa::component::container::MechanicalObject<sofa::defaulttype::StdVectorTypes<sofa::defaulttype::Vec<3, double>, sofa::defaulttype::Vec<3, double>, double> > *mstate;

you just need to write:

MechanicalObject3d *mstate;

The rules are simple: the typedef consists in the name of the component + prefix corresponding to its data type.

Prefix Generation
sofa::defaulttype::StdVectorTypes<sofa::defaulttype::Vec<3, double>, sofa::defaulttype::Vec<3, double>, double> 3d
sofa::defaulttype::StdVectorTypes<sofa::defaulttype::Vec<2, float>, sofa::defaulttype::Vec<2, float>, float> 1f
sofa::defaulttype::StdRigidTypes<3, double> Rigid3d
sofa::defaulttype::ExtVectorTypes<sofa::defaulttype::Vec<3, float>, sofa::defaulttype::Vec<3, float>, float> > > Ext3f

For instance, if you want to use the component ConstantForceField:

ConstantForceField3d *constant3d; //force field using particules in 3 dimension, using double precision
ConstantForceFieldRigid3f *constantRigid3f; //forcefield using rigid frames in 3 dimension, using simple precision

The typedef for Mappings are slightly different as they make the link between two objects of somewhat different datatypes. The BarycentricMapping is one of the most used mapping in Sofa scenes. To create a barycentric mechanical mapping in C++, you have to write:

sofa::component::mapping::BarycentricMapping<sofa::core::componentmodel::behavior::MechanicalMapping<sofa::core::componentmodel::behavior::MechanicalState<sofa::defaulttype::StdVectorTypes<sofa::defaulttype::Vec<3, double>, sofa::defaulttype::Vec<3, double>, double> >, sofa::core::componentmodel::behavior::MechanicalState<sofa::defaulttype::StdVectorTypes<sofa::defaulttype::Vec<3, double>, sofa::defaulttype::Vec<3, double>, double> > > > *mapping(mstate1,mstate2);

Using our typedef, it gives:

BarycentricMechanicalMapping3d_to_3d *mapping(mstate1,mstate2);

The rules to find the typedef for the mappings are : name of the mapping + prefix for Object1 + "_to_"prefix for Mapped Object2 See the table above to get the prefix. If the mapping is mechanical (it propagates the velocities from the DOFs to the mapped state, and the forces from the mapped state to the DOFs), you have to write MechanicalMapping. If the mapping is done just in position, like a VisualMapping, you have to write Mapping.

BarycentricMapping3d_to_Ext3f *baryMapping(mstate,visualmodel); //Visual Mapping: often used to add a visual model to a deformable simulated body
RigidMechanicalMappingRigid3d_to_3d *rigidMapping(rigidState, mappedState); //Mechanical Mapping: often used to add a collision model to a rigid simulated body