iMSTK
Interactive Medical Simulation Toolkit
All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Pages
pbdClothRemapExample.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 "imstkGeometryUtilities.h"
10 #include "imstkKeyboardDeviceClient.h"
11 #include "imstkKeyboardSceneControl.h"
12 #include "imstkMouseDeviceClient.h"
13 #include "imstkMouseSceneControl.h"
14 #include "imstkNew.h"
15 #include "imstkPbdModel.h"
16 #include "imstkPbdModelConfig.h"
17 #include "imstkPbdObject.h"
18 #include "imstkRenderMaterial.h"
19 #include "imstkScene.h"
20 #include "imstkSceneManager.h"
21 #include "imstkSimulationManager.h"
22 #include "imstkSimulationUtils.h"
23 #include "imstkSpotLight.h"
24 #include "imstkSurfaceMesh.h"
25 #include "imstkSurfaceMeshSubdivide.h"
26 #include "imstkVisualModel.h"
27 #include "imstkVTKViewer.h"
28 
29 using namespace imstk;
30 
39 static std::shared_ptr<PbdObject>
40 makeClothObj(const std::string& name,
41  const double width,
42  const double height,
43  const int nRows,
44  const int nCols)
45 {
46  imstkNew<PbdObject> clothObj(name);
47 
48  // Setup the Geometry
49  std::shared_ptr<SurfaceMesh> clothMesh =
50  GeometryUtils::toTriangleGrid(Vec3d::Zero(),
51  Vec2d(width, height), Vec2i(nRows, nCols));
52 
53  // Setup the Parameters
54  imstkNew<PbdModelConfig> pbdParams;
55  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1.0e2);
56  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 1.0e1);
57  pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
58  pbdParams->m_dt = 0.01;
59  pbdParams->m_iterations = 5;
60 
61  // Setup the Model
62  imstkNew<PbdModel> pbdModel;
63  pbdModel->configure(pbdParams);
64 
65  // Setup the VisualModel
66  imstkNew<RenderMaterial> material;
67  material->setBackFaceCulling(false);
68  material->setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface);
69 
70  imstkNew<VisualModel> visualModel;
71  visualModel->setGeometry(clothMesh);
72  visualModel->setRenderMaterial(material);
73 
74  // Setup the Object
75  clothObj->addVisualModel(visualModel);
76  clothObj->setPhysicsGeometry(clothMesh);
77  clothObj->setDynamicalModel(pbdModel);
78  clothObj->getPbdBody()->fixedNodeIds = { 0, nCols - 1 };
79  clothObj->getPbdBody()->uniformMassValue = width * height / (nRows * nCols);
80 
81  return clothObj;
82 }
83 
88 int
89 main()
90 {
91  // Write log to stdout and file
93 
94  // Setup a scene
95  imstkNew<Scene> scene("PBDCloth");
96  scene->getActiveCamera()->setFocalPoint(0.0, -5.0, 0.0);
97  scene->getActiveCamera()->setPosition(0.0, 1.5, 25.0);
98  scene->getActiveCamera()->setViewUp(0.0, 1.0, 0.0);
99 
100  std::shared_ptr<PbdObject> clothObj = makeClothObj("Cloth", 10.0, 10.0, 8, 8);
101  scene->addSceneObject(clothObj);
102 
103  // Light (white)
104  imstkNew<DirectionalLight> whiteLight;
105  whiteLight->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
106  whiteLight->setIntensity(1.0);
107  scene->addLight("whitelight", whiteLight);
108 
109  // Light (red)
110  imstkNew<SpotLight> colorLight;
111  colorLight->setPosition(Vec3d(-5.0, -3.0, 5.0));
112  colorLight->setFocalPoint(Vec3d(0.0, -5.0, 5.0));
113  colorLight->setIntensity(100.);
114  colorLight->setColor(Color::Red);
115  colorLight->setSpotAngle(30.0);
116  scene->addLight("colorlight", colorLight);
117 
118  // Run the simulation
119  {
120  // Setup a viewer to render
121  imstkNew<VTKViewer> viewer;
122  viewer->setActiveScene(scene);
123 
124  // Setup a scene manager to advance the scene
125  imstkNew<SceneManager> sceneManager;
126  sceneManager->setActiveScene(scene);
127  sceneManager->pause(); // Start simulation paused
128 
130  driver->addModule(viewer);
131  driver->addModule(sceneManager);
132  driver->setDesiredDt(0.005);
133 
134  // Add default mouse and keyboard controls to the viewer
135  std::shared_ptr<Entity> mouseAndKeyControls =
136  SimulationUtils::createDefaultSceneControl(driver);
137  scene->addSceneObject(mouseAndKeyControls);
138 
139  // Queue keypress to be called after scene thread
140  queueConnect<KeyEvent>(viewer->getKeyboardDevice(), &KeyboardDeviceClient::keyPress, sceneManager, [&](KeyEvent* e)
141  {
142  // When i is pressed replace the PBD cloth with a subdivided one
143  if (e->m_key == 'i')
144  {
145  // This has a number of issues that make it not physically realistic
146  // - Mass is not conservative when interpolated from subdivide
147  // - Constraint resting lengths are not correctly reinited
148  std::shared_ptr<SurfaceMesh> clothMesh = std::dynamic_pointer_cast<SurfaceMesh>(clothObj->getPhysicsGeometry());
150  subdiv->setInputMesh(clothMesh);
151  subdiv->setNumberOfSubdivisions(1);
152  subdiv->setSubdivisionType(SurfaceMeshSubdivide::Type::LINEAR);
153  subdiv->update();
154  std::shared_ptr<SurfaceMesh> newClothMesh = subdiv->getOutputMesh();
155 
156  // RenderDelegates cannot visually have entire geometries swapped yet, so even though we could just set the geometry
157  // on the model, you would not visually see it. Instead we replace the vertex and index buffers of the existing one
158  // Another issue here is that initial geometry is not remapped so reset will not reset to undeformed config
159  clothMesh->setInitialVertexPositions(std::make_shared<VecDataArray<double, 3>>(*newClothMesh->getVertexPositions()));
160  clothMesh->setVertexPositions(newClothMesh->getVertexPositions());
161  clothMesh->setCells(newClothMesh->getCells());
162  clothMesh->setVertexAttribute("Velocities", newClothMesh->getVertexAttribute("Velocities"));
163  clothMesh->postModified();
164 
165  // Re-setup the constraints on the object
166  clothObj->initialize();
167  clothObj->getPbdModel()->initialize();
168  }
169  });
170 
171  driver->start();
172  }
173 
174  return 0;
175 }
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.
void setColor(const Color &c)
Set the light color.
Definition: imstkLight.h:61
std::shared_ptr< KeyboardDeviceClient > getKeyboardDevice() const override
Returns the device that emits key events.
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.
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
Provides the information of a key event (press, release, & which key)
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
void setRenderMaterial(std::shared_ptr< RenderMaterial > renderMaterial)
Set/Get render material.
double m_dt
Time step size.
void setSpotAngle(const double angle)
Set the spotlight angle in degrees.
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.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
Vec3d m_gravity
Gravity acceleration.