iMSTK
Interactive Medical Simulation Toolkit
PBDFluidsExample.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 "imstkKeyboardDeviceClient.h"
9 #include "imstkKeyboardSceneControl.h"
10 #include "imstkMeshIO.h"
11 #include "imstkMouseDeviceClient.h"
12 #include "imstkMouseSceneControl.h"
13 #include "imstkNew.h"
14 #include "imstkPbdModel.h"
15 #include "imstkPbdModelConfig.h"
16 #include "imstkPbdObject.h"
17 #include "imstkPbdObjectCollision.h"
18 #include "imstkRenderMaterial.h"
19 #include "imstkScene.h"
20 #include "imstkSceneManager.h"
21 #include "imstkSimulationManager.h"
22 #include "imstkSimulationUtils.h"
23 #include "imstkSurfaceMesh.h"
24 #include "imstkVisualModel.h"
25 #include "imstkVTKViewer.h"
26 #include "imstkPbdCollisionHandling.h"
27 
28 using namespace imstk;
29 
30 // mesh file name
31 const std::string tetMeshFileName = iMSTK_DATA_ROOT "/asianDragon/asianDragon.veg";
32 
36 std::shared_ptr<PbdObject>
37 createPbdFluid(const std::string& tetMeshName)
38 {
39  // Load a sample mesh
40  std::shared_ptr<PointSet> tetMesh = MeshIO::read(tetMeshName);
41 
42  imstkNew<PointSet> fluidMesh;
43  fluidMesh->initialize(tetMesh->getInitialVertexPositions());
44 
45  imstkNew<VisualModel> fluidVisualModel;
46  fluidVisualModel->setGeometry(fluidMesh);
47 
48  imstkNew<RenderMaterial> material;
49  material->setDisplayMode(RenderMaterial::DisplayMode::Fluid);
50  material->setVertexColor(Color::Red);
51  material->setPointSize(0.5); // Control visual particle size
52  fluidVisualModel->setRenderMaterial(material);
53 
54  imstkNew<PbdObject> deformableObj("Dragon");
55  deformableObj->addVisualModel(fluidVisualModel);
56  deformableObj->setCollidingGeometry(fluidMesh);
57  deformableObj->setPhysicsGeometry(fluidMesh);
58 
59  imstkNew<PbdModel> pbdModel;
60 
61  // Configure model
62  auto pbdParams = std::make_shared<PbdModelConfig>();
63  const double particleRadius = 0.5;
64  pbdParams->enableConstantDensityConstraint(1.0, particleRadius);
65  pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
66  pbdParams->m_dt = 0.005;
67  pbdParams->m_iterations = 2;
68  pbdModel->configure(pbdParams);
69 
70  deformableObj->setDynamicalModel(pbdModel);
71  deformableObj->getPbdBody()->uniformMassValue = 1.0;
72 
73  return deformableObj;
74 }
75 
79 std::shared_ptr<SurfaceMesh>
80 createCollidingSurfaceMesh()
81 {
83  VecDataArray<double, 3>& vertices = *verticesPtr.get();
84  int nSides = 5;
85  double width = 40.0;
86  double height = 40.0;
87  int nRows = 2;
88  int nCols = 2;
89  vertices.resize(nRows * nCols * nSides);
90  const double dy = width / static_cast<double>(nCols - 1);
91  const double dx = height / static_cast<double>(nRows - 1);
92  for (int i = 0; i < nRows; ++i)
93  {
94  for (int j = 0; j < nCols; j++)
95  {
96  const double y = static_cast<double>(dy * j);
97  const double x = static_cast<double>(dx * i);
98  vertices[i * nCols + j] = Vec3d(x - 20, -10.0, y - 20);
99  }
100  }
101 
102  // c. Add connectivity data
103  std::shared_ptr<VecDataArray<int, 3>> trianglesPtr = std::make_shared<VecDataArray<int, 3>>();
104  VecDataArray<int, 3>& triangles = *trianglesPtr;
105  for (int i = 0; i < nRows - 1; ++i)
106  {
107  for (int j = 0; j < nCols - 1; j++)
108  {
109  triangles.push_back(Vec3i(i * nCols + j, i * nCols + j + 1, (i + 1) * nCols + j));
110  triangles.push_back(Vec3i((i + 1) * nCols + j + 1, (i + 1) * nCols + j, i * nCols + j + 1));
111  }
112  }
113 
114  int nPointPerSide = nRows * nCols;
115  //sidewalls 1 and 2 of box
116  width = 10.0;
117  height = 40.0;
118  nRows = 2;
119  nCols = 2;
120  const double dz = width / static_cast<double>(nCols - 1);
121  const double dx1 = height / static_cast<double>(nRows - 1);
122  for (int i = 0; i < nRows; ++i)
123  {
124  for (int j = 0; j < nCols; j++)
125  {
126  const double z = static_cast<double>(dz * j);
127  const double x = static_cast<double>(dx1 * i);
128  vertices[(nPointPerSide) + i * nCols + j] = Vec3d(x - 20, z - 10.0, 20);
129  vertices[(nPointPerSide * 2) + i * nCols + j] = Vec3d(x - 20, z - 10.0, -20);
130  }
131  }
132 
133  // c. Add connectivity data
134  for (int i = 0; i < nRows - 1; ++i)
135  {
136  for (int j = 0; j < nCols - 1; j++)
137  {
138  triangles.push_back(Vec3i((nPointPerSide) + i * nCols + j, (nPointPerSide) + i * nCols + j + 1, (nPointPerSide) + (i + 1) * nCols + j));
139  triangles.push_back(Vec3i((nPointPerSide) + (i + 1) * nCols + j + 1, (nPointPerSide) + (i + 1) * nCols + j, (nPointPerSide) + i * nCols + j + 1));
140 
141  triangles.push_back(Vec3i((nPointPerSide * 2) + i * nCols + j + 1, (nPointPerSide * 2) + i * nCols + j, (nPointPerSide * 2) + (i + 1) * nCols + j));
142  triangles.push_back(Vec3i((nPointPerSide * 2) + (i + 1) * nCols + j, (nPointPerSide * 2) + (i + 1) * nCols + j + 1, (nPointPerSide * 2) + i * nCols + j + 1));
143  }
144  }
145 
146  //sidewalls 3 and 4 of box
147  width = 10.0;
148  height = 40.0;
149  nRows = 2;
150  nCols = 2;
151  const double dz1 = width / static_cast<double>(nCols - 1);
152  const double dy1 = height / static_cast<double>(nRows - 1);
153  for (int i = 0; i < nRows; ++i)
154  {
155  for (int j = 0; j < nCols; j++)
156  {
157  const double z = static_cast<double>(dz1 * j);
158  const double y = static_cast<double>(dy1 * i);
159  vertices[(nPointPerSide * 3) + i * nCols + j] = Vec3d(20, z - 10.0, y - 20);
160  vertices[(nPointPerSide * 4) + i * nCols + j] = Vec3d(-20, z - 10.0, y - 20);
161  }
162  }
163 
164  // c. Add connectivity data
165  for (int i = 0; i < nRows - 1; ++i)
166  {
167  for (int j = 0; j < nCols - 1; j++)
168  {
169  triangles.push_back(Vec3i((nPointPerSide * 3) + i * nCols + j + 1, (nPointPerSide * 3) + i * nCols + j, (nPointPerSide * 3) + (i + 1) * nCols + j));
170  triangles.push_back(Vec3i((nPointPerSide * 3) + (i + 1) * nCols + j, (nPointPerSide * 3) + (i + 1) * nCols + j + 1, (nPointPerSide * 3) + i * nCols + j + 1));
171 
172  triangles.push_back(Vec3i((nPointPerSide * 4) + i * nCols + j, (nPointPerSide * 4) + i * nCols + j + 1, (nPointPerSide * 4) + (i + 1) * nCols + j));
173  triangles.push_back(Vec3i((nPointPerSide * 4) + (i + 1) * nCols + j + 1, (nPointPerSide * 4) + (i + 1) * nCols + j, (nPointPerSide * 4) + i * nCols + j + 1));
174  }
175  }
176 
177  imstkNew<SurfaceMesh> floorMeshColliding;
178  floorMeshColliding->initialize(verticesPtr, trianglesPtr);
179  return floorMeshColliding;
180 }
181 
186 int
187 main()
188 {
189  // Setup logger (write to file and stdout)
191 
192  imstkNew<Scene> scene("PBDFluid");
193  {
194  scene->getActiveCamera()->setPosition(0.0, 15.0, 20.0);
195 
196  std::shared_ptr<PbdObject> fluidObj = createPbdFluid(tetMeshFileName);
197  scene->addSceneObject(fluidObj);
198 
199  imstkNew<CollidingObject> floorObj("Floor");
200  std::shared_ptr<SurfaceMesh> floorGeom = createCollidingSurfaceMesh();
201  floorObj->setVisualGeometry(floorGeom);
202  floorObj->setCollidingGeometry(floorGeom);
203  scene->addSceneObject(floorObj);
204 
205  // Collisions
206  auto interaction = std::make_shared<PbdObjectCollision>(fluidObj, floorObj);
207  auto handling = std::dynamic_pointer_cast<PbdCollisionHandling>(interaction->getCollisionHandlingA());
208  handling->setEnableBoundaryCollisions(true);
209  scene->addInteraction(interaction);
210  }
211 
212  // Run the simulation
213  {
214  // Setup a viewer to render
215  imstkNew<VTKViewer> viewer;
216  viewer->setActiveScene(scene);
217 
218  // Setup a scene manager to advance the scene
219  imstkNew<SceneManager> sceneManager;
220  sceneManager->setActiveScene(scene);
221  sceneManager->pause(); // Start simulation paused
222 
224  driver->addModule(viewer);
225  driver->addModule(sceneManager);
226 
227  // Add default mouse and keyboard controls to the viewer
228  std::shared_ptr<Entity> mouseAndKeyControls =
229  SimulationUtils::createDefaultSceneControl(driver);
230  scene->addSceneObject(mouseAndKeyControls);
231 
232  driver->start();
233  }
234 
235  return 0;
236 }
void initialize(std::shared_ptr< VecDataArray< double, 3 >> positions)
Initializes the data structure given vertex positions.
void configure(std::shared_ptr< PbdModelConfig > params)
Set simulation parameters.
void setActiveScene(std::shared_ptr< Scene > scene) override
Set scene to be rendered.
Implements PBD based collision handling. Given an input PbdObject and CollisionData it creates & adds...
Renders a set of points using a screen-space fluid renderer.
Compound Geometry.
void addModule(std::shared_ptr< Module > module) override
Add a module to run.
void initialize(std::shared_ptr< VecDataArray< double, 3 >> vertices, std::shared_ptr< VecDataArray< int, 3 >> triangleIndices, const bool computeDerivedData=false)
Initializes the rest of the data structures given vertex positions and triangle connectivity.
void resize(const int size) override
Resize data array to hold exactly size number of values.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
const std::shared_ptr< T > & get() const
Returns const ref to STL smart pointer.
Definition: imstkNew.h:56
std::shared_ptr<T> obj = std::make_shared<T>(); equivalent, convenience class for STL shared allocati...
Definition: imstkNew.h:29
void setEnableBoundaryCollisions(const bool enableBoundaryCollisions)
Get enableBoundaryCollision.
void setRenderMaterial(std::shared_ptr< RenderMaterial > renderMaterial)
Set/Get render material.
static std::shared_ptr< PointSet > read(const std::string &filePath)
Read external file.
Definition: imstkMeshIO.cpp:46
void setActiveScene(std::string newSceneName)
Sets the currently updating scene.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.