iMSTK
Interactive Medical Simulation Toolkit
pbdClothExample.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 "imstkGeometryUtilities.h"
9 #include "imstkImageData.h"
10 #include "imstkKeyboardDeviceClient.h"
11 #include "imstkKeyboardSceneControl.h"
12 #include "imstkMeshIO.h"
13 #include "imstkMouseDeviceClient.h"
14 #include "imstkMouseSceneControl.h"
15 #include "imstkNew.h"
16 #include "imstkPbdModel.h"
17 #include "imstkPbdModelConfig.h"
18 #include "imstkPbdObject.h"
19 #include "imstkRenderMaterial.h"
20 #include "imstkScene.h"
21 #include "imstkSceneManager.h"
22 #include "imstkSimulationManager.h"
23 #include "imstkSimulationUtils.h"
24 #include "imstkSurfaceMesh.h"
25 #include "imstkVisualModel.h"
26 #include "imstkVTKViewer.h"
27 
28 using namespace imstk;
29 
30 static void
31 setFabricTextures(std::shared_ptr<RenderMaterial> material)
32 {
33  auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricDiffuse.jpg");
34  material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
35  auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricNormal.jpg");
36  material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
37  auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fabricORM.jpg");
38  material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
39 }
40 
41 static void
42 setFleshTextures(std::shared_ptr<RenderMaterial> material)
43 {
44  auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshDiffuse.jpg");
45  material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
46  auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshNormal.jpg");
47  material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
48  auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT "/textures/fleshORM.jpg");
49  material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
50 }
51 
60 static std::shared_ptr<PbdObject>
61 makeClothObj(const std::string& name,
62  const double width,
63  const double height,
64  const int rowCount,
65  const int colCount)
66 {
67  imstkNew<PbdObject> clothObj(name);
68 
69  // Setup the Geometry
70  std::shared_ptr<SurfaceMesh> clothMesh =
71  GeometryUtils::toTriangleGrid(Vec3d::Zero(),
72  Vec2d(10.0, 10.0), Vec2i(16, 16), Quatd::Identity(), 2.0);
73 
74  // Setup the Parameters
75  imstkNew<PbdModelConfig> pbdParams;
76  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 1.0e2);
77  pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 1.0e1);
78  pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0);
79  pbdParams->m_dt = 0.005;
80  pbdParams->m_iterations = 5;
81 
82  // Setup the Model
83  imstkNew<PbdModel> pbdModel;
84  pbdModel->configure(pbdParams);
85 
86  // Setup the VisualModel
87  imstkNew<RenderMaterial> material;
88  material->setBackFaceCulling(false);
89  material->setDisplayMode(RenderMaterial::DisplayMode::Surface);
90  material->setShadingModel(RenderMaterial::ShadingModel::PBR);
91  setFleshTextures(material);
92  imstkNew<VisualModel> visualModel;
93  visualModel->setGeometry(clothMesh);
94  visualModel->setRenderMaterial(material);
95 
96  // Setup the Object
97  clothObj->addVisualModel(visualModel);
98  clothObj->setPhysicsGeometry(clothMesh);
99  clothObj->setDynamicalModel(pbdModel);
100  clothObj->getPbdBody()->fixedNodeIds = { 0, colCount - 1 };
101  clothObj->getPbdBody()->uniformMassValue = width * height / (rowCount * colCount);
102 
103  return clothObj;
104 }
105 
110 int
111 main()
112 {
113  // Write log to stdout and file
115 
116  // Setup a scene
117  imstkNew<Scene> scene("PBDCloth");
118  scene->getActiveCamera()->setFocalPoint(0.0, -5.0, 0.0);
119  scene->getActiveCamera()->setPosition(0.0, 1.5, 25.0);
120  scene->getActiveCamera()->setViewUp(0.0, 1.0, 0.0);
121 
122  std::shared_ptr<PbdObject> clothObj = makeClothObj("Cloth", 10.0, 10.0, 16, 16);
123  scene->addSceneObject(clothObj);
124 
125  // Run the simulation
126  {
127  // Setup a viewer to render
128  imstkNew<VTKViewer> viewer;
129  viewer->setActiveScene(scene);
130 
131  // Setup a scene manager to advance the scene
132  imstkNew<SceneManager> sceneManager;
133  sceneManager->setActiveScene(scene);
134  sceneManager->pause(); // Start simulation paused
135 
137  driver->addModule(viewer);
138  driver->addModule(sceneManager);
139  driver->setDesiredDt(0.001);
140 
141  // Add default mouse and keyboard controls to the viewer
142  std::shared_ptr<Entity> mouseAndKeyControls =
143  SimulationUtils::createDefaultSceneControl(driver);
144  scene->addSceneObject(mouseAndKeyControls);
145 
146  using Vec3uc = Eigen::Matrix<unsigned char, 3, 1>;
147  queueConnect<KeyEvent>(viewer->getKeyboardDevice(), &KeyboardDeviceClient::keyPress, sceneManager, [&](KeyEvent* e)
148  {
149  // Set new textures
150  if (e->m_key == '1')
151  {
152  setFleshTextures(clothObj->getVisualModel(0)->getRenderMaterial());
153  }
154  else if (e->m_key == '2')
155  {
156  setFabricTextures(clothObj->getVisualModel(0)->getRenderMaterial());
157  }
158  // Darken the texture pixel values
159  else if (e->m_key == 'h')
160  {
161  auto imageData = clothObj->getVisualModel(0)->getRenderMaterial()->getTexture(Texture::Type::Diffuse)->getImageData();
162  std::shared_ptr<VecDataArray<unsigned char, 3>> scalars = std::dynamic_pointer_cast<VecDataArray<unsigned char, 3>>(imageData->getScalars());
163  Vec3uc* scalarPtr = scalars->getPointer();
164  for (int i = 0; i < scalars->size(); i++)
165  {
166  scalarPtr[i] = (scalarPtr[i].cast<double>() * 0.8).cast<unsigned char>();
167  }
168  clothObj->getVisualModel(0)->getRenderMaterial()->getTexture(Texture::Type::Diffuse)->postModified();
169  }
170  });
171 
172  driver->start();
173  }
174 
175  return 0;
176 }
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.
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.
Simple dynamic array implementation that also supports event posting and viewing/facade.
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)
void setRenderMaterial(std::shared_ptr< RenderMaterial > renderMaterial)
Set/Get render material.
double m_dt
Time step size.
void setActiveScene(std::string newSceneName)
Sets the currently updating scene.
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.
Vec3d m_gravity
Gravity acceleration.