iMSTK
Interactive Medical Simulation Toolkit
SPH-Obj-SDFInteractionExample.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 "imstkDirectionalLight.h"
9 #include "imstkKeyboardDeviceClient.h"
10 #include "imstkKeyboardSceneControl.h"
11 #include "imstkMeshIO.h"
12 #include "imstkMouseDeviceClient.h"
13 #include "imstkMouseSceneControl.h"
14 #include "imstkNew.h"
15 #include "imstkRenderMaterial.h"
16 #include "imstkScene.h"
17 #include "imstkSceneManager.h"
18 #include "imstkSignedDistanceField.h"
19 #include "imstkSimulationManager.h"
20 #include "imstkSimulationUtils.h"
21 #include "imstkSphModel.h"
22 #include "imstkSphObject.h"
23 #include "imstkSphObjectCollision.h"
24 #include "imstkSurfaceMesh.h"
25 #include "imstkSurfaceMeshDistanceTransform.h"
26 #include "imstkViewer.h"
27 #include "imstkVisualModel.h"
28 #include "imstkVTKViewer.h"
29 
30 using namespace imstk;
31 
35 std::shared_ptr<VecDataArray<double, 3>>
36 generateBoxShapeFluid(const double particleRadius, const Vec3d& boxCenter, const Vec3d& boxSize)
37 {
38  double bounds[6] =
39  {
40  boxCenter.x() - boxSize.x() * 0.5,
41  boxCenter.x() + boxSize.x() * 0.5,
42  boxCenter.y() - boxSize.y() * 0.5,
43  boxCenter.y() + boxSize.y() * 0.5,
44  boxCenter.z() - boxSize.z() * 0.5,
45  boxCenter.z() + boxSize.z() * 0.5
46  };
47 
48  const double spacing = 2.0 * particleRadius;
49  const Vec3i dim = {
50  static_cast<int>(boxSize.x() / spacing),
51  static_cast<int>(boxSize.y() / spacing),
52  static_cast<int>(boxSize.z() / spacing)
53  };
54 
56  particles->reserve(dim[0] * dim[1] * dim[2]);
57 
58  for (double z = bounds[4]; z < bounds[5]; z += spacing)
59  {
60  for (double y = bounds[2]; y < bounds[3]; y += spacing)
61  {
62  for (double x = bounds[0]; x < bounds[1]; x += spacing)
63  {
64  particles->push_back(Vec3d(x, y, z));
65  }
66  }
67  }
68 
69  return particles;
70 }
71 
72 std::shared_ptr<SphObject>
73 makeSPHBoxObject(const std::string& name, const double particleRadius, const Vec3d& boxShift, const Vec3d& boxSize)
74 {
75  // Create the sph object
76  imstkNew<SphObject> fluidObj(name);
77 
78  // Setup the Geometry
79  std::shared_ptr<VecDataArray<double, 3>> particles = generateBoxShapeFluid(particleRadius, boxShift, boxSize);
80  LOG(INFO) << "Number of particles: " << particles->size();
81  imstkNew<PointSet> fluidGeometry;
82  fluidGeometry->initialize(particles);
83 
84  // Setup the Parameters
85  imstkNew<SphModelConfig> sphParams(particleRadius);
86  sphParams->m_bNormalizeDensity = true;
87  sphParams->m_kernelOverParticleRadiusRatio = 6.0;
88  //sphParams->m_viscosityCoeff = 0.5;
89  sphParams->m_surfaceTensionStiffness = 5.0;
90  sphParams->m_gravity = Vec3d(0.0, -70.0, 0.0);
91 
92  // Setup the Model
93  imstkNew<SphModel> sphModel;
94  sphModel->setModelGeometry(fluidGeometry);
95  sphModel->configure(sphParams);
96  sphModel->setTimeStepSizeType(TimeSteppingType::RealTime);
97 
98  // Setup the VisualModel
99  imstkNew<VisualModel> fluidVisualModel;
100  fluidVisualModel->setGeometry(fluidGeometry);
101  imstkNew<RenderMaterial> fluidMaterial;
102  fluidMaterial->setDisplayMode(RenderMaterial::DisplayMode::Fluid);
103  fluidMaterial->setVertexColor(Color::Orange);
104  fluidMaterial->setPointSize(particleRadius);
105  fluidVisualModel->setRenderMaterial(fluidMaterial);
106 
107  // Setup the Object
108  fluidObj->addVisualModel(fluidVisualModel);
109  fluidObj->setCollidingGeometry(fluidGeometry);
110  fluidObj->setDynamicalModel(sphModel);
111  fluidObj->setPhysicsGeometry(fluidGeometry);
112 
113  return fluidObj;
114 }
115 
116 static std::shared_ptr<CollidingObject>
117 makeDragonCollidingObject(const std::string& name, const Vec3d& position)
118 {
119  // Create the pbd object
120  imstkNew<CollidingObject> collidingObj(name);
121 
122  // Setup the Geometry (read dragon mesh)
123  auto dragonSurfMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT "/asianDragon/asianDragon.obj");
124  dragonSurfMesh->translate(position, Geometry::TransformType::ApplyToData);
125 
127  computeSdf->setInputMesh(dragonSurfMesh);
128  computeSdf->setDimensions(100, 100, 100);
129  computeSdf->update();
130 
131  // Setup the VisualModel
132  imstkNew<RenderMaterial> material;
133  material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
134  imstkNew<VisualModel> surfMeshModel;
135  surfMeshModel->setGeometry(dragonSurfMesh);
136  surfMeshModel->setRenderMaterial(material);
137 
138  // Setup the Object
139  collidingObj->addVisualModel(surfMeshModel);
140  collidingObj->setCollidingGeometry(std::make_shared<SignedDistanceField>(computeSdf->getOutputImage()));
141 
142  return collidingObj;
143 }
144 
149 int
150 main()
151 {
152  // Write log to stdout and file
154 
155  // Setup the scene
156  imstkNew<Scene> scene("SPH-Obj-SDFInteraction");
157  {
158  //scene->getConfig()->taskTimingEnabled = true;
159  scene->getActiveCamera()->setPosition(0, 2.0, 15.0);
160 
161  // Static Dragon object
162  std::shared_ptr<CollidingObject> dragonObj = makeDragonCollidingObject("Dragon", Vec3d(0.0, 0.0, 0.0));
163  scene->addSceneObject(dragonObj);
164 
165  // SPH fluid box overtop the dragon
166  std::shared_ptr<SphObject> sphFluidBox = makeSPHBoxObject("Box", 0.1, Vec3d(0.0, 7.0, 0.0), Vec3d(3.0, 7.0, 3.0));
167  scene->addSceneObject(sphFluidBox);
168 
169  // Interaction
170  scene->addInteraction(
171  std::make_shared<SphObjectCollision>(sphFluidBox, dragonObj));
172 
173  // Light
175  light->setDirection(0.0, -1.0, -1.0);
176  light->setIntensity(1);
177  scene->addLight("light", light);
178  }
179 
180  // Run the simulation
181  {
182  // Setup a viewer to render in its own thread
183  imstkNew<VTKViewer> viewer;
184  viewer->setActiveScene(scene);
185  viewer->setBackgroundColors(Color(0.3285, 0.3285, 0.6525), Color(0.13836, 0.13836, 0.2748), true);
186 
187  // Setup a scene manager to advance the scene in its own thread
188  imstkNew<SceneManager> sceneManager("Scene Manager 1");
189  sceneManager->setActiveScene(scene);
190  sceneManager->pause(); // Start simulation paused
191 
193  driver->addModule(viewer);
194  driver->addModule(sceneManager);
195  driver->setDesiredDt(0.03);
196 
197  // Add default mouse and keyboard controls to the viewer
198  std::shared_ptr<Entity> mouseAndKeyControls =
199  SimulationUtils::createDefaultSceneControl(driver);
200  scene->addSceneObject(mouseAndKeyControls);
201 
202  driver->start();
203  }
204 
205  return 0;
206 }
void initialize(std::shared_ptr< VecDataArray< double, 3 >> positions)
Initializes the data structure given vertex positions.
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.
void configure(const std::shared_ptr< SphModelConfig > &params)
Set simulation parameters.
Definition: imstkSphModel.h:90
Renders a set of points using a screen-space fluid renderer.
virtual void setTimeStepSizeType(const TimeSteppingType type)
Get/Set the type of approach used to update the time step size after every frame. ...
Compound Geometry.
void addModule(std::shared_ptr< Module > module) override
Add a module to run.
virtual void setBackgroundColors(const Color color1, const Color color2=Color(0.0, 0.0, 0.0), const bool gradientBackground=false) override
Set the coloring of the screen background If &#39;gradientBackground&#39; is false or not supplied color1 wil...
void setIntensity(const double intensity)
Set the light intensity. This value is unbounded.
Definition: imstkLight.h:71
std::shared_ptr<T> obj = std::make_shared<T>(); equivalent, convenience class for STL shared allocati...
Definition: imstkNew.h:29
void update()
Do the actual algorithm.
void setModelGeometry(std::shared_ptr< Geometry > geometry)
Sets the model geometry.
void setRenderMaterial(std::shared_ptr< RenderMaterial > renderMaterial)
Set/Get render material.
void setDirection(const Vec3d &dir)
Set the direction of the light.
Color in RGB space.
Definition: imstkColor.h:24
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
void setInputMesh(std::shared_ptr< SurfaceMesh > surfMesh)
Required input, port 0.