iMSTK
Interactive Medical Simulation Toolkit
SDFHapticsExample.cpp
1 /*
2 ** This file is part of the Interactive Medical Simulation Toolkit (iMSTK)
3 ** iMSTK is distributed under the Apache License, Version 2.0.
4 ** See accompanying NOTICE for details.
5 */
6 
7 #include "imstkAxesModel.h"
8 #include "imstkCamera.h"
9 #include "imstkCollidingObject.h"
10 #include "imstkDeviceManager.h"
11 #include "imstkDeviceManagerFactory.h"
12 #include "imstkDirectionalLight.h"
13 #include "imstkImplicitFunctionFiniteDifferenceFunctor.h"
14 #include "imstkKeyboardDeviceClient.h"
15 #include "imstkMeshIO.h"
16 #include "imstkScene.h"
17 #include "imstkSceneManager.h"
18 #include "imstkSimulationManager.h"
19 #include "imstkSimulationUtils.h"
20 #include "imstkSurfaceMesh.h"
21 #include "imstkSurfaceMeshFlyingEdges.h"
22 #include "imstkVTKViewer.h"
23 
24 using namespace imstk;
25 
30 int
31 main()
32 {
33  // Setup logger (write to file and stdout)
35 
36  auto scene = std::make_shared<Scene>("SDFHaptics");
37  scene->getActiveCamera()->setPosition(-2.3, 23.81, 45.65);
38  scene->getActiveCamera()->setFocalPoint(9.41, 8.45, 5.76);
39 
40  auto bunnyObj = std::make_shared<CollidingObject>("Bunny");
41  std::shared_ptr<ImageData> sdfImage = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/stanfordBunny/stanfordBunny_SDF.nii");
42  auto sdf = std::make_shared<SignedDistanceField>(sdfImage->cast(IMSTK_DOUBLE));
43  {
44  bunnyObj->setCollidingGeometry(sdf);
45 
46  SurfaceMeshFlyingEdges isoExtract;
47  isoExtract.setInputImage(sdfImage);
48  isoExtract.update();
49 
50  isoExtract.getOutputMesh()->flipNormals();
51  bunnyObj->setVisualGeometry(isoExtract.getOutputMesh());
52  }
53  scene->addSceneObject(bunnyObj);
54 
55  auto axesObj = std::make_shared<Entity>("Axes");
56  auto axesModel = axesObj->addComponent<AxesModel>("AxesModel");
57  scene->addSceneObject(axesObj);
58 
59  // Light
60  auto light = std::make_shared<DirectionalLight>();
61  light->setDirection(Vec3d(0.0, -8.0, -5.0));
62  light->setIntensity(1.0);
63  scene->addLight("light", light);
64 
65  // Setup default haptics manager
66  std::shared_ptr<DeviceManager> hapticManager = DeviceManagerFactory::makeDeviceManager();
67  std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
68 
69  // Run the simulation
70  {
71  // Setup a viewer to render in its own thread
72  auto viewer = std::make_shared<VTKViewer>();
73  viewer->setActiveScene(scene);
74 
75  // Setup a scene manager to advance the scene in its own thread
76  auto sceneManager = std::make_shared<SceneManager>();
77  sceneManager->setActiveScene(scene);
78 
79  auto driver = std::make_shared<SimulationManager>();
80  driver->addModule(viewer);
81  driver->addModule(sceneManager);
82  driver->addModule(hapticManager);
83 
85  centralGrad.setFunction(sdf);
86  centralGrad.setDx(sdf->getImage()->getSpacing());
87  connect<Event>(sceneManager, &SceneManager::postUpdate, [&](Event*)
88  {
89  const Vec3d pos = deviceClient->getPosition() * 100.0 + Vec3d(10.0, 0.1, 10.0);
90 
91  axesModel->setPosition(pos);
92  axesModel->setOrientation(deviceClient->getOrientation());
93 
94  double dx = sdf->getFunctionValue(pos);
95  if (dx < 0.0)
96  {
97  const Vec3d g = centralGrad(pos);
98  deviceClient->setForce(-g.normalized() * dx * 4.0);
99  }
100  });
101 
102  // Add default mouse and keyboard controls to the viewer
103  std::shared_ptr<Entity> mouseAndKeyControls =
104  SimulationUtils::createDefaultSceneControl(driver);
105  scene->addSceneObject(mouseAndKeyControls);
106 
107  driver->start();
108  }
109 
110  return 0;
111 }
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Compound Geometry.
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
This filter extracts a single isocontour from an imstkImageData.
void update()
Do the actual algorithm.
Gradient given by central finite differences.
Defines an axes that should be rendered.
void setInputImage(std::shared_ptr< ImageData > inputImage)
Required input, port 0.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.