7 #include "imstkLevelSetCH.h" 8 #include "imstkCollisionData.h" 9 #include "imstkImageData.h" 10 #include "imstkLevelSetDeformableObject.h" 11 #include "imstkLevelSetModel.h" 12 #include "imstkRbdConstraint.h" 13 #include "imstkRigidObject2.h" 17 LevelSetCH::LevelSetCH()
22 LevelSetCH::~LevelSetCH()
24 if (m_kernelWeights !=
nullptr)
26 delete[] m_kernelWeights;
31 LevelSetCH::setInputLvlSetObj(std::shared_ptr<LevelSetDeformableObject> lvlSetObj)
37 LevelSetCH::setInputRigidObj(std::shared_ptr<RigidObject2> rbdObj)
39 setInputObjectB(rbdObj);
43 std::shared_ptr<LevelSetDeformableObject>
44 LevelSetCH::getLvlSetObj()
46 return std::dynamic_pointer_cast<LevelSetDeformableObject>(
getInputObjectA());
49 std::shared_ptr<RigidObject2>
50 LevelSetCH::getRigidObj()
52 return std::dynamic_pointer_cast<RigidObject2>(getInputObjectB());
59 m_kernelSigma = sigma;
62 LOG(WARNING) <<
"LevelSetCH kernel size must be odd, increasing by 1";
65 if (m_kernelWeights !=
nullptr)
67 delete[] m_kernelWeights;
69 m_kernelWeights =
new double[size * size * size];
71 const double invDiv = 1.0 / (2.0 * sigma * sigma);
72 const int halfSize =
static_cast<int>(size * 0.5);
74 for (
int z = -halfSize; z < halfSize + 1; z++)
76 for (
int y = -halfSize; y < halfSize + 1; y++)
78 for (
int x = -halfSize; x < halfSize + 1; x++)
80 const double dist = Vec3i(x, y, z).cast<
double>().norm();
81 m_kernelWeights[i++] = std::exp(-dist * invDiv);
89 const std::vector<CollisionElement>& elementsA,
90 const std::vector<CollisionElement>& elementsB)
92 std::shared_ptr<LevelSetDeformableObject> lvlSetObj = getLvlSetObj();
93 std::shared_ptr<RigidObject2> rbdObj = getRigidObj();
95 if (lvlSetObj ==
nullptr || rbdObj ==
nullptr)
100 std::shared_ptr<LevelSetModel> lvlSetModel = lvlSetObj->getLevelSetModel();
101 std::shared_ptr<ImageData> grid = std::dynamic_pointer_cast<
SignedDistanceField>(lvlSetModel->getModelGeometry())->getImage();
105 LOG(FATAL) <<
"Error: level set model geometry is not ImageData";
110 const Vec3d& invSpacing = grid->getInvSpacing();
111 const Vec3d& origin = grid->getOrigin();
114 if (elementsA.size() != elementsB.size())
119 if (m_useProportionalForce)
122 for (
size_t i = 0; i < elementsA.size(); i++)
127 if (lsmContactElement.m_type != CollisionElementType::PointDirection
128 || rbdContactElement.m_type != CollisionElementType::PointIndexDirection)
134 if (m_ptIdMask.count(rbdContactElement.m_element.m_PointIndexDirectionElement.ptIndex) != 0)
136 const Vec3d& pos = lsmContactElement.m_element.m_PointDirectionElement.pt;
137 const Vec3d& normal = lsmContactElement.m_element.m_PointDirectionElement.dir;
138 const Vec3i coord = (pos - origin).cwiseProduct(invSpacing).cast<
int>();
141 const double fN = normal.normalized().dot(rbdObj->getRigidBody()->getForce()) / rbdObj->getRigidBody()->getForce().norm();
142 const double S = std::max(fN, 0.0) * m_velocityScaling;
144 const int halfSize =
static_cast<int>(m_kernelSize * 0.5);
146 for (
int z = -halfSize; z < halfSize + 1; z++)
148 for (
int y = -halfSize; y < halfSize + 1; y++)
150 for (
int x = -halfSize; x < halfSize + 1; x++)
152 const Vec3i fCoord = coord + Vec3i(x, y, z);
153 lvlSetModel->addImpulse(fCoord, S * m_kernelWeights[j++]);
163 for (
size_t i = 0; i < elementsA.size(); i++)
168 if (lsmContactElement.m_type != CollisionElementType::PointDirection
169 || rbdContactElement.m_type != CollisionElementType::PointIndexDirection)
175 if (m_ptIdMask.count(rbdContactElement.m_element.m_PointIndexDirectionElement.ptIndex) != 0)
177 const Vec3d& pos = lsmContactElement.m_element.m_PointDirectionElement.pt;
179 const Vec3i coord = (pos - origin).cwiseProduct(invSpacing).cast<
int>();
180 const double S = m_velocityScaling;
182 const int halfSize =
static_cast<int>(m_kernelSize * 0.5);
184 for (
int z = -halfSize; z < halfSize + 1; z++)
186 for (
int y = -halfSize; y < halfSize + 1; y++)
188 for (
int x = -halfSize; x < halfSize + 1; x++)
190 const Vec3i fCoord = coord + Vec3i(x, y, z);
191 lvlSetModel->addImpulse(fCoord, S * m_kernelWeights[j++]);
203 std::shared_ptr<PointSet> pointSet = std::dynamic_pointer_cast<
PointSet>(getRigidObj()->getCollidingGeometry());
204 for (
int i = 0; i < pointSet->getNumVertices(); i++)
206 m_ptIdMask.insert(i);
Base class for all geometries represented by discrete points and elements The pointsets follow a pipe...
void setInputObjectA(std::shared_ptr< CollidingObject > objectA)
Set the input objects.
void maskAllPoints()
Allow all points to effect the levelset.
void handle(const std::vector< CollisionElement > &elementsA, const std::vector< CollisionElement > &elementsB) override
Compute forces and velocities based on collision data.
Union of collision elements. We use a union to avoid polymorphism. There may be many elements and acc...
void setKernel(const int size, const double sigma=1.0)
Set/Get the size + sigma of gaussian kernel used to apply impulse in levelset.
std::shared_ptr< CollidingObject > getInputObjectA() const
Get the input objects.
Structured field of signed distances implemented with ImageData The SDF differs in that when you scal...