Create your scene in Cpp
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/simulation/Node.h>
#include <sofa/helper/system/PluginManager.h>
#include <sofa/simulation/config.h> // #defines SOFA_HAVE_DAG (or not)
#include <sofa/simulation/common/init.h>
#include <sofa/simulation/graph/init.h>
#include <sofa/simulation/graph/DAGSimulation.h>
#include <sofa/helper/BackTrace.h>
#include <sofa/gui/common/ArgumentParser.h>
#include <sofa/core/ObjectFactory.h>
// Add any other includes needed by your scene
// #include<path_to/myComponent.h>
// ...
int main(int argc, char** argv)
{
sofa::helper::BackTrace::autodump();
ExecParams::defaultInstance()->setAspectID(0);
// 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();
sofa::simulation::graph::init();
if (simulationType == "tree")
msg_warning("runSofa") << "Tree based simulation, switching back to graph simulation.";
assert(sofa::simulation::getSimulation());
auto& pluginManager = PluginManager::getInstance();
for (const auto& plugin : plugins)
{
pluginManager.loadPlugin(plugin);
}
// Here start the description of your scene in C++
// you can create nodes
sofa::simulation::Node::SPtr groot = New<sofa::simulation::graph::DAGNode>();
groot->setName ("root");
sofa::defaulttype::Vec3d g = sofa::defaulttype::Vec3d (0,-9.81,0);
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
sofa::simulation::Node::SPtr childNode = New<sofa::simulation::graph::DAGNode>();
childNode->setName( "child_of_root" );
groot->addChild(childNode);
addMyComponent(childNode);
// initialization of the graph
sofa::simulation::node::initRoot(groot.get());
// Run the simulation
groot->setAnimate(true);
// close the simulation
if (groot!=NULL)
sofa::simulation::getSimulation()->unload(groot);
sofa::simulation::common::cleanup();
sofa::simulation::graph::cleanup();
return 0;
}
// this function illustrates how to add a component to a node
myComponent *addMyComponent(sofa::simulation::tree::GNode *node) {
myComponent* myComp = new myComponent;
myComp->setName ("myComponentName");
myComp->addTag ((Tag)"myTag");
myComp->d_data.setValue(0.02); // any public data of the component can thus be defined
node->addObject (myComp);
return (myComponent *)solver;
}
In your CMakeList.txt, do not forget to find the Sofa.Framework package:
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:
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 SofaPython3
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.