diff --git a/Examples/PDBPicking/CMakeLists.txt b/Examples/PDBPicking/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..17355b81fce860db0699f5899fb289f6b03935e5 --- /dev/null +++ b/Examples/PDBPicking/CMakeLists.txt @@ -0,0 +1,37 @@ +########################################################################### +# +# Copyright (c) Kitware, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0.txt +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### +if(iMSTK_USE_OpenHaptics) + + project(Example-PBDPicking) + + #----------------------------------------------------------------------------- + # Create executable + #----------------------------------------------------------------------------- + imstk_add_executable(${PROJECT_NAME} PBDPickingExample.cpp) + + #----------------------------------------------------------------------------- + # Add the target to Examples folder + #----------------------------------------------------------------------------- + SET_TARGET_PROPERTIES (${PROJECT_NAME} PROPERTIES FOLDER Examples/Haptics) + + #----------------------------------------------------------------------------- + # Link libraries to executable + #----------------------------------------------------------------------------- + target_link_libraries(${PROJECT_NAME} SimulationManager apiUtilities) + +endif() diff --git a/Examples/PDBPicking/PBDPickingExample.cpp b/Examples/PDBPicking/PBDPickingExample.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1a3037a43accfd1f76170fe2f7e0b78a34028cd9 --- /dev/null +++ b/Examples/PDBPicking/PBDPickingExample.cpp @@ -0,0 +1,264 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#include "imstkCamera.h" +#include "imstkCDObjectFactory.h" +#include "imstkCollidingObject.h" +#include "imstkCollisionData.h" +#include "imstkCollisionGraph.h" +#include "imstkCollisionPair.h" +#include "imstkCollisionDetection.h" +#include "imstkHapticDeviceClient.h" +#include "imstkHapticDeviceManager.h" +#include "imstkKeyboardDeviceClient.h" +#include "imstkKeyboardSceneControl.h" +#include "imstkLight.h" +#include "imstkMouseSceneControl.h" +#include "imstkNew.h" +#include "imstkPlane.h" +#include "imstkRenderMaterial.h" +#include "imstkScene.h" +#include "imstkSceneManager.h" +#include "imstkSceneObjectController.h" +#include "imstkSphere.h" +#include "imstkVirtualCouplingCH.h" +#include "imstkVisualModel.h" +#include "imstkVTKViewer.h" + +#include "imstkLogger.h" +#include "imstkPbdModel.h" +#include "imstkPbdObject.h" +#include "imstkSurfaceMesh.h" + +#include "imstkPBDPickingCH.h" +#include "imstkPbdObjectPickingPair.h" + +// global variables +const std::string phantomOmni1Name = "Default Device"; + +using namespace imstk; + +// Parameters to play with +const double width = 50.0; +const double height = 50.0; +const int nRows = 16; +const int nCols = 16; + +/// +/// \brief Creates cloth geometry +/// +static std::shared_ptr<SurfaceMesh> +makeClothGeometry(const double width, + const double height, + const int nRows, + const int nCols) +{ + imstkNew<SurfaceMesh> clothMesh; + + StdVectorOfVec3d vertList; + vertList.resize(nRows * nCols); + const double dy = width / (double)(nCols - 1); + const double dx = height / (double)(nRows - 1); + for (int i = 0; i < nRows; ++i) + { + for (int j = 0; j < nCols; j++) + { + vertList[i * nCols + j] = Vec3d((double)dx * i, 1.0, (double)dy * j); + } + } + clothMesh->setInitialVertexPositions(vertList); + clothMesh->setVertexPositions(vertList); + + // Add connectivity data + std::vector<SurfaceMesh::TriangleArray> triangles; + for (std::size_t i = 0; i < nRows - 1; ++i) + { + for (std::size_t j = 0; j < nCols - 1; j++) + { + SurfaceMesh::TriangleArray tri[2]; + const size_t index1 = i * nCols + j; + const size_t index2 = index1 + nCols; + const size_t index3 = index1 + 1; + const size_t index4 = index2 + 1; + + // Interleave [/][\] + if (i % 2 ^ j % 2) + { + tri[0] = { { index1, index2, index3 } }; + tri[1] = { { index4, index3, index2 } }; + } + else + { + tri[0] = { { index2, index4, index1 } }; + tri[1] = { { index4, index3, index1 } }; + } + triangles.push_back(tri[0]); + triangles.push_back(tri[1]); + } + } + + clothMesh->setTrianglesVertices(triangles); + + return clothMesh; +} + +/// +/// \brief Creates cloth object +/// +static std::shared_ptr<PbdObject> +makeClothObj(const std::string& name, + const double width, + const double height, + const int nRows, + const int nCols) +{ + imstkNew<PbdObject> clothObj(name); + + // Setup the Geometry + std::shared_ptr<SurfaceMesh> clothMesh(makeClothGeometry(width, height, nRows, nCols)); + + // Setup the Parameters + imstkNew<PBDModelConfig> pbdParams; + pbdParams->enableConstraint(PbdConstraint::Type::Distance, 1.0e2); + pbdParams->enableConstraint(PbdConstraint::Type::Dihedral, 1.0e1); + pbdParams->m_fixedNodeIds = { 0, static_cast<size_t>(nCols) - 1 }; + pbdParams->m_uniformMassValue = width * height / ((double)nRows * (double)nCols); + pbdParams->m_gravity = Vec3d(0.0, -9.8, 0.0); + pbdParams->m_defaultDt = 0.005; + pbdParams->m_iterations = 5; + + // Setup the Model + imstkNew<PbdModel> pbdModel; + pbdModel->setModelGeometry(clothMesh); + pbdModel->configure(pbdParams); + + // Setup the VisualModel + imstkNew<RenderMaterial> material; + material->setBackFaceCulling(false); + material->setDisplayMode(RenderMaterial::DisplayMode::WireframeSurface); + + imstkNew<VisualModel> visualModel(clothMesh); + visualModel->setRenderMaterial(material); + + // Setup the Object + clothObj->addVisualModel(visualModel); + clothObj->setPhysicsGeometry(clothMesh); + clothObj->setCollidingGeometry(clothMesh); + clothObj->setDynamicalModel(pbdModel); + + return clothObj; +} + +/// +/// \brief This example demonstrates the concept of PBD picking +/// for haptic interaction. NOTE: Requires GeoMagic Touch device +/// +int +main() +{ + // Setup logger (write to file and stdout) + Logger::startLogger(); + + // Scene + imstkNew<Scene> scene("PBDPicking"); + + // Create the virtual coupling object controller + + // Device Server + imstkNew<HapticDeviceManager> server; + std::shared_ptr<HapticDeviceClient> client = server->makeDeviceClient(phantomOmni1Name); + + // Object + imstkNew<Sphere> geom(Vec3d(0.0, 0.0, 0.0), 2.0); + imstkNew<CollidingObject> obj("VirtualObject"); + obj->setVisualGeometry(geom); + obj->setCollidingGeometry(geom); + scene->addSceneObject(obj); + + std::shared_ptr<PbdObject> clothObj = makeClothObj("Cloth", width, height, nRows, nCols); + scene->addSceneObject(clothObj); + + // Create and add virtual coupling object controller in the scene + imstkNew<SceneObjectController> controller(obj, client); + scene->addController(controller); + + // Add interaction pair for pbd picking + imstkNew<PbdObjectPickingPair> pair(clothObj, obj, CollisionDetection::Type::PointSetToSphere); + scene->getCollisionGraph()->addInteraction(pair); + + // Camera + scene->getActiveCamera()->setPosition(Vec3d(200, 200, 200)); + scene->getActiveCamera()->setFocalPoint(Vec3d(0, 0, 0)); + + // Light + imstkNew<DirectionalLight> light("light"); + light->setFocalPoint(Vec3d(5.0, -8.0, -5.0)); + light->setIntensity(1.0); + scene->addLight(light); + + //Run the simulation + { + // Setup a viewer to render in its own thread + imstkNew<VTKViewer> viewer("Viewer"); + viewer->setActiveScene(scene); + + // Setup a scene manager to advance the scene in its own thread + imstkNew<SceneManager> sceneManager("Scene Manager"); + sceneManager->setActiveScene(scene); + viewer->addChildThread(sceneManager); // SceneManager will start/stop with viewer + + viewer->addChildThread(server); + + // Add mouse and keyboard controls to the viewer + { + imstkNew<MouseSceneControl> mouseControl(viewer->getMouseDevice()); + mouseControl->setSceneManager(sceneManager); + viewer->addControl(mouseControl); + + imstkNew<KeyboardSceneControl> keyControl(viewer->getKeyboardDevice()); + keyControl->setSceneManager(sceneManager); + keyControl->setViewer(viewer); + viewer->addControl(keyControl); + } + // Not perfectly thread safe movement lambda, ijkl movement instead of wasd because d is already used + std::shared_ptr<KeyboardDeviceClient> keyDevice = viewer->getKeyboardDevice(); + connect<Event>(sceneManager, EventType::PreUpdate, [&](Event*) + { + std::shared_ptr<PBDPickingCH> ch = std::static_pointer_cast<PBDPickingCH>(pair->getCollisionHandlingA()); + // Activate picking + if (keyDevice->getButton('i') == KEY_PRESS) + { + ch->activatePickConstraints(); + } + // Unpick + if (keyDevice->getButton('u') == KEY_PRESS) + { + ch->removePickConstraints(); + } + }); + + // Start viewer running, scene as paused + sceneManager->requestStatus(ThreadStatus::Paused); + viewer->start(); + } + + return 0; +} diff --git a/Source/CollisionHandling/imstkCollisionHandling.h b/Source/CollisionHandling/imstkCollisionHandling.h index ec367199aa9ba16ed09e25de9e508a37a0084887..46ffed1cd6f0190cd4e5e9a5a5a4726f8b435c19 100644 --- a/Source/CollisionHandling/imstkCollisionHandling.h +++ b/Source/CollisionHandling/imstkCollisionHandling.h @@ -51,6 +51,7 @@ public: BoneDrilling, SPH, PBD, + PBDPicking, RBD, LevelSet }; diff --git a/Source/CollisionHandling/imstkPBDPickingCH.cpp b/Source/CollisionHandling/imstkPBDPickingCH.cpp new file mode 100644 index 0000000000000000000000000000000000000000..cae89764e5f8875749a2c3e7c005b948e592c002 --- /dev/null +++ b/Source/CollisionHandling/imstkPBDPickingCH.cpp @@ -0,0 +1,130 @@ +/*========================================================================= + +Library: iMSTK + +Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, +& Imaging in Medicine, Rensselaer Polytechnic Institute. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0.txt + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ + +#include "imstkPBDPickingCH.h" +#include "imstkCollisionData.h" + +#include "imstkPbdModel.h" +#include "imstkPbdObject.h" +#include "imstkSphere.h" +#include "imstkPointSet.h" + +namespace imstk +{ +PBDPickingCH::PBDPickingCH(const CollisionHandling::Side& side, + const std::shared_ptr<CollisionData> colData, + std::shared_ptr<PbdObject> pbdObj, + std::shared_ptr<CollidingObject> pickObj) : + CollisionHandling(Type::PBDPicking, side, colData), + m_pbdObj(pbdObj), + m_pickObj(pickObj) +{ + m_isPicking = false; + m_pickedPtIdxOffset.clear(); +} + +void +PBDPickingCH::processCollisionData() +{ + CHECK(m_pbdObj != nullptr && m_pickObj != nullptr) + << "PBDPickingCH::handleCollision error: " + << "no picking collision handling available the object"; + + if (m_isPicking) + { + this->updatePickConstraints(); + } +} + +void +PBDPickingCH::updatePickConstraints() +{ + if (m_pickedPtIdxOffset.size() == 0) + { + this->removePickConstraints(); + return; + } + + std::shared_ptr<PbdModel> model = m_pbdObj->getPbdModel(); + std::shared_ptr<Sphere> pickSphere = std::dynamic_pointer_cast<Sphere>(m_pickObj->getCollidingGeometry()); + for (auto iter = m_pickedPtIdxOffset.begin(); iter != m_pickedPtIdxOffset.end(); iter++) + { + model->getCurrentState()->setVertexPosition(iter->first, pickSphere->getPosition() + iter->second); + } +} + +void +PBDPickingCH::addPickConstraints(std::shared_ptr<PbdObject> pbdObj, std::shared_ptr<CollidingObject> pickObj) +{ + if (m_colData->MAColData.isEmpty()) + { + return; + } + + CHECK(pbdObj != nullptr && pickObj != nullptr) + << "PBDPickingCH:addPickConstraints error: " + << "no pdb object or colliding object."; + + std::shared_ptr<PbdModel> model = pbdObj->getPbdModel(); + + //TODO: extending to other types of geometry + std::shared_ptr<Sphere> pickSphere = std::dynamic_pointer_cast<Sphere>(pickObj->getCollidingGeometry()); + CHECK(pickSphere != nullptr) << "Colliding geometry is not Sphere"; + + ParallelUtils::SpinLock lock; + ParallelUtils::parallelFor(m_colData->MAColData.getSize(), + [&](const size_t idx) { + const auto& cd = m_colData->MAColData[idx]; + const auto& pv = cd.penetrationVector; + const auto& relativePos = -pickSphere->getRadius() * pv.normalized(); + + lock.lock(); + m_pickedPtIdxOffset[cd.nodeIdx] = relativePos; + //model->setFixedPoint(cd.nodeIdx); + model->getCurrentState()->setVertexPosition(cd.nodeIdx, pickSphere->getPosition() + relativePos); + lock.unlock(); + }); +} + +void +PBDPickingCH::removePickConstraints() +{ + std::shared_ptr<PbdModel> model = m_pbdObj->getPbdModel(); + m_isPicking = false; + for (auto iter = m_pickedPtIdxOffset.begin(); iter != m_pickedPtIdxOffset.end(); ++iter) + { + //model->setPointUnfixed(iter->first); + //CHECK(model->getInvMass(iter->first) > 0.0) + // << "PBDPickingCH: unable to set invmasses back"; + } + m_pickedPtIdxOffset.clear(); +} + +void +PBDPickingCH::activatePickConstraints() +{ + if (!m_colData->MAColData.isEmpty()) + { + this->addPickConstraints(m_pbdObj, m_pickObj); + m_isPicking = true; + } +} +} diff --git a/Source/CollisionHandling/imstkPBDPickingCH.h b/Source/CollisionHandling/imstkPBDPickingCH.h new file mode 100644 index 0000000000000000000000000000000000000000..99fa77244bb2431315d726f43cedb20477a026c6 --- /dev/null +++ b/Source/CollisionHandling/imstkPBDPickingCH.h @@ -0,0 +1,89 @@ +/*========================================================================= + + Library: iMSTK + + Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, + & Imaging in Medicine, Rensselaer Polytechnic Institute. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0.txt + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +=========================================================================*/ + +#pragma once + +#include "imstkCollisionHandling.h" + +#include "imstkMath.h" +namespace imstk +{ +class CollidingObject; +class PbdObject; +struct CollisionData; + +/// +/// \class PBDPickingCH +/// +/// \brief Implements nodal picking for PBD object +/// +class PBDPickingCH : public CollisionHandling +{ +public: + + /// + /// \brief Constructor + /// + PBDPickingCH(const Side& side, + const std::shared_ptr<CollisionData> colData, + std::shared_ptr<PbdObject> pbdObj, + std::shared_ptr<CollidingObject> pickObj); + + PBDPickingCH() = delete; + + /// + /// \brief Destructor + /// + virtual ~PBDPickingCH() override = default; + + /// + /// \brief Compute forces based on collision data + /// + void processCollisionData() override; + + /// + /// \brief Add picking constraints for the node that is picked + /// + void addPickConstraints(std::shared_ptr<PbdObject> pbdObj, std::shared_ptr<CollidingObject> pickObj); + + /// + /// \brief Update picking constraints for the node that is picked + /// + void updatePickConstraints(); + + /// + /// \brief Remove picking constraints for the node that is picked + /// + void removePickConstraints(); + + /// + /// \brief Activate picking constraints for nodes in the collision data + /// + void activatePickConstraints(); + + +private: + bool m_isPicking; + std::map<size_t, Vec3d> m_pickedPtIdxOffset; ///> Map for picked nodes. + std::shared_ptr<PbdObject> m_pbdObj; ///> PBD object + std::shared_ptr<CollidingObject> m_pickObj; ///> Picking tool object +}; +} diff --git a/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp b/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp index e95368d560fe689b565016ae2c1a86631c27a3c9..59e930ed8a700dd773742630873643e1da6f870d 100644 --- a/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp +++ b/Source/DynamicalModels/ObjectModels/imstkPbdModel.cpp @@ -41,6 +41,7 @@ namespace imstk PbdModel::PbdModel() : DynamicalModel(DynamicalModelType::PositionBasedDynamics), m_mass(std::make_shared<StdVectorOfReal>()), m_invMass(std::make_shared<StdVectorOfReal>()), + m_fixedNodeInvMass(std::make_shared<std::map<size_t, double>>()), m_constraints(std::make_shared<PBDConstraintVector>()), m_partitionedConstraints(std::make_shared<std::vector<PBDConstraintVector>>()), m_parameters(std::make_shared<PBDModelConfig>()) @@ -663,13 +664,27 @@ PbdModel::setParticleMass(const double val, const size_t idx) void PbdModel::setFixedPoint(const size_t idx) { - StdVectorOfReal& invMasses = *m_invMass; + StdVectorOfReal& invMasses = *m_invMass; + std::map<size_t, double>& fixedNodeInvMass = *m_fixedNodeInvMass; if (idx < m_mesh->getNumVertices()) { + fixedNodeInvMass[idx] = invMasses[idx]; invMasses[idx] = 0.0; } } +void +PbdModel::setPointUnfixed(const size_t idx) +{ + StdVectorOfReal& invMasses = *m_invMass; + std::map<size_t, double>& fixedNodeInvMass = *m_fixedNodeInvMass; + if (fixedNodeInvMass.find(idx) != fixedNodeInvMass.end()) + { + invMasses[idx] = fixedNodeInvMass[idx]; + fixedNodeInvMass.erase(idx); + } +} + void PbdModel::integratePosition() { diff --git a/Source/DynamicalModels/ObjectModels/imstkPbdModel.h b/Source/DynamicalModels/ObjectModels/imstkPbdModel.h index 641797c75ed9dcb577a1acda8f5a3a78caaf068e..e560e65e9fcfa3509a556c207b66f65fc4776f6a 100644 --- a/Source/DynamicalModels/ObjectModels/imstkPbdModel.h +++ b/Source/DynamicalModels/ObjectModels/imstkPbdModel.h @@ -26,6 +26,8 @@ #include "imstkPbdFEMConstraint.h" #include "imstkPbdState.h" +#include <map> + namespace imstk { class PointSet; @@ -209,10 +211,15 @@ public: void setParticleMass(const double val, const size_t idx); /// - /// \brief Se the node as fixed + /// \brief Set the node as fixed /// void setFixedPoint(const size_t idx); + /// + /// \brief Set the node as unfixed + /// + void setPointUnfixed(const size_t idx); + /// /// \brief Get the inverse of mass of a certain node /// @@ -273,10 +280,11 @@ protected: bool m_partitioned = false; /// \todo this is used in initialize() as a temporary fix to problems on linux size_t m_partitionThreshold = 16; ///> Threshold for constraint partitioning - std::shared_ptr<PbdSolver> m_pbdSolver = nullptr; ///> PBD solver - std::shared_ptr<PointSet> m_mesh = nullptr; ///> PointSet on which the pbd model operates on - std::shared_ptr<StdVectorOfReal> m_mass = nullptr; ///> Mass of nodes - std::shared_ptr<StdVectorOfReal> m_invMass = nullptr; ///> Inverse of mass of nodes + std::shared_ptr<PbdSolver> m_pbdSolver = nullptr; ///> PBD solver + std::shared_ptr<PointSet> m_mesh = nullptr; ///> PointSet on which the pbd model operates on + std::shared_ptr<StdVectorOfReal> m_mass = nullptr; ///> Mass of nodes + std::shared_ptr<StdVectorOfReal> m_invMass = nullptr; ///> Inverse of mass of nodes + std::shared_ptr<std::map<size_t, double>> m_fixedNodeInvMass = nullptr; ///> Map for archiving fixed nodes' mass. std::shared_ptr<PBDConstraintVector> m_constraints = nullptr; ///> List of pbd constraints std::shared_ptr<std::vector<PBDConstraintVector>> m_partitionedConstraints = nullptr; ///> List of pbd constraints diff --git a/Source/Scene/imstkObjectInteractionFactory.cpp b/Source/Scene/imstkObjectInteractionFactory.cpp index 34b4fc302311904e70c426cd03f89fc47fb91d72..80b9cd1ece2734e9f346739e61373aea98e776ea 100644 --- a/Source/Scene/imstkObjectInteractionFactory.cpp +++ b/Source/Scene/imstkObjectInteractionFactory.cpp @@ -26,6 +26,8 @@ limitations under the License. #include "imstkFeDeformableObject.h" #include "imstkPbdObject.h" #include "imstkPbdObjectCollisionPair.h" +#include "imstkPbdObjectPickingPair.h" +#include "imstkPBDPickingCH.h" #include "imstkPenaltyCH.h" #include "imstkPickingCH.h" #include "imstkImplicitGeometryToPointSetCD.h" @@ -51,6 +53,10 @@ makeObjectInteractionPair(std::shared_ptr<CollidingObject> obj1, std::shared_ptr { results = std::make_shared<PbdObjectCollisionPair>(std::dynamic_pointer_cast<PbdObject>(obj1), std::dynamic_pointer_cast<PbdObject>(obj2), cdType); } + else if (intType == InteractionType::PbdObjToCollidingObjPicking && isType<PbdObject>(obj1)) + { + results = std::make_shared<PbdObjectPickingPair>(std::dynamic_pointer_cast<PbdObject>(obj1), std::dynamic_pointer_cast<CollidingObject>(obj2), cdType); + } //else if (intType == InteractionType::PbdObjToCollidingObjCollision && isType<PbdObject>(obj1)) //{ // results = std::make_shared<PbdCollidingObjCollisionPair>( diff --git a/Source/Scene/imstkObjectInteractionFactory.h b/Source/Scene/imstkObjectInteractionFactory.h index 1f3fec2c58f3a7d69e4a2b0efee21f34aa24c97a..4d097cc78839948e682b329efc71e53feca2f0d3 100644 --- a/Source/Scene/imstkObjectInteractionFactory.h +++ b/Source/Scene/imstkObjectInteractionFactory.h @@ -32,6 +32,7 @@ class ObjectInteractionPair; enum class InteractionType { PbdObjToPbdObjCollision, + PbdObjToCollidingObjPicking, PbdObjToCollidingObjCollision, SphObjToCollidingObjCollision, diff --git a/Source/Scene/imstkPbdObjectPickingPair.cpp b/Source/Scene/imstkPbdObjectPickingPair.cpp new file mode 100644 index 0000000000000000000000000000000000000000..7fb9f26039e786eac0bdcace7f5f85476b064d53 --- /dev/null +++ b/Source/Scene/imstkPbdObjectPickingPair.cpp @@ -0,0 +1,52 @@ +/*========================================================================= + +Library: iMSTK + +Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, +& Imaging in Medicine, Rensselaer Polytechnic Institute. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0.txt + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ + +#include "imstkPbdObjectPickingPair.h" +#include "imstkCDObjectFactory.h" +#include "imstkCollisionData.h" +#include "imstkPBDPickingCH.h" +#include "imstkPbdModel.h" +#include "imstkPbdObject.h" +#include "imstkPbdSolver.h" +#include "imstkTaskGraph.h" + +namespace imstk +{ +// Pbd Collision will be tested before any step of pbd, then resolved after the solve steps of the two objects +PbdObjectPickingPair::PbdObjectPickingPair(std::shared_ptr<PbdObject> obj1, std::shared_ptr<CollidingObject> obj2, + CollisionDetection::Type cdType) : CollisionPair(obj1, obj2) +{ + // Setup the CD + m_colData = std::make_shared<CollisionData>(); + setCollisionDetection(makeCollisionDetectionObject(cdType, obj1->getCollidingGeometry(), obj2->getCollidingGeometry(), m_colData)); + + // Setup the handler + std::shared_ptr<PBDPickingCH> ch = std::make_shared<PBDPickingCH>(CollisionHandling::Side::A, m_colData, obj1, obj2); + setCollisionHandlingA(ch); +} + +void +PbdObjectPickingPair::apply() +{ + // Add the collision interaction + CollisionPair::apply(); +} +} \ No newline at end of file diff --git a/Source/Scene/imstkPbdObjectPickingPair.h b/Source/Scene/imstkPbdObjectPickingPair.h new file mode 100644 index 0000000000000000000000000000000000000000..1cbc91a9931cd188c7ea9da34737744ba6e3f9fa --- /dev/null +++ b/Source/Scene/imstkPbdObjectPickingPair.h @@ -0,0 +1,52 @@ +/*========================================================================= + +Library: iMSTK + +Copyright (c) Kitware, Inc. & Center for Modeling, Simulation, +& Imaging in Medicine, Rensselaer Polytechnic Institute. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0.txt + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +=========================================================================*/ + +#pragma once + +#include "imstkCollisionPair.h" +#include "imstkCollisionDetection.h" + +namespace imstk +{ +class PbdObject; +class PbdSolver; + +/// +/// \class PbdObjectCollisionPair +/// +/// \brief This class defines a collision interaction between two PbdObjects +/// +class PbdObjectPickingPair : public CollisionPair +{ +public: + PbdObjectPickingPair(std::shared_ptr<PbdObject> obj1, std::shared_ptr<CollidingObject> obj2, + CollisionDetection::Type cdType = CollisionDetection::Type::PointSetToSphere); + + virtual ~PbdObjectPickingPair() override = default; + + void apply() override; + +private: + // Pbd defines two interactions (one at CD and one at solver) + Inputs m_solveNodeInputs; + Outputs m_solveNodeOutputs; +}; +} \ No newline at end of file