iMSTK
Interactive Medical Simulation Toolkit
pbdClothGrabExample.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 "imstkCollisionUtils.h"
9 #include "imstkGeometryUtilities.h"
10 #include "imstkImageData.h"
11 #include "imstkKeyboardDeviceClient.h"
12 #include "imstkKeyboardSceneControl.h"
13 #include "imstkMeshIO.h"
14 #include "imstkMouseDeviceClient.h"
15 #include "imstkMouseSceneControl.h"
16 #include "imstkNew.h"
17 #include "imstkPbdModel.h"
18 #include "imstkPbdModelConfig.h"
19 #include "imstkPbdObject.h"
20 #include "imstkPbdObjectCollision.h"
21 #include "imstkPbdObjectGrasping.h"
22 #include "imstkPlane.h"
23 #include "imstkRenderMaterial.h"
24 #include "imstkScene.h"
25 #include "imstkSceneManager.h"
26 #include "imstkSimulationManager.h"
27 #include "imstkSimulationUtils.h"
28 #include "imstkSphere.h"
29 #include "imstkSurfaceMesh.h"
30 #include "imstkVisualModel.h"
31 #include "imstkVTKViewer.h"
32 
33 using namespace imstk;
34 
43 static std::shared_ptr<PbdObject>
44 makeThinTissueObj(const std::string& name,
45  const Vec2d size,
46  const Vec2i dim,
47  const Vec3d pos)
48 {
49  imstkNew<PbdObject> tissueObj(name);
50 
51  // Setup the Geometry
52  std::shared_ptr<SurfaceMesh> tissueMesh =
53  GeometryUtils::toTriangleGrid(pos, size, dim,
54  Quatd::Identity(), 2.0);
55 
56  // Setup the DynamicalModel parameters
57  imstkNew<PbdModelConfig> pbdParams;
58  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1.0e2);
59  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 0.05);
60  pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
61  pbdParams->m_dt = 0.005;
62  pbdParams->m_iterations = 10;
63 
64  // Setup the DynamicalModel to simulate
65  imstkNew<PbdModel> pbdModel;
66  pbdModel->configure(pbdParams);
67 
68  // Setup the material for rendering
69  imstkNew<RenderMaterial> material;
70  material->setBackFaceCulling(false);
71  material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
72  material->setShadingModel(RenderMaterial::ShadingModel::PBR);
73  auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshDiffuse.jpg");
74  material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
75  auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshNormal.jpg");
76  material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
77  auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshORM.jpg");
78  material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
79 
80  // Setup the VisualModel to render the mesh
81  imstkNew<VisualModel> visualModel;
82  visualModel->setGeometry(tissueMesh);
83  visualModel->setRenderMaterial(material);
84 
85  // Setup the Object
86  tissueObj->addVisualModel(visualModel);
87  tissueObj->setPhysicsGeometry(tissueMesh);
88  tissueObj->setCollidingGeometry(tissueMesh);
89  tissueObj->setDynamicalModel(pbdModel);
90  tissueObj->getPbdBody()->uniformMassValue = size[0] * size[1] / (dim[0] * dim[1]) * 0.01;
91 
92  return tissueObj;
93 }
94 
99 int
100 main()
101 {
102  // Write log to stdout and file
104 
105  // Setup a scene
106  imstkNew<Scene> scene("PbdClothGrab");
107  std::shared_ptr<PbdObject> tissueObj =
108  makeThinTissueObj("Tissue", Vec2d(5.0, 5.0), Vec2i(4, 4), Vec3d(0.0, 6.0, 0.0));
109  scene->addSceneObject(tissueObj);
110 
111  auto planeObj = std::make_shared<CollidingObject>("Plane");
112  imstkNew<Plane> plane(Vec3d(0.0, 0.0, 0.0), Vec3d(0.0, 1.0, 0.0));
113  plane->setWidth(10.0);
114  planeObj->setVisualGeometry(plane);
115  planeObj->getVisualModel(0)->getRenderMaterial()->setDisplayMode(RenderMaterial::DisplayMode::Wireframe);
116  planeObj->setCollidingGeometry(plane);
117  scene->addSceneObject(planeObj);
118 
119  // Adjust camera
120  scene->getActiveCamera()->setFocalPoint(-0.116722, 1.70485, 0.625839);
121  scene->getActiveCamera()->setPosition(2.25549, 8.07292, 14.8692);
122 
123  auto clothCollision = std::make_shared<PbdObjectCollision>(tissueObj, planeObj);
124  clothCollision->setDeformableStiffnessA(0.3);
125  scene->addInteraction(clothCollision);
126 
127  auto pbdGrasping = std::make_shared<PbdObjectGrasping>(tissueObj);
128  pbdGrasping->setStiffness(0.3);
129  scene->addInteraction(pbdGrasping);
130 
131  // Make two sphere's for indication
132  imstkNew<SceneObject> clickObj("clickObj");
133  imstkNew<Sphere> clickSphere(Vec3d(0.0, 0.0, 0.0), 0.1);
134  clickObj->setVisualGeometry(clickSphere);
135  clickObj->getVisualModel(0)->getRenderMaterial()->setShadingModel(RenderMaterial::ShadingModel::None);
136  clickObj->getVisualModel(0)->getRenderMaterial()->setColor(Color::Red);
137  scene->addSceneObject(clickObj);
138 
139  // Run the simulation
140  {
141  // Setup a viewer to render
142  imstkNew<VTKViewer> viewer;
143  viewer->setActiveScene(scene);
144 
145  // Setup a scene manager to advance the scene
146  imstkNew<SceneManager> sceneManager;
147  sceneManager->setActiveScene(scene);
148  sceneManager->pause(); // Start simulation paused
149 
151  driver->addModule(viewer);
152  driver->addModule(sceneManager);
153  driver->setDesiredDt(0.01);
154 
155  // Add default mouse and keyboard controls to the viewer
156  std::shared_ptr<Entity> mouseAndKeyControls =
157  SimulationUtils::createDefaultSceneControl(driver);
158  scene->addSceneObject(mouseAndKeyControls);
159 
160  connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseButtonPress,
161  [&](MouseEvent* e)
162  {
163  if (e->m_buttonId == 0)
164  {
165  // Get mouse position (0, 1) with origin at bot left of screen
166  const Vec2d mousePos = viewer->getMouseDevice()->getPos();
167  // To NDC coordinates
168  const Vec3d rayDir = scene->getActiveCamera()->getEyeRayDir(
169  Vec2d(mousePos[0] * 2.0 - 1.0, mousePos[1] * 2.0 - 1.0));
170  const Vec3d rayStart = scene->getActiveCamera()->getPosition();
171 
172  pbdGrasping->beginRayPointGrasp(clickSphere, rayStart, rayDir);
173  }
174  });
175  connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseMove,
176  [&](MouseEvent*)
177  {
178  // Get mouse position (0, 1) with origin at bot left of screen
179  const Vec2d mousePos = viewer->getMouseDevice()->getPos();
180  // To NDC coordinates
181  const Vec3d rayDir = scene->getActiveCamera()->getEyeRayDir(
182  Vec2d(mousePos[0] * 2.0 - 1.0, mousePos[1] * 2.0 - 1.0));
183  const Vec3d rayStart = scene->getActiveCamera()->getPosition();
184 
185  Vec3d iPt = Vec3d::Zero();
186  if (CollisionUtils::testRayToPlane(rayStart, rayDir,
187  plane->getPosition(), plane->getNormal(), iPt))
188  {
189  clickSphere->setPosition(iPt);
190  }
191  });
192  // Unselect/drop the sphere
193  connect<MouseEvent>(viewer->getMouseDevice(), &MouseDeviceClient::mouseButtonRelease,
194  [&](MouseEvent* e)
195  {
196  if (e->m_buttonId == 0)
197  {
198  pbdGrasping->endGrasp();
199  }
200  });
201 
202  connect<Event>(sceneManager, &SceneManager::preUpdate, [&](Event*)
203  {
204  // Run the model in real time
205  tissueObj->getPbdModel()->getConfig()->m_dt = sceneManager->getDt();
206  });
207 
208  driver->start();
209  }
210 
211  return 0;
212 }
void addTexture(std::shared_ptr< Texture > texture)
Add/Remove/Get texture.
void configure(std::shared_ptr< PbdModelConfig > params)
Set simulation parameters.
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.
std::shared_ptr< SurfaceMesh > toTriangleGrid(const Vec3d &center, const Vec2d &size, const Vec2i &dim, const Quatd orientation=Quatd::Identity(), const double uvScale=1.0)
Produces a triangle grid on a plane given the imstkPlane.
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Renders without shading, no lighting.
Compound Geometry.
void addModule(std::shared_ptr< Module > module) override
Add a module to run.
void enableConstraint(ConstraintGenType type, const double stiffness, const int bodyId=2)
Enables a constraint of type defined by ConstraintGenType with given stiffness. If constraint of that...
unsigned int m_iterations
Internal constraints pbd solver iterations.
std::shared_ptr<T> obj = std::make_shared<T>(); equivalent, convenience class for STL shared allocati...
Definition: imstkNew.h:29
void setRenderMaterial(std::shared_ptr< RenderMaterial > renderMaterial)
Set/Get render material.
double m_dt
Time step size.
Provides the information of a mouse event, this includes button presses/releases and scrolling...
void setActiveScene(std::string newSceneName)
Sets the currently updating scene.
Physically based rendering.
std::shared_ptr< MouseDeviceClient > getMouseDevice() const override
Returns the device that emits mouse events.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
Vec3d m_gravity
Gravity acceleration.