7 #include "imstkSurfaceMeshToCapsuleCD.h" 8 #include "imstkCapsule.h" 9 #include "imstkCollisionUtils.h" 10 #include "imstkParallelUtils.h" 11 #include "imstkSurfaceMesh.h" 15 SurfaceMeshToCapsuleCD::SurfaceMeshToCapsuleCD()
17 setRequiredInputType<SurfaceMesh>(0);
18 setRequiredInputType<Capsule>(1);
23 std::shared_ptr<Geometry> geomA,
24 std::shared_ptr<Geometry> geomB,
25 std::vector<CollisionElement>& elementsA,
26 std::vector<CollisionElement>& elementsB)
28 std::shared_ptr<SurfaceMesh> surfMesh = std::dynamic_pointer_cast<
SurfaceMesh>(geomA);
29 std::shared_ptr<Capsule> capsule = std::dynamic_pointer_cast<
Capsule>(geomB);
32 const double capsuleRadius = capsule->getRadius();
33 const double capsuleLength = capsule->getLength();
34 const Quatd& capsuleOrientation = capsule->getOrientation();
35 const Vec3d& capsulePosA = capsulePos - 0.5 * capsuleLength * capsuleOrientation.toRotationMatrix().col(1);
36 const Vec3d& capsulePosB = capsulePos + (capsulePos - capsulePosA);
38 std::shared_ptr<VecDataArray<int, 3>> indicesPtr = surfMesh->getCells();
40 std::shared_ptr<VecDataArray<double, 3>> verticesPtr = surfMesh->getVertexPositions();
43 Eigen::AlignedBox3d box1, box2;
45 geomA->computeBoundingBox(lower, upper);
48 geomB->computeBoundingBox(lower, upper);
52 if (!box1.intersects(box2))
59 ParallelUtils::parallelFor(indices.size(), [&](
int i)
61 const Vec3i& cell = indices[i];
62 const Vec3d& x1 = vertices[cell[0]];
63 const Vec3d& x2 = vertices[cell[1]];
64 const Vec3d& x3 = vertices[cell[2]];
67 int unusedCaseType = 0;
68 const Vec3d trianglePointA = CollisionUtils::closestPointOnTriangle(capsulePosA, x1, x2, x3, unusedCaseType);
69 const Vec3d trianglePointB = CollisionUtils::closestPointOnTriangle(capsulePosB, x1, x2, x3, unusedCaseType);
71 const auto segmentPointA = CollisionUtils::closestPointOnSegment(trianglePointA, capsulePosA, capsulePosB, unusedCaseType);
72 const auto segmentPointB = CollisionUtils::closestPointOnSegment(trianglePointB, capsulePosA, capsulePosB, unusedCaseType);
74 const auto distanceA = (segmentPointA - trianglePointA).squaredNorm();
75 const auto distanceB = (segmentPointB - trianglePointB).squaredNorm();
77 const double sphereRadius = capsuleRadius;
78 Vec3d spherePos(0, 0, 0);
81 Vec3d triTipProjection;
83 if (distanceA < distanceB)
85 spherePos = segmentPointA;
87 else if (distanceA > distanceB)
89 spherePos = segmentPointB;
93 spherePos = (segmentPointA + segmentPointB) / 2.0;
98 const Vec3d centroid = (x1 + x2 + x3) / 3.0;
101 const double rSqr1 = (centroid - x1).squaredNorm();
102 const double rSqr2 = (centroid - x2).squaredNorm();
103 const double rSqr3 = (centroid - x3).squaredNorm();
104 const double triangleBoundingRadius = std::sqrt(std::max(rSqr1, std::max(rSqr2, rSqr3)));
106 const double distSqr = (centroid - spherePos).squaredNorm();
107 const double rSum = triangleBoundingRadius + sphereRadius;
108 if (distSqr <= rSum * rSum)
113 Vec3d triangleContactPt;
117 int caseType = CollisionUtils::testSphereToTriangle(
118 spherePos, sphereRadius,
121 edgeContact, pointContact);
125 const bool inserted = CollisionUtils::testSegmentTriangle(
126 capsulePosA, capsulePosB,
136 auto intersectionPt = uvw[0] * x1 + uvw[1] * x2 + uvw[2] * x3;
138 auto capsuleSegTipDistA = (capsulePosA - intersectionPt).squaredNorm();
139 auto capsuleSegTipDistB = (capsulePosB - intersectionPt).squaredNorm();
141 if (capsuleSegTipDistA <= capsuleSegTipDistB)
143 nearestTip = capsulePosA;
144 triTipProjection = trianglePointA;
148 nearestTip = capsulePosB;
149 triTipProjection = trianglePointB;
157 elemA.ids[0] = edgeContact[0];
158 elemA.ids[1] = edgeContact[1];
161 elemA.cellType = IMSTK_EDGE;
163 Vec3d contactNormal = (spherePos - triangleContactPt);
164 const double dist = contactNormal.norm();
165 const double penetrationDepth = sphereRadius - dist;
166 contactNormal /= dist;
169 elemB.dir = contactNormal;
170 elemB.pt = spherePos - sphereRadius * contactNormal;
171 elemB.penetrationDepth = penetrationDepth;
174 elementsA.push_back(elemA);
175 elementsB.push_back(elemB);
179 else if (caseType == 2)
182 elemA.ids[0] = cell[0];
183 elemA.ids[1] = cell[1];
184 elemA.ids[2] = cell[2];
187 elemA.cellType = IMSTK_TRIANGLE;
189 Vec3d contactNormal = (spherePos - triangleContactPt);
190 const double dist = contactNormal.norm();
191 const double penetrationDepth = sphereRadius - dist;
192 contactNormal /= dist;
195 elemB.dir = contactNormal;
196 elemB.pt = spherePos - sphereRadius * contactNormal;
197 elemB.penetrationDepth = penetrationDepth;
200 elementsA.push_back(elemA);
201 elementsB.push_back(elemB);
205 else if (caseType == 3)
207 Vec3d contactNormal = (spherePos - triangleContactPt);
208 const double dist = contactNormal.norm();
209 const double penetrationDepth = sphereRadius - dist;
210 contactNormal /= dist;
214 elemA.ptIndex = pointContact;
215 elemA.dir = -contactNormal;
216 elemA.penetrationDepth = penetrationDepth;
219 elemB.pt = spherePos - sphereRadius * contactNormal;
220 elemB.dir = contactNormal;
221 elemB.penetrationDepth = penetrationDepth;
224 elementsA.push_back(elemA);
225 elementsB.push_back(elemB);
229 else if (caseType == 4)
232 elemA.ids[0] = cell[0];
233 elemA.ids[1] = cell[1];
234 elemA.ids[2] = cell[2];
237 elemA.cellType = IMSTK_TRIANGLE;
240 Vec3d contactNormal = (x2 - x1).cross(x3 - x1).normalized();
241 Vec3d penetrationVec = (triTipProjection - nearestTip);
243 Vec3d projectionToNormal = penetrationVec.dot(contactNormal) * contactNormal;
244 const double dist = projectionToNormal.norm();
245 const double penetrationDepth = dist + sphereRadius;
248 elemB.dir = contactNormal;
249 elemB.pt = spherePos - contactNormal * penetrationDepth;
250 elemB.penetrationDepth = penetrationDepth;
253 elementsA.push_back(elemA);
254 elementsB.push_back(elemB);
258 }, surfMesh->getNumTriangles() > 200);
void unlock()
End a thread-safe region.
Vec3d getPosition(DataType type=DataType::PostTransform)
Get the local or global position (post transformed)
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.
void lock()
Start a thread-safe region, where only one thread can execute at a time until a call to the unlock fu...
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...
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.