7 #include "imstkCamera.h" 8 #include "imstkCollisionDetectionAlgorithm.h" 9 #include "imstkDirectionalLight.h" 10 #include "imstkGeometryUtilities.h" 11 #include "imstkImageData.h" 12 #include "imstkIsometricMap.h" 13 #include "imstkKeyboardDeviceClient.h" 14 #include "imstkKeyboardSceneControl.h" 15 #include "imstkMeshIO.h" 16 #include "imstkMouseDeviceClient.h" 17 #include "imstkMouseSceneControl.h" 18 #include "imstkNeedle.h" 19 #include "imstkObjectControllerGhost.h" 20 #include "imstkPbdModel.h" 21 #include "imstkPbdModelConfig.h" 22 #include "imstkPbdObject.h" 23 #include "imstkPointwiseMap.h" 24 #include "imstkRenderMaterial.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 "imstkVisualModel.h" 32 #include "imstkVTKViewer.h" 33 #include "NeedleInteraction.h" 35 #ifdef iMSTK_USE_HAPTICS 36 #include "imstkDeviceManager.h" 37 #include "imstkDeviceManagerFactory.h" 39 #include "imstkDummyClient.h" 42 using namespace imstk;
48 setSphereTexCoords(std::shared_ptr<SurfaceMesh> surfMesh,
const double uvScale)
51 surfMesh->computeBoundingBox(min, max);
52 const Vec3d size = max - min;
53 const Vec3d center = (max + min) * 0.5;
55 const double radius = (size * 0.5).norm();
57 auto uvCoordsPtr = std::make_shared<VecDataArray<float, 2>>(surfMesh->getNumVertices());
59 for (
int i = 0; i < surfMesh->getNumVertices(); i++)
61 const Vec3d vertex = surfMesh->getVertexPosition(i) - center;
64 const double theta = asin(vertex[0] / radius);
65 const double phi = atan2(vertex[1], vertex[2]);
66 uvCoords[i] = Vec2f(phi / (PI * 2.0) + 0.5, theta / (PI * 2.0) + 0.5) * uvScale;
68 surfMesh->setVertexTCoords(
"tcoords", uvCoordsPtr);
78 static std::shared_ptr<PbdObject>
79 makeTissueObj(
const std::string& name,
80 const Vec3d& size,
const Vec3i& dim,
const Vec3d& center)
84 std::shared_ptr<SurfaceMesh> surfMesh = tissueMesh->extractSurfaceMesh();
85 setSphereTexCoords(surfMesh, 6.0);
88 auto pbdParams = std::make_shared<PbdModelConfig>();
90 pbdParams->m_femParams->m_YoungModulus = 5.0;
91 pbdParams->m_femParams->m_PoissonRatio = 0.4;
92 pbdParams->enableFemConstraint(PbdFemConstraint::MaterialType::StVK);
93 pbdParams->m_doPartitioning =
true;
94 pbdParams->m_gravity = Vec3d(0.0, 0.0, 0.0);
95 pbdParams->m_dt = 0.05;
96 pbdParams->m_iterations = 9;
97 pbdParams->m_linearDampingCoeff = 0.05;
100 auto pbdModel = std::make_shared<PbdModel>();
101 pbdModel->configure(pbdParams);
104 auto material = std::make_shared<RenderMaterial>();
106 auto diffuseTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT
"/textures/fleshDiffuse.jpg");
107 material->addTexture(std::make_shared<Texture>(diffuseTex, Texture::Type::Diffuse));
108 auto normalTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT
"/textures/fleshNormal.jpg");
109 material->addTexture(std::make_shared<Texture>(normalTex, Texture::Type::Normal));
110 auto ormTex = MeshIO::read<ImageData>(iMSTK_DATA_ROOT
"/textures/fleshORM.jpg");
111 material->addTexture(std::make_shared<Texture>(ormTex, Texture::Type::ORM));
112 material->setNormalStrength(0.3);
115 auto visualModel = std::make_shared<VisualModel>();
116 visualModel->setGeometry(surfMesh);
117 visualModel->setRenderMaterial(material);
126 auto tissueObj = std::make_shared<PbdObject>(name);
127 tissueObj->addVisualModel(visualModel);
128 tissueObj->setPhysicsGeometry(tissueMesh);
129 tissueObj->setCollidingGeometry(surfMesh);
130 tissueObj->setPhysicsToCollidingMap(std::make_shared<PointwiseMap>(tissueMesh, surfMesh));
131 tissueObj->setDynamicalModel(pbdModel);
132 tissueObj->getPbdBody()->uniformMassValue = 0.1;
134 for (
int z = 0; z < dim[2]; z++)
136 for (
int y = 0; y < dim[1]; y++)
138 for (
int x = 0; x < dim[0]; x++)
140 if (x == 0 || x == dim[0] - 1 )
142 tissueObj->getPbdBody()->fixedNodeIds.push_back(x + dim[0] * (y + dim[1] * z));
153 static std::shared_ptr<RigidObject2>
156 auto toolGeom = std::make_shared<LineMesh>();
162 auto syringeMesh = MeshIO::read<SurfaceMesh>(iMSTK_DATA_ROOT
"/Surgical Instruments/Syringes/Disposable_Syringe.stl");
163 syringeMesh->scale(0.4, Geometry::TransformType::ApplyToData);
164 syringeMesh->rotate(Vec3d(1.0, 0.0, 0.0), -PI_2, Geometry::TransformType::ApplyToData);
165 syringeMesh->translate(Vec3d(0.0, 4.4, 0.0), Geometry::TransformType::ApplyToData);
167 auto toolObj = std::make_shared<RigidObject2>(
"NeedleRbdTool");
168 toolObj->setVisualGeometry(syringeMesh);
169 toolObj->setCollidingGeometry(toolGeom);
170 toolObj->setPhysicsGeometry(toolGeom);
171 toolObj->setPhysicsToVisualMap(std::make_shared<IsometricMap>(toolGeom, syringeMesh));
172 toolObj->getVisualModel(0)->getRenderMaterial()->setColor(
Color(0.9, 0.9, 0.9));
174 toolObj->getVisualModel(0)->getRenderMaterial()->setRoughness(0.5);
175 toolObj->getVisualModel(0)->getRenderMaterial()->setMetalness(1.0);
176 toolObj->getVisualModel(0)->getRenderMaterial()->setIsDynamicMesh(
false);
178 std::shared_ptr<RigidBodyModel2> rbdModel = std::make_shared<RigidBodyModel2>();
179 rbdModel->getConfig()->m_gravity = Vec3d::Zero();
180 toolObj->setDynamicalModel(rbdModel);
182 toolObj->getRigidBody()->m_mass = 0.1;
183 toolObj->getRigidBody()->m_intertiaTensor = Mat3d::Identity() * 10000.0;
184 toolObj->getRigidBody()->m_initPos = Vec3d(0.0, 2.0, 0.0);
188 needle->setNeedleGeometry(toolGeom);
192 controller->setControlledObject(toolObj);
193 controller->setTranslationScaling(50.0);
194 controller->setLinearKs(1000.0);
195 controller->setAngularKs(10000000.0);
196 controller->setUseCritDamping(
true);
197 controller->setForceScaling(0.0045);
198 controller->setSmoothingKernelSize(15);
199 controller->setUseForceSmoothening(
true);
203 controllerGhost->setController(controller);
219 auto scene = std::make_shared<Scene>(
"PbdTissueSurfaceNeedleContact");
220 scene->getActiveCamera()->setPosition(-0.06, 7.29, 11.69);
221 scene->getActiveCamera()->setFocalPoint(0.0, 0.0, 0.0);
222 scene->getActiveCamera()->setViewUp(0.0, 1.0, 0.0);
225 std::shared_ptr<PbdObject> tissueObj = makeTissueObj(
"Tissue",
226 Vec3d(10.0, 3.0, 10.0), Vec3i(7, 3, 6), Vec3d(0.1, -1.0, 0.0));
227 scene->addSceneObject(tissueObj);
229 std::shared_ptr<RigidObject2> toolObj = makeToolObj();
230 scene->addSceneObject(toolObj);
232 scene->addInteraction(std::make_shared<NeedleInteraction>(tissueObj, toolObj));
235 auto light = std::make_shared<DirectionalLight>();
236 light->setDirection(Vec3d(5.0, -8.0, -5.0));
237 light->setIntensity(1.0);
238 scene->addLight(
"Light", light);
243 auto viewer = std::make_shared<VTKViewer>();
244 viewer->setActiveScene(scene);
245 viewer->setVtkLoggerMode(VTKViewer::VTKLoggerMode::MUTE);
246 viewer->setDebugAxesLength(0.1, 0.1, 0.1);
249 auto sceneManager = std::make_shared<SceneManager>();
250 sceneManager->setActiveScene(scene);
251 sceneManager->pause();
253 auto driver = std::make_shared<SimulationManager>();
254 driver->addModule(viewer);
255 driver->addModule(sceneManager);
256 driver->setDesiredDt(0.001);
258 #ifdef iMSTK_USE_HAPTICS 261 std::shared_ptr<DeviceClient> deviceClient = hapticManager->makeDeviceClient();
262 driver->addModule(hapticManager);
264 auto deviceClient = std::make_shared<DummyClient>();
265 connect<Event>(sceneManager, &SceneManager::postUpdate, [&](
Event*)
267 const Vec2d mousePos = viewer->getMouseDevice()->getPos();
268 const Vec3d desiredPos = Vec3d(mousePos[0] - 0.5, mousePos[1] - 0.5, 0.0) * 0.2 + Vec3d(0.0, 0.025, 0.0);
269 const Quatd desiredOrientation = Quatd(Rotd(0.0, Vec3d(1.0, 0.0, 0.0)));
271 deviceClient->setPosition(desiredPos);
276 controller->setDevice(deviceClient);
278 connect<Event>(sceneManager, &SceneManager::preUpdate,
282 toolObj->getRigidBodyModel2()->getConfig()->m_dt = sceneManager->getDt();
287 std::shared_ptr<Entity> mouseAndKeyControls =
288 SimulationUtils::createDefaultSceneControl(driver);
289 scene->addSceneObject(mouseAndKeyControls);
Base class for events which contain a type, priority, and data priority defaults to 0 and uses a grea...
Place this on an object to make it puncturable by a needle. This allows puncturables to know they've ...
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.
Definition of straight, single segment needle.
Simple dynamic array implementation that also supports event posting and viewing/facade.
static std::shared_ptr< DeviceManager > makeDeviceManager()
Attempts to create a new DeviceManager by whichever is default If multiple haptic managers are built ...
This class uses the provided device to control the provided rigid object via virtual coupling...
A behaviour that renders a second copy of the controlled object at a lower opacity in the physical po...
Physically based rendering.
static LoggerG3 & startLogger()
Starts logger with default sinks, use getInstance to create a logger with no sinks.