Skip to content

ENH: Entity-Component Model

Andrew Wilson requested to merge andrew.wilson/iMSTK:ComponentModel2 into master

This introduces the beginnings of an ECS in iMSTK. Note: Stems of GeometryClone branch, merge that to remove some diffs.

Resolves: #455 (closed) #384 (closed) #366 (closed) #255 (closed)

Partially Resolves: https://gitlab.kitware.com/iMSTK/iMSTK/-/issues/397

Entity-Component-System

  • Entity was introduced which is just an object with a set of Components, name, and id.
  • Component was introduced which represents functionality on an object. Also has a name. It does not implement any logic. Systems do.
  • A system is abstract and can be anything that has a reference to the components of an entity and does function. In this way a Renderer, Scene, CollisionHandler, etc are all systems.
  • Behaviour was introduced which gives update and visualUpdate virtual functions to a Component for an easy way to implement a single component system.

Implementation

  • Entity is now the base class to SceneObject. Usages around imstk were replaced with it instead (for instance Scene takes Entity now). The inheritance tree (PbdObject, RbdObject, etc) were kept to avoid breaking many parts of imstk (also its more work, these can slowly change later).
  • Initialization was reworked to support dependent components (also a bit cleaner now).
  • A helper function to generate example default components was added.

Components Added

ObjectControllerGhost

Give it a controller and pop it on an object. It will display a transparent clone of that object at the physical location of the device. This iss done in many examples, now generalized.

Previously we did:

// Setup a debug ghost tool for virtual coupling
auto ghostToolObj = std::make_shared<SceneObject>("ghostTool");
auto toolMesh      = std::dynamic_pointer_cast<SurfaceMesh>(toolObj->getVisualGeometry());
auto toolGhostMesh = std::make_shared<SurfaceMesh>();
toolGhostMesh->initialize(
  std::make_shared<VecDataArray<double, 3>>(*toolMesh->getVertexPositions(Geometry::DataType::PreTransform)),
  std::make_shared<VecDataArray<int, 3>>(*toolMesh->getCells()));
ghostToolObj->setVisualGeometry(toolGhostMesh);
ghostToolObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Orange);
ghostToolObj->getVisualModel(0)->getRenderMaterial()->setLineWidth(5.0);
ghostToolObj->getVisualModel(0)->getRenderMaterial()->setOpacity(0.3);
ghostToolObj->getVisualModel(0)->getRenderMaterial()->setIsDynamicMesh(false);
scene->addSceneObject(ghostToolObj);

// Update the ghost debug geometry
connect<Event>(viewer, &SceneManager::preUpdate,
  [&](Event*)
  {
    std::shared_ptr<Geometry> toolGhostMesh = ghostToolObj->getVisualGeometry();
    toolGhostMesh->setRotation(controller->getOrientation());
    toolGhostMesh->setTranslation(controller->getPosition());
    toolGhostMesh->updatePostTransformData();
    toolGhostMesh->postModified();
  });

Now all that's needed is:

auto ghostTool = toolObj->addComponent<ObjectControllerGhost>();
ghostTool->setController(myPbdControlller); // Or rigid controller

Additionally it can exist on the tool rather than as a separate object.

Needle & Puncturable

Implements the data part of needles. Eliminates all NeedleObject's in examples. Still no function done in these, just contains needle states. StraightNeedle and ArcNeedle stem from Needle for now. This would be setup like so:

auto needle = needleObj->addComponent<StraightNeedle>();
needle->setLineGeometry(...);
...
tissueObj->addComponent<Puncturable>();

These were designed to support:

  • Puncturing more than one entity
  • Puncturing more than 'thing' (like a face id) on an entity (via a secondary/support id).
  • Inserted, touching, and removed states. Though touching isn't required in all scenarios.

Additionally puncturable is not needed in many scenarios. However, from experience, it allows the tissueObj to have a sense of state without needing the needle. Meaning if you only have tissueObj, you could tell if it was punctured. By coincidence of nice design this also allows puncturing to be used in other contexts besides needles.

ControllerForceText

Displays virtual coupling forces as text via TextVisualModel. Instead of some 100 lines it can be done re-usably like so:

auto vcText = needle->addComponent<VirtualCouplingText>();
vcText->setController(controller);

Debug & Example Defaults

A set of debug & example functionalities were moved or added as components. All of these are added in the examples like so:

// Add default mouse and keyboard controls to the viewer
std::shared_ptr<Entity> mouseAndKeyControls =
  SimulationUtils::createDefaultSceneControlEntity(driver);
scene->addSceneObject(mouseAndKeyControls);

Usage of VTKTextStatusManager was eliminated and replaced with the more general TextVisualModel's.

KeyboardSceneControl & MouseSceneControl

Controls were refactored to be behaviours.

FpsTxtCounter

The FpsTxtCounter moves the implementation of the display of the counter (not the actual counting itself) to its own component. This can now be reused or even omitted entirely. The user can it if they choose, but its provided in a set of defaults provided in the imstk examples. The user can also grab it and tweak font size, etc. It reuses TextVisualModel

PerformanceGraph

Updates the performance graph defined in the VTKRenderer. Only one is ever supported in a scene due to its use of the internals of VTKRenderer. Eventually this should move to a more general graph component with RenderDelegate.

SceneControlText

As before gives a giant text that indicates the state of the simulation. But now its independent of the KeyboardSceneControl and MouseSceneControl. So you don't need these control scheme's to use this. It is provided by default in examples via: createDefaultSceneControlEntity.

AxesObject

Also used in debug. But now reuseable elsewhere such as in the SDFHaptics example which was loading its own axes.

DebugGeometryObject -> DebugGeometryModel, CollisionDataDebugObject -> CollisionDataDebugModel

Object moved to component. Renamed as model is more in line with our other VisualModel, AxesModel, TextVisualModel components.

Edited by Andrew Wilson

Merge request reports