7 #include "imstkCamera.h" 8 #include "imstkCapsule.h" 9 #include "imstkDirectionalLight.h" 10 #include "imstkGeometryUtilities.h" 11 #include "imstkKeyboardDeviceClient.h" 12 #include "imstkKeyboardSceneControl.h" 13 #include "imstkLineMesh.h" 14 #include "imstkMouseDeviceClient.h" 15 #include "imstkMouseSceneControl.h" 16 #include "imstkPbdModel.h" 17 #include "imstkPbdModelConfig.h" 18 #include "imstkPbdObject.h" 19 #include "imstkPbdObjectCollision.h" 20 #include "imstkPbdObjectStitching.h" 21 #include "imstkPointwiseMap.h" 22 #include "imstkRbdConstraint.h" 23 #include "imstkRenderMaterial.h" 24 #include "imstkRigidBodyModel2.h" 25 #include "imstkRigidObject2.h" 26 #include "imstkRigidObjectController.h" 27 #include "imstkScene.h" 28 #include "imstkSceneManager.h" 29 #include "imstkSimulationManager.h" 30 #include "imstkSimulationUtils.h" 31 #include "imstkSurfaceMesh.h" 32 #include "imstkTetrahedralMesh.h" 33 #include "imstkVisualModel.h" 34 #include "imstkVTKViewer.h" 36 using namespace imstk;
40 #ifdef iMSTK_USE_HAPTICS 41 #include "imstkDeviceManager.h" 42 #include "imstkDeviceManagerFactory.h" 44 #include "imstkDummyClient.h" 54 static std::shared_ptr<PbdObject>
55 makeTetTissueObj(
const std::string& name,
56 const Vec3d& size,
const Vec3i& dim,
const Vec3d& center)
58 auto tissueObj = std::make_shared<PbdObject>(name);
62 std::shared_ptr<SurfaceMesh> surfMesh = tissueMesh->extractSurfaceMesh();
65 auto pbdParams = std::make_shared<PbdModelConfig>();
68 pbdParams->m_femParams->m_YoungModulus = 1000.0;
69 pbdParams->m_femParams->m_PoissonRatio = 0.4;
70 pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::StVK);
73 pbdParams->m_doPartitioning =
false;
74 pbdParams->m_gravity = Vec3d(0.0, 0.0, 0.0);
75 pbdParams->m_dt = 0.001;
76 pbdParams->m_iterations = 5;
77 pbdParams->m_linearDampingCoeff = 0.05;
80 auto pbdModel = std::make_shared<PbdModel>();
81 pbdModel->configure(pbdParams);
84 auto material = std::make_shared<RenderMaterial>();
85 material->setDisplayMode(RenderMaterial::DisplayMode::Wireframe);
86 material->setColor(
Color(0.77, 0.53, 0.34));
87 material->setEdgeColor(
Color(0.87, 0.63, 0.44));
88 material->setOpacity(0.5);
91 tissueObj->setVisualGeometry(surfMesh);
92 tissueObj->getVisualModel(0)->setRenderMaterial(material);
93 tissueObj->setPhysicsGeometry(tissueMesh);
94 tissueObj->setCollidingGeometry(surfMesh);
95 tissueObj->setPhysicsToCollidingMap(std::make_shared<PointwiseMap>(tissueMesh, surfMesh));
96 tissueObj->setDynamicalModel(pbdModel);
97 tissueObj->getPbdBody()->uniformMassValue = 0.00001;
99 for (
int z = 0; z < dim[2]; z++)
101 for (
int y = 0; y < dim[1]; y++)
103 for (
int x = 0; x < dim[0]; x++)
107 tissueObj->getPbdBody()->fixedNodeIds.push_back(x + dim[0] * (y + dim[1] * z));
119 static std::shared_ptr<PbdObject>
120 makeTriTissueObj(
const std::string& name,
121 const Vec2d& size,
const Vec2i& dim,
const Vec3d& center)
123 auto tissueObj = std::make_shared<PbdObject>(name);
126 std::shared_ptr<SurfaceMesh> triMesh =
128 Quatd::Identity(), 1.0);
131 auto pbdParams = std::make_shared<PbdModelConfig>();
132 pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Distance, 0.1);
133 pbdParams->enableConstraint(PbdModelConfig::ConstraintGenType::Dihedral, 1e-6);
134 pbdParams->m_gravity = Vec3d(0.0, 0.0, 0.0);
135 pbdParams->m_dt = 0.001;
136 pbdParams->m_iterations = 5;
137 pbdParams->m_linearDampingCoeff = 0.025;
140 auto pbdModel = std::make_shared<PbdModel>();
141 pbdModel->configure(pbdParams);
144 auto material = std::make_shared<RenderMaterial>();
145 material->setBackFaceCulling(
false);
146 material->setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface);
147 material->setColor(
Color(0.77, 0.53, 0.34));
148 material->setEdgeColor(
Color(0.87, 0.63, 0.44));
151 tissueObj->setVisualGeometry(triMesh);
152 tissueObj->getVisualModel(0)->setRenderMaterial(material);
153 tissueObj->setPhysicsGeometry(triMesh);
154 tissueObj->setCollidingGeometry(triMesh);
155 tissueObj->setDynamicalModel(pbdModel);
156 tissueObj->getPbdBody()->uniformMassValue = 0.00001;
158 for (
int y = 0; y < dim[1]; y++)
160 for (
int x = 0; x < dim[0]; x++)
164 tissueObj->getPbdBody()->fixedNodeIds.push_back(x + dim[0] * y);
172 static std::shared_ptr<RigidObject2>
175 auto toolGeom = std::make_shared<LineMesh>();
176 auto verticesPtr = std::make_shared<VecDataArray<double, 3>>(2);
177 (*verticesPtr)[0] = Vec3d(0.0, -0.05, 0.0);
178 (*verticesPtr)[1] = Vec3d(0.0, 0.05, 0.0);
179 auto indicesPtr = std::make_shared<VecDataArray<int, 2>>(1);
180 (*indicesPtr)[0] = Vec2i(0, 1);
181 toolGeom->initialize(verticesPtr, indicesPtr);
183 auto toolObj = std::make_shared<RigidObject2>(
"ToolObj");
184 toolObj->setVisualGeometry(toolGeom);
185 toolObj->setCollidingGeometry(toolGeom);
186 toolObj->setPhysicsGeometry(toolGeom);
187 toolObj->getVisualModel(0)->getRenderMaterial()->setColor(
Color(0.9, 0.9, 0.9));
189 toolObj->getVisualModel(0)->getRenderMaterial()->setRoughness(0.5);
190 toolObj->getVisualModel(0)->getRenderMaterial()->setMetalness(1.0);
191 toolObj->getVisualModel(0)->getRenderMaterial()->setIsDynamicMesh(
false);
193 auto rbdModel = std::make_shared<RigidBodyModel2>();
194 rbdModel->getConfig()->m_gravity = Vec3d::Zero();
195 rbdModel->getConfig()->m_maxNumIterations = 5;
196 toolObj->setDynamicalModel(rbdModel);
198 toolObj->getRigidBody()->m_mass = 0.3;
199 toolObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 10000.0;
200 toolObj->getRigidBody()->m_initPos = Vec3d(0.0, 0.0, 0.0);
204 controller->setControlledObject(toolObj);
205 controller->setLinearKs(1000.0);
206 controller->setAngularKs(10000000.0);
207 controller->setUseCritDamping(
true);
208 controller->setForceScaling(0.0045);
209 controller->setSmoothingKernelSize(15);
210 controller->setUseForceSmoothening(
true);
221 const double capsuleRadius = 0.02;
222 const double tissueLength = 0.15;
228 auto scene = std::make_shared<Scene>(
"PbdTissueStitch");
229 scene->getActiveCamera()->setPosition(0.0012, 0.0451, 0.1651);
230 scene->getActiveCamera()->setFocalPoint(0.0, 0.0, 0.0);
231 scene->getActiveCamera()->setViewUp(0.0, 0.96, -0.28);
234 #ifdef USE_THIN_TISSUE 235 std::shared_ptr<PbdObject> tissueObj = makeTriTissueObj(
"Tissue",
236 Vec2d(tissueLength, 0.07), Vec2i(15, 5),
237 Vec3d(tissueLength * 0.5, -0.01 - capsuleRadius, 0.0));
239 std::shared_ptr<PbdObject> tissueObj = makeTetTissueObj(
"Tissue",
240 Vec3d(tissueLength, 0.01, 0.07), Vec3i(15, 2, 5),
241 Vec3d(tissueLength * 0.5, -0.01 - capsuleRadius, 0.0));
243 scene->addSceneObject(tissueObj);
246 auto cdObj = std::make_shared<CollidingObject>(
"collisionObject");
247 auto capsuleGeom = std::make_shared<Capsule>();
248 capsuleGeom->setPosition(0.0, 0.0, 0.0);
249 capsuleGeom->setRadius(capsuleRadius);
250 capsuleGeom->setLength(0.08);
251 capsuleGeom->setOrientation(Quatd(Rotd(PI_2, Vec3d(1.0, 0.0, 0.0))));
252 cdObj->setVisualGeometry(capsuleGeom);
253 cdObj->getVisualModel(0)->getRenderMaterial()->setColor(
254 Color(246.0 / 255.0, 127.0 / 255.0, 123.0 / 255.0));
255 cdObj->setCollidingGeometry(capsuleGeom);
256 scene->addSceneObject(cdObj);
258 std::shared_ptr<RigidObject2> toolObj = makeToolObj();
259 scene->addSceneObject(toolObj);
262 auto collisionInteraction = std::make_shared<PbdObjectCollision>(tissueObj, cdObj);
263 collisionInteraction->setFriction(0.0);
264 collisionInteraction->setDeformableStiffnessA(0.3);
265 scene->addInteraction(collisionInteraction);
267 auto stitching = std::make_shared<PbdObjectStitching>(tissueObj);
268 stitching->setStitchDistance(0.015);
269 scene->addInteraction(stitching);
272 auto light1 = std::make_shared<DirectionalLight>();
273 light1->setFocalPoint(Vec3d(5.0, -8.0, -5.0));
274 light1->setIntensity(0.5);
275 scene->addLight(
"light1", light1);
276 auto light2 = std::make_shared<DirectionalLight>();
277 light2->setFocalPoint(Vec3d(-5.0, -8.0, -5.0));
278 light2->setIntensity(0.5);
279 scene->addLight(
"light2", light2);
284 auto viewer = std::make_shared<VTKViewer>();
285 viewer->setActiveScene(scene);
286 viewer->setDebugAxesLength(0.001, 0.001, 0.001);
289 auto sceneManager = std::make_shared<SceneManager>();
290 sceneManager->setActiveScene(scene);
291 sceneManager->pause();
293 auto driver = std::make_shared<SimulationManager>();
294 driver->addModule(viewer);
295 driver->addModule(sceneManager);
296 driver->setDesiredDt(0.001);
298 #ifdef iMSTK_USE_HAPTICS 301 std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
302 driver->addModule(hapticManager);
304 auto deviceClient = std::make_shared<DummyClient>();
305 connect<Event>(sceneManager, &SceneManager::postUpdate,
308 const Vec2d& pos = viewer->getMouseDevice()->getPos();
309 #ifdef USE_THIN_TISSUE 310 deviceClient->setPosition(Vec3d(40.0, 40.0, -(pos[1] * 100.0 - 50.0)));
311 deviceClient->setOrientation(Quatd(Rotd(-0.6, Vec3d(0.0, 0.0, 1.0))));
313 deviceClient->setPosition(Vec3d(37.0, 0.0, -(pos[1] * 100.0 - 50.0)));
314 deviceClient->setOrientation(Quatd(Rotd(0.65, Vec3d(0.0, 0.0, 1.0))));
320 controller->setDevice(deviceClient);
322 #ifdef iMSTK_USE_HAPTICS 323 connect<ButtonEvent>(deviceClient, &DeviceClient::buttonStateChanged,
326 if (e->m_button == 0 && e->m_buttonState == BUTTON_PRESSED)
328 auto toolGeom = std::dynamic_pointer_cast<
LineMesh>(toolObj->getCollidingGeometry());
330 const Vec3d& v2 = toolGeom->getVertexPosition(1);
331 stitching->beginStitch(v1, (v2 - v1).normalized());
337 connect<KeyEvent>(viewer->getKeyboardDevice(), &KeyboardDeviceClient::keyPress,
343 Vec3d& g = tissueObj->getPbdModel()->getConfig()->m_gravity;
344 g = Vec3d(0.0, -static_cast<double>(!(g.norm() > 0.0)), 0.0);
347 else if (e->m_key ==
's')
349 auto toolGeom = std::dynamic_pointer_cast<
LineMesh>(toolObj->getCollidingGeometry());
351 const Vec3d& v2 = toolGeom->getVertexPosition(1);
352 stitching->beginStitch(v1, (v2 - v1).normalized());
355 else if (e->m_key ==
'r')
362 std::vector<Vec3d> initPositions;
365 std::dynamic_pointer_cast<
PointSet>(tissueObj->getPhysicsGeometry());
366 std::shared_ptr<VecDataArray<double, 3>> verticesPtr = pointMesh->
getVertexPositions();
368 const std::vector<int> fixedNodes = tissueObj->getPbdBody()->fixedNodeIds;
369 for (
size_t i = 0; i < fixedNodes.size(); i++)
371 initPositions.
push_back(vertices[fixedNodes[i]]);
373 bool stopped =
false;
376 connect<Event>(sceneManager, &SceneManager::postUpdate,
379 const double dt = sceneManager->getDt();
383 for (
size_t i = 0; i < fixedNodes.size(); i++)
385 Vec3d initPos = initPositions[i];
386 Vec3d& pos = vertices[fixedNodes[i]];
388 const double r = (capsuleGeom->getPosition().head<2>() - initPos.head<2>()).norm();
389 pos = Vec3d(-sin(t) * r, -cos(t) * r, initPos[2]);
398 tissueObj->getPbdBody()->fixedNodeIds.clear();
399 tissueObj->getPbdModel()->initialize();
405 std::shared_ptr<Entity> mouseAndKeyControls =
406 SimulationUtils::createDefaultSceneControl(driver);
407 scene->addSceneObject(mouseAndKeyControls);
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
std::shared_ptr< SurfaceMesh > toTriangleGrid(const Vec3d ¢er, 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...
std::shared_ptr< TetrahedralMesh > toTetGrid(const Vec3d ¢er, const Vec3d &size, const Vec3i &divisions, const Quatd orientation=Quatd::Identity())
Produces a tetrahedral grid given the OrientedBox with the given divisions.
void push_back(const ValueType &val)
Append the data array to hold the new value, resizes if neccesary.
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
const Vec3d & getVertexPosition(const size_t vertNum, DataType type=DataType::PostTransform) const
Returns the position of a vertex given its index.
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
Provides the information of a key event (press, release, & which key)
Base class for all volume mesh types.
This class uses the provided device to control the provided rigid object via virtual coupling...
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.