7 #include "imstkLineMeshToCapsuleCD.h" 8 #include "imstkCollisionData.h" 9 #include "imstkCollisionUtils.h" 10 #include "imstkParallelUtils.h" 11 #include "imstkCapsule.h" 12 #include "imstkLineMesh.h" 16 LineMeshToCapsuleCD::LineMeshToCapsuleCD()
18 setRequiredInputType<LineMesh>(0);
19 setRequiredInputType<Capsule>(1);
24 std::shared_ptr<Geometry> geomA,
25 std::shared_ptr<Geometry> geomB,
26 std::vector<CollisionElement>& elementsA,
27 std::vector<CollisionElement>& elementsB)
29 std::shared_ptr<LineMesh> lineMesh = std::dynamic_pointer_cast<
LineMesh>(geomA);
30 std::shared_ptr<Capsule> capsule = std::dynamic_pointer_cast<
Capsule>(geomB);
33 const double capsuleRadius = capsule->getRadius();
34 const double capsuleLength = capsule->getLength();
35 const Quatd& capsuleOrientation = capsule->getOrientation();
36 const Vec3d& capsulePosA = capsulePos - 0.5 * capsuleLength * capsuleOrientation.toRotationMatrix().col(1);
37 const Vec3d& capsulePosB = capsulePos + (capsulePos - capsulePosA);
39 std::shared_ptr<VecDataArray<int, 2>> indicesPtr = lineMesh->getCells();
41 std::shared_ptr<VecDataArray<double, 3>> verticesPtr = lineMesh->getVertexPositions();
44 Eigen::AlignedBox3d box1, box2;
46 geomA->computeBoundingBox(lower, upper);
49 geomB->computeBoundingBox(lower, upper);
53 if (!box1.intersects(box2))
59 ParallelUtils::parallelFor(indices.size(), [&](
int i)
61 const Vec2i& cell = indices[i];
62 const Vec3d& x1 = vertices[cell[0]];
63 const Vec3d& x2 = vertices[cell[1]];
65 double capBoundingRaidus = (capsuleLength / 2.0) + capsuleRadius;
69 const Vec3d centroid = (x1 + x2) / 2.0;
72 const double rSqr1 = (centroid - x1).squaredNorm();
74 const double lineBoundingRadius = std::sqrt(rSqr1);
76 const double distSqr = (centroid - capsulePos).squaredNorm();
77 const double rSum = lineBoundingRadius + capBoundingRaidus;
80 if (distSqr < rSum * rSum)
83 int unusedCaseType = 0;
84 Vec3d capClosestPt = Vec3d::Zero();
85 Vec3d segClosestPt = Vec3d::Zero();
87 unusedCaseType = CollisionUtils::edgeToEdgeClosestPoints(
88 capsulePosA, capsulePosB,
90 capClosestPt, segClosestPt);
92 double seperationDistance = (capClosestPt - segClosestPt).norm();
95 if (seperationDistance <= capsuleRadius)
99 if ((x1 - segClosestPt).norm() <= 1E-12)
103 else if ((x2 - segClosestPt).norm() <= 1E-12)
107 else if (seperationDistance <= 1E-12)
116 Vec3d contactNormal = (capClosestPt - segClosestPt);
121 const double penetrationDepth = capsuleRadius - seperationDistance;
122 contactNormal /= seperationDistance;
125 elemA.ptIndex = cell[0];
126 elemA.dir = -contactNormal;
127 elemA.penetrationDepth = penetrationDepth;
130 elemB.pt = capClosestPt - capsuleRadius * contactNormal;
131 elemB.dir = contactNormal;
132 elemB.penetrationDepth = penetrationDepth;
135 elementsA.push_back(elemA);
136 elementsB.push_back(elemB);
140 else if (caseType == 1)
142 const double penetrationDepth = capsuleRadius - seperationDistance;
143 contactNormal /= seperationDistance;
146 elemA.ptIndex = cell[1];
147 elemA.dir = -contactNormal;
148 elemA.penetrationDepth = penetrationDepth;
151 elemB.pt = capClosestPt - capsuleRadius * contactNormal;
152 elemB.dir = contactNormal;
153 elemB.penetrationDepth = penetrationDepth;
156 elementsA.push_back(elemA);
157 elementsB.push_back(elemB);
161 else if (caseType == 2)
164 elemA.ids[0] = cell[0];
165 elemA.ids[1] = cell[1];
168 elemA.cellType = IMSTK_EDGE;
170 const double penetrationDepth = capsuleRadius - seperationDistance;
171 contactNormal /= seperationDistance;
174 elemB.dir = contactNormal;
175 elemB.pt = capClosestPt - capsuleRadius * contactNormal;
176 elemB.penetrationDepth = penetrationDepth;
179 elementsA.push_back(elemA);
180 elementsB.push_back(elemB);
184 else if (caseType == 3)
186 Vec3d segVec = x2 - x1;
187 Vec3d capVec = capsulePosB - capsulePosA;
188 Vec3d escapeDirection = capVec.cross(segVec).normalized();
191 elemA.ids[0] = cell[0];
192 elemA.ids[1] = cell[1];
195 elemA.cellType = IMSTK_EDGE;
197 const double penetrationDepth = capsuleRadius - seperationDistance;
198 contactNormal /= seperationDistance;
201 elemB.dir = escapeDirection;
202 elemB.pt = capClosestPt - capsuleRadius * escapeDirection;
203 elemB.penetrationDepth = penetrationDepth;
206 elementsA.push_back(elemA);
207 elementsB.push_back(elemB);
212 }, indices.size() > 500);
void unlock()
End a thread-safe region.
Vec3d getPosition(DataType type=DataType::PostTransform)
Get the local or global position (post transformed)
void lock()
Start a thread-safe region, where only one thread can execute at a time until a call to the unlock fu...
Base class for all volume mesh types.
Represents a cell by a single cell id OR by N vertex ids. Which case can be determined by the idCount...
Direclty gives a point-direction contact as its collision data, point given by index.
Capsule geometry, default configuration is centered at origin with length running up and down the y a...
Direclty gives a point-direction contact as its collision data.
void computeCollisionDataAB(std::shared_ptr< Geometry > geomA, std::shared_ptr< Geometry > geomB, std::vector< CollisionElement > &elementsA, std::vector< CollisionElement > &elementsB) override
Compute collision data for AB simultaneously.