First of all, you can really get inspiration from all Tutorials available in applications/Tutorials, that are C++ files implementing the XML tutorials available in examples/Tutorials/. In addition, you can read the Main.cpp of runSofa from applications/projects/runSofa/.
Here is a short template about how to write a scene in C++:
#include <sstream>
using std::ostringstream ;
#include <fstream>
#include <sofa/helper/ArgumentParser.h>
#include <SofaSimulationCommon/common.h>
#include <sofa/simulation/Node.h>
#include <sofa/helper/system/PluginManager.h>
#include <sofa/simulation/config.h> // #defines SOFA_HAVE_DAG (or not)
#include <SofaSimulationCommon/init.h>
#include <SofaSimulationTree/init.h>
#include <SofaSimulationTree/TreeSimulation.h>
#include <SofaComponentCommon/initComponentCommon.h>
#include <SofaComponentBase/initComponentBase.h>
#include <SofaComponentGeneral/initComponentGeneral.h>
#include <SofaComponentAdvanced/initComponentAdvanced.h>
#include <SofaComponentMisc/initComponentMisc.h>
#include <sofa/helper/BackTrace.h>
// Add any other includes needed by your scene
// #include<path_to/myComponent.h>
// ...
int main(int argc, char** argv)
{
sofa::helper::BackTrace::autodump();0);
ExecParams::defaultInstance()->setAspectID(
// here you can init the GUI you wish
// as an example, see : applications/projects/runSofa/Main.cpp
sofa::simulation::tree::init();
sofa::component::initComponentBase();
sofa::component::initComponentCommon();
sofa::component::initComponentGeneral();
sofa::component::initComponentAdvanced();
sofa::component::initComponentMisc();
new sofa::simulation::tree::TreeSimulation());
sofa::simulation::setSimulation(
std::ostringstream no_error_message;
"MyPlugin",&no_error_message);
sofa::helper::system::PluginManager::getInstance().loadPlugin(
sofa::helper::system::PluginManager::getInstance().init();
// Here start the description of your scene in C++
// you can create nodes
new sofa::simulation::tree::GNode;
sofa::simulation::tree::GNode* groot = "root");
groot->setName (0,-9.81,0);
sofa::defaulttype::Vec3d g = sofa::defaulttype::Vec3d (
groot->setGravityInWorld(g);
// you can create components in these nodes
addMyComponent(groot);
// you can add new child nodes and repeat the process to build your scene
new sofa::simulation::tree::GNode;
sofa::simulation::tree::GNode* childNode = "child_of_root" );\r
childNode->setName(
groot->addChild(childNode);
addMyComponent(childNode);
sofa::simulation::getSimulation()->init(groot.get());
// Run the simulation
true);
groot->setAnimate(
// close the simulation
if (groot!=NULL)
sofa::simulation::getSimulation()->unload(groot);
sofa::simulation::common::cleanup();
sofa::simulation::tree::cleanup();return 0;
}
// this function illustrates how to add a component to a node
myComponent *addMyComponent(sofa::simulation::tree::GNode *node) {
new myComponent;
myComponent* myComp = "myComponentName");
myComp->setName ("myTag");
myComp->addTag ((Tag)0.02); // any public data of the component can thus be defined
myComp->d_data.setValue(
node->addObject (myComp);
return (myComponent *)solver;
}
In your CMakeList.txt, do not forget to find the SofaFramework package:
find_package(SofaFramework REQUIRED)
To define your executable:
if(APPLE AND RUNSOFA_INSTALL_AS_BUNDLE)
add_executable(${PROJECT_NAME} MACOSX_BUNDLE ${RC_FILES} Main.cpp )
else()
add_executable(${PROJECT_NAME} ${RC_FILES} Main.cpp)
endif()
And then, depending on the components used in your Main.cpp, add the dependencies:
target_link_libraries(${PROJECT_NAME} SofaComponentCommon)
Note
Just to mention that an easy way to write scenes is to use Python. Running SOFA scenes using Python might also reduce the learning curve, since you’ll only focus on the scene creation rather than SOFA internal book-keeping.
In case you choose this option, you need to enable the SofaPython
plugin during compilation. Then a minimal python scene would look like:
def createScene(node):
# create a node in the scene graph (i.e. 'Node' in xml scenes)
child_node = node.createChild('child name')
# create a component under the graph node
child_dofs = child_node.addObject('MechanicalObject', template = 'Vec3', name = 'dofs')
Please refer to the documentation for further details.
Last modified: 15 May 2023