7 #include "imstkRigidBodyCH.h" 8 #include "imstkCollisionData.h" 9 #include "imstkCollisionUtils.h" 10 #include "imstkLineMesh.h" 11 #include "imstkRbdContactConstraint.h" 12 #include "imstkRbdFrictionConstraint.h" 13 #include "imstkRigidBodyModel2.h" 14 #include "imstkRigidObject2.h" 15 #include "imstkSurfaceMesh.h" 16 #include "imstkVecDataArray.h" 21 RigidBodyCH::setInputRigidObjectA(std::shared_ptr<RigidObject2> rbdObjA)
29 setInputObjectB(rbdObjB);
35 setInputObjectB(colObjB);
38 std::shared_ptr<RigidObject2>
39 RigidBodyCH::getRigidObjA()
44 std::shared_ptr<RigidObject2>
45 RigidBodyCH::getRigidObjB()
47 return std::dynamic_pointer_cast<
RigidObject2>(getInputObjectB());
52 const std::vector<CollisionElement>& elementsA,
53 const std::vector<CollisionElement>& elementsB)
55 std::shared_ptr<RigidObject2> rbdObjA = getRigidObjA();
56 std::shared_ptr<RigidObject2> rbdObjB = getRigidObjB();
57 std::shared_ptr<CollidingObject> colObjB = getInputObjectB();
60 if (rbdObjA !=
nullptr && rbdObjB !=
nullptr)
63 if (elementsB.size() == 0 && elementsA.size() != 0)
70 std::shared_ptr<RigidBodyModel2> rbdModelA = rbdObjA->getRigidBodyModel2();
71 std::shared_ptr<RigidBodyModel2> rbdModelB = rbdObjB->getRigidBodyModel2();
75 if (rbdModelA != rbdModelB)
77 if (rbdModelA !=
nullptr)
81 if (rbdModelB !=
nullptr)
94 else if (rbdObjA !=
nullptr && colObjB !=
nullptr)
103 std::shared_ptr<RigidObject2> rbdObjA,
104 std::shared_ptr<RigidObject2> rbdObjB,
105 const std::vector<CollisionElement>& elementsA,
106 const std::vector<CollisionElement>& elementsB)
108 if (elementsA.size() != elementsB.size())
113 auto geom = std::dynamic_pointer_cast<
PointSet>(rbdObjA->getCollidingGeometry());
116 std::shared_ptr<RigidBodyModel2> rbdModelAB = rbdObjA->getRigidBodyModel2();
117 for (
size_t i = 0; i < elementsA.size(); i++)
120 if (colElemA.m_type == CollisionElementType::PointDirection)
122 const Vec3d& dir = colElemA.m_element.m_PointDirectionElement.dir;
123 const double depth = colElemA.m_element.m_PointDirectionElement.penetrationDepth;
124 const Vec3d& contactPt = colElemA.m_element.m_PointDirectionElement.pt;
128 else if (colElemA.m_type == CollisionElementType::PointIndexDirection)
131 const Vec3d& dir = colElemA.m_element.m_PointIndexDirectionElement.dir;
132 const double depth = colElemA.m_element.m_PointIndexDirectionElement.penetrationDepth;
133 const Vec3d& contactPt = (*geom->getVertexPositions())[colElemA.m_element.m_PointIndexDirectionElement.ptIndex];
142 std::shared_ptr<RigidObject2> rbdObj,
143 std::shared_ptr<CollidingObject> colObj,
144 const std::vector<CollisionElement>& elementsA,
145 const std::vector<CollisionElement>& elementsB)
148 for (
size_t i = 0; i < elementsA.size(); i++)
151 if (colElem.m_type == CollisionElementType::PointDirection)
153 const Vec3d& dir = colElem.m_element.m_PointDirectionElement.dir;
154 const double depth = colElem.m_element.m_PointDirectionElement.penetrationDepth;
155 const Vec3d& contactPt = colElem.m_element.m_PointDirectionElement.pt;
159 else if (colElem.m_type == CollisionElementType::PointIndexDirection)
162 auto geom = std::dynamic_pointer_cast<
PointSet>(rbdObj->getCollidingGeometry());
163 const Vec3d& dir = colElem.m_element.m_PointIndexDirectionElement.dir;
164 const double depth = colElem.m_element.m_PointIndexDirectionElement.penetrationDepth;
165 const Vec3d& contactPt = (*geom->getVertexPositions())[colElem.m_element.m_PointIndexDirectionElement.ptIndex];
172 if (elementsA.size() != elementsB.size() || colObj ==
nullptr)
178 auto geomA = std::dynamic_pointer_cast<
PointSet>(rbdObj->getCollidingGeometry());
179 auto geomB = std::dynamic_pointer_cast<
PointSet>(colObj->getCollidingGeometry());
180 if (geomA ==
nullptr || geomB ==
nullptr)
187 std::shared_ptr<VecDataArray<double, 3>> verticesBPtr = geomB->getVertexPositions();
191 std::shared_ptr<RigidBodyModel2> rbdModelA = rbdObj->getRigidBodyModel2();
192 for (
size_t i = 0; i < elementsA.size(); i++)
198 if (colElemA.m_type != CollisionElementType::CellIndex || colElemB.m_type != CollisionElementType::CellIndex)
207 if (elemA.cellType == IMSTK_VERTEX && elemB.cellType == IMSTK_TRIANGLE)
209 const Vec3d& p = verticesA[elemA.ids[0]];
211 Vec3i tri = Vec3i::Zero();
212 if (elemB.idCount == 1)
214 tri = (*
dynamic_cast<SurfaceMesh*
>(geomB.get())->getCells().get())[elemB.ids[0]];
216 else if (elemB.idCount == 3)
218 tri = Vec3i(elemB.ids[0], elemB.ids[1], elemB.ids[2]);
220 const Vec3d& a = verticesB[tri[0]];
221 const Vec3d& b = verticesB[tri[1]];
222 const Vec3d& c = verticesB[tri[2]];
228 const Vec3d v0 = b - a;
229 const Vec3d v1 = c - a;
230 const Vec3d v2 = p - a;
231 n = v0.cross(v1).normalized();
234 Vec3d contactPt = p + n * depth;
239 else if (elemA.cellType == IMSTK_EDGE && elemB.cellType == IMSTK_EDGE)
241 Vec2i edgeA = Vec2i::Zero();
242 if (elemA.idCount == 1)
244 edgeA = (*
dynamic_cast<LineMesh*
>(geomA.get())->getCells().get())[elemA.ids[0]];
246 else if (elemA.idCount == 2)
248 edgeA = Vec2i(elemA.ids[0], elemA.ids[1]);
250 Vec2i edgeB = Vec2i::Zero();
251 if (elemB.idCount == 1)
253 edgeB = (*
dynamic_cast<LineMesh*
>(geomB.get())->getCells().get())[elemB.ids[0]];
255 else if (elemB.idCount == 2)
257 edgeB = Vec2i(elemB.ids[0], elemB.ids[1]);
262 CollisionUtils::edgeToEdgeClosestPoints(
263 verticesA[edgeA[0]], verticesA[edgeA[1]],
264 verticesB[edgeB[0]], verticesB[edgeB[1]], pA, pB);
266 const Vec3d diff = pB - pA;
267 const double l = diff.norm();
271 const Vec3d n = diff / l;
278 else if (elemA.cellType == IMSTK_EDGE && elemB.cellType == IMSTK_VERTEX)
280 Vec2i edge = Vec2i::Zero();
281 if (elemA.idCount == 1)
283 edge = (*
dynamic_cast<LineMesh*
>(geomA.get())->getCells().get())[elemA.ids[0]];
285 else if (elemA.idCount == 2)
287 edge = Vec2i(elemA.ids[0], elemA.ids[1]);
289 const Vec3d& a = verticesA[edge[0]];
290 const Vec3d& b = verticesA[edge[1]];
292 const Vec3d& pt = verticesB[elemB.ids[0]];
294 const Vec3d ab = b - a;
295 const double length = ab.norm();
296 const Vec3d dir1 = ab / length;
299 const Vec3d diff = pt - a;
300 const double p = dir1.dot(diff);
303 const Vec3d diff1 = diff - p * dir1;
304 const double l = diff1.norm();
307 const Vec3d n = diff1 / l;
308 const Vec3d contactPt = pt - n * l;
312 else if (elemA.cellType == IMSTK_VERTEX && elemB.cellType == IMSTK_EDGE)
314 const Vec3d& pt = verticesA[elemA.ids[0]];
316 Vec2i edge = Vec2i::Zero();
317 if (elemB.idCount == 1)
319 edge = (*
dynamic_cast<LineMesh*
>(geomB.get())->getCells().get())[elemB.ids[0]];
321 else if (elemB.idCount == 2)
323 edge = Vec2i(elemB.ids[0], elemB.ids[1]);
325 const Vec3d& a = verticesB[edge[0]];
326 const Vec3d& b = verticesB[edge[1]];
328 const Vec3d ab = b - a;
329 const double length = ab.norm();
330 const Vec3d dir1 = ab / length;
333 const Vec3d diff = pt - a;
334 const double p = dir1.dot(diff);
337 const Vec3d diff1 = diff - p * dir1;
338 const double l = diff1.norm();
341 const Vec3d n = diff1 / l;
342 const Vec3d contactPt = pt + n * l;
346 else if (elemA.cellType == IMSTK_VERTEX && elemB.cellType == IMSTK_VERTEX)
348 const Vec3d& a = verticesA[elemA.ids[0]];
349 const Vec3d& b = verticesB[elemB.ids[0]];
351 const Vec3d diff = b - a;
352 const double l = diff.norm();
363 std::shared_ptr<RigidObject2> rbdObj,
364 const Vec3d& contactPt,
const Vec3d& contactNormal,
365 const double contactDepth)
367 auto contactConstraint = std::make_shared<RbdContactConstraint>(
368 rbdObj->getRigidBody(),
nullptr,
369 contactNormal.normalized(), contactPt, contactDepth,
371 RbdConstraint::Side::A);
372 contactConstraint->compute(rbdObj->getRigidBodyModel2()->getTimeStep());
373 rbdObj->getRigidBodyModel2()->addConstraint(contactConstraint);
377 std::shared_ptr<RbdFrictionConstraint> frictionConstraint =
378 std::make_shared<RbdFrictionConstraint>(
379 rbdObj->getRigidBody(),
nullptr,
380 contactPt, contactNormal.normalized(), contactDepth,
381 m_frictionalCoefficient,
382 RbdConstraint::Side::A);
383 frictionConstraint->compute(rbdObj->getRigidBodyModel2()->getTimeStep());
384 rbdObj->getRigidBodyModel2()->addConstraint(frictionConstraint);
390 std::shared_ptr<RigidObject2> rbdObjA,
391 std::shared_ptr<RigidObject2> rbdObjB,
392 const Vec3d& contactPt,
const Vec3d& contactNormal,
393 const double contactDepth)
396 if (rbdObjA->getRigidBodyModel2() == rbdObjB->getRigidBodyModel2())
398 auto contactConstraint = std::make_shared<RbdContactConstraint>(
399 rbdObjA->getRigidBody(), rbdObjB->getRigidBody(),
400 contactNormal.normalized(), contactPt, contactDepth,
402 contactConstraint->compute(rbdObjA->getRigidBodyModel2()->getTimeStep());
403 rbdObjA->getRigidBodyModel2()->addConstraint(contactConstraint);
407 auto frictionConstraint = std::make_shared<RbdFrictionConstraint>(
408 rbdObjA->getRigidBody(), rbdObjB->getRigidBody(),
409 contactPt, contactNormal.normalized(), contactDepth,
410 m_frictionalCoefficient,
411 RbdConstraint::Side::AB);
412 frictionConstraint->compute(rbdObjA->getRigidBodyModel2()->getTimeStep());
413 rbdObjA->getRigidBodyModel2()->addConstraint(frictionConstraint);
419 addConstraint(rbdObjA, contactPt, contactNormal, contactDepth);
420 addConstraint(rbdObjB, contactPt, -contactNormal, contactDepth);
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 setInputCollidingObjectB(std::shared_ptr< CollidingObject > colObjB)
Second input colliding object is optional.
void setInputRigidObjectB(std::shared_ptr< RigidObject2 > rbdObjB)
Second input rigid object is optional.
void handleRbdStaticOneWay(std::shared_ptr< RigidObject2 > rbdObj, std::shared_ptr< CollidingObject > colObj, const std::vector< CollisionElement > &elementsA, const std::vector< CollisionElement > &elementsB)
Handle rigid vs static one-way edge-edge, vertex-triangle, etc.
Union of collision elements. We use a union to avoid polymorphism. There may be many elements and acc...
std::shared_ptr< VecDataArray< double, 3 > > getVertexPositions(DataType type=DataType::PostTransform) const
Returns the vector of current positions of the mesh vertices.
Base class for all volume mesh types.
virtual void handle(const std::vector< CollisionElement > &elementsA, const std::vector< CollisionElement > &elementsB) override
Add rigid body constraints according to contacts.
Represents a set of triangles & vertices via an array of Vec3d double vertices & Vec3i integer indice...
Represents a cell by a single cell id OR by N vertex ids. Which case can be determined by the idCount...
std::shared_ptr< CollidingObject > getInputObjectA() const
Get the input objects.
Scene objects that are governed by rigid body dynamics under the RigidBodyModel2. ...
virtual void addConstraint(std::shared_ptr< RigidObject2 > rbdObj, const Vec3d &contactPt, const Vec3d &contactNormal, const double contactDepth)
Add constraint for the rigid body given contact.
void handleRbdRbdTwoWay(std::shared_ptr< RigidObject2 > rbdObjA, std::shared_ptr< RigidObject2 > rbdObjB, const std::vector< CollisionElement > &elementsA, const std::vector< CollisionElement > &elementsB)
Handle rigid vs rigid two-way edge-edge, vertex-triangle, etc.