iMSTK
Interactive Medical Simulation Toolkit
RenderingCustomDelegateExample.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 "imstkCamera.h"
8 #include "imstkDataArray.h"
9 #include "imstkDirectionalLight.h"
10 #include "imstkDummyClient.h"
11 #include "imstkKeyboardDeviceClient.h"
12 #include "imstkKeyboardSceneControl.h"
13 #include "imstkLogger.h"
14 #include "imstkMeshIO.h"
15 #include "imstkMouseDeviceClient.h"
16 #include "imstkMouseSceneControl.h"
17 #include "imstkNew.h"
18 #include "imstkRbdConstraint.h"
19 #include "imstkRenderDelegateObjectFactory.h"
20 #include "imstkRenderMaterial.h"
21 #include "imstkRigidBodyModel2.h"
22 #include "imstkRigidObject2.h"
23 #include "imstkRigidObjectController.h"
24 #include "imstkScene.h"
25 #include "imstkSceneManager.h"
26 #include "imstkSimulationManager.h"
27 #include "imstkSimulationUtils.h"
28 #include "imstkSurfaceMesh.h"
29 #include "imstkVTKChartRenderDelegate.h"
30 #include "imstkVTKViewer.h"
31 
32 using namespace imstk;
33 
37 template<typename T>
38 static void
39 queueToArray(std::deque<T>& vals, DataArray<T>& arr)
40 {
41  arr.resize(vals.size());
42  size_t i = 0;
43  for (auto val : vals)
44  {
45  arr[i++] = val;
46  }
47 }
48 
52 template<typename T>
53 static std::shared_ptr<DataArray<T>>
54 seqArray(int size)
55 {
56  auto arrPtr = std::make_shared<DataArray<T>>(size);
57  DataArray<T>& arr = *arrPtr;
58  for (int i = 0; i < size; i++)
59  {
60  arr[i] = static_cast<T>(i);
61  }
62  return arrPtr;
63 }
64 
69 int
70 main()
71 {
72  // Tell the factory to utilize the VTKChartRenderDelegate, for the delegate hint "Chart"
73  RenderDelegateRegistrar<VTKChartRenderDelegate> registerChartDelegate("Chart");
74 
75  // Setup logger (write to file and stdout)
77 
78  // Scene
79  imstkNew<Scene> scene("RenderingCustomDelegate");
80 
81  const int rbdCount = 2;
82  std::vector<std::shared_ptr<RigidObject2>> rbdObjs(rbdCount);
83  std::vector<std::shared_ptr<RigidObjectController>> rbdControllers(rbdCount);
84  std::vector<std::shared_ptr<DummyClient>> deviceClients(rbdCount);
85  for (int i = 0; i < rbdCount; i++)
86  {
87  rbdObjs[i] = std::make_shared<RigidObject2>("rbdObj" + std::to_string(i));
88  {
90  rbdModel->getConfig()->m_dt = 0.001;
91  rbdModel->getConfig()->m_gravity = Vec3d::Zero();
92  rbdObjs[i]->setDynamicalModel(rbdModel);
93  rbdObjs[i]->getRigidBody()->m_mass = 0.5;
94  rbdObjs[i]->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 1000000.0;
95  rbdObjs[i]->getRigidBody()->m_initPos = Vec3d(1.0, 0.0, 0.0); // Start the tool a unit off from controller
96 
97  auto surfMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/Surgical Instruments/Scissors/Metzenbaum Scissors/Metz_Scissors.stl");
98  rbdObjs[i]->setCollidingGeometry(surfMesh);
99  rbdObjs[i]->setVisualGeometry(surfMesh);
100  rbdObjs[i]->setPhysicsGeometry(surfMesh);
101 
102  std::shared_ptr<RenderMaterial> mat = rbdObjs[i]->getVisualModel(0)->getRenderMaterial();
103  mat->setShadingModel(RenderMaterial::ShadingModel::PBR);
104  mat->setRoughness(0.5);
105  mat->setMetalness(1.0);
106  }
107  scene->addSceneObject(rbdObjs[i]);
108 
109  deviceClients[i] = std::make_shared<DummyClient>("test");
110 
111  // Create a virtual coupling controller
112  rbdControllers[i] = std::make_shared<RigidObjectController>();
113  rbdControllers[i]->setControlledObject(rbdObjs[i]);
114  rbdControllers[i]->setDevice(deviceClients[i]);
115  if (i == 0)
116  {
117  rbdControllers[i]->setLinearKs(10.0);
118  rbdControllers[i]->setLinearKd(1.0);
119  }
120  else
121  {
122  rbdControllers[i]->setLinearKs(30.0);
123  rbdControllers[i]->setLinearKd(1.0);
124  }
125  rbdControllers[i]->setAngularKs(1000000000.0);
126  rbdControllers[i]->setAngularKd(300000000.0);
127  rbdControllers[i]->setTranslationScaling(1.0);
128  //controller->setTranslationScaling(0.02);
129  rbdControllers[i]->setForceScaling(0.001);
130  scene->addControl(rbdControllers[i]);
131  }
132 
133  // Graph the springs with this object
134  imstkNew<SceneObject> graphObject("Graph");
135  imstkNew<ChartVisualModel> chartModel;
136  graphObject->addVisualModel(chartModel);
137  chartModel->setViewBounds(Vec4d(0.0, 1000.0, 0.0, 300.0));
138  scene->addSceneObject(graphObject);
139 
140  // Camera
141  scene->getActiveCamera()->setPosition(Vec3d(0.0, 5.0, 10.0));
142  scene->getActiveCamera()->setFocalPoint(Vec3d(0.0, -1.0, 0.0));
143  scene->getActiveCamera()->setViewUp(Vec3d(0.0, 1.0, 0.0));
144 
145  // Light
147  light->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
148  light->setIntensity(1.0);
149  scene->addLight("light0", light);
150 
151  // Run the simulation
152  {
153  // Setup a viewer to render
154  imstkNew<VTKViewer> viewer;
155  viewer->setActiveScene(scene);
156 
157  // Setup a scene manager to advance the scene
158  imstkNew<SceneManager> sceneManager;
159  sceneManager->setActiveScene(scene);
160 
162  //driver->addModule(hapticsManager);
163  driver->addModule(viewer);
164  driver->addModule(sceneManager);
165  driver->setDesiredDt(0.001);
166 
167  // Setup some queues to keep running track of spring forces
168  const int recordSize = 5000;
169  auto timesPtr = std::make_shared<DataArray<double>>(recordSize);
170 
171  std::deque<double> timesQueue;
172  for (int j = 0; j < recordSize; j++)
173  {
174  timesQueue.push_back(0.0);
175  }
176  queueToArray(timesQueue, *timesPtr);
177 
178  std::vector<std::deque<double>> springForceQueues(rbdCount);
179  std::vector<std::shared_ptr<DataArray<double>>> springForcesPtrs(rbdCount);
180  std::vector<Plot2d> plots(rbdCount);
181  for (int i = 0; i < rbdCount; i++)
182  {
183  springForcesPtrs[i] = std::make_shared<DataArray<double>>(recordSize);
184  for (int j = 0; j < recordSize; j++)
185  {
186  springForceQueues[i].push_back(0.0);
187  }
188  queueToArray(springForceQueues[i], *springForcesPtrs[i]);
189 
190  Plot2d plot;
191  plot.xVals = timesPtr;
192  plot.yVals = springForcesPtrs[i];
193  if (i == 0)
194  {
195  plot.lineColor = Color::Red;
196  }
197  else if (i == 1)
198  {
199  plot.lineColor = Color::Green;
200  }
201  else if (i == 2)
202  {
203  plot.lineColor = Color::Blue;
204  }
205  chartModel->addPlot(plot);
206  }
207 
208  double t = 0.0;
209  connect<Event>(sceneManager, &SceneManager::postUpdate,
210  [&](Event*)
211  {
212  t += sceneManager->getDt();
213 
214  timesQueue.pop_front();
215  timesQueue.push_back(t);
216  queueToArray(timesQueue, *timesPtr);
217 
218  for (int i = 0; i < rbdCount; i++)
219  {
220  springForceQueues[i].pop_front();
221  springForceQueues[i].push_back(rbdControllers[i]->getSpringForce().norm());
222  queueToArray(springForceQueues[i], *springForcesPtrs[i]);
223  }
224  });
225 
226  connect<Event>(sceneManager, &SceneManager::postUpdate, [&](Event*)
227  {
228  // Run the rbd model in real time
229  for (int i = 0; i < rbdCount; i++)
230  {
231  rbdObjs[i]->getRigidBodyModel2()->getConfig()->m_dt = sceneManager->getDt();
232  }
233  });
234 
235  // Add default mouse and keyboard controls to the viewer
236  std::shared_ptr<Entity> mouseAndKeyControls =
237  SimulationUtils::createDefaultSceneControl(driver);
238  scene->addSceneObject(mouseAndKeyControls);
239 
240  driver->start();
241  }
242 
243  return 0;
244 }
void setDesiredDt(const double dt)
Sets the target fixed timestep (may violate), seconds This ultimately effects the number of iteration...
void setActiveScene(std::shared_ptr< Scene > scene) override
Set scene to be rendered.
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Compound Geometry.
void addModule(std::shared_ptr< Module > module) override
Add a module to run.
void setIntensity(const double intensity)
Set the light intensity. This value is unbounded.
Definition: imstkLight.h:71
double getDt() const
Get/Set the time step.
Definition: imstkModule.h:63
std::shared_ptr<T> obj = std::make_shared<T>(); equivalent, convenience class for STL shared allocati...
Definition: imstkNew.h:29
void resize(const int size) override
Resize data array to hold exactly size number of values.
void setFocalPoint(const Vec3d &p)
Get/Set the light focal point.
Definition: imstkLight.h:33
void setActiveScene(std::string newSceneName)
Sets the currently updating scene.
Physically based rendering.
Simple dynamic array implementation that also supports event posting and viewing/facade.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
Templated class that can add to the object factory with objects that will be generated via std::make_...
Definition: imstkFactory.h:87