7 #include "imstkClosedSurfaceMeshToCapsuleCD.h" 8 #include "imstkCapsule.h" 9 #include "imstkCollisionUtils.h" 10 #include "imstkParallelUtils.h" 11 #include "imstkSurfaceMesh.h" 15 ClosedSurfaceMeshToCapsuleCD::ClosedSurfaceMeshToCapsuleCD()
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();
37 const Vec3d& capsulePosA = capsulePos - 0.5 * capsuleLength * capsuleOrientation.toRotationMatrix().col(1);
38 const Vec3d& capsulePosB = capsulePos + (capsulePos - capsulePosA);
40 std::shared_ptr<VecDataArray<int, 3>> indicesPtr = surfMesh->getCells();
42 std::shared_ptr<VecDataArray<double, 3>> verticesPtr = surfMesh->getVertexPositions();
47 ParallelUtils::parallelFor(indices.size(), [&](
int cellId)
49 const Vec3i& cell = indices[cellId];
50 const Vec3d& x1 = vertices[cell[0]];
51 const Vec3d& x2 = vertices[cell[1]];
52 const Vec3d& x3 = vertices[cell[2]];
55 double minSDV = std::numeric_limits<double>::max();
56 for (
int vertId = 0; vertId < 3; vertId++)
58 auto SDV = capsule->getFunctionValue(vertices[cell[vertId]]);
59 minSDV = std::min(minSDV, SDV);
62 if (minSDV <= capsuleRadius * 8.0)
65 int unusedCaseType = 0;
66 const Vec3d trianglePointA = CollisionUtils::closestPointOnTriangle(capsulePosA, x1, x2, x3, unusedCaseType);
67 const Vec3d trianglePointB = CollisionUtils::closestPointOnTriangle(capsulePosB, x1, x2, x3, unusedCaseType);
69 const auto segmentPointA = CollisionUtils::closestPointOnSegment(trianglePointA, capsulePosA, capsulePosB, unusedCaseType);
70 const auto segmentPointB = CollisionUtils::closestPointOnSegment(trianglePointB, capsulePosA, capsulePosB, unusedCaseType);
72 const auto distanceA = (segmentPointA - trianglePointA).squaredNorm();
73 const auto distanceB = (segmentPointB - trianglePointB).squaredNorm();
75 const double sphereRadius = capsuleRadius;
76 Vec3d spherePos(0, 0, 0);
78 if (distanceA < distanceB)
80 spherePos = segmentPointA;
82 else if (distanceA > distanceB)
84 spherePos = segmentPointB;
88 spherePos = (segmentPointA + segmentPointB) / 2.0;
94 Vec3d triangleContactPt;
96 int caseType = CollisionUtils::testSphereToTriangle(
97 spherePos, sphereRadius,
103 const bool inserted = CollisionUtils::testSegmentTriangle(
104 capsulePosA, capsulePosB,
119 elemA.ids[0] = cell[0];
120 elemA.ids[1] = cell[1];
121 elemA.ids[2] = cell[2];
123 elemA.parentId = cellId;
124 elemA.cellType = IMSTK_TRIANGLE;
126 Vec3d contactNormal = (spherePos - triangleContactPt);
127 const double dist = contactNormal.norm();
128 const double penetrationDepth = sphereRadius - dist;
129 contactNormal /= dist;
132 elemB.dir = contactNormal;
133 elemB.pt = spherePos - sphereRadius * contactNormal;
134 elemB.penetrationDepth = penetrationDepth;
137 elementsA.push_back(elemA);
138 elementsB.push_back(elemB);
142 else if (caseType == 2)
145 elemA.ids[0] = cell[0];
146 elemA.ids[1] = cell[1];
147 elemA.ids[2] = cell[2];
149 elemA.parentId = cellId;
150 elemA.cellType = IMSTK_TRIANGLE;
152 Vec3d contactNormal = (spherePos - triangleContactPt);
153 const double dist = contactNormal.norm();
154 double penetrationDepth = sphereRadius - dist;
155 contactNormal /= dist;
157 contactNormal = (x2 - x1).cross(x3 - x1).normalized();
159 penetrationDepth = sphereRadius * 2.0;
162 elemB.dir = contactNormal;
163 elemB.pt = spherePos - sphereRadius * contactNormal;
164 elemB.penetrationDepth = penetrationDepth;
167 elementsA.push_back(elemA);
168 elementsB.push_back(elemB);
172 }, 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...
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.